A futures bot :)
A multi-agent, ML-powered futures trading terminal for MES and MNQ.
Midas is a sophisticated, machine-learning-assisted Order Flow trading terminal that transforms a real-time data feed into actionable, high-probability trade signals. It is designed to move beyond simple, rule-based scripting into a multi-agent system where specialized AI "brains" are deployed based on the current market regime.
This document serves as the master guide to the project. It details the architecture, operational procedures, and the development backlog, ensuring you can understand the system's state and your next steps, even after a long break.
Midas is a multi-threaded Flask application that separates the web interface from the background trading engine, preventing the UI from freezing during market analysis.
| Component | Tool | Purpose |
|---|---|---|
| Backend Framework | Flask | Lightweight web server to host the UI and handle API requests. |
| Concurrency | Python threading |
Allows the bot to loop infinitely in the background while the website stays responsive. |
| Futures Data | NinjaTrader 8 + C# | The MidasBridge.cs indicator runs inside NT8, pushing live market data (Trades, L2 DOM, 15m EMA) via a TCP socket to the Python engine. |
| Frontend | Bootstrap 5, Chart.js, AJAX | Powers the dark-mode dashboard, charts, and real-time data updates without page reloads. |
| AI Brains | scikit-learn |
RandomForestClassifier models are trained on historical data to predict price movements. |
| State Management | core/state_manager.py |
A thread-safe global dictionary that shares information (market data, PnL, signals) between the Flask UI and the background engine. |
| Trade Execution | core/adapters |
An adapter pattern (NTFuturesAdapter) translates the engine's generic buy/sell commands into specific execution orders for NinjaTrader. |
Midas uses a Strategy Manager (core/engine.py) that analyzes the market's "choppiness" and deploys the appropriate AI agent for the job.
- Models:
models/midas_brain.pkl(Long) &models/midas_brain_short.pkl(Short) - Purpose: These are
RandomForestClassifiermodels trained to detect high-momentum breakouts. They are the primary agents when the market is trending (Choppiness Index < 50). - Training: They are trained on features designed to detect liquidity vacuums and order book pressure, such as
Bid_Drop_Velocity,Ask_Surge_Velocity, andImbalance_Skew_30s.
- Model:
models/midas_brain_pingpong.pkl - Purpose: This agent is deployed when the market is sideways and choppy (
Choppiness Index > 50). It stops looking for breakouts and instead plays "ping-pong," buying the floor and selling the ceiling of the established range. - Training: It's trained on features like
Distance_from_SMA60andChop_Indexto identify high-probability mean-reversion setups.
- Model:
models/midas_rl_model.zip - Purpose: A high-level supervisor (
PPOmodel fromstable_baselines3) that provides a final "go/no-go" recommendation (HOLD,BUY,SELL). It can veto a signal from the other agents if its own analysis of the broader market context (price, EMA, ATR, whale presence) disagrees.
- The Decision Trace: To solve the "black box" problem, the engine logs a detailed checklist for every potential signal, showing exactly which filter passed or failed.
[SIGNAL GENERATED]: MES @ 5300.00 [CHECK] Trend Filter: [PASS] [CHECK] Volatility Filter: [PASS] [CHECK] ML Confidence: [PASS] (82% >= 70%) [CHECK] RL Supervisor: [FAIL] (VETO: Recommends HOLD) --- FINAL DECISION: [VETOED] --- - Phase 2 Institutional Guards: Hard-coded safety rules in
logic.pythat prevent the AI from making common mistakes:- DOM Imbalance: Vetoes shorting if buyers globally outnumber sellers 2-to-1 (and vice-versa for longs).
- Macro Misalignment (Rubber Band): Vetoes counter-trend trades unless the price has stretched dangerously far (
10.0points) from the 15-minute EMA, indicating an imminent snap-back.
- Tiered Ratchet Position Management: An advanced, dynamic stop-loss system in
engine.py:- Gear 1 (Initial): A standard dynamic stop-loss (
-6.0points). - Gear 2 (Auto-Breakeven): If a trade goes
+3.5points in profit, the stop moves to+0.5points, guaranteeing no loss. - Gear 3 (The Runner): If a trade goes
+4.0points in profit, a dynamic trailing stop activates to lock in gains as the trade runs.
- Gear 1 (Initial): A standard dynamic stop-loss (
- Virtual Squawk Box (5th Key): The
TapeScannerclass inlogic.pyanalyzes the trade feed in real-time to detect rhythmic institutional algorithms (e.g., a "shredder" buying 50 contracts every 3 seconds). If a signal aligns with a detected "Whale" footprint, its confidence score is significantly boosted.
- Prerequisites:
- NinjaTrader 8 with an active data feed (Live or Replay).
- The
MidasBridge.csindicator compiled and added to a 1-minuteMESchart in NT8. - Python 3.9+.
- Installation:
# Create a virtual environment python -m venv venv source venv/bin/activate # or .\venv\Scripts\activate on Windows # Install dependencies (assuming a requirements.txt exists) pip install -r requirements.txt
- Configuration:
- Open
config.py. - Set
TRADING_MODE = 'NT_FUTURES'. This is the primary mode for live trading and market replay. - Ensure
NT_PORTmatches the port configured in theMidasBridge.csindicator settings in NinjaTrader.
- Open
- Execution:
- Start NinjaTrader and ensure the chart with
MidasBridge.csis active. - Run the Flask application:
python app.py
- Open your web browser to
http://127.0.0.1:5000. - Use the dashboard to start the engine, monitor logs, and manage trades.
- Start NinjaTrader and ensure the chart with
This is the most critical workflow for long-term success. When you have new market data and want to improve the AI's performance, follow these steps.
- Action: Use NinjaTrader's Market Replay feature.
- Process: Load 1-3 months of
MESMarket Replay data. Attach theMidasBridge.csscript to a chart and run the replay at max speed. - Result: The C# script will dump millions of rows of millisecond-accurate Level 2 order book data into massive
.csvfiles in your NinjaTrader documents folder. Move these files toE:/NT_lvl_2_data(or update the path in the scripts).
- Action: Run the
story_makerscripts. - Process:
python scripts/story_maker.py # Hunts for 2-point JUMPS python scripts/story_maker_short.py # Hunts for 2-point DROPS
- Result: These scripts process the raw data and create two new files:
Master_ML_Ready_Data_Long.csvandMaster_ML_Ready_Data_Short.csv. They label every second of data as1(a successful 2-point move occurred in the next 60s) or0(it didn't).
- Action: Run the
brain_builderscripts. - Process:
# (Assuming a brain_builder.py exists for longs) python scripts/brain_builder_short.py - Result: These scripts train the
RandomForestClassifieron the labeled "story" data. They will output new, smartermidas_brain.pklandmidas_brain_short.pklfiles.
- Action: Run the
train_pingpongscript. - Process:
python scripts/train_pingpong.py
- Result: This script specifically looks for choppy, sideways market conditions in the raw data and trains a dedicated agent for those scenarios, saving it as
midas_brain_pingpong.pkl.
- Action: Copy the newly trained
.pklfiles from thescriptsdirectory into the/modelsdirectory, overwriting the old ones. - Process: Restart the
app.pyengine. The bot will automatically load the new, improved brains.