it works buty its not good\

This commit is contained in:
zastian-dev
2026-02-11 18:00:12 +00:00
parent c53fb1f7b5
commit 189694cc09
14 changed files with 1380 additions and 308 deletions

View File

@@ -0,0 +1,56 @@
# Consistency Auditor Memory
## Last Audit: 2026-02-11 (Hourly Trading Update)
### CRITICAL FINDINGS
#### 1. Cooldown Timer Missing in Live Bot ❌
**Location**: backtester.rs has it (lines 40, 63, 174-179, 275-281), bot.rs missing
**Issue**: Backtester prevents whipsaw re-entry for REENTRY_COOLDOWN_BARS (7 bars) after stop-loss. Live bot can immediately re-buy on same cycle.
**Impact**: Live bot will churn more, potentially re-entering failed positions immediately. Backtest vs live divergence.
**Fix Required**: Add cooldown_timers HashMap to TradingBot, track in execute_sell, check in execute_buy.
#### 2. Gradual Ramp-Up Missing in Live Bot ⚠️
**Location**: backtester.rs has it (lines 42, 64, 196-198, 226, 508), bot.rs missing
**Issue**: Backtester limits new positions to 1 per bar during first RAMPUP_PERIOD_BARS (30 bars). Live bot could deploy all capital on first cycle.
**Impact**: Live initial deployment faster/riskier than backtest simulates.
**Fix Required**: Add new_positions_this_cycle counter to TradingBot, reset each cycle, check in execute_buy.
### Confirmed Consistent (2026-02-11)
#### Core Trading Logic ✅
- **Drawdown halt**: Time-based (35 bars), bot uses trading_cycle_count vs backtester current_bar (equivalent)
- **bars_held increment**: Both at START of trading cycle/bar (bot:660-663, bt:531-534) — previous bug FIXED
- **Position sizing**: Identical ATR volatility adjustment, confidence scaling (0.7+0.3*conf), caps
- **Stop-loss**: Identical 2.5x ATR + 4% hard cap + fixed fallback
- **Trailing stop**: Identical 1.5x ATR activation/distance + fixed fallback
- **Time exit**: Identical 30-bar threshold
- **Sector limits**: Both max 2 per sector (was 3 in daily)
- **Max positions**: Both 5 concurrent (was 8 in daily)
- **Config constants**: All parameters identical (verified config.rs)
#### Warmup Requirements ✅
**Hourly min_bars()**: max(35 MACD, 15 RSI, 100 EMA, 28 ADX, 20 BB, 63 momentum) + 5 = 105 bars
Both fetch ~158 calendar days for hourly. MACD needs slow+signal (26+9=35), ADX needs 2x (14*2=28), all accounted for.
#### Expected Differences ✅
- **Slippage**: Backtester 10 bps, live actual fills (correct)
- **Already-holding**: Different APIs, same logic
### Config (2026-02-11 Hourly)
- RISK_PER_TRADE: 0.75% (was 1% daily)
- ATR_STOP_MULTIPLIER: 2.5x (was 2.0x daily)
- ATR_TRAIL_MULTIPLIER: 1.5x
- ATR_TRAIL_ACTIVATION_MULTIPLIER: 1.5x
- MAX_CONCURRENT_POSITIONS: 5 (was 8 daily)
- MAX_SECTOR_POSITIONS: 2 (was 3 daily)
- TIME_EXIT_BARS: 30 (~4.3 days)
- REENTRY_COOLDOWN_BARS: 7 (~1 day)
- RAMPUP_PERIOD_BARS: 30 (~4.3 days)
- DRAWDOWN_HALT_BARS: 35 (~5 days)
- Partial exits REMOVED (was destroying avg win/loss ratio)
- Take profit REMOVED (was capping winners)
### Hourly Indicator Periods
RSI/MACD/ADX/BB/ATR: Standard periods (14, 12/26/9, etc) — NOT 7x scaled
Momentum: 63 (~9 days), EMA: 20/50/100. Uses textbook periods appropriate for hourly bars.

View File

