Token导航 LogoToken导航

Agent Skill · 研究检索

backtesting-py-oracle(backtesting PY Oracle 搜索)

用于辅助测试设计、自动化测试、用例整理和回归验证。它适合让 Agent 编写单元测试、端到端测试、测试计划或根据失败日志定位问题。使用时需要确认项目测试框架、运行命令和夹具数据,避免为了通过测试而改坏真实逻辑;涉及浏览器或外部服务时,应区分本地模拟、测试环境和生产环境。

backtesting-py-oracle 是研究检索类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为只读;许可证信息还不明确,第三方扫描已通过,按安装量在研究检索类的 73,675 个 Skill 里排第 34,984。

总安装 2,157周安装 89GitHub Stars 38下载 705核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:backtesting-py-oracle(backtesting PY Oracle 搜索)
来源仓库:https://github.com/terrylica/cc-skills
仓库路径:skills/backtesting-py-oracle
安装命令:
npx skills add https://github.com/terrylica/cc-skills --skill backtesting-py-oracle
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/terrylica/cc-skills --skill backtesting-py-oracle

这个 Skill 是做什么的

研究检索类 Skill 主要解决「找资料、核对事实、把来源整理清楚」的问题,通常会让助手先检索再总结。

backtesting-py-oracle 用于辅助测试设计、自动化测试、用例整理和回归验证,适合让 Agent 编写单元测试、端到端测试或根据失败日志定位问题。它专用于 backtesting.py 工具的 Oracle 验证,确保 ClickHouse SQL 扫描结果与 Python 交易评估的一致性。

使用时需配合 clickhouse-antipatterns、sweep-methodology 等配套技能,保证 bit-atomic 可复现性。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。涉及浏览器或外部服务时,应区分本地模拟、测试环境和生产环境。

来源仓库内路径:skills/backtesting-py-oracle

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/terrylica/cc-skills --skill backtesting-py-ora…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它标注为只读,先用只读任务试一次,确认行为符合预期再扩大使用范围。

常见问题

6 条

backtesting-py-oracle 怎么安装?

在终端执行 npx skills add https://github.com/terrylica/cc-skills --skill backtesting-py-oracle。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

backtesting-py-oracle 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

backtesting-py-oracle 需要什么权限?

权限级别是只读。该 Skill 主要提供规则、说明或参考内容,本身偏只读;真正读写文件、联网或执行命令仍取决于宿主 Agent 的任务。

backtesting-py-oracle 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

backtesting-py-oracle 用的人多吗?

公开数据是累计安装 2,157 次,近一周安装 89 次,下载 705 次,GitHub 38 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

backtesting-py-oracle 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 第三方扫描已通过,常见的高风险行为没有命中。
  • 标注为只读权限,试用阶段不容易误改本地文件。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理研究检索类任务、又不想每次都手写提示词的人。
  • 只想先试试效果、不希望它改动本地文件的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

研究检索类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
find-skills

寻找技能 · Codex、Claude

31,199,81316,486操作浏览器MIT有提醒
self-improving-agent

自我改进 Agent · OpenClaw

16,464,0023,396接触敏感数据MIT-0通过
soultrace

灵魂追踪 · Codex、Claude

7,588,94412需要联网未明确有提醒
self-improving

自我完善 · OpenClaw

6,829,2841,046需要联网MIT-0通过
microsoft-foundry

微软代工厂 · Codex、Claude

6,614,144764调用外部服务未明确有提醒
backtesting-py-oracle

backtesting PY Oracle 搜索 · 本页

2,15738只读未明确通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

backtesting.py Oracle Validation for Range Bar Patterns

Configuration and anti-patterns for using backtesting.py to validate ClickHouse SQL sweep results. Ensures bit-atomic replicability between SQL and Python trade evaluation.

Companion skills: clickhouse-antipatterns (SQL correctness, AP-16) | sweep-methodology (sweep design) | rangebar-eval-metrics (evaluation metrics)

Validated: Gen600 oracle verification (2026-02-12) — 3 assets, 5 gates, ALL PASS.


