Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NQ Futures Bot — ATB (ATR Breakout) Strategy (RETIRED)

The headline backtest said 74.6% win rate. The honest one said 61.1% with a 35-month underwater period. This repo is the bot that was running live in May 2026 — and the backtest that got it switched off. Published so the failure mode is documented, not buried.

Automated intraday trading bot for NASDAQ E-mini futures (NQ / MNQ) via the Tradovate API, running an ATR Breakout (ATB) strategy with a 2-contract D3 partial-exit structure.

Status: RETIRED — code preserved for reference only

  • 2026-05-18: Live bot stopped after the honest 3-year backtest exposed marginal real edge.
  • 2026-05-21: systemd service nq-bot.service removed and /opt/nq-futures-bot/ deleted from the VPS. No instance of this code is running anywhere.
  • Replaced by nq-strategy-b-bot (multi-timeframe FVG confluence — 4× more profit, 4× less drawdown on the same 3-year dataset).

This repository is read-only history. Do not deploy this code. If you want to run something on NQ, fork the successor.


⚠ Honest Backtest — Read This First

Initial 7-month results (Oct 2025 → May 2026, the cherry-picked recovery window) suggested:

74.6% WR · PF 2.38 · +$10,499 net

Full 3-year out-of-sample run on the same code told a different story:

Period: Jan 2023 → May 2026 (235k 5-min bars, 849 trading days)
ATB D3 — 1 MNQ baseline:
  Trades:        332
  Win Rate:      61.1%
  Profit Factor: 1.20      ← marginal
  Net P&L:       +$4,153   ← ~$1,250/year
  Max DD:        -$3,005   ← 72% of total profit
  Underwater:    Jan 2023 → Nov 2025 (35 months)

ATB D3 — 2 MNQ (the live config):
  Net P&L:  +$8,305    Max DD: -$6,010

The whole "edge" is the last 6 months of the test window. Everything before was choppy — strategy bled slowly for 2.5 years, then rode one trending regime back to positive. That's what the 7-month cherry-pick was capturing.

ATB D3 equity curve — 3 years

Why ATB struggles

ATR breakout strategies need trending markets. NQ in 2023-2024 was range-bound and choppy, producing constant whipsaws. The strategy only worked once trends established in late 2025. Cherry-picking the recovery period gave misleadingly good numbers.


Strategy Summary

Entry signal:

  • 15-min Opening Range Breakout (ORB) on 5-min bars
  • Bias filter from previous-day OHLC direction
  • Skip Tuesdays (statistically the worst day in backtest)
  • Cutoff at 12:00 ET (no new entries after midday)
  • Skip days with 30-60 point gap (too volatile or too quiet)

Position structure (D3 mode):

  • Enter 2 MNQ contracts on breakout candle
  • Partial exit: 1 contract at 1.5× ATR profit
  • Runner: 1 contract continues toward 3× ATR
  • Stop: 2× ATR (both contracts; runner stop intentionally NOT moved to BE — outperforms BE version per backtest)

Risk controls:

  • Max 2 trades per day
  • Daily loss cap: 40 ticks
  • Daily profit cap: 80 ticks
  • Hard exit: 15:45 ET

See signals/atr_breakout.py for the entry signal implementation. See main.py for the asyncio execution loop and order placement.


Repository Layout

.
├── main.py                      # Async event loop, asyncio + Tradovate
├── config.py                    # Reads .env into typed dataclass
├── requirements.txt             # Python dependencies
├── pytest.ini                   # Test config
│
├── signals/                     # Strategy modules
│   ├── atr_breakout.py          # ATB entry signal (the live strategy)
│   ├── inverse_fvg.py           # Inverse FVG (experimental)
│   └── premarket.py             # Monday pre-market gap-down setup
│
├── execution/                   # Broker layer
│   ├── tradovate.py             # Auth + market data WebSocket
│   ├── schwab_stream.py         # Backup real-time data feed
│   └── yf_stream.py             # Backtest data fallback
│
├── risk/
│   └── manager.py               # Daily P&L caps, trade-count limits
│
├── backtest/                    # Simulation infrastructure
│   ├── simulator.py
│   ├── walk_forward.py
│   └── trade_analyzer.py
│
├── analysis/                    # Research scripts
│   ├── ict_fvg_backtest.py      # 3 ICT strategies — Strategy A/B/C
│   ├── smc_breakout_backtest.py # SMC variants
│   ├── atb_refinement_backtest.py
│   └── ...
│
├── data/                        # Historical bars (CSVs, parquet)
│   └── fetch_databento.py       # 3-year NQ via Databento
│
├── deploy/                      # VPS deployment scripts
│
└── run_*.py                     # CLI backtest runners
    ├── run_atb_d3_full.py       # 3-year ATB D3 backtest
    ├── run_atb_vs_strategy_b.py # Direct comparison vs Strategy B
    └── ...

Setup

1. Tradovate account

  • Sign up at tradovate.com (demo or live)
  • API credentials: Settings → API Access
  • You'll need: username, password, app_id, cid, secret

2. Install dependencies

python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt

3. Configure environment

cp .env.example .env
# Edit .env with your Tradovate credentials
# CRITICAL: keep TRADOVATE_ENV=demo until you've validated on paper

4. Run a backtest first

# 3-year ATB D3 backtest with full statistics
python run_atb_d3_full.py

# Side-by-side vs Strategy B (the recommended replacement)
python run_atb_vs_strategy_b.py

5. Live (or demo) trading

python main.py
# Or as systemd service — see deploy/ for VPS setup

Backtest Results — All Variants Tested

All numbers from data/nq_databento_5min.csv (Databento GLBX.MDP3, 235k 5-min bars Jan 2023 – May 2026). 1 MNQ contract baseline.

Strategy variant Trades WR PF Net (1 MNQ) MaxDD
ATB D3 (this bot, 2 MNQ live) 332 61.1% 1.20 +$8,305 (2 MNQ) -$6,010
ATB D3 — 1 MNQ baseline 332 61.1% 1.20 +$4,153 -$3,005
ATB + 15-min FVG filter 78 64.1% 3.08 +$7,306 -$674
5-min IFVG inside 15-min FVG (Strategy B) 641 50.2% 1.87 +$22,926 -$1,251
ORB + Golden Pocket 157 22.3% 1.26 +$1,234 -$989

Strategy B dominates on every metric and is the strategy this bot was replaced with. See nq-strategy-b-bot.


Why this code is being archived

  1. Marginal real edge — PF 1.20 over 3 years is borderline tradeable
  2. Long drawdown periods — 35 months underwater in 2023-2024
  3. Concentration risk — most profit came from late-2025/early-2026 trending markets; flat or down in chop
  4. Better alternative exists — Strategy B from the same research delivers 2× more profit with 5× less drawdown on the same dataset

License

MIT


Disclaimers

  • This is NOT financial advice. Published for educational and research purposes only.
  • Trading futures involves substantial risk. Past performance does not guarantee future results.
  • The author has no financial relationship with Tradovate, Schwab, Databento, or any broker mentioned here.
  • If you choose to run this code with real capital, do so at your own risk. Always demo trade first for at least 30 days.

About

RETIRED — NQ futures bot removed from production 2026-05-21 after honest 3-year backtest exposed that the 74% WR headline was a 7-month cherry-pick. Code preserved as a 'don't do this' reference. Successor: nq-strategy-b-bot.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages