X8: signal 669: rewrite the protection block - #1298
Merged
Merged
Conversation
Signal 669 (dump hunter, short, experimental, disabled) carried 34 protection chains, 82% of them built from columns outside the four families the rest of the file uses. They were never measured chain by chain. This replaces them with 153 chains measured on three populations, all on cached booleans, all thresholds multiples of five, none longer than three clauses. Measured with grinding and position adjustment off, 20 slots, tag 669 alone, on binance 2022, bybit 2026 and binance 2026: raw (no protections) 8,326 trades 506 losses -16,593 this block 2,097 trades 28 losses +99,131 The signal stays disabled. Co-Authored-By: Claude Opus 5 (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.
Signal 669 (dump hunter, short, experimental) is disabled, and its protection block was mine, from #1201. It had 34 chains, 82% of them built from columns the rest of the file does not use (
PH_*,SQZ_CNT,UO,WILLR_480, raw percent-change columns), and no chain in it was ever measured on its own. This replaces the whole block.The new block is 153 chains. Every clause is a cached boolean that already exists in the entry scope, every threshold on a 0-100 column is a multiple of five, no chain has four clauses, and the clause order is low timeframe to high.
Rig
position_adjustment_enable: false, grinding off,grind_mode_max_slots: 0, 20 slots, signal 669 added alone to the standing enabled set. Three populations: binance 2022 (bear), bybit 2026 and binance 2026. The profit-max cache is deleted before every run. Every number below is a real backtest, not an offline projection.Result
Per population, against the last intermediate block so the last step is visible:
53 trades bought 17 losses and 22% more money.
How it was built
The backbone came from a measured round; everything after it is per-loss work. The last two passes read the remaining losses one at a time and wrote a chain for each at zero winner cost in its own population — 16 chains, 14 of them three-clause.
Binance 2022's twelve residual losses split into four scenes:
rsi_3_4h1.5 / 3.4,rsi_3_1h0.5,stochrsi_k_1d0.0,willr_14_4h-99.6rsi_3_change_pct_1d+2269% / +785% against a winner median of -9.65change_pct_4h+1.3 / +0.8, 98th percentileThe first scene is the signal's own blind spot: the Logic checks
roc_288 > -10, so it already refuses to sell a 24h that has crashed — but nothing checked whether the 1h, 4h and 1d were spent. Those chains are the complement of a filter the signal already has.What was measured and rejected
rsi_3_lt_15/rsi_3_lt_20, which are not cached in the entry scope, and two more needed non-round raw thresholds (roc_9 < -0.5,roc_9_15m > -2).The 28 that remain
They are not fast squeezes. Most stay open longer than two days: the break is correct and the market walks over it. Four independent attempts to separate them at entry failed, which is what you would expect from a signal that fires at the break rather than after it — the winner and the loser are the same candle. 170 could be reduced to five losses because it fires after capitulation, when the context already describes the move.
short_entry_condition_669_enablestaysFalse.ruff formatandruff checkclean at the pinned version,py_compileclean, and the bare block the measurements ran on is byte-identical to the one in this diff.🤖 Generated with Claude Code