@@ -0,0 +1,33 @@
# Quant-Rust-Strategist Memory
## Architecture Overview
- 50-symbol universe across 9 sectors (MAG7, semis, growth tech, healthcare, fintech, financials, industrials, consumer, energy)
- Hybrid momentum + mean-reversion strategy via composite signal scoring in `generate_signal()`
- Backtester restricts buys to top 8 momentum stocks; live mode also uses TOP_MOMENTUM_COUNT=8
- Signal thresholds: StrongBuy>=6.0, Buy>=4.5, Sell<=-3.5, StrongSell<=-6.0
## Critical Finding: Hourly Mode is Catastrophically Broken (2026-02-11)
See [hourly-backtest-analysis-2026-02-11.md](hourly-backtest-analysis-2026-02-11.md) for full details.
### Root Causes (Priority Order)
1. **7x period scaling creates absurd indicator requirements**: RSI=98, MACD slow=182, EMA trend=350, momentum=441. min_bars()~450. Most indicators are NaN for majority of the data.
2. **Drawdown halt at 10% is terminal for short backtests**: After -11.44% in 8 days, system sat in 100% cash for 2+ months (Nov 21 to Feb 11). This made the loss permanent.
3. **Churning in opening days**: MU 3x, AMD 3x, GOOGL 3x in first 8 days. Cooldown helps but insufficient when all indicators trigger simultaneously on warmup.
4. **IEX feed**: `feed=iex` gives thin volume, unreliable for hourly OHLCV.
5. **Concentrated sector exposure**: MU, AMD, ASML all semis.
### Previous Finding: Daily Churning (also 2026-02-11)
See [backtest-analysis-2026-02-11.md](backtest-analysis-2026-02-11.md) for daily mode analysis.
- 12 whipsaw events cost $7,128, 16 same-day round-trips at 0% win rate
- Fixed by: cooldown timer (7 bars), ATR stop widened to 2.0x, buy threshold raised to 4.5
## Key Parameters (config.rs) - Current as of 2026-02-11
- ATR Stop: 2.0x | ATR Trail: 1.5x distance, 1.5x activation
- Max-loss cap: 4% | Position sizing: 1% risk / ATR_stop_pct, capped at 22%
- Max 6 positions, max 2 per sector | Drawdown halt: 10% | Time exit: 30 bars
- Cooldown: 7 bars | Slippage: 10bps
- Hourly mode: ALL indicator periods multiplied by 7 (HOURS_PER_DAY=7)
## Build Notes
- `cargo build --release` compiles clean (only pre-existing dead_code warnings)
- No tests exist

View File

@@ -0,0 +1,51 @@
# 1-Month Hourly Backtest Analysis - 2026-02-11
## Summary Results
- Return: +0.61% ($611.10 on $100k) | CAGR: 7.58%
- Sharpe: -0.15 (reported), annualized from hourly: 0.26
- Max Drawdown: -7.52% | Sortino: negative
- 75 trades: 33W/42L (44% win rate)
- Avg win: $548.85 vs Avg loss: -$416.69 (1.32:1 ratio -- good)
- Profit factor: 1.03
## Problem #1: Whipsaw/Churning (Biggest PnL Drain)
No cooldown mechanism exists. Phase 1 sells, Phase 2 rebuys same bar.
- 12 identified whipsaw events: -$7,128
- 16 same-day roundtrips: 0% win rate, -$7,966
- 62 sell-then-rebuy events; 84% rebought within 1% of sell price
- 55 same-day sell-rebuy events
### Worst offenders:
- MU: 17 round-trips, 10 losses, 7 wins. Net +$2,062 vs +14% simple hold
- ASML: 9 trades, 6 losses. Net +$271 vs +7.9% simple hold
- LLY: 7 trades, 5 losses. Net -$1,450 (LLY was in downtrend)
## Problem #2: ATR Stop Too Tight (1.5x)
23 trades exited >2% loss = $12,882 total loss. Many immediately re-entered.
For hourly bars, 1.5x ATR is roughly 1-sigma noise. Getting stopped on noise.
## Problem #3: Excessive Turnover
- Total capital deployed: $1.21M in 22 trading days = 12.1x monthly turnover
- Annualized: 145x. Slippage: $2,420 (2.4% of capital).
- Even at 10 bps, this is destructive. Real-world slippage may be higher.
## Problem #4: Overnight Gap Exposure
- Two gap-downs >1%: total -$4,360
- No overnight risk management (positions held through weekend gaps)
## Holding Period vs Win Rate
- 0-2h: 6 trades, 0% win rate, -$3,318
- 2-7h: 10 trades, 0% win rate, -$4,648
- 14-35h: 19 trades, 32% win rate, -$2,762
- 35-70h: 11 trades, 46% win rate, -$585
- 70h+: 29 trades, 76% win rate, +$11,923
## Sector Concentration
- Healthcare: 22 trades, 41% WR, -$2,985 (LLY and ISRG biggest losers)
- Semis: 26 trades, 39% WR, +$2,333 (MU volume, but churning drag)
- Industrials: 10 trades, 60% WR, +$984 (CAT 100% WR)
## Position Count vs Returns
- 5 positions: -4.89% total (worst)
- 7-8 positions: +2.4% and +1.8% (better)
- Being invested more fully correlated with better returns in uptrending market

