Strategies
SOL Bybit Dual Thrust Intraday Open-Range Breakout, Long-Short, Flat at UTC Day Close (SOLUSDT.BYBIT 1H, pure OHLCV, single leg)
Outcome: Abandoned
SolBybitDualThrustIntradayLS
Outcome Summary
The strategy proposed a pure-OHLCV intraday breakout for SOLUSDT.BYBIT with long and short entries and daily flattening. It produced no backtest or optimization results because Layer 1 static analysis failed. The run was abandoned at iteration 5 before later stages.
Hypothesis
Implements the hypothesis unchanged. Iteration 5 changes only the docstring, and that change records the diagnosis under L155(b)/(c). I reproduced the Layer-3 timeout locally (the real subprocess backtest took 421 s) and profiled it with cProfile: 548 s total, with 475 s inside nautilus ParquetDataCatalog.query. That query runs an fsspec glob over 131,667 bar directories (235k ls calls and 1.3M stat calls). Another ~50 s is spent on imports. The strategy's per-bar work is O(1) scalar state and does not show up in the profile. Neither the per-bar cost nor the config can shorten a catalog-wide directory scan, so this is infrastructure, not a strategy defect. The fix belongs in the catalog query path, for example querying by the exact bar-type directory or caching the file list. A 7-month local run (2026-03 to 2026-09) completed with 178 trades, avg_trade_return_pct -0.019%, PF 0.70, Sharpe -1.08 and max DD 25%. On that recent window the edge is below fees, which the analyst should weigh once a full sandbox run gets through.
verification_loop: Verification failed (Layer 1 — static analysis): - Syntax error: invalid decimal literal (<unknown>, line 1) (line 1)
Implementation
Dual Thrust intraday open-range breakout on SOLUSDT.BYBIT 1H. The range is max(HH-LC, HC-LL) over the prior 2 completed UTC days. The signal is (close - today's 00:00 UTC open) / range. It goes long at >= +0.5 and short at <= -0.5, with at most one entry per UTC day, and is flat at every UTC day close. Notional is 0.4 x 2x leverage = 0.8x equity, capped at 1.0x.
Verification Results
Verification failed (Layer 1 — static analysis): - Syntax error: invalid decimal literal (<unknown>, line 1) (line 1)
Optional: set _entered_day only once an entry is actually submitted (e.g. in on_position_opened).
should_enter sets _entered_day/_pos_day before position_size and the min-notional check run. If the order is dropped (size 0 or below $5), that UTC day's single entry is still used up. This is harmless at 95% equity sizing but hides dropped signals.
Consider a risk-based size cap or a stop at the opposite trigger (the source's reverse level) if drawdown floors bind at analysis.
There is no intraday stop. Each trade carries 95% of equity of unhedged SOL exposure for up to ~23h (sandbox largest loss is about -$16k). This matches the hypothesis (the exit is the session close; the SAR stop was dropped), and it is not the L148 always-in pattern: the strategy is flat about 81% of the time, sizing happens once per day, and worst-case gross is 0.95 x 1 leg x 1.0 leverage, which is at or below equity. Per-trade risk is not capped at 1-2% of equity, though.
None required.
min_bars_required is overridden to 20. That is fine, because the strategy gates itself on having two full, consecutive prior UTC days (48+ bars) before any signal fires.
The sandbox's own ledger does not add up. avg_trade_return_pct is +0.088% over 351 trades, which implies about +31%, but total_return is -46% and PF is 0.88 (L116/L140 sign and magnitude mismatch). The per-trade number can't be compared with the Bybit fee floor (~0.11% taker round trip plus impact of about $26k, commission $36.8k) until the analyst reconciles it against the full backtest. Even at face value, 0.088% is below the 0.15% floor. Losses are concentrated in the calm-vol tercile (-70%) and the strategy is flat in the stressed tercile, which fits an open-range breakout that gets chopped on low-range days. min_range_pct (currently 0) is the natural filter to check first. PF 0.88 on 351 trades is not in the L125 polarity-suspicion zone (<0.70).
Analysis
Backtest gate: - metrics unreliable: Incoherent: Sharpe 0.73 disagrees in sign with total_return -100.00% — the Sharpe is computed from the mtm_equity_curve series while the return comes from the equity curve. Judge on the equity curve.
Iteration History
sandbox_timeout: Verification failed (Layer 3 — sandbox backtest): smoke test exceeded the 300s wall-clock limit on a ~20000-bar window (833 days of SOLUSDT.BYBIT-1-HOUR-LAST-EXTERNAL). This almost always means per-bar work that scales with history — e.g. rescanning the full funding/supplementary series, or rebuilding a list and calling min()/sorted() inside calculate_signal()/on_bar() on every bar. Precompute sorted timestamp arrays ONCE in __init__ and use bisect, or cache lookups keyed by timestamp, so per-bar cost is O(log n) not O(n).
Outcome Summary
Ensure generated strategy source is syntactically valid before verification.
It was abandoned after iteration 5 when Layer 1 static analysis found an invalid decimal literal on line 1. Later stages were not reached.
The strategy tried an intraday, long-short SOL Bybit open-range breakout based on half the prior two completed UTC days' range from the daily open, flattening at UTC day close.
No backtest or optimization metrics were recorded because verification did not complete.
Abandon Reason
verification_loop: Verification failed (Layer 1 — static analysis): - Syntax error: invalid decimal literal (<unknown>, line 1) (line 1)
Analysis
用Python实现一个Dual Thrust数字货币量化交易策略
Backtest Review
- Sharpe
- 0.73
- Total return
- -100.00%
- Max drawdown
- 100.00%
- Trades
- 751
- Win rate
- 48.9%
- Profit factor
- 0.85
Backtest and paper results are hypothetical. Trading involves risk of loss.