Skip to main content
This is the recurring maintenance routine. Most of it is automated — the Sunday cron handles the heavy lifting. Your role is to review results and intervene only when needed.
Developer/operator lane only. Regular users should run onboarding, select profile 1-5, pull approved model revisions from R2, and run trading.

Automated (every Sunday 2am UTC)

scripts/weekly_optimize.py runs autonomously on the trading VM:
  1. Pre-flight integrity check
  2. Select risk profile (loads saved profile; prompts interactively on first run)
  3. Fresh data from MT5 API
  4. SHAP analysis
  5. Optuna tuning (signal + position)
  6. Retrain all models
  7. Parameter sweep (scoped to selected profile’s config ranges)
  8. Apply best config + profile safety limits
  9. OOS backtest
  10. Keep or rollback (2% improvement gate)
  11. Push models to R2
  12. Update strategy_params.json + PERF_HISTORY.md
  13. Git commit
  14. Dry-run smoke test
  15. Telegram notification with full report
You receive a Telegram message when it finishes. If it improved: nothing to do. If it reverted: review the log and optionally trigger a manual optimization. After accepted runs, publish approved revisions in R2 and notify users which revision to pull for each profile (1-5).
The Phase 5 sweep only sees the first 70% of the OOS window. The final evaluation (Phase 7) uses the full OOS window. This 70/30 split prevents the sweep from picking configs that fit the OOS data rather than generalise. The split is skipped if the OOS window is shorter than 90 days.
The sweep is also scoped to your risk profile — it only tests parameter combinations within the profile’s risk and confidence bounds. Profile 1 never tests 3% risk configs; Profile 5 never tests 0.65+ confidence configs. See Risk profiles for the full table.

Your weekly checklist

Sunday — after the cron fires

Check the Telegram notification. It tells you:
  • Whether the run improved or reverted
  • New Score vs previous Score
  • What specifically changed (confidence, SL/TP multiplier, etc.)
  • Whether any tech debt was addressed
If improved and Score >= 10: no action needed. If reverted (Score didn’t improve by 2%): log in and inspect:
# Read the weekly log
tail -100 logs/weekly.log

# Check the last optimization result
python3 -c "
import json
b = json.load(open('models/optimize_best.json'))
print('Best ever Score:', b.get('score'))
print('Config:', json.dumps(b.get('config', {}), indent=2))
"
Decide whether to run a manual optimization cycle.

Monday — performance review

Check live trading performance from the past week:
python scripts/performance_monitor.py --lookback 50
If WR >= 55% and PF >= 2.0 and consecutive losses < 7: healthy. If degraded:
# Deeper look
python scripts/dashboard.py --full
Read the block reasons. If low_confidence dominates: lower the threshold. If atr_below_min dominates: market is ranging — this is expected during low-volatility periods.

Wednesday — mid-week spot check

Quick one-liner to confirm everything is still running:
pm2 status && python scripts/performance_monitor.py --lookback 20

As needed — when Score drops

If you notice live WR declining or a degradation Telegram alert fires:
# Step 1: establish current state
python backtest_config.py \
  --balance 500 --no-swap --leverage 500 \
  --spread 16.95 --oos-only --no-chart

# Step 2: quick config sweep (< 30 min, no retrain)
python scripts/sweep.py --target signal --mode confidence
python scripts/sweep.py --target signal --mode sltp

# Step 3: if sweep didn't help, trigger manual optimization
TASK="Run 1 optimization iteration: python scripts/optimize_loop.py --iterations 1 --trials 50 --drop-threshold 0.0. No feature dropping. When done send Telegram."
./scripts/run_agent.sh novosky-optimizer "$TASK"
Manual sweeps via scripts/sweep.py use the full OOS window. The automated weekly pipeline (weekly_optimize.py) applies a 70/30 split — the sweep only sees the first 70% of OOS data and the final evaluation uses all of it. If you want the same guard for manual sweeps, add --oos-end YYYY-MM-DD to your backtest_config.py calls to cap the sweep window.

Intervention triggers

SignalAction
Telegram: weekly run revertedReview log, optionally run manual loop
Live WR < 55% over 50 tradesperformance_monitor.py --retrain
Live PF < 2.0 over 50 tradesConfig sweep → if no improvement, retrain
Consecutive losses = circuit breaker limitBot pauses automatically. Review after 1 trading day
Telegram: HARD DRAWDOWN HALT (exit 99)Bot stopped permanently. Review equity, update risk_profile.starting_balance_usd, restart manually
Score < 6.0 on latest OOSPause live trading, run full optimization
Score < 10.0 on latest OOSTrigger manual optimization loop

Log files to watch

FileCheck for
logs/weekly.logWeekly pipeline outcome
logs/trades.csvWin/loss streak, hold times
blocked_signals.csvBlock reason distribution
state.jsonCircuit breaker counter
models/optimize_log.jsonScore history across runs

Monthly review

Once a month, do a deeper review:
# All-time stats
python scripts/performance_monitor.py --lookback 0

# Score history
python3 -c "
import json
log = json.load(open('models/optimize_log.json'))
for e in log[-10:]:
    print(e.get('date','?')[:10], e.get('decision','?'), 'score:', e.get('final_score','?'))
"

# Compare current config vs 1 month ago (if you kept a backup)
python scripts/compare_configs.py --old-config config_month_ago.json --old-ml ml_config_month_ago.json
Review whether the production Score target (10.0+) is consistently met. If not, consider whether a new feature engineering pass is warranted — see Feature Engineering.