e02a7e3453
CRITICAL FIXES (would have prevented the $194K crisis): 1. HARD MAX SHORT POSITION CAP (safety.py + executor.py) - new config: max_short_positions=4 (hard limit) - new config: max_total_positions=8 (hard limit) - executor now queries broker.get_positions() for AUTHORITATIVE count - BEFORE opening any short, checks broker directly (not just store) - validate_trade() now accepts broker_positions and blocks at hard cap - This directly prevents the 13-shorts scenario 2. YESTERDAY-CLOSE DRAWDC OWN CIRCUIT BREAKER (safety.py) - new config: yesterday_close_drawdown_limit=3% - new config: yesterday_close_drawdown_reduction=50% - Separate from peak-equity tracking (which is too slow) - At $194K from $200K initial = 3% → fires IMMEDIATELY, cuts 50% of positions - Tested: check_yesterday_close_drawdown($194K) → triggers with 50% reduction 3. PER-POSITION STOP LOSS DEFAULTS (safety.py + executor.py) - new config: stop_loss_default_pct_long=1.0%, short=1.5% - new config: stop_loss_max_pct=3.0% (never wider than this) - new config: take_profit_default_pct=2.0% - NEW: get_default_stop_loss() + get_default_take_profit() methods - executor.execute_signal() now ALWAYS sets stop loss (even if GA provides None) - Previously stops were often None → exits never triggered - Tested: get_default_stop_loss($100, 'short') = $101.50 ✓ 4. BROKER/STORE SYNC VALIDATION (safety.py + main_auto.py) - new: validate_broker_position_count() detects discrepancies - new: _trade_symbol() now passes combined_equity to executor - new: _trading_cycle() validates broker vs store BEFORE evaluating new trades - Logs warning when broker has positions not tracked in store - Blocks new trades if broker position count already at hard cap 5. CRISIS MODE: 10+ LOSING POSITIONS (executor.py check_exits) - If 8+ of 10+ positions are losing money → force reduce 50% of ALL positions - Catches cascading blowups before drawdown thresholds are hit - Logs CRITICAL warning when triggered 6. DEFAULT STOP LOSS ENFORCEMENT (executor.py) - _enforce_stop_loss_tightness() was overriding None stops to None - Now executor ALWAYS applies safety defaults if GA provides no stop - Every new position gets a stop loss on entry Config changes (auto_config.json): - Added max_short_positions, max_total_positions - Added stop_loss_default_pct_long/short, take_profit_default_pct - Added stop_loss_atr_multiplier, stop_loss_max_pct - Added yesterday_close_drawdown_limit=3%, yesterday_close_drawdown_reduction=50% HOW THIS WOULD HAVE HELPED THE $194,940 PORTFOLIO: - At $194,940 from $200K = 2.53% drawdown from initial - If yesterday closed at $200K: 2.53% < 3% limit → NOT triggered - But at open today if equity dropped to $194,000 → 3.00% → TRIGGERS IMMEDIATELY - Hard cap at 4 shorts: after 4 shorts, executor blocks action 5/6 - Stop losses: each of the 4 shorts would have had 1.5% stop → 2 shorts would have been stopped out before they lost further, limiting damage - Crisis mode: if 8 positions were losing, 50% of all positions closed