Skip to content
All work

ML Trading Bot

Futures execution where the risk manager outranks the model.

Futures trading · SystemsClosed source

A production-focused futures trading system for ES and NQ with paper and live execution paths, a realistic backtester, and strict prop-firm risk controls. A rule-based strategy makes the entries; the reinforcement-learning layer can only veto or shrink them.

Problem
Execute and evaluate futures strategies under realistic costs and prop-firm constraints.
Constraint
Experimental models and fabricated or placeholder P&L can overstate an unproven strategy and hide operational risk.
Decision
Let rules originate trades, allow reinforcement learning only to veto or downscale, and route every order through audited risk controls.
Evidence
Walk-forward validation uses purge, embargo, and train-only normalization; allow and block decisions are written to an audit log.
Python 3.12PyTorchPostgreSQLSQLiteStreamlit

What it is

A futures trading system built for the parts that usually get skipped: realistic backtesting with costs, a risk manager that can refuse an order, an audited trail of why it refused, and a dashboard that tells the truth when it has no data.

The README opens by refusing to claim guaranteed profits, and instructs treating every strategy and model as unproven until it has passed clean data validation, realistic cost assumptions, paper trading, and prop-firm rule checks.

Order flow

  1. Market data
    evaluated on bar close, after warm-up
  2. Rule-based strategy
    primary entry source
    filter or downscale
  3. RL filter
    optional, off by default
  4. Position sizing
    bot.risk
  5. PropFirmRiskManager
    allow or block, always audited
    submits orders
  6. Broker adapter
    paper, ProjectX, bridge, Tradovate
The rule-based strategy is the only thing that can originate a trade. Every later stage can reduce or refuse it, and nothing reaches the broker without clearing the risk manager.

Where the model is allowed to sit

The rule-based intraday strategy remains the primary trade-entry source. An optional hybrid wrapper can filter or downscale rule signals when explicitly enabled — it cannot force entries, and it must still pass risk controls. Reinforcement learning is experimental and off by default.

Offline training and evaluation use walk-forward validation with purge and embargo, train-only normalization, and commission, slippage, and latency assumptions. Online learning on a funded or evaluation account is out.

Risk controls

Safety limits are command-line flags on the live runner, so a session states its own constraints at launch rather than inheriting them from a config nobody reread.

  • Daily loss limit, max total loss, and trailing drawdown.
  • Max contracts, max trades per day, and max consecutive losses.
  • Cooldown after a loss, and flatten before the close.
  • An emergency kill switch.

Allow and block decisions are audited to logs/prop_firm_risk_audit.jsonl, and the dashboard surfaces recent block events alongside the remaining daily loss allowance.

The trade ledger

Closed live and paper trades are stored in data/trades.db. Each record carries the trade ID, instrument, side, quantity, entry and exit time and price, stop, target, estimated fees, slippage, gross and net P&L, strategy name, entry and exit reason, risk metadata, and whether the session was paper or live.

If no live engine or local bars are available, the dashboard shows empty states instead of fake trade or P&L data. An empty dashboard is a correct dashboard.