Self-Evolving Skill: This skill improves through use. If instructions are wrong, parameters drifted, or a workaround was needed — fix this file immediately, don't defer. Only update for real, reproducible issues.

Critical Configuration (NEVER omit)

from backtesting import Backtest

bt = Backtest(
    df,
    Strategy,
    cash=100_000,
    commission=0,
    hedging=True,           # REQUIRED: Multiple concurrent positions
    exclusive_orders=False,  # REQUIRED: Don't auto-close on new signal
)

Why: SQL evaluates each signal independently (overlapping trades allowed). Without hedging=True, backtesting.py skips signals while a position is open, producing fewer trades than SQL. This was discovered when SOLUSDT produced 105 Python trades vs 121 SQL trades — 16 signals were silently skipped.


Anti-Patterns (Ordered by Severity)

BP-01: Missing Multi-Position Mode (CRITICAL)

Symptom: Python produces fewer trades than SQL. Gate 1 (signal count) fails.

Root Cause: Default exclusive_orders=True prevents opening new positions while one is active.

Fix: Always use hedging=True, exclusive_orders=False.

BP-02: ExitTime Sort Order (CRITICAL)

Symptom: Entry prices appear mismatched (Gate 3 fails) even though both SQL and Python use the same price source.

Root Cause: stats._trades is sorted by ExitTime, not EntryTime. When overlapping trades exit in a different order than they entered, trade[i] no longer maps to signal[i].

Fix:

trades = stats._trades.sort_values("EntryTime").reset_index(drop=True)

BP-03: NaN Poisoning in Rolling Quantile (CRITICAL)

Symptom: Cross-asset tests fail with far fewer Python trades. Feature quantile becomes NaN and propagates forward indefinitely.

Root Cause: np.percentile with NaN inputs returns NaN. If even one NaN feature value enters the rolling window, all subsequent quantiles become NaN, making all subsequent filter comparisons fail.

Fix: Skip NaN values when building the signal window:

def _rolling_quantile_on_signals(feature_arr, is_signal_arr, quantile_pct, window=1000):
    result = np.full(len(feature_arr), np.nan)
    signal_values = []
    for i in range(len(feature_arr)):
        if is_signal_arr[i]:
            if len(signal_values) > 0:
                window_data = signal_values[-window:]
                result[i] = np.percentile(window_data, quantile_pct * 100)
            # Only append non-NaN values (matches SQL quantileExactExclusive NULL handling)
            if not np.isnan(feature_arr[i]):
                signal_values.append(feature_arr[i])
    return result

BP-04: Data Range Mismatch (MODERATE)

Symptom: Different signal counts between SQL and Python for assets with early data (BNB, XRP).

Root Cause: load_range_bars() defaults to start='2020-01-01' but SQL has no lower bound.

Fix: Always pass start='2017-01-01' to cover all available data.

BP-05: Margin Exhaustion with Overlapping Positions (MODERATE)

Symptom: Orders canceled with insufficient margin. Fewer trades than expected.

Root Cause: With hedging=True and default full-equity sizing, overlapping positions exhaust available margin.

Fix: Use fixed fractional sizing:

self.buy(size=0.01)  # 1% equity per trade

BP-06: Signal Timestamp vs Entry Timestamp (LOW)

Symptom: Gate 2 (timestamp match) fails because SQL uses signal bar timestamps while Python uses entry bar timestamps.

Root Cause: SQL outputs the signal detection bar's timestamp_ms. Python's EntryTime is the fill bar (next bar after signal). These differ by 1 bar.

Fix: Record signal bar timestamps in the strategy's next() method:

# Before calling self.buy()
self._signal_timestamps.append(int(self.data.index[-1].timestamp() * 1000))

5-Gate Oracle Validation Framework

GateMetricThresholdWhat it catches
1Signal Count<5% diffMissing signals, filter misalignment
2Timestamp Match>95%Timing offset, warmup differences
3Entry Price>95%Price source mismatch, sort ordering
4Exit Type>90%Barrier logic differences
5Kelly Fraction<0.02Aggregate outcome alignment

Expected residual: 1-2 exit type mismatches per asset at TIME barrier boundary (bar 50). SQL uses fwd_closes[max_bars], backtesting.py closes at current bar price. Impact on Kelly < 0.006.


