+$17K net, only $786 max drawdown over 3 years on 1 MNQ futures. Built after the predecessor strategy (nq-atb-bot-archived) was retired for marginal real-world edge. Same data, same fees, same execution layer — 4× the profit, 4× less drawdown.
Long-only ICT-style intraday strategy for NASDAQ futures (NQ / MNQ), running via the Tradovate API. Detects 5-minute Inverse Fair Value Gap (IFVG) retests that occur inside an active 15-minute Bull FVG zone — a multi-timeframe confluence that selects for genuine follow-through, not random breakouts.
LONG-ONLY (deployed configuration), 1 MNQ baseline:
Trades: 432 over 3 years (~140/year, ~2-3/week)
Win Rate: 53.5%
Profit Factor: ~2.3
Net P&L: +$17,187
Max DD: $786 ← outstanding risk-adjusted
Return/DD: ~22x
Profitable years: 4/4 (every year positive)
Profitable quarters: 13/14 (93%)
| ATB D3 (archived) | Strategy B (this bot) | |
|---|---|---|
| Trades | 332 | 432 (+30%) |
| Net P&L (1 MNQ) | +$8,305 | +$17,187 (2.07×) |
| Max monthly drawdown | $5,766 | $537 (10.7× less) |
| Profitable months | 21/41 (51%) | 35/41 (85%) |
| 2023 P&L | -$5,292 | +$1,564 (saved -$7K) |
| Months underwater | 35 | 6 |
Strategy B was ahead of ATB starting month 1 and never gave up the lead across the full 3-year period.
| Year | Trades | WR | PF | Net | MaxDD |
|---|---|---|---|---|---|
| 2023 | 127 | 46.5% | 1.44 | +$1,974 | $621 |
| 2024 | 139 | 52.5% | 2.24 | +$5,430 | $610 |
| 2025 | 117 | 57.3% | 2.47 | +$6,623 | $786 |
| 2026 (4mo) | 47 | 68.1% | 2.82 | +$3,319 | $668 |
Every year profitable. WR improving over time.
Multi-timeframe FVG confluence (long-only):
15-min timeframe 5-min timeframe
──────────────── ────────────────
┌──────────┐ ┌──────┐
│ 15m │ ──→ confluence │ 5m │
│ Bull │ check │ Bull │
│ FVG │ │ FVG │
│ zone │ │ zone │
└──────────┘ └──────┘
↑
Price dips into 5m FVG,
closes back above → IFVG retest
↓
┌─ LONG ENTRY (next bar open) ─┐
│ Stop: 5m FVG bottom - 2pts │
│ Target: 2 × risk │
│ Exit by: 15:45 ET │
└──────────────────────────────┘
Setup detected when ALL of the following are true:
- An active 5-min bull FVG exists (not yet mitigated)
- That 5-min FVG sits inside an active 15-min bull FVG zone (with 5-pt buffer at top)
- Current 5-min bar's low dips into the 5-min FVG (
bottom ≤ low ≤ top) - Current 5-min bar's close is back above the 5-min FVG top
- Bar time is between 09:30 and 12:00 ET (entry window)
- No position currently open AND day's trade count below cap
Why long-only: Backtest showed shorts are much weaker (42.5% WR vs 56.5% long). NQ has positive drift over time; the symmetry isn't there.
Why this works: FVGs form when one bar's high < bar+2's low (or vice versa) — that's a price inefficiency indicating fast institutional flow. Multi-timeframe confluence requires institutional momentum AND structural setup AND a retest entry — a real edge instead of random breakouts.
.
├── main.py # Async event loop (Schwab stream + Tradovate)
├── config.py # Reads .env, exposes typed Cfg
├── requirements.txt
├── pytest.ini
│
├── signals/
│ └── strategy_b.py # Live Strategy B detector
│ - FVGTracker (5m + 15m)
│ - FifteenMinAggregator
│ - StrategyBDetector → StrategyBSignal
│
├── execution/
│ ├── tradovate.py # Auth + REST + WebSocket
│ └── schwab_stream.py # Real-time 5-min bar feed
│
├── risk/
│ └── manager.py # Daily P&L caps, trade-count
│
├── analysis/ # Reproducible backtests
│ ├── ict_fvg_backtest.py # The original Strategy B (A/B/C variants)
│ └── smc_breakout_backtest.py # Underlying simulator helpers
│
├── data/
│ ├── nq_databento_5min.csv # 3 years of 5-min NQ bars (Databento)
│ ├── vix_daily.csv
│ └── fetch_databento.py
│
├── run_strategy_b_robustness.py # Year/quarter walk-forward of Strategy B
└── run_atb_vs_strategy_b.py # Side-by-side vs ATB (same dataset)
git clone https://github.com/prashanthaitha24/nq-strategy-b-bot.git
cd nq-strategy-b-bot
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txtcp .env.example .env
# Edit with your Tradovate credentials
# KEEP TRADOVATE_ENV=demo until you have 30+ days of paper data# Reproduces the +$16,468 Strategy B headline number
python analysis/ict_fvg_backtest.py
# Year-by-year + quarter-by-quarter robustness
python run_strategy_b_robustness.py
# Side-by-side Strategy B vs the archived ATB
python run_atb_vs_strategy_b.pypython main.py
# Tail logs: tail -f logs/strategy-b.log- Review daily logs — confirm signal cadence matches backtest (~2 trades/week)
- Confirm fills match backtest entries (real slippage is the unknown)
- Only THEN consider switching
TRADOVATE_ENV=live - Start with 1 contract even when going live
| Account size | Max DD risk | Recommended contracts |
|---|---|---|
| $5,000 | Backtest max $840 → ~17% account hit | 1 MNQ |
| $10,000 | Same DD → ~8% account hit | 1 MNQ |
| $25,000+ | Comfortable | up to 2 MNQ |
| $50,000+ | Could scale to 1 NQ | 1 NQ = 10× MNQ exposure |
Backtest's $840 max DD over 3 years is exceptional but not a guarantee. Real-world max DD will likely be 2-3× worse due to slippage, missed fills, and regime changes. Plan accordingly.
What backtest says:
- ~100 trades/year, 56% WR, +$5K/year on 1 MNQ
- Max DD only $840 over the full period
What real-world will likely produce (haircuts for fills, commissions, edge erosion):
- 50-55% real WR
- +$3-4K/year per MNQ
- Max DD probably $1,500-2,500 in real conditions
- 1-2 losing months per year
Bad signs to watch for in demo:
- More than 5 trades/week (likely a bug — backtest is ~2/week)
- Win rate below 45% over 30+ trades
- Multiple consecutive stop-outs without trend reversal
Good signs:
- 1-3 trades/week
- Most exits are PROFIT_TARGET (the 2× R:R hits)
- Drawdowns recover within 1-2 weeks
- 15-min FVG zones are visible in logs before each signal
MIT
- NOT financial advice. Published for educational purposes.
- Trading futures involves substantial leverage and risk of total loss.
- Past performance does not guarantee future results.
- The author has no financial relationship with Tradovate, Schwab, Databento, or any broker.
- Demo trade for AT LEAST 30 days before considering live capital.
- Backtests use 5-min bars as a proxy for 1-min IFVG entry timing. Real 1-min execution may differ.
