Skip to main content

Verify before going live

Always run these checks before your first live session.
Recommended first command: python scripts/onboarding.py --balance 500 --profile 1|2|3|4|5. Onboarding sets your risk profile in config.json and can pull model files from R2. For user setups, skip the optional first optimization prompt.
If you use strict config drift blocking in automation, see config_sync.py.

Model compatibility check

python3 -c "
import json
mc = json.load(open('models/model_compat.json'))
ml = json.load(open('ml_config.json'))
assert mc['feature_count'] == len(ml['features']), 'MISMATCH'
print('OK:', mc['feature_count'], 'features — trained', mc['trained_at'][:10])
"
If this fails, the models and feature config are out of sync. Pull the approved model revision from R2.

True OOS backtest

python backtest_config.py \
  --balance 500 --no-swap --leverage 500 \
  --spread 16.95 --oos-only --no-chart
This runs the backtester on data the models have never seen. Expect WR around 57–86% depending on the OOS window length. See Backtesting for how to interpret results.

Dry-run

The --dry flag is diagnostic-only. It runs the full logic — candle fetch, feature engineering, signal generation, filter pipeline — but keeps all external side effects disabled. In --dry mode:
  • No real orders are sent.
  • No close/SLTP requests are sent.
  • No Telegram messages are sent.
  • Telegram command bot is not started.
  • No Supabase writes are made.
  • No runtime CSV/state files are written.
python trading.py --dry
Run this until you see the main loop cycling correctly and signals appearing in the output before going live.

Go live

python trading.py

What happens on startup

  1. Loads config from .env, config.json, ml_config.json
  2. Checks model_compat.json for feature compatibility
  3. Auto-pulls models from R2 if models/ensemble_rf.onnx is missing
  4. Connects to MT5 API (/ping, /account)
  5. Loads ONNX models into memory
  6. Measures MT5 API latency (local round-trip + broker latency)
  7. Sends a startup Telegram message with balance, API status, and active filters
  8. Starts the main loop (~60s cycle)

PM2 handles auto-restart on crash and reboot persistence.
npm install -g pm2

Start

# Start with API readiness check (waits for MT5 API before starting)
bash scripts/pm2-start.sh

# First-time only: enable auto-start on machine reboot
bash scripts/pm2-start.sh --setup

Manage

pm2 logs novosky       # tail live output
pm2 status             # process health
pm2 restart novosky    # restart
pm2 stop novosky       # stop

What the main loop does

Every ~60 seconds:
  1. Market open check — timezone-aware session filter
  2. Fetch 250 BTCUSD M15 bars from /symbols/BTCUSD/rates
  3. Feature engineering — computes all 56 features
  4. Inject live news — overwrites session/news features with live values
  5. Get signal — RF + XGBoost + LightGBM vote (requires ≥2/3 + conf ≥60%)
  6. Apply filters — ATR floor, news block, EMA trend, circuit breaker
  7. ExecutePOST /orders with SL=0.8×ATR, TP=0.8×ATR, 2% equity risk
  8. Monitor positions — position model checks open trades: HOLD / EXIT / ADD
  9. Notify (live only) — Telegram + Supabase sync

Log files

These are written during live runs (not in --dry mode):
trade_log.csv           # per-trade log (append-mode)
blocked_signals.csv     # every blocked signal + reason
state.json              # circuit breaker + daily counters (survives restarts)
logs/trades.csv         # structured trade log
logs/signals.csv        # every signal + execution decision
logs/daily_summary.csv  # daily aggregated stats
trade_notifications.log # full text of all Telegram messages sent