View File

@@ -0,0 +1,115 @@
# Hourly Backtest Catastrophic Failure Analysis (2026-02-11)
## Results Summary
- Period: 3 months hourly (Nov 12, 2025 - Feb 11, 2026)
- Total Return: -11.44% ($88,563 from $100k)
- CAGR: -38.48%, Sharpe: -2.53, Sortino: -0.38
- Win Rate: 10% (2/20), Profit Factor: 0.08
- All 20 trades occurred in first 8 trading days, then system went to 100% cash permanently
## Trade-by-Trade Analysis
All trades between Nov 12-21 (8 trading days, ~56 hourly bars):
### Buys
1. Nov 12 17:00 - MU @$245.29 (89 shares = $21.8k)
2. Nov 12 17:00 - AMD @$255.39 (86 shares = $21.9k)
3. Nov 12 20:00 - GOOGL @$287.08 (76 shares = $21.8k)
4. Nov 12 20:00 - CAT @$573.69 (38 shares = $21.8k)
5. Nov 12 20:00 - SNOW @$269.80 (28 shares = $7.6k) -- total 5 positions, 95% invested
### Sell Cascade (Nov 13-21)
Nov 13: GOOGL -$636 (-2.9%), MU -$694 (-3.2%), SNOW -$226 (-3.0%), CAT -$744 (-3.4%)
Nov 13: Rebuy ASML, AAPL
Nov 14: ASML -$705 (-3.4%), AMD -$1,352 (-6.2%!!) -- exceeded 4% max loss cap
Nov 14: Rebuy MU, GOOGL, CAT, SNOW
Nov 17: AAPL -$440 (-2.1%), MU -$699 (-3.3%)
Nov 17: Rebuy AMD, GOOGL, ASML
Nov 18: AMD -$1,582 (-7.6%!!), CAT -$493 (-2.4%), GOOGL -$426 (-2.0%)
Nov 18: Rebuy AAPL, MU
Nov 19: MU -$941 (-4.6%), SNOW -$39 (-0.6%)
Nov 19: Rebuy AMD, ISRG, SNOW
Nov 20: AMD -$1,170 (-5.8%!), ISRG -$385 (-1.9%), SNOW -$164 (-2.6%), ASML -$442 (-2.2%)
Nov 20: Rebuy MU
Nov 21: MU -$1,274 (-6.6%!!), AAPL +$275 (+1.4%) -- ONLY WIN
### Key Observations
1. AMD losses: -$1,352, -$1,582, -$1,170 = -$4,104 total (36% of all losses). ALL exceeded the 4% max loss cap.
2. MU losses: -$694, -$699, -$941, -$1,274 = -$3,608 (32% of all losses).
3. After Nov 21: drawdown hit 11.65%, exceeding 10% halt. System went to 100% cash PERMANENTLY.
4. Equity curve shows 0 positions from Nov 21 through Feb 11 (461 bars of nothing).
5. Only 2 wins out of 20: GOOGL +$701, AAPL +$275. Total wins = $976.
## Root Cause #1: Absurd Indicator Period Scaling (FUNDAMENTAL)
The 7x multiplier creates these hourly indicator periods:
- RSI: 14 * 7 = 98 bars (14 trading days)
- MACD fast: 12 * 7 = 84 bars
- MACD slow: 26 * 7 = 182 bars (26 trading days)
- MACD signal: 9 * 7 = 63 bars
- EMA short: 9 * 7 = 63 bars
- EMA long: 21 * 7 = 147 bars
- EMA trend: 50 * 7 = 350 bars (50 trading days)
- ADX: 14 * 7 = 98 bars
- Bollinger: 20 * 7 = 140 bars
- Volume MA: 20 * 7 = 140 bars
- Momentum (ROC): 63 * 7 = 441 bars (63 trading days)
min_bars() = max(182+63, 98+1, 350, 98*2, 140, 441) + 5 = 446 bars
This means the system needs ~64 trading days (446/7) of WARMUP before it can even produce a valid signal. For a 3-month backtest, that eats most of the data. The indicators that DO produce values are extremely slow-moving and unresponsive to hourly price action.
### Why 7x is Wrong
The daily parameters (RSI-14, MACD 12/26/9) are designed for daily price action noise. On hourly bars, there are 6.5-7 bars per day, so naively you'd think 7x preserves the "look-back in days." But this ignores that:
1. Hourly bars have fundamentally different noise characteristics (mean-reverting intraday patterns)
2. A 98-period RSI on hourly bars is insanely slow -- it would take a massive multi-week move to push RSI to oversold/overbought
3. MACD with 182-period slow EMA cannot detect hourly momentum shifts
4. The strategy's edge is supposed to be momentum + pullback detection. A 441-bar momentum period on hourly data measures ~3-month trends, not tactical momentum.
## Root Cause #2: Drawdown Halt is Terminal
MAX_DRAWDOWN_HALT = 10%, MAX_DRAWDOWN_RESUME = 5%.
Once drawdown exceeds 10%, the system stops buying. It only resumes when drawdown recovers to 5%. But with 0 positions, there's no way to recover! The portfolio sits in cash forever.
This is a logical impossibility: you can't recover from drawdown without taking new positions, but the system won't take new positions until drawdown recovers.
## Root Cause #3: Max Loss Cap Not Working
AMD lost -6.2%, -7.6%, -5.8% in three trades despite MAX_LOSS_PCT = 4%.
MU lost -6.6% in one trade.
The check_stop_loss_take_profit function checks `pnl_pct <= -MAX_LOSS_PCT` but this only triggers on the NEXT bar after the loss occurs. If a stock gaps down or moves 6% in one hourly bar, the 4% cap is breached before the check runs. On hourly timeframe, overnight gaps can easily exceed 4%.
## Root Cause #4: All Indicators Fire Simultaneously at Warmup Edge
When indicators first become valid (right after the warmup period), all the EMA crossovers, MACD crossovers, etc. fire at once. This creates a burst of buy signals, putting 95% of capital at risk immediately. The system went from 0 to 5 positions in 3 hours on Nov 12.
## Proposed Fixes
### Fix 1: Proper Hourly Indicator Periods (NOT 7x scaling)
Use empirically appropriate periods for hourly timeframe:
- RSI: 14 (same as daily -- 14 hourly bars captures 2 trading days of momentum)
- MACD: 12/26/9 (same as daily -- these already work on any timeframe)
- EMA short: 20, EMA long: 50, EMA trend: 100 (~14 trading days)
- ADX: 14
- Bollinger: 20
- Volume MA: 20
- ATR: 14
- Momentum ROC: 63 (same as daily -- 63 hourly bars = ~9 trading days)
Rationale: Most technical indicators were designed for BARS, not calendar time. RSI-14 means "14 bars of price action" regardless of timeframe. The 7x scaling was conceptually wrong -- it assumed indicators need calendar-day equivalence, but they need bar-count equivalence.
### Fix 2: Remove or Redesign Drawdown Halt for Backtesting
Options:
a) Remove drawdown halt entirely in backtesting (it's more appropriate for live trading where you want manual review)
b) Make drawdown halt time-based: halt for N bars, then auto-resume
c) Change to a gradual reduction: reduce position size by 50% instead of going to 0
### Fix 3: Limit Initial Deployment Speed
Don't go from 0 to 5 positions in one bar. Add a "ramp-up" period where max positions increases gradually (e.g., 1 per day for first week).
### Fix 4: Tighter Max Loss Cap with Intra-Bar Checks
For hourly mode, use tighter max loss (3%) or check at open price vs entry to catch gap losses earlier.
### Fix 5: Use SIP Feed Instead of IEX
Change `feed=iex` to `feed=sip` for consolidated market data. IEX-only volume is unreliable for volume-based signals.