- MLFilter.from_model() classmethod eliminates brittle __new__() private-attribute
manipulation in backtester walk-forward model injection
- backtest_validator._check_invariants() now accepts cfg and uses cfg.initial_balance
instead of a hardcoded 1000.0 for the negative-balance invariant check
- backtester.py walk-forward injection block simplified to use the new factory method
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
C5: Remove duplicate entry_fee deduction in backtester (balance and net_pnl)
C1: Add SL/TP retry (3x) with emergency market close on final failure
C3: Add _close_lock to prevent PnL double recording between callback and monitor
C8: Add SIGTERM/SIGINT handler with per-symbol order cancellation before exit
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- fix(bot): prevent PnL double recording in _close_and_reenter using asyncio.Event
- fix(bot): prevent SYNC detection PnL duplication with _close_handled_by_sync flag
- fix(notifier): move sync HTTP call to background thread via run_in_executor
- fix(risk_manager): make is_trading_allowed async with lock for thread safety
- fix(exchange): cache exchange info at class level (1 API call for all symbols)
- fix(exchange): use `is not None` instead of truthy check for price/stop_price
- refactor(backtester): extract _calc_trade_stats to eliminate code duplication
- fix(ml_features): apply rolling z-score to OI/funding rate in serving (train-serve skew)
- fix(bot): use config.correlation_symbols instead of hardcoded BTCUSDT/ETHUSDT
- fix(bot): expand OI/funding history deque to 96 for z-score window
- cleanup(config): remove unused stop_loss_pct, take_profit_pct, trailing_stop_pct fields
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add payoff_ratio and max_consecutive_losses to backtester summary
- Add compare_symbols.py: per-symbol parameter sweep for candidate evaluation
- Add position_sizing_analysis.py: robust Monte Carlo position sizing
- Fetch historical data for SOL, LINK, AVAX candidates (365 days)
- Update existing symbol data (XRP, TRX, DOGE)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
WF backtester always passed trained models to Backtester.run(ml_models=...),
overriding ml_filters even when use_ml=False. This caused 0 trades in
--no-ml mode because underfitted models (trained on ~27 samples) blocked
all entries with proba < 0.55 threshold.
- Skip model training when use_ml=False (saves computation)
- Only inject ml_models when use_ml=True
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix LightGBM predict_proba ValueError by filtering FEATURE_COLS and casting to float64
- Extract BTC/ETH correlation data from embedded parquet columns instead of missing separate files
- Disable ONNX priority in ML filter tests to use mocked LightGBM correctly
- Add NO_ML_FILTER=true to .env.example (ML adds no value with current signal thresholds)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>