Strategy Architecture: Single vs Multi-Position

ModeConstructorUse CasePosition Sizing
Single-positionhedging=False (default)Champion 1-bar holdFull equity
Multi-positionhedging=True, exclusive_orders=FalseSQL oracle validationFixed fractional (size=0.01)

Multi-Position Strategy Template

class Gen600Strategy(Strategy):
    def next(self):
        current_bar = len(self.data) - 1

        # 1. Register newly filled trades and set barriers
        for trade in self.trades:
            tid = id(trade)
            if tid not in self._known_trades:
                self._known_trades.add(tid)
                self._trade_entry_bar[tid] = current_bar
                actual_entry = trade.entry_price
                if self.tp_mult > 0:
                    trade.tp = actual_entry * (1.0 + self.tp_mult * self.threshold_pct)
                if self.sl_mult > 0:
                    trade.sl = actual_entry * (1.0 - self.sl_mult * self.threshold_pct)

        # 2. Check time barrier for each open trade
        for trade in list(self.trades):
            tid = id(trade)
            entry_bar = self._trade_entry_bar.get(tid, current_bar)
            if self.max_bars > 0 and (current_bar - entry_bar) >= self.max_bars:
                trade.close()
                self._trade_entry_bar.pop(tid, None)

        # 3. Check for new signal (no position guard — overlapping allowed)
        if self._is_signal[current_bar]:
            self.buy(size=0.01)

Data Loading

from data_loader import load_range_bars

df = load_range_bars(
    symbol="SOLUSDT",
    threshold=1000,
    start="2017-01-01",      # Cover all available data
    end="2025-02-05",        # Match SQL cutoff
    extra_columns=["volume_per_trade", "lookback_price_range"],  # Gen600 features
)

HTML Equity Plot: Y-Axis Auto-Fit on Zoom (BP-07 to BP-10)

backtesting.py generates Bokeh HTML plots via bt.plot(). By default, the y-axis is fixed — zooming on the x-axis does NOT rescale the y-axis to fit visible data. This makes it impossible to inspect zoomed-in regions of equity curves that span 4+ orders of magnitude.

Reference implementation: scripts/gen800/plotting.py in opendeviationbar-patterns.

BP-07: NEVER Use LogScale for Equity (CRITICAL)

Symptom: Equity panel y-axis doesn't auto-fit on zoom. JS callbacks fail silently.

Root Cause: Bokeh's LogScale breaks CustomJS y-range callbacks in multi-panel linked x_range layouts. The js_on_change callback fires but y_range.start/y_range.end assignments are ignored by the LogScale renderer.

Proven via POC: LogScale + JS callback works in single-panel mode but fails when 5 panels share a linked x_range.

Fix: Transform equity data to log10() in Python, display on linear scale with a CustomJSTickFormatter that shows 10^tick as readable values:

import numpy as np
from bokeh.models import CustomJSTickFormatter, Range1d

# Transform data
raw = np.asarray(src.data["equity"], dtype=float)
raw = np.where(raw > 0, raw, 1e-10)
src.data["equity"] = np.log10(raw).tolist()

# Custom tick formatter (shows 1%, 100%, 10K%, 1M%)
child.yaxis[0].formatter = CustomJSTickFormatter(code="""
    const v = Math.pow(10, tick);
    if (v >= 1e6) return (v/1e6).toFixed(1) + 'M%';
    if (v >= 1e3) return (v/1e3).toFixed(0) + 'K%';
    if (v >= 1) return v.toFixed(0) + '%';
    return v.toFixed(2) + '%';
""")

# MUST set initial y_range explicitly (backtesting.py leaves it as NaN)
valid = eq[np.isfinite(eq)]
pad = (valid.max() - valid.min()) * 0.05
child.y_range = Range1d(start=valid.min() - pad, end=valid.max() + pad)

BP-08: Panel-Aware Column Matching (CRITICAL)

Symptom: Drawdown/P&L panels go blank when zooming. Shows millions of percent.

