EV metrics + EV-weighted evolution + stop-loss cooldown + pool-history hard gate#94
Open
hadhaz wants to merge 3 commits into
Open
EV metrics + EV-weighted evolution + stop-loss cooldown + pool-history hard gate#94hadhaz wants to merge 3 commits into
hadhaz wants to merge 3 commits into
Conversation
Win rate alone hides exit asymmetry (small wins, rare catastrophic losses — 'picking pennies in front of a steamroller'). Add EV measurement and make auto-tuning weight positions by magnitude instead of win-frequency. - computeEdge(): EV per position (% + USD), avg win/loss, payoff ratio, worst loss, steamroller flag; wired into getPerformanceSummary + getPerformanceHistory - evolveThresholds split into pure deriveThresholdChanges(); fee/organic floors now weighted by |pnl_pct| so penny-wins stop validating low-fee zones (the 'naikin win rate doang' trap) - briefing: EV line + steamroller warning - test/test-ev.js: 7 unit checks (no runner/server data needed) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…escaping Consolidates direct-on-server/local hotfixes that never reached origin: - stopLossCooldownHours (default 12): after a stop-loss close, set pool + base-mint cooldown so we don't immediately re-enter a token that just cost a realized loss (config + update_config mapping + pool-memory enforcement) - SCREEN_ON_START gate: skip the redundant immediate screening run on restart (cron already schedules it) to save tokens; set SCREEN_ON_START=true to force - briefing: escapeHtml() on lesson rules to prevent broken Telegram HTML Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The agent kept redeploying into pools its own memory flagged as bad (e.g. glippy-SOL: 67% raw win rate / +2.26% avg PnL looked fine, but adjusted_win_rate was 0% over 0 clean closes — all 3 deploys left the range via OOR/pump, pure price variance, never a real in-range earner). The signal was visible to the LLM but overridable, and it rationalized past it. - getPoolMemory now returns oor_exclusion_rate (frac of past deploys that closed OOR/pumped vs clean in-range) - evaluatePoolHistoryGate(): pure, two reject signatures — range-unstable (oor_exclusion_rate >= maxPoolExclusionRate) or in-range loser (adjusted_win_rate < minPoolAdjustedWinRate with >= 2 clean closes) - enforced in runSafetyChecks deploy_position → non-LLM-overridable - config.screening: minPoolDeploysForGate (3), maxPoolExclusionRate (0.6), minPoolAdjustedWinRate (20); all tunable via update_config - test/test-pool-gate.js: 6 checks incl. the real glippy case Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Win rate alone hides exit asymmetry — small wins, rare catastrophic losses ("picking pennies in front of a steamroller"). Measured on prod data: 62% win rate but EV ≈ 0 (payoff 0.55:1, gross -$19.79 over 274 closed positions). This PR makes the agent measure EV, stops auto-tuning from optimizing win-frequency, and hard-gates redeploys into pools its own memory already flagged as bad.
Commits
1. EV/risk-reward metrics + EV-weighted threshold evolution (
ee4bfca)computeEdge(): EV per position (% + USD), avg win/loss, payoff ratio, worst loss, steamroller flag — wired intogetPerformanceSummary+getPerformanceHistoryevolveThresholdssplit into purederiveThresholdChanges(); fee/organic floors weighted by|pnl_pct|so penny-wins stop validating low-fee zonestest/test-ev.js: 7 checks2. Stop-loss cooldown + skip-screening-on-startup + briefing HTML escaping (
6821c12)stopLossCooldownHours(default 12): cooldown pool + base-mint after a stop-loss closeSCREEN_ON_STARTgate: skip redundant immediate screening on restartescapeHtml()on lesson rules3. Pool-history hard gate in
deploy_positionsafety checks (a9a8d2d)adjusted_win_ratewas 0% over 0 clean closes — all 3 deploys left the range (OOR/pump), pure price variance, never a real in-range earner. The signal was LLM-visible but overridable; it rationalized past it and went OOR 55s after deploy.getPoolMemorynow returnsoor_exclusion_rateevaluatePoolHistoryGate()(pure): rejects range-unstable (oor_exclusion_rate >= maxPoolExclusionRate) or in-range loser (adjusted_win_rate < minPoolAdjustedWinRate, ≥2 clean closes)runSafetyChecks→ non-LLM-overridableminPoolDeploysForGate(3),maxPoolExclusionRate(0.6),minPoolAdjustedWinRate(20) — tunable viaupdate_configtest/test-pool-gate.js: 6 checks incl. the real glippy caseVerification
npm test(full-repo syntax) passesnode test/test-ev.js→ 7/7,node test/test-pool-gate.js→ 6/6 (pass on server node too)main🤖 Generated with Claude Code