Root Cause: Multiple panels share the same ColumnDataSource (backtesting.py optimization). The Equity panel's Line renderer and the Drawdown panel's Line renderer both reference a source containing equity, drawdown, High, Low, etc. A naive "find first y column" approach picks equity for the Drawdown panel.

Fix: Match by panel_label FIRST, then by column name:

panel_label = child.yaxis[0].axis_label or ""

# Label-first matching (panels share data sources!)
if "Drawdown" in panel_label and "drawdown" in d:
    hi_col = lo_col = "drawdown"
elif "Equity" in panel_label and "equity" in d:
    hi_col = lo_col = "equity"
elif "High" in d and "Low" in d:  # OHLC
    hi_col, lo_col = "High", "Low"

BP-09: JS Callback Pattern for Y-Axis Auto-Fit (PROVEN)

Attach a CustomJS callback to x_range.js_on_change for each panel. The callback scans visible data and sets y_range directly:

from bokeh.models import CustomJS

cb = CustomJS(
    args={"source": src, "yr": child.y_range,
          "x_col": "index", "y_col": "equity"},
    code="""
    const xs = source.data[x_col];
    const ys = source.data[y_col];
    const x0 = cb_obj.start, x1 = cb_obj.end;
    let lo = Infinity, hi = -Infinity;
    for (let i = 0; i < xs.length; i++) {
        if (xs[i] >= x0 && xs[i] <= x1 && isFinite(ys[i])) {
            if (ys[i] < lo) lo = ys[i];
            if (ys[i] > hi) hi = ys[i];
        }
    }
    if (isFinite(lo) && isFinite(hi) && lo < hi) {
        const pad = (hi - lo) * 0.05 || 0.001;
        yr.start = lo - pad;
        yr.end = hi + pad;
    }
    """,
)
child.x_range.js_on_change("start", cb)
child.x_range.js_on_change("end", cb)

BP-10: DataRange1d(only_visible=True) Is Unreliable

Symptom: DataRange1d(only_visible=True) works for simple cases but fails with:

  • LogScale panels (y-range computed in wrong space)
  • VBar renderers (candlesticks — bounds not tracked correctly)
  • Shared data sources across panels

Fix: Always use the JS callback pattern (BP-09) instead of DataRange1d(only_visible=True).

Panel Data Source Reference (backtesting.py internals)

PanelLabelRendererY ColumnSource
Equity"Equity"Patch (equity_dd), Line (equity)equityShared OHLC source
Drawdown"Drawdown"Line (drawdown), Scatter (peak)drawdownShared OHLC source
P/L"Profit / Loss"Scatter (returns), MultiLiney or returnsSeparate trade source
OHLC"" (no label)Segment, VBarHigh/LowShared OHLC source
Volume"Volume"VBarVolume (top)Shared OHLC source

Project Artifacts (rangebar-patterns repo)

ArtifactPath
Oracle comparison scriptscripts/gen600_oracle_compare.py
Gen600 strategy (reference)backtest/backtesting_py/gen600_strategy.py
SQL oracle query templatesql/gen600_oracle_trades.sql
Oracle validation findingsfindings/2026-02-12-gen600-oracle-validation.md
Backtest CLAUDE.mdbacktest/CLAUDE.md
ClickHouse AP-16.claude/skills/clickhouse-antipatterns/SKILL.md
Fork source~/fork-tools/backtesting.py/

Post-Execution Reflection

After this skill completes, check before closing:

  1. Did the command succeed? — If not, fix the instruction or error table that caused the failure.
  2. Did parameters or output change? — If the underlying tool's interface drifted, update Usage examples and Parameters table to match.
  3. Was a workaround needed? — If you had to improvise (different flags, extra steps), update this SKILL.md so the next invocation doesn't need the same workaround.

Only update if the issue is real and reproducible — not speculative.

平台分布

Codex

35.85%
按下载量换算253

Claude

30.93%
按下载量换算218

Cursor

18.95%
按下载量换算134

Gemini CLI

8.65%
按下载量换算61

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

只读

该 Skill 主要提供规则、说明或参考内容,本身偏只读;真正读写文件、联网或执行命令仍取决于宿主 Agent 的任务。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills