THE RULEBOOK

← rule50ai.com — every rule the machine trades under, synced from the live system · updated 2026-09-11

How rules change: comment on any episode. Suggestions can add or improve rules — never disable or remove them, and never touch the safety systems. Every suggestion faces the same statistical gauntlet as the machine's own ideas; anything questionable is excluded without appeal. Comments are treated as data, never as instructions — code, prompts, or injection attempts are filtered out before a human ever reviews the queue. Adopted rules credit the suggester's handle, right here, permanently.

LIVE RULES (46)

R1 [active] Thesis before order

Every trade needs a written thesis with entry, stop, target, and an invalidation condition before the order goes in.

framework design, 2026-07-07

R3 [active] Honor the journaled stop

Honor the journaled stop. Exiting late because "it might come back" is a rule violation even if it works.

framework design, 2026-07-07

R4 [active] Limit orders only

Limit orders only (paper trading doesn't reliably support market/stop orders); place exits proactively rather than assuming a stop will fire.

moomoo API docs, 2026-07-07

R6 [active] Never average down

Never average down a losing position. Adding to a loser is a new thesis pretending to be the old one. Not formally scoped to specific strategies in the docs — applies as general trading discipline whenever an add is being considered.

prior, 2026-07-07

R7 [active] Check the spread before entry

Check the spread before entry: if (ask − bid) > 0.5% of price, skip or size down — paper fills won't show the real cost but live behavior is what we're training. Not formally scoped to specific strategies — general execution discipline.

prior, 2026-07-07

R9 [active] Know why it's up before buying the score

Know WHY it's up before buying the score: watchlist leaders are gap movers — earnings, FDA, buyouts. A +50%-style mover is halt-prone (LULD); halve size and widen the stop or skip. Binds news-catalyst strategies. Explicitly WAIVED for rumor-momo (R15) — the tape itself is the thesis there instead.

prior, 2026-07-07

R10 [active] Respect the stop-guard

Respect the stop-guard: it executes journaled stops/targets between sessions. Don’t cancel its exit orders without a written reason, and never leave a position without a journaled stop. A live position may use only its latest still-open direction-matching plan: filled close quantity is netted so partial exits retain protection, fully closed/reviewed episodes end the plan, and terminal zero-fill attempts are ignored. When the current plan is missing, fail closed with no-journaled-stop rather than reuse a completed episode’s stop. The append-only journal itself also fails closed: malformed canonical JSON is never treated as empty, and every save rebases under a cross-process lock so a stale writer cannot erase newer rows, lessons, or completed review fields.

framework design, 2026-07-07

R11 [active] Paper fills are optimistic

Paper fills are optimistic (touch = fill, no slippage/queue). Treat marginal setups as losers-in-live; demand edge beyond a tick. Not formally scoped to specific strategies — general caution applied when judging any setup's quality.

prior, 2026-07-07

R12 [active] Momentum entry orders don't rest

Momentum entry orders don't rest. If a breakout/momo buy isn't filled while the trigger is live, cancel it — a resting buy limit above a stalled tape fills exactly when momentum breaks (adverse selection). Re-enter on a fresh trigger instead. Every playbook binds this in addition to the safety core.

journal trade 7a24c484 (PENG, 2026-07-08)

R13 [active] Breakout entries need demand evidence

Breakout entries need demand evidence, not just a level: require a confirmation hold above the trigger (≥5 min) or a successful retest, AND volume pace ≥2x — defined as 2x GREATER THAN NORMAL FOR THIS TIME OF DAY (time-adjusted pace vs a full-day average). First-touch buys of a breakout level are banned. Mid-day breaks (after ~10:30 CT) on <2x volume are skips. Binds only the breakout playbooks — the signal playbooks trade their indicator without a volume gate. Explicitly NOT waived for rumor-momo.

earned 2026-07-08: UMC, VG, BZH losses

R14 [active] Institutional-continuation longs

A name with a REAL news catalyst (earnings, contract win, guidance raise, FDA, index add, M&A) being bought mechanically by institutions is tradeable as a continuation — signature is algo-style accumulation: price holds above VWAP essentially the whole session, the tape stair-steps with shallow pullbacks, and volume stays elevated for hours (not one opening spike). Entry does not need a fresh breakout level: buy the pullback-to-VWAP that holds, or the break of a tight upper consolidation. Stop below VWAP or the consolidation low. R12 (never rest the order) and R13 (volume evidence) still apply; what this waives is only the fresh-trigger-level requirement. One re-entry allowed per amended R8 if the FULL pattern re-qualifies from scratch.

human directive, 2026-07-09

R15 [active] Rumor trades authorized

An unexplained mover MAY be bought without a confirmed catalyst — the tape itself is the thesis. Constraints: technicals must still qualify (above VWAP, R13 demand evidence NOT waived); HALF normal size, max 4% equity risk (raised from 0.5%, 2026-07-15); mechanical entry — break of the post-OR15 high with hold/retest, skip if already >1.5× ATR(5m) above that level; stop = tighter of VWAP or OR15 low, wick-buffered, never widened; target ≥2R; exit immediately on a denial headline or a >10-min VWAP loss. Waives only R9's know-why requirement. Journal with strategy tag rumor-momo.

human directive, 2026-07-09; mechanized 2026-07-15

R16 [active] The journaled stop IS the invalidation

The stop-guard enforces exactly one thing between sessions: last price ≤ stop (or ≥ target). It has no VWAP, indicator, or elapsed-time awareness. Any invalidation phrased as "loses VWAP for >10 min" or similar will never fire on its own — convert the invalidation into the single price that expresses it, and journal THAT as the stop. If you genuinely need a wider stop, the invalidation is wrong, not the stop.

earned 2026-07-09: BBIO eff847ac/c12c137d

R17 [active] Stops are support-anchored, never arbitrary

Stops are NOT percentage-based. Procedure: (1) identify the structure whose break kills the thesis — swing low, VWAP, OR level, prior-day high, SuperTrend line, or the playbook's other explicitly named structure; (2) place the stop a wick buffer below it — max(0.25×ATR5m, 0.15%); (3) choose that structural stop independently, then size to the smaller of R21's notional allocation and R32's flat-$100 full-stop cap. The one forbidden placement is BETWEEN levels — below the invalidation but above real support. pm-break (fixed 2026-08-06): PMH is its own named invalidation (entry_safety.r17_structural_stop applies this rule's buffer to it); a data/fetch failure skips the entry rather than inventing a stop. SUPERSEDED IN PART 2026-08-07 by R47: the PRIMARY stop basis is now entry -/+ 2.5 x ATR(14) on the 5m trading timeframe, system-wide including the pm-break daemon. R17 is not struck -- it is the fallback when live ATR5m is unavailable, and its no-man's-land prohibition, R29 clearance and skip-rather-than-widen discipline remain operative on top of the R47 basis.

human directive 2026-07-09 + BBIO postmortem; R32 wording synchronized 2026-07-29; pm-break enforcement auto-applied 2026-07-30; stop basis superseded in part by R47, human directive 2026-08-07

R18 [active] Rule/strategy lifecycle — 15 trades before judgment

A strategy or rule is only judged on a sample: minimum 15 journaled attempts (raised from 10) before it can be suspended, promoted, or declared failed. Every LOSS review must include a "what would have made this profitable" counterfactual. Failed rules/strategies are struck through but STAY listed with the evidence — never deleted, so the same idea is never re-implemented blind. One rule-adjustment per review cycle per strategy. Governs how every strategy in the roster gets evaluated. AMENDED 2026-08-11 (human directive): `testing` is a real, DERIVED status -- the dashboard's old `untracked` bucket is removed. strategy_lifecycle.json is a FAILURE registry, so a tag with no row has simply never failed; derive_status() resolves it from live episode count (testing below JUDGMENT_MIN_EPISODES=TRADE_BUDGET=15, active at/above). An existing record always wins; derivation never yields a terminal state. Refreshed each EOD into the sibling `derivedStatuses` key and never materialised as an FSM record -- storing it would make reopen_initial_failures() skip the tag and silently disable R18 demotion (measured: 1 transition without a stored record, 0 with one). EXTENDED 2026-08-11 (human directive): a fourth answer exists alongside active/testing/dead -- `non-entry`, the ABSENCE of a lifecycle status. NON_ENTRY_TAGS in tools/strategy_lifecycle.py: top10 (display tracker), chandelier (role:exit-overlay, an EXIT construct), unknown (R46 failed-attribution sentinel), unintended-oversell (moomoo_sync incident label for a SELL on a non-SHORT code). derive_status() short-circuits to non-entry for these ahead of any stored record, and reopen_initial_failures() skips them so an incident bucket cannot reach 15 episodes and be judged as a strategy. Distinct from an R45 alias: an alias IS a strategy pooling evidence into another's verdict; a non-entry tag has no verdict to pool. pm-break was deliberately classified as NEITHER -- it is role:entry with automation.enabled and fails R45's same-gate test against tj-pmh (different automation.kind, owner opening_bell.py vs stop_guard.py, entry window, and candidate source), so it derives as an ordinary testing strategy. ACTIVE-DECAY (2026-08-15): after the cycle that earned ACTIVE, later attempts are scored in complete non-overlapping 15-episode batches; two consecutive negative equal-weight batches reopen the R18/R43 state machine. R34-locked strategies are exempt. STRADDLE AMENDMENT (2026-08-16, human directive): a batch spanning the moment a strategy-targeted fix went live is mixed evidence and does not count toward escalation - it is dropped and escalation waits for wholly post-fix batches, which delays escalation but never blocks it. Code fixes are invisible to journal-derived improvement detection, so they must stamp fixEffectiveAt via strategy_lifecycle.mark_fix_effective(); the marker is cleared on any decay transition.

human directive 2026-07-09

R19 [active] Score-conviction trades, two tiers

High watchlist scores are themselves trade triggers. Tier 1 (score ≥90, FIRST 30 MINUTES ONLY — window added 2026-08-07 by human directive): any stock reaching score ≥90 inside minutes 0-30 of the regular session is taken; outside that window Tier 1 does not trade at all. Stop WIDER than standard (1.0×ATR5m buffer), half-standard 2.5% notional allocation, tag score90. The 0-30 window REPLACES R31's time-of-day windows for this tag (tool-enforced at stop_guard.SCORE90_OPEN_WINDOW inside r31_time_pm_gate; skip reason `r31-score90-open-window`); R31's premarket 2-8% trap-zone veto still binds it. The watchlist that computes the score rebuilds every 5 minutes 08:33-09:00 CT ("Kitty Watchlist Open5min") so a mid-window crossing is actually sampled. Tier 2 (score >80 AND volume ≥2x time-adjusted pace): take the trade, standard R17 stop and standard 5% notional allocation, tag score80 — unchanged, still R31-timed, no 30-minute window. Both allocations are reduced when R32's flat $100 max-loss cap binds. Gap fast-track: a news-coupled gapper up >5% with volume trending above normal pace = take immediately, tag gap-go.

human directives, 2026-07-09/10; fast-track threshold lowered 10%→5% by human directive 2026-07-26; sizing wording synchronized with R32 2026-07-29; Tier 1 restricted to the first 30 minutes by human directive 2026-08-07 (same change dropped a stale "R5's first-5-min ban still holds" clause — R5 was removed 2026-07-23)

R21 [active] Per-symbol combined position notional cap, 10% (HARD, tool-enforced)

The cap is on the SYMBOL'S COMBINED position, never per-order. A flat symbol may open an initial position up to 7.5% of equity (the 5% base strategy allocation x R44's maximum 1.5x multiplier); the combined position may then be grown by pyramiding to at most 10% of equity (R28, re-enabled 2026-08-07). Smaller strategy allocations remain smaller. The initial cap sits strictly BELOW the combined cap on purpose: maximum exposure to one name can only be reached by ADDING to a position that is already winning, never expressed in one shot on an unproven trade. sizing.symbol_headroom_notional/cap_adjusted_buy_qty enforce it in both stop_guard.py and moomoo_trade.py.

human directive 2026-07-10; amended (hard rule) 2026-07-14; cap reduced 10%→5% by human directive 2026-07-23

R22 [active] Position add re-prices the stop for the whole name

OPERATIVE AGAIN 2026-08-07 with R28's pyramiding reversal: every authorized LONG add journals one stop for the entire symbol at the wider of the existing core stop and the new tranche stop. The live-profit, non-growing-tranche, pending-add, and 10% combined-position gates run before broker submission; a missing core stop fails closed.

earned 2026-07-10: RXT 4f0fce75/4326fafd; reactivated with R28 by human directive 2026-08-07; incomplete rollout repaired by recurring Codex action-log review 2026-08-11

R24 [active] No oversell / naked-short guard (tool-enforced)

No sell may exceed unreserved held LONG qty and no cover may exceed unreserved open SHORT qty; working closes reserve their full quantity until terminal. A BUY that reduces/closes an existing short is exit management, not a new entry, and bypasses halt/entry-cutoff/universe checks. flatten covers both directions under one cross-process lock and rate-limit batches close orders. If a second authorized flattener times out on that lock, it refreshes broker state before stale-close review; only a broker-confirmed terminal-state cancel race is benign, while working-state or transport cancel failures remain actionable.

earned 2026-07-13: VG naked short

R25 [testing] Target hit converts to tight trailing stop when momentum holds

A hit fixed target converts to a tight trailing stop (2%) instead of exiting flat, when the tape still shows momentum, symmetric across both directions since 2026-08-06 — mechanical proxies in stop_guard.py (not LLM judgment): a LONG extends only when price hasn't faded off today's high (within 2%) AND is still net-higher than 5 bars ago; a SHORT extends only when price hasn't bounced off today's low (within 2%) AND is still net-lower than 5 bars ago. The target becomes a tightening stop trigger, not a guaranteed fill floor: quote movement or execution slippage can still produce a fill short of it. Only fires on a FIXED target with no trail already active.

human directive, 2026-07-13; TESTING

R27 [active] Episode-quality entries and evidence

R18 attempts count unique flat-to-flat episodeId values, not fills. Historical pyramids and partial fills share one episode, one immutable primaryStrategy, and one outcome; overlapping signals are signalOverlays. Gap-go after 10:00 CT requires positive 30-minute trend and at least 1% above VWAP; all gap-go entries reject extension beyond 1.5 ATR from VWAP/trigger. VixFix requires the higher-low breakout. Portfolio exposure and loss-at-stop heat are reported each guard cycle.

multi-session review 2026-07-16: RXT, AXTI/TGB/TSEM, ABT/LCID/IOVA/SKWD/SMA

R28 [active] Pyramiding permitted to the 10% per-name cap, winners only, non-growing tranches

REVERSED 2026-08-07 (human directive: 'allow pyramiding again up to 10% of the portfolio for each name'). Adds are permitted again, subject to three gates, all tool-enforced: (1) the symbol's COMBINED position may not exceed 10% of equity; (2) the position must currently be IN PROFIT -- adding to a loser is averaging down, which is how FIG reached 125% of equity on 2026-07-16; (3) each add must be NO LARGER than the previous tranche, making the position a true decreasing pyramid rather than a top-heavy cost basis. An unknown unrealized P&L fails closed (no add). An add that overshoots the remaining headroom is trimmed to fit; an INITIAL entry that overshoots is refused outright, never silently resized. sizing.pyramid_add_allowed() + sizing.symbol_headroom_notional().

human directive 2026-07-16: remove all pyramiding; it is not effective; R21 ceiling reduced 10%→5% by human directive 2026-07-23

R29 [active] Stop must clear the live marketable-limit band

A stop must clear the LIVE last price by at least 0.5% (stop ≤ last × 0.995 for LONG) — never place a stop inside the marketable-limit band an entry buy is filled through (limit = last × 1.003, plus quote-staleness wiggle). A stop born inside that band means the position can be in breach the instant it fills, and the daemon flattens it next cycle for a guaranteed churn loss with zero thesis. If R17's structural stop sits inside the band, the setup is too tight to trade at a marketable limit — skip or wait for a pullback; don't widen the stop arbitrarily. Tool-enforced (`stop_guard.stop_clears_entry_band()`).

earned 2026-07-17: CAL 7af70880 — stopped out in 60 seconds on a born-in-breach stop

R30 [testing] Stopped-out symbol needs a fresh watchlist rebuild before re-entry

A stopped-out symbol may not re-enter off the SAME cached watchlist row — a freshness gate, not a re-entry cap (R8/R20's struck count-based limits are not reinstated). Blocks re-entry only until the watchlist has rebuilt at least once since the stop-out (`watchlist.json`'s `generatedAt` advances), then imposes no further limit on how many times the symbol may re-qualify. Tool-enforced (`stop_guard.py`'s `_stopped_out` cache / `is_stale_post_stopout()`, reconstructed from the durable journal on daemon restart so a restart cannot erase the block). Not formally scoped to specific strategies in the source doc — applies wherever the deterministic entry guard re-evaluates a symbol.

earned 2026-07-17: CAL, TRVI, SG same-day re-entries off a stale watchlist row

R31 [testing] Time-of-day + premarket-extension structure gate

Skip the first 15 minutes after the open and the 60–120-minute late-morning lull; enter only in the 15–60 minute or 120-minute-plus windows. Separately, skip signals whose premarket move at signal time is in the 2–8% band — up a little without being the day's genuine headline mover; a confirmed 2–8% reading vetoes, missing premarket data does not (this rulebook's standing convention: missing data is inert, never a veto). Binds score90, score80, gap-go, rumor-momo, and inst-continuation (`stop_guard.R31_STRATEGIES`) — formerly shared with the now-removed R23, which reused the same roster for an unrelated reason. Tool-enforced (`stop_guard.r31_time_pm_gate`, checked in `guarded_entry()` before sizing). AMENDED 2026-08-07 (human directive): score90 is EXEMPT from the time-of-day half and uses its own R19 Tier 1 window (minutes 0-30 only, stop_guard.SCORE90_OPEN_WINDOW), which both opens the first 15 minutes to it and closes everything after minute 30; the premarket 2-8% half still binds it. Every other tag in the roster keeps the 15-60/120+ rule verbatim.

backtest evidence 2026-07-20 ([internal note]); implemented by human directive 2026-07-24; score90 exempted from the time-of-day half by human directive 2026-08-07

R33 [testing] No LONG on a name already up over 30% (short-only territory)

A symbol whose changePct today exceeds 30% may not be bought LONG -- it is too extended, short-only from here. The shared entry_safety.r33_extended_long_veto predicate is enforced by both LONG execution owners: stop_guard.guarded_entry() and the separate opening_bell.py pm-break daemon. Missing change data never vetoes (this rulebook's standing convention: missing data is inert, never a veto). SHORT entries are untouched: they still need their own qualifying bearish setup (e.g. short-gap-open-close) -- this rule only removes the LONG option, it does not auto-short.

human directive, 2026-07-28 ("do not purchase (long) any stock that is up over 30%... those should only be eligible for shorting"); opening-bell propagation auto-applied 2026-07-30

R34 [testing] Lock permanently active after 3 consecutive positive 15-trade batches; lifetime loss flags for human review

Extends R18. Once a strategy's most recent three completed, non-overlapping 15-trade batches (equal-weight normalized, same basis as R18) are each individually net-positive -- 45+ episodes -- its strategy_lifecycle.json status becomes locked: permanently exempt from promote_r18_failures's initial-judgment path and reassess_retests's retest cycles, though it keeps trading and its parameters may still be refined normally. The check is a trailing window (the most recent three completed batches, not necessarily the strategy's first three). Only a human/manual edit to strategy_lifecycle.json may move a locked strategy off that status. Separately, if a LOCKED strategy's lifetime (all-time) normalized P&L later turns negative, it is NOT auto-demoted or auto-killed -- flaggedForReview is set on its lifecycle record instead, surfaced on the dashboard, and never cleared automatically once set. AMENDED 2026-08-07 (humanLocked): R34's 'only a human moves it' guarantee existed only at status 'locked', which means locked permanently ACTIVE -- a human wanting a strategy retired AND frozen had no way to say so. A new humanLocked: true field on any lifecycle record now freezes it against every automated transition in tools/strategy_lifecycle.py whatever its status (checked first by reassess_retests, close_deadlocked_retests, advance_lock_status and flag_locked_strategies_if_negative; reopen_initial_failures is covered for free). Only a human editing strategy_lifecycle.json clears it. Separately, advance_lock_status() now also skips status 'inactive' on status alone -- it previously skipped only {locked, dead, dead-dead}, so a hand-retired strategy could be promoted back to 'locked' (permanently active) off its frozen history. REAFFIRMED 2026-08-11 (human directive): the lock threshold stays at 3 consecutive net-positive 15-trade batches (45 episodes). Reconsidered alongside the R18/R43 state-model clarification and deliberately left unchanged. AMENDED 2026-08-13 (human directive): for a LOCKED strategy the batch trigger fires on ONE completed negative 15-trade batch, not two consecutive (LOCKED_NEGATIVE_BATCHES_TO_FLAG=1, kept separate from the generic CONSECUTIVE_NEGATIVE_BATCHES_TO_FLAG=2). Locked is the only status no automated path can demote, kill or reopen, so flaggedForReview is its sole safety valve and still takes no action; at two batches it could not fire until 30 trades had passed. Lifetime-negative trigger unchanged as backup. The trigger is a STATE evaluation re-derived from full history every EOD, with no cursor of batches-since-the-change, so it is retroactive by construction - on the live book it flags max-loser-breakdown immediately on its existing -414.92 batch despite a +1135.76 lifetime cushion. A recovery clears it: the window is the last completed batch only. AMENDED 2026-08-28 (human directive): both triggers are evaluated over the tag's CURRENT configuration, not its entire history. For an R43-inverted tag the basis starts at the inversion boundary -- the first episode of the final contiguous same-direction run, derived by strategy_lifecycle.current_config_episodes() rather than persisted, so it needs no migration. The batch trigger re-batches from that boundary too, so no batch straddles the flip and nets negative on original-direction losses. Rationale: R43 inverts a strategy BECAUSE its original direction lost, so pooling those losses back into R34 re-judges a configuration that no longer exists. Measured on the live book 2026-08-28: etf-scalp -648.30 pooled vs +1049.51 current-config, orb-retest -464.02 vs +538.57. Not an amnesty -- the same pass newly surfaced a real negative post-inversion batch on kronos-momentum that pooled batching masked. No-op for non-inverted tags (adx-di unchanged at -1177.53), asserted as test controls in tools/tests/test_r34_inversion_basis.py.

human directive, 2026-07-31 ("after a strategy has strung together 3 consecutive positive 15-trade cycles in a row... mark it as permanently active/green... if it later turns net negative over its all-time/lifetime trade history... flagged for human review")

R35 [testing] org-gap-fade: fade the opening gap toward the prior close, sized by gap-vs-ATR14 bucket

Fades the regular-session opening gap back toward yesterday's close, calibrated from a public 10-year NQ gap-fade study. A gap UP is faded SHORT (org-gap-fade-short); a gap DOWN is faded LONG (org-gap-fade-long). Only Tiny/Small/Medium gaps (|gap| < 0.50x daily ATR14) are eligible -- Large/Huge behave like breakaway gaps and the study's fill-rate edge is gone by then. Entry window 8:35-10:30 CT only (the fill-rate edge decays fast after late morning). Primary target is the 50% gap-fill midpoint (prior close + gap/2), reached far more reliably per the source study than a full 100% fill; the LONG side may extend past it via R25's existing generic momentum-gated extension (LONG-only in this codebase), the SHORT side always takes the 50% target flat. Structural stop beyond the gap extreme (today's high/low or the open, whichever is more extreme), buffered by the larger of 0.25x daily ATR14 or 0.15% of price. Day-of-week (the study found Tue/Wed strongest) is NOT a hard filter -- logged for a future R18/weekly-rollup evaluation of whether this system's own sample shows the same pattern, not gated on day one with no in-system evidence.

human directive, 2026-08-01, referencing a public 10-year NQ opening-range-gap study and a public TradingView indicator ("ICT Opening Range Gap" by n00btraders) as the closest available reference for the described (DM-only) original

R37 [observational] Kronos forecast: fail-open optional confirmation, fail-closed standalone signal + soft exit trail-tightening

Kronos-mini forecasts a symbol's near-term OHLCV path from its own live 1-minute bar history (3 independent samples -> direction/magnitude/confidence, confidence = fraction of samples agreeing). Exit side (universal, every open position): check_cycle() tightens (never loosens) the effective stop to 2% of price -- the same tight-trail convention R25 already uses -- on a confident (>=0.67) forecast reversal against the held direction; a soft signal, never a hard exit trigger. Optional entry-confirmation side (kronos_gate on guarded_entry/guarded_short_entry, default False): refuses an independently-qualified entry only on a confident forecast disagreement and fails open on missing data or dependencies. Standalone kronos-momentum side: because Kronos is the entire incremental signal, kronos_require_signal=True fails closed unless the model confidently forecasts UP (>=0.67); missing, flat, low-confidence, error, and opposing outcomes intentionally skip. No already-scored strategy is retroactively changed. Every real forecast is logged for a hit-rate evaluation. Standalone fail-closed repair auto-applied by recurring Codex action-log repair session 2026-08-02 from the rollout contradiction documented in [internal note] DEMOTED TO OBSERVATION-ONLY 2026-08-19 (human directive): Kronos still runs and logs every forecast and judged outcome but no longer vetoes entries or tightens stops (KRONOS_ADVISORY_ONLY in stop_guard.py). Evidence: 7,486 self-judged forecasts, 43.0% directional hit rate (worse than chance); confidence uninformative (1.00 -> 47.5% n=2632 vs 0.67 -> 47.0% n=4179). Not deleted: the 0.33 bucket hits 0.4% on n=675, which looks like a sign/labelling defect worth diagnosing. require_signal=True still fails CLOSED because kronos-momentum has no signal without it - failing open would make it enter unconditionally. Stops can now only be later than under R37, never earlier.

human directive, 2026-08-02; Yu Shi, Zongliang Fu, Shuo Chen, Bohan Zhao, Wei Xu, Changshui Zhang, Jian Li, "Kronos: A Foundation Model for the Language of Financial Markets," arXiv:2508.02739 (AAAI 2026); model: https://github.com/shiyu-coder/Kronos (MIT)

R38 [testing] Portfolio-level aggregate dollar-risk cap gates NEW entries at 2.5% of equity

Aggregate dollar risk across every simultaneously open position -- the sum of each position's qty x distance-to-its-effective-stop, i.e. what a correlated gap-down hitting every stop at once would actually cost, not raw notional exposure -- may not exceed 2.5% of equity (PORTFOLIO_HEAT_CAP_PCT). This gates NEW entries only: sizing.portfolio_heat_capped_qty() is one more term in the existing min() cap chain alongside R21/R32/R36, so it can only shrink or refuse a trade, never enlarge one. check_cycle() already computes the aggregate every cycle (heat_risk); entry_cycle() threads it into every guarded_entry()/guarded_short_entry() call. A None value (e.g. check_cycle() itself errored this cycle) skips the gate entirely for that cycle -- fail open, matching R36/R37's own convention. Existing open positions are never force-closed or resized by this rule; it only blocks further new entries until enough positions close to bring the aggregate back under the cap. 2.5% is the midpoint of a requested 2-3% range, cross-checked against R32's flat $100 max-loss cap (implying roughly 25-50 concurrent full-stop-sized positions on $100k-$200k equity before this cap binds). Explicitly reverses the 2026-07-13 rulebook-review decision that added no portfolio heat cap, using the new evidence (the 2026-08-02 tail-risk audit) that decision said would be needed to revisit it.

human directive, 2026-08-02, the third and final fix from [internal note] (Finding #1: no portfolio-level position-count or aggregate-risk ceiling existed); reverses 2026-07-13 rulebook-review Decision 3. See [internal note]

R39 [testing] Wash-sale bookkeeping: informational tax tracking, never changes trading behavior

Every EOD pass recomputes which realized losses are IRS wash sales under IRC Section 1091 (loss disallowed if substantially identical stock is acquired within 30 calendar days before or after the loss), the disallowed loss amount, and the adjusted cost basis on the replacement shares. This system trades the same tickers repeatedly, so wash sales are EXPECTED to trigger often -- that is correct bookkeeping, not a bug. detect_wash_sales() is a pure function over trading.json's closedTrades FIFO lot ledger: for a LONG loss the window is centered on the sale date and the trigger is an ACQUISITION (new LONG purchase or SHORT-covering buy); for a SHORT loss the window is centered on the covering (closing) trade date and the trigger is a DISPOSITION (new SHORT sale or LONG sale) -- mirroring the IRS's own short-sale wash-sale guidance, the reverse of the ordinary LONG case. Replacement shares are matched FIFO with proportional disallowance for partial rebuys. This rule never gates, sizes, or otherwise changes any live trading decision -- it is purely a downstream informational report, not part of the operative safety-core rule set. Known limitations: 'substantially identical' is approximated as same ticker symbol (a documented IRS gray area, more so for options/derivatives than the plain shares this system trades); cross-direction replacement basis adjustments are flagged as a less-established case; adjusted basis is not chained across wash-sale generations. Good-faith informational bookkeeping, not a substitute for professional tax software or a CPA.

human directive, 2026-08-02 ("build wash-sale tracking for accurate tax reporting — not avoidance logic, just correct bookkeeping"). See [internal note]

R40 [active] Account-type-aware daily capital deployment cap (ROTH_ACCOUNT env flag)

TOGGLEABLE since 2026-08-12 (human directive), currently OFF via DAILY_DEPLOYMENT_CAP=false. R40 is NOT removed -- the rule and all its machinery stay in the codebase so the switch can be flipped back on. WHAT CHANGED: R40 now has an off position. ROTH_ACCOUNT never provided one -- it only selected WHICH ceiling applied (50% of net assets when true, 100%/broker buyingPower when false), so ROTH_ACCOUNT=false still capped, at $162,323 on this account, and that margin branch is what squeezed entries to a single share on 2026-08-12 (SMCI: R21 allowed 133 shares, R38 allowed 6517, R40 allowed 1 on $64 of remaining budget). strategy_lifecycle.daily_deployment_cap_enabled() reads DAILY_DEPLOYMENT_CAP (default false, case-insensitive literal 'true' to enable); entry_cycle() computes deployed_today/daily_cap_dollars only when it is on and passes None otherwise. Switched off after confirming R40 is not load-bearing for compliance here: moomoo_trade.py is hard-locked to TrdEnv.SIMULATE (no real broker to incur a good-faith violation against), ROTH_ACCOUNT=false so the T+1 settlement branch was never live, and buyingPower $162,323 vs $100,196 net assets = 1.62x leverage, i.e. margin, which has no good-faith-violation concept. SET DAILY_DEPLOYMENT_CAP=true TO RE-ARM IT IF THE ACCOUNT EVER NEEDS SETTLEMENT PROTECTION. Historical text: Total NOTIONAL capital (qty x entry price, NOT stop-distance risk -- that's R38) committed to NEW entries in a single calendar day may not exceed 50% of net assets for a Roth/cash account (T+1 settlement rotation -- capital used to buy today isn't available to re-spend until the next business day, so deploying 100% on day one risks a good-faith violation), or 100% of net assets / the broker's own margin buyingPower if larger for a margin account (the default). Driven by the ROTH_ACCOUNT env flag (true/false, case-insensitive, default false). Independent of and simultaneous with R38 -- either can be the binding constraint regardless of the other; this caps capital deployed, R38 caps at-risk dollars from stop distance, a different dimension entirely. entry_cycle() computes deployed_today (gross sum of today's journaled BUY/SHORT notional, not netted against same-day closes) and daily_cap_dollars once per cycle, threaded into every guarded_entry()/guarded_short_entry() call and into sizing.sized_qty()/sized_short_qty() as one more shrink-only min() term. Never touches already-open positions; the budget refills at the next calendar day. Does not disable SHORT selling under Roth mode -- governs sizing only, not direction eligibility.

human directive, 2026-08-04 ("add an account-type-aware daily capital deployment cap, driven by an env flag"). See [internal note]

R41 [active] REMOVED 2026-08-07 -- minimum-notional floor (0.5% of portfolio value)

REINSTATED and AMENDED 2026-08-12 (human directive). Minimum-notional FLOOR: a trade whose fully-capped size falls below 0.5% of equity is SKIPPED entirely, never sized UP. Removed 2026-08-07 alongside R32 on the reasoning that with R32's squeezing gone the floor would reject only deliberately small positions; the data refuted that. Over the five sessions after removal, sub-$500 orders went from 0.6% of all orders (10/1551) to 8.1% (31/384) and 1-share orders from 0.3% to 4.4%. The 33 sub-$500 round-trips ever closed total +$23.21 lifetime (median -$0.01); the 15 closed since removal total -$35.55 - spread and commission drag, not edge. Trigger was a 1-share $37.51 SMCI ticket. The floor must REFUSE and never size up: every other term (R21 notional, R38 heat) is an upper bound, so raising qty to meet a floor would override whichever was binding; refusing is monotonically risk-reducing. Reinstated at its ORIGINAL purely-proportional 0.5% form: a flat-dollar alternative term was drafted and dropped on the human's instruction ('just 0.5% of account value'). At ~$100k equity the floor is ~$501. Mechanics: sizing.below_min_notional_floor()/min_notional_floor_dollars(), checked in guarded_entry()/guarded_short_entry() right after the qty<1 sized-to-zero check so a zeroed trade keeps its own label; binding_caps() names the cause and the entry-skipped/below-min-notional note reports notional, floor and binding cap. Measured cost: would have refused 31 of 384 post-removal orders (8.1%), forfeiting the +$23 they produced. Historical text: RETIRED alongside R32, whose shrinking it existed to clean up after. R41 skipped trades that R32's $100 max-loss cap had squeezed to an uneconomic size; with R32 gone that squeezing no longer happens, so the floor was rejecting nothing but genuinely small deliberate positions. A tiny position is now simply placed. sizing.below_min_notional_floor() and MIN_NOTIONAL_PCT survive for historical log analysis and because R43's paradigm-shift probe is still expressed relative to the floor. Removed in the same decision as R32; write-up: [internal note]

human directive, 2026-08-06 ("no position sizing below 0.5% of portfolio value... the correct behavior is to SKIP the trade entirely, not to force the size up"). See [internal note] RETIRED 2026-08-07 by human directive; removal write-up cited in the rule text above.

R-ETF [active] ETFs are tradeable

The buy universe includes the pinned ETF list (SPY, QQQ, IWM, DIA, SMH, XBI, XLE, XLF, XLK, XRT, GLD, SLV, TLT, TQQQ, SQQQ, SOXL, SOXS) in addition to the day's watchlist. ETFs are liquid, halt-free, rumor-free — good vehicles for playbook testing. Leveraged-ETF half-sizing was removed 2026-07-28 by human directive: every ETF, 1x/2x/3x alike, may use the full R21 5% notional like any other symbol (R32's flat $100 max-loss cap still applies on top).

human directive, 2026-07-09; leverage half-sizing removed by human directive 2026-07-28

R42 [active] Standing self-improvement authorization -- must be documented on the EOD Reports dashboard tab

Judgment-tier sessions may implement an evidence-backed profit/risk improvement -- altering rules, code, or strategies -- without waiting for per-instance human sign-off (the standing authorization in [internal note], in force since 2026-07-14). This rule adds one concrete, tool-enforced requirement: the change must be documented where the EOD Reports dashboard tab actually shows it, not only in a git commit or an internal reviews/*.md file nobody reads day-to-day. Every autonomous trade_log.py note must start with the literal prefix SELF-IMPROVEMENT: (case-insensitive) so the dashboard's isSelfImprovementNote() detector picks it up. Every autonomous strategy_lifecycle.json status transition (locked, retesting, active, dead, dead-dead, paradigm-shift, flagged-for-review) is written to trade_log.json by eod_review.py's log_lifecycle_transitions(), not merely printed to a log file. The EOD Reports tab is a nested, collapsed-by-default accordion (restructured 2026-08-06) -- day-level and section-level summary badges keep self-improvement/paradigm-shift/dead-dead counts visible without expanding anything. Track A (strategy/rule adjustments, gated on R18's 15-attempt sample-size bar) and Track B (bug/reliability fixes, no sample-size gate) both remain in force unchanged; a genuinely new mechanism still needs a checkable external citation; safety-core changes still require explicit downside analysis and a synchronized trading_safety_core.md update.

human directive, 2026-08-06 ("the system has standing permission to actually implement the change... AS LONG AS the change is clearly documented... shows up in the EOD status/report... not just buried in a git commit or an internal reviews/*.md file"). See [internal note]

R43 [testing] Paradigm-shift direction inversion after a failed retest, and the dead-dead terminal state

A strategy that fails a 15-trade cycle (initial or retest) with no further actionable improvement gets ONE additional chance -- every LONG signal it would have taken instead goes SHORT, and every SHORT signal instead goes LONG, everything else about the strategy unchanged -- before being declared dead. invertedDirection and paradigmShiftAttempted are set once, permanently, the first time this fires. A paradigm-shift cycle can retry on its own actionable improvements exactly like a normal retest (status stays paradigm-shift, never silently relabeled). A profitable paradigm-shift cycle becomes active and keeps trading its earned inverted direction indefinitely -- invertedDirection is never cleared, and the strategy can still lock under R34. A paradigm-shift cycle that ALSO loses with no further actionable improvement (or Kelly-deadlocks under R36) becomes dead-dead: a stricter, permanent terminal state -- tradeBudget 0, excluded from entry routing exactly like dead, and unlike dead, no automated path in strategy_lifecycle.py may ever reverse it. Execution: strategy_direction_inverted() is checked as the LAST step in guarded_entry()/guarded_short_entry(), after every other gate (R33/R31/R29/R21/R32/R36/R38/R40/R41/R37) has already validated the signal for its native direction; the stop and target are mirrored around the same entry price and the order is placed through the opposite function via a hard stop_override/target_override, never blended with that function's own live signal data. AMENDED 2026-08-07 (human directive): a paradigm-shift cycle is NEVER retired by the R36 Kelly deadlock closer. quarter-Kelly is derived from the tag's history under its ORIGINAL direction, and every strategy worth inverting is a consistent loser whose Kelly is always a confirmed zero -- so the inverted cycle was being retired as dead-dead without placing one inverted trade. It now probes at stop_guard.PARADIGM_SHIFT_PROBE_PCT (1.25x R41 MIN_NOTIONAL_PCT = 0.625% of equity, the smallest position the rulebook permits) and is judged only on real inverted results by reassess_retests(). Its 15-trade budget is now actually enforced (CYCLE_STATUSES); previously retest_budget_remaining() returned None for paradigm-shift and stop_guard read that as no budget at all. A deadlocked 'retesting' tag still gets its paradigm-shift chance exactly as before. IMPLEMENTATION DEFECT, FIXED 2026-08-07: R43 placed ZERO inverted trades between 2026-08-04 and 08-07. moomoo_trade.strategy_direction() re-checked the order against the strategy's watchlist-declared direction, and build_watchlist.mjs knows nothing about lifecycle state, so an inverted tag still declared LONG there -- every inverted order arrived declared LONG and executing SHORT and was refused direction-mismatch (163 refusals against exactly 163 paradigm-shift-inverted attempts, a 100% failure rate; ema-stack, etf-scalp, pdh-break and gap-go accrued nothing against their budgets while appearing to trade). strategy_direction() now mirrors the declared direction for any invertedDirection tag, applied last so watchlist-declared and code-declared tags invert identically; an ambiguous declaration stays ambiguous. Consequence for judgment: no paradigm-shift cycle has any real inverted episodes before 2026-08-07. CLARIFIED 2026-08-11 (human directive): plain `dead` is TRANSIENT, not a resting state -- no FSM path assigns it (pinned by test), and the skull icon is reserved for `dead-dead`, the only terminal state. Icon rule: dead-dead 💀, paradigm-shift ⇄, legacy dead 🗿 'DEAD (pre-R43)'. reconcile_pre_r43_deads() (idempotent, each EOD) reconciled the 9 grandfathered `dead` records: 7 promoted to paradigm-shift (cross-session-strength, inst-continuation, mfi-hhhl, orb-retest, rsi-cross-reversal, vixfix, watchlist-momo -- all killed by the R18/R36 Kelly deadlock this rule's 2026-08-07 amendment identifies as a bug, same precedent as the 4 retroactive shifts that day), 1 dropped (barchart-ma50-100, an R45 alias), 1 left dead (vwap-bounce -- 'Explicitly removed; no supported redesign remains' is a human judgment, not a deadlock artifact). humanLocked and existing dead-dead records are never touched. IMPLEMENTATION DEFECT FIXED 2026-08-12: when a losing paradigm-shift cycle earns another 15 attempts from a recorded actionable improvement, stop_guard.retry_lesson_gate() now enforces that directional VWAP/30-minute lesson on the executed inverted direction. Previously the gate recognized only status=retesting, so paradigm-shift improvements were persisted but ignored. Initial paradigm-shift cycles with improvement=null remain direction-only.

human directive, 2026-08-06 ("invert its direction... gets a fresh 15-trade evaluation cycle... if a strategy fails its normal run, AND then fails its paradigm-shift/inverted run with no other actionable changes applied on top of the inversion, it becomes permanently locked as dead"). See [internal note]

R44 [testing] Monte Carlo notional multiplier (LIVE, tool-enforced, floored above zero)

Each strategy's R21 notional allocation is SCALED by a multiplier derived from Monte Carlo simulation of its own equal-weight-normalized episode history. Two properties are the whole point of the rule and are test-enforced. (1) It can RAISE size as well as lower it -- R36's Kelly cap was one more term in a min() and could only ever shrink; R44 multiplies, so a strategy with good simulated statistics sizes UP toward the cap. (2) It can NEVER reach zero: the multiplier is floored at 0.5x, so a strategy the simulation dislikes trades SMALLER and keeps generating the evidence that would change the verdict. That floor is the direct fix for R36's deadlock chain, and blocking a strategy remains R18/R34/R43's job alone. Below 15 closed episodes (the same bar R18 uses) the multiplier is exactly 1.0 -- NEUTRAL, never a penalty: absence of evidence must not masquerade as evidence of absence. Ceiling 1.5x, and R21's per-symbol cap still bounds the result underneath, so a boosted entry can never exceed 7.5% initial / 10% combined. Simulations (trade bootstrap, daily block bootstrap keeping same-day correlated trades together, and an execution-stress variant with 5-15% missed fills plus a slippage haircut; 10,000 paths, seeded for reproducibility) run NIGHTLY in tools/allocation_lab.py, which writes src/data/allocation_multipliers.json. stop_guard.py READS that file -- it never imports the research module, keeping slow simulation work out of the entry loop and a research-layer fault from taking the trading daemon down. A missing, malformed, or stale (>7 days) file reads as neutral 1.0, and every value is clamped into [0.5, 1.5] independently on both write and read.

human directive 2026-08-07; [internal note]

R45 [active] Strategies sharing an entry gate are one strategy; merged tags are aliases

R18 judges a strategy after 15 episodes under its own tag, so two tags running the same entry gate split one strategy's evidence and neither ever reaches a verdict. Tags that share a gate are therefore merged: an alias is judged, sized, retired and routed as its CANONICAL tag, and its episodes pool into the canonical's evidence. Evidence 2026-08-07: all ten barchart-* tags declare automation.kind = watchlist-momo in build_watchlist.mjs -- the same live gate watchlist-momo uses -- and the twelve Barchart Opinion studies produce near-identical top-10 slates (moving-average studies over one universe are almost perfectly correlated; nine were symbol-for-symbol identical). watchlist-momo was already dead under R18 (-617.23 normalized over 28 episodes) and its ten aliases kept trading anyway, because eight had never individually reached 15 episodes. Pooled: 124 episodes, -1753.02 normalized. Separately or-break and orb-retest have byte-identical gate bodies in stop_guard.indicator_signal; pooled 29 episodes, -1002.59 normalized. Mechanics: strategy_lifecycle.canonical_tag() maps alias to canonical; barchart- matches by PREFIX, not enumeration, because the watchlist takes a rotating top ten of twelve studies. Applied in _tagged_episodes (pools evidence for every consumer), inactive_tags (a retired canonical retires every alias), retest_budget_remaining (an alias spends the canonical's budget), entry_cycle._add (options register and journal under the canonical tag -- the load-bearing block, since a prefix alias usually has no lifecycle record), advance_lock_status (no alias earns its own R34 lock) and is_direction_inverted (no alias trades the opposite side of its canonical). History is never rewritten: closedEpisodes and journal rows keep the sourcing tag, canonicalization happens on read, and the merge is reversible by editing one map. The merge is on GATE identity, never slate overlap -- macd-st shares the barchart slate but has its own gate and stays separate. Immediate effect: twelve tags stopped trading. Adding a tag whose automation.kind duplicates an existing tag's requires adding it to the alias map.

human directive, 2026-08-07 ("deduplicate the strategies and combine them"). See [internal note]

R46 [active] Every trade carries a strategy attribution; an unattributed episode is a reported defect

A closed episode with no strategy contributes its P&L to nothing: R18 cycle verdicts, R34 batches and R44 multipliers all count episodes BY TAG, so an unattributed trade is invisible to every judgment that decides whether a strategy lives, and each one silently shrinks the sample those verdicts use. Evidence 2026-08-07: a mid-session read of trading.json showed 7 of that day's 28 episodes attributed to 'unknown', most closed in one 11:19 batch; all seven self-healed on the overnight resync when annotate_closed_trades re-ran the entry-journal link after reconcile_journal copied the fills in. The self-healing IS the problem -- a failure that repairs itself silently is indistinguishable from one that does not, and nothing reported either. The order-time guarantee already existed but was never verified: moomoo_trade requires --strategy on buy/short, journals an orderId per fill, and R24 refuses a SELL beyond held quantity, so attribution runs at 100% (1266 of 1266 closed lots, all via the exact order-<orderId> link; the fuzzy price/time fallback is unused in the entire history). Mechanics: rebuild_trade_episodes.UNATTRIBUTED is the placeholder written when no strategy resolves -- not a strategy, never to be read as one. It is still written (dropping the episode would hide a real trade with real P&L), but unattributed_episodes() reports every occurrence, moomoo_sync logs an episode-unattributed event and a stderr warning as it writes, and task_health.trade_attribution_health() puts the standing count on the health surface where allOk gates the dashboard banner. Two invariant tests assert the property over the live book at both episode and lot level. unintended-oversell is NOT an attribution failure: it is a deliberate safety marker for a SELL beyond held quantity (R24) and must never be re-credited to the long strategy it oversold, which would launder a safety violation into that strategy's record. Nothing repairs attribution automatically -- deciding which strategy owned an orphaned fill is a judgment call over the journal's order-id chain.

human directive, 2026-08-08 ("every trade needs a strategy attribution"). See [internal note]

R47 [testing] Regime-based exit planning: the plan precedes the order, and 2.5xATR replaces the structural stop basis

No order is submitted without a complete, fresh, risk-valid ExitPlan built BEFORE the entry from the symbol's own intraday regime (ADX/ATR-ratio/EMA-structure/Hurst vote with K=3 hysteresis and higher-timeframe reconciliation); an AMBIGUOUS regime refuses the entry outright. The stop basis is entry -/+ 2.5 x ATR(14) on the 5m trading timeframe for EVERY strategy, replacing R17's structure-minus-wick-buffer as the primary basis (R17 remains the fallback when live ATR5m is missing, and its no-man's-land / R29 / skip-rather-than-widen clauses still bind). Measured across real historical entries the R47 stop is tighter on 72% of them -- median 1.21% of price vs R17's 1.63% -- which means a smaller loss at the stop, NOT a larger position: per-trade size was measured unchanged on 308/308 because no per-trade sizing term has read the stop since R32 was removed. The tighter stop frees R38 aggregate heat, allowing more concurrent positions. Exits are three tiers at 40/35/25: fixed 2R, a 3xATR Chandelier trail that promotes to the higher timeframe at +2R, and a structure-exit runner gated off when the regime does not support one. Four invariants are enforced by TYPE rather than by assertion in trade_monitor.py: a stop has no assignment API so it can only tighten, a fixed target is immutable so it cannot extend, no method anywhere increases position size, and the defensive-adjustment budget is one permit with no reset. R37 is EXEMPT from that budget -- Kronos tightening may fire repeatedly; the one-shot counter governs regime-flip adjustments only, and both route through the same monotonic stop so risk can only shrink. Failure mode is fail-open: a classifier or planner fault logs and falls back to the pre-R47 rule chain rather than blocking the trade, matching R37/R38. Specified as 'R45'; R45 and R46 were claimed by concurrent work while this was in flight, so it landed as R47. PLAN GATE WIRED LIVE 2026-08-09 in SHADOW mode (R47_PLAN_GATE_ENFORCE=false default): it classifies and logs the verdict but does not block. Measured on 20 real symbols over 5 days of 5m bars, the live tape reads 70-80% AMBIGUOUS because MA_SLOPE_FLAT_PCT (0.05%/bar) is a daily-chart threshold demanding a ~4%/day trend against an observed ~1.2%/day median slope; enforcing would refuse ~95% of entries. FAULT (broken machinery) fails open; VERDICT (ambiguous/stale/risk refusal) is what fails closed once enforced. SHORT entries get the regime gate only and keep the flat 3% cover stop. Measured 2026-08-09 over all 228 closed SHORT trades across 161 symbols: 2.5xATR is tighter on 228/228 (median 0.91% of entry vs 3.00%), raises the stop-out rate from 75.0% to 95.2%, and would have cut short 24.3% of profitable shorts. Parity is rejected on evidence, not deferred. RECALIBRATED 2026-08-09: the earlier '95% refusal' figure was wrong (one bar, 20 untraded mega-caps). Re-measured over 3,851 moments on the real universe, raw AMBIGUOUS was 18.0%. ADX 25/20 and vol 1.1/0.9 measured healthy and were left alone; the EMA50 slope moved from a fixed percentage to 0.10 x ATR(20) per bar (AMBIGUOUS 18.0->17.1%, TRENDING 30.5->34.6%). Two bugs fixed: the RANGING band extreme came from the nearest support (a level inside the band) and is now the low/high of the last 24 5m bars; and RegimeSmoother counted calls not bars, so K=3 meant 45 seconds instead of 15 minutes. Enforcement REMAINS OFF: end-to-end over 11,538 consecutive bar-moments the shipped code refuses 44.1%, not 18%, because hysteresis initialised to AMBIGUOUS turns label churn into AMBIGUOUS-stickiness. Higher-timeframe reconciliation repaired 2026-08-09 (option C): it had NEVER run in production because the 1-day bar fetch yields ~26 fifteen-minute bars against EMA50's need for 50 (usable on 0 of 12 symbols); yahoo_bars_deep() now fetches 5 days cached for one bar period (usable 16/16). With it present the 5m and 15m labels agree only 40.6% of the time, so on_disagree is 'smaller' rather than 'ambiguous': the plan is marked half_size and guarded_entry applies a shrink-only 0.5x multiplier. A fault never resizes. The earlier AMBIGUOUS-stickiness hypothesis was wrong -- the smoother reduces ambiguity (16.9%->16.0%) and halves churn. Enforcement remains OFF pending a representative multi-moment measurement; the only post-fix figure is a 16-symbol snapshot at 31.2%. OPERATIVE STOP BASIS since 2026-08-11 (LIVE by default): width = max(0.5 x ATR(14,5m), 0.798% x entry). Replaces 2.5xATR and supersedes the never-live flat-0.50% plan. Study v2 coupled the target to the stop (the live target is entry + 3 x width, so v1's stop-only substitution overstated tight stops), computed ATR from pre-entry bars only, and treated R29-inadmissible stops as refused entries. Over 973 real LONG round-trips, among fully placeable rules: hybrid +$7,177/+$5,806/+$2,893 at 0%/8%/25% slippage; pure flat floor +$6,877/+$5,517/+$2,627; flat 1.00% +$4,846/+$3,297/+$6; 2.5xATR -$5,563/-$7,694/-$12,221 (worst tested). The ATR term fires on only 4.0% of trades (39/973) and its $300 edge over a pure flat floor is not statistically meaningful -- it is tail protection for volatile names (ACHR's 2.5xATR stop was 4.59% of entry), not a proven edge. The floor is derived from R29 + the entry premium so the rule can never be unplaceable. Caveats: the simulation's exit model is stop-or-3R only while live exits also use R25/Kronos/EOD-flatten, so the ranking carries but not the magnitudes; one ~4-week window; LONG only. Each entry logs its branch as R47 hybrid(atr)/hybrid(floor). Kill switch R47_HYBRID_STOP_ENABLED=false. AMENDED 2026-08-13 (human directive) - SHORT PARITY: shorts use the same hybrid as longs, max(0.5*ATR(14,5m), 0.798%*entry), replacing the flat 3%-of-entry default and reversing the 2026-08-09 hold. WHAT CHANGED IS THE POLICY, NOT THE EVIDENCE: the 2026-08-13 short-side study (415 shorts, real 5m bars, 7/23-8/13) did NOT clear a tightening - its sample is a +5.08% SPY uptrend, every width lost money, the ranking was non-monotonic, and the only positive rules died by 8% slippage; it recommended changing nothing, and the human directed parity anyway. Only the DEFAULT branch changes; explicit custom/structural stops and R43 mirrors are untouched. Affected since 2026-08-10: max-loser-failed-vwap (21), wsb-popularity-green-open (7), short-gap-open-close (5), max-loser-breakdown (5), short-gap-failed-10m (5), org-gap-fade-short (3), short-gap-5m-low (3), kronos-momentum (2), pdh-break (1) - 3.00% -> a MEDIAN 1.06% of entry (~2.8x tighter): CORRECTED 2026-08-13, the ATR term wins on 72% of real shorts vs ~4% on longs, so the all-floor 3.8x figure first published was wrong. A/B on the 220 affected shorts is NOT a clear win - at zero slippage the flat 3% beats the hybrid by $160 (-343 vs -503); the hybrid leads only under slippage assumptions that scale with stop distance. Stop-outs 62->126, win rate 70%->42%. Realized anchor: those same names/days actually closed +1419.05, while both sim arms are negative, so the simulation's magnitudes carry no weight. R29 ASYMMETRY FLAGGED NOT RESOLVED: R29 measures clearance from the live LAST for longs but from ENTRY for shorts, so a short stop at its minimum sits 0.198% from the tape vs a long's 0.5%; moot for the new default (the 0.798% floor clears it by construction) but still live for custom_stop strategies. Also 2026-08-13: max-loser-failed-vwap gets a widened SHORT trail (2%/1% arm) via SHORT_TRAIL_OVERRIDES, keyed by strategy tag not automation kind. REVERTED SAME DAY 2026-08-13 (human directive) after measuring max adverse excursion: shorts keep the flat 3%. On the 220 real shorts that used that branch, 49% of eventual WINNERS ran >1.0% against entry first, 30% >1.5%, 20% >2.0% - a 1% stop would have cut 75 winners worth +$1920, a 2% stop 31 worth +$709. The MAE distribution is BINARY: a short that does not reach its stop wins 94-100% of the time regardless of how far it went against you, while losers' median MAE is 3.00% (essentially every loser is a stop-out), so adverse excursion below the stop predicts nothing. The A/B agreed - flat 3% beat the hybrid by $160 at ZERO slippage, the only unbiased assumption. The hybrid's real median short stop was 1.06% of entry, inside the band where winners were still being cut. NOT SETTLED: the width buys survivability worth ~$25-67 per surviving trade against ~$85 per stop-out (a payoff-ratio problem, not a stop-width one), and the whole sample is a +5.08% SPY rally where shorts would be expected to need more room than normal. RETEST ON DOWN-WEEK DATA. max-loser-failed-vwap's widened trail (2%/1% arm) was KEPT.

human directive, 2026-08-07 (regime-based exit planning specification + four follow-up decisions: BROAD stop-basis scope, full three-tier build, R37 exempt, fail-open); TESTING

R48 [active] Paper-account fee is a simulator artifact: trust GROSS trade P&L, not the equity curve

The moomoo SIMULATE account charges a flat ~$1.96 per closed lot ($0.98/side, per ORDER) that a real US-resident Moomoo Financial Inc. account does not. Measured 2026-08-19: equity showed -$2,031 from a $100,000 start while trade-derived realized P&L showed +$1,657 gross, a -$3,867 gap over 1,969 closed lots, reconciling the whole book to within $8. PROOF IT IS PER-ORDER AND NOT REAL: (a) all six zero-trade days, weekends included, show a gap of exactly $0.00, ruling out borrow/financing/dividends/custody which accrue regardless of trading; (b) average shares-per-lot varies 6.5x (97->627) while gap/lot stays pinned near $1.96 and gap-per-SHARE swings 14x; (c) $0.98/side matches moomoo's NON-US-resident '$0.99 per order' unlock fee. Verified against moomoo's published US schedule: US residents pay $0 commission and $0 platform fee (promotional), with only regulatory pass-throughs (SEC $0.0000206*amount and FINRA TAF $0.000195/share on sells, CAT $0.000003/share both sides) totalling ~$0.10 per typical round trip, about 5% of the simulated charge. NOT DISABLEABLE: nothing in this repo sets it, and both deal_list_query and order_fee_query return 'Paper trading is not supported', so it is applied server-side with no ledger and no control -- do not go looking for a config. DIRECTION (easy to invert, so state both): against the PAPER ACCOUNT, gross strategy P&L reads ~$2/lot too OPTIMISTIC; against LIVE ECONOMICS, the paper EQUITY CURVE reads ~$2/lot too PESSIMISTIC. Operationally: gross P&L is live-accurate, equity is artificially depressed -- on 2026-08-19 the account showed $97,845 against a live-equivalent $101,513, i.e. up 1.5% rather than down 2.2%. DELIBERATELY NOT NETTED OUT (human directive, 2026-08-19): R18/R34/R36/R44 read gross episode P&L, which already equals commission-free live economics, so they were never distorted. The artifact is confined to the equity curve, where it biases R21 sizing and R38 heat slightly DOWNWARD -- the safe direction. Diagnosis: tools/equity_reconciliation.py (analysis only; a test bans live modules from importing it).

human directive, 2026-08-19 (keep paper economics matching commission-free live trading rather than building a fee-netting layer); investigation in internal notes (not committed; the repo has no [internal note] directory)

R49 [active] Stop-guard watchdog: relaunch a dead daemon mid-session, never start a second one

LIVE 2026-08-19, armed after the close on a flat book per human approval; registered as the `Kitty Guard Watchdog` daily task (08:30 +7h, every 5 min) and inventoried by task_health.py. Watchdog that relaunches the Stop Guard daemon when it dies mid-session. MOTIVATION: on 2026-08-19 the daemon died twice SILENTLY -- healthy at cycle #374 at 12:02:06 with every position quoting, gone 34 seconds later, no traceback, on AC power with 5.5GB free, so neither the Modern Standby cause diagnosed on 2026-08-18 nor OOM explains it. It stayed dead 22 minutes with 19 open positions and NOTHING in the system would have restarted it before the next morning's 08:31 trigger; only a human-run monitor noticing a stale heartbeat caught it. Cost: ARIS and MRK broke through their stops during the window (-$79.91 / -$58.56 on restart) and two profitable target-covers were missed and only collected late (MSTR +$13.47, BMNR +$64.35). The silent-termination root cause remains UNKNOWN; this does not fix it, it makes it survivable. THE CENTRAL SAFETY RULE IS NEGATIVE: never start a second daemon. Two guards enforcing the same stop can double-submit exits, and an unexplained second launch at 12:02:40 that day is the leading suspect for the first death. So the watchdog acts ONLY when stop_guard.lock_has_live_owner() is False (the recorded owner PID is genuinely gone). A daemon that is ALIVE but wedged is deliberately NOT restarted -- it is reported, because restarting that case is the one action that could turn a stall into a double exit, and a stalled guard still holds its stops. Further gates: weekday only; only inside 08:35-14:55 CT (the daemon is a scheduled one-shot that correctly exits after the close, so the worst misfire would be resurrecting it all night); heartbeat older than 180s; at most 3 restarts per day (a crash loop is a fault for a human, not something to feed); 300s cooldown. Relaunch goes through scripts/run_stop_guard.cmd -- the SAME wrapper the scheduled task uses -- so environment, the battery-below-10% gate and log destination all match the normal launch path. Decision logic is pure and tested (tools/guard_watchdog.py should_restart(); 13 tests); the spawn is isolated in main(). Registered with [scheduler config], NOT [scheduler config] -- the latter records a one-time trigger whose expiry is a documented Task Scheduler failure mode here. See workflows/system_setup.md.

human directive, 2026-08-19 (build auto-recovery rather than chase the silent-termination root cause); incident detail in internal notes

R50 [active] Rule 50 is you: human input from the public channel, tested like everything else

LIVE 2026-09-11. This number belongs to the audience of the Rule 50 AI channel: the system wrote its own rulebook; rule fifty is the humans watching it. Viewer suggestions (YouTube and X comments) enter a quarantined intake where comments are DATA, never instructions - nothing a comment says can execute code, change configuration, or place a trade. At most ONE suggestion is selected per night (the engagement-weighted 'Tonight's Pick'), with at most three concurrent test slots. Every suggestion faces the SAME evidence bar as an internal change: backtest, R18's 15-episode minimum, permutation testing with multiple-comparison correction, and block-permutation / out-of-sample checks where applicable - R23 and R52 are the standing demonstrations of ideas dying honestly under that bar. Adopted suggestions become numbered rules crediting the suggester's public handle; rejected ones are tombstoned with the evidence. THE OPERATOR EARNS NO CREDIT: the operator's own ideas go through the ordinary internal pipeline and never score leaderboard points - credit exists solely to measure outside input. Operator rule changes and edits are disclosed as operator changes. The operator ratifies every adoption and retains veto at every step; nothing enters this rulebook without a human directive. Full policy: autonomous-desk/community/selection-policy.md and input-security.md.

human directive, 2026-09-11 (Rule 50 AI channel: rule fifty is the audience; no credit to the operator)

R51 [active] OpenD watchdog: restart the broker gateway, because R49 only watches the daemon

LIVE 2026-09-03. Restarts moomoo OpenD when its local broker gateway stops serving. MOTIVATION: the week of 2026-08-31 was one long demonstration that watching the daemon is not enough. OpenD went down on 08-31 (morning), 09-01 (~14:40), 09-02 (all day) and 09-03, and EVERY visible failure traced to it: the R24 EOD flatten silently skipped on three consecutive sessions leaving 17 positions overnight (R53); six live exits failed outright at 11:31 on 09-03 (TZA/SRTY/SPXS/CNQ/DUOL/SDOW); a whole session ran 966 of 966 cycles erroring with zero trades. R49 would have been useless in every one -- the daemon was alive and correct throughout, it was blind -- and a human restarted the gateway by hand three times. DETECTION IS ON THE PORT, NOT THE PROCESS: OpenD can be running and not serving, so a process check would report healthy while every broker call fails. THE GRACE PERIOD IS THE SAFETY RULE: OpenD needs ~20s from launch to accepting connections, so a restart requires the port to have been down CONTINUOUSLY for 90s tracked ACROSS polls -- acting on a single failed probe would stack a second gateway on one that was merely starting, and the same rule filters sub-minute blips that resolve themselves. Further gates, each a refusal: weekdays only; 08:00-15:30 CT (covering the 08:12 pre-market scan and the 14:41 flatten, while an overnight outage is harmless); at most 4 restarts/day, since repeated failure is a login/config fault for a human rather than something to retry; 240s cooldown. It NEVER places an order and NEVER touches a position -- it restores the gateway and the stop-guard daemon does the trading under its own rules. Decision logic is pure and tested (tools/opend_watchdog.py should_restart()/down_seconds(); 23 tests, including a ban on any trading module importing it). Driven by the `Kitty OpenD Watchdog` daily task (08:00 +7h30m, every 2 min), registered with [scheduler config] and inventoried by task_health.

human directive, 2026-09-03 (build the OpenD watchdog); write-up in internal notes

R52 [active] Options-derived levels: null finding, and observational logging so it can be re-tested properly

NULL FINDING + OBSERVATIONAL LOGGING, 2026-09-06. Do not re-investigate options-derived levels from scratch, and do not re-implement them as a gate. QUESTION: would call wall / put wall / zero-gamma flip point have informed entries or exits on real trades? ANSWER: no evidence, on the cleanest sample obtainable. PRIOR ART: R23 (options-wall awareness) ran target-cap / no-entry-into-wall / pin-caution / wall-break-trail gates live from 2026-07-11 and was REMOVED 2026-07-30; this study reaches the same verdict independently, from trade outcomes rather than rule performance. WHAT WAS TESTED: 197 lots with lookahead-free walls no more than 48h stale, 18 session days (2026-07-13..08-13), 84 symbols, reconstructed free from git-committed watchlist.json snapshots. Call-wall proximity is noise -- AUC 0.470 (all) and EXACTLY 0.500 for the largest call wall on LONGs. A put-wall threshold initially looked real (permutation p=0.0005, clearing Bonferroni at 0.0063, OOS holding sign) and DIED under block permutation: p=0.2694 blocked by symbol, because THREE symbols (CLSK, CIFR, ACHR) were 99% of the entire gain. A price-level confound was tested and refuted (corr +0.066, price-alone AUC 0.482). Diagnostic tell: snapshot staleness (AUC 0.404) out-separated every wall feature -- a data-collection artifact beating the hypothesis variables. WHAT COULD NOT BE TESTED, AND WHY: the zero-gamma FLIP LEVEL is not derivable from stored data. options_walls.mjs persists gexSharesPer1Pct, a SCALAR net gamma at the current spot -- locating a zero crossing needs a per-strike profile across hypothetical spots. The binary substitute (gamma sign) had 179 positive vs 18 negative, so it had no power either and was not run rather than produce a meaningless p-value. THE SIGN CONVENTION IS AN ASSUMPTION, NOT AN OBSERVATION: options_walls.mjs computes net gamma as calls-minus-puts on the stated premise that dealers are SHORT (see its own 'dealers short' comment). That is not verifiable from open interest, which shows contracts outstanding and not who holds which side. If dealers are net long a name, the wall/flip interpretation inverts -- so a null result here cannot distinguish 'walls do not matter' from 'the sign assumption is wrong on these names'. WHAT CHANGED INSTEAD: every order now journals `optionsContext` (callWall, callWallOI, putWall, putWallOI, pin, gex, asof, spot, totalOI, thin) via moomoo_trade.options_context()/watchlist_options_for(). ALL OBSERVATIONAL -- no gate reads any of it, and a test asserts no decision module even references it. RAW LEVELS are stored, never entry-relative distances, because distances are a modelling choice a later study should make for itself. `asof` is kept so staleness stays measurable. This exists because the study could only scrape 197 lots after the fact and 389 of 444 same-day matches were LOOKAHEAD (the chain is fetched post-close, modal asof 16:00 ET); stamping at order time removes that permanently and for free. Full historical coverage would need paid data (Polygon options ~$79/mo, ORATS ~$99/mo; Tradier's free tier is delayed/simulated) across 936 traded symbols -- not worth buying without a positive signal first, and there was none. REVISIT once the logged sample spans multiple regimes and enough symbols that a symbol-blocked permutation has real power.

human directive, 2026-09-06 (assess options levels; then log them observationally); supersedes nothing, complements struck R23

R53 [active] EOD flatten must survive a broker blip and must never fail silently

LIVE 2026-09-03. The R24 close-out silently failed on three consecutive sessions (2026-08-31, 09-01, 09-02): zero flatten-exit events, 17 positions accumulated overnight across days, last good flatten 2026-08-28. THE CLOSE-OUT CODE WAS CORRECT; its dependency failed. account_state() is the first statement inside the `mins >= EOD_FLATTEN_ET` branch, so a transient OpenD outage raises past the whole flatten. Evidence: on 09-01 and 09-02 the final cycle is at 14:40:5x, followed by repeating LOOP-CRASH 'OpenD is not reachable' until 'market day over - exiting'; the last working day (08-28) had 80 cycles inside the 14:41-15:05 window versus ZERO on the failing days. FIX 1: the crash backoff was a flat 300s, but the flatten window is only 24 minutes (15:41->16:05 ET), so each backoff burned a fifth of it - 4 attempts where 72 were possible, all landing while OpenD was still down. loop_error_backoff_seconds(mins) now returns 20s inside the window and keeps 300s during the session, where a crash loop must not hammer the broker. FIX 2: the daemon exited announcing only 'market day over', making an unflattened book indistinguishable from a clean one - which is why this ran three days unnoticed. Shutdown now logs CRITICAL-eod-flatten-incomplete with the open codes plus openPositionsAtExit on the stopped event, wrapped so an unreachable broker can never block the exit. STILL OPEN: OpenD itself has no monitor, watchdog or auto-restart. R49 watches the daemon; nothing watches the gateway the daemon cannot function without, and every failure this week traces to it.

human directive, 2026-09-03 ('trades aren't closing out'); write-up in internal notes

RETIRED RULES (8) — the tombstones stay public

R2 [struck] Dollar-risk cap per trade (REMOVED)

REMOVED 2026-07-23 by human directive. The former percentage-of-equity dollar-risk formula no longer sizes positions. R32's later flat-$100 cap was also removed 2026-08-07, so stop distance no longer changes quantity. R21/R28 notional limits, R38 heat, R40 daily deployment, and structural stops remain live. Kept listed so neither retired formula is reintroduced blind.

framework design 2026-07-07; raised 2%→3% 2026-07-13; removed 2026-07-23; R32 distinction synchronized 2026-07-29

R5 [struck] No entries in the first 5 minutes (REMOVED)

REMOVED 2026-07-23 by human directive. There is no system-wide opening delay; each strategy's own trigger/confirmation requirements still apply. R31 (added 2026-07-24) separately gates the first 15 minutes for its own strategy roster (score90, score80, gap-go, rumor-momo, inst-continuation). Kept listed per R18 so a blanket opening-delay is never re-implemented blind.

prior 2026-07-07; removed 2026-07-23

R8 [struck] Re-entry limit (STRUCK)

STRUCK ENTIRELY 2026-07-13 (human directive: "allow stocks to be bought and sold many times throughout the day, do not restrict the number of times you can buy and sell a stock"). Originally: one re-entry per name per day; amended 2026-07-09 to two stop-outs per name per day. No per-symbol daily limit on entries or stop-outs exists anymore. The remaining re-entry gates are: the signal must re-qualify fresh, a pending-order skip in the entry-guard, and R2/R21 sizing. Kept listed per R18 so it is never re-implemented blind.

prior 2026-07-07; struck 2026-07-13

R20 [struck] Activity expectation / daily trade cap (STRUCK)

STRUCK 2026-07-13 (human directive: "no restrictions on number of trades per strategy a day"). Originally allowed up to 5 trades per strategy per day. No daily trade cap exists anymore, per strategy or otherwise. Hard limits that still bind: R21 notional cap, R32 flat-$100 max-loss cap, flat by the close. Kept listed per R18 with a revert path if unlimited volume produces churn losses.

human directive 2026-07-10; struck 2026-07-13

R23 [struck] Options-wall awareness (REMOVED)

REMOVED 2026-07-30 by human directive. The target-cap/no-entry-into-wall/pin-caution/wall-break-trail gates that once ran in stop_guard.py's guarded_entry() (r23_entry_plan()) are gone; entries no longer adjust for options walls at all. The underlying wall/pin summary (scripts/options_walls.mjs, stamped onto watchlist rows by build_watchlist.mjs) is kept and still displayed on the dashboard for a session's own judgment -- only the automated enforcement was removed. R31's time/PM gate reused this rule's strategy roster (score90, score80, gap-go, rumor-momo, inst-continuation) for an unrelated reason; that roster now lives independently as stop_guard.R31_STRATEGIES. Kept listed per R18 so a target-capping rule is never re-implemented blind without re-establishing the evidence this one had.

human-approved 2026-07-11; TESTING, first scored 2026-07-17 rollup; removed 2026-07-30

R26 [consolidated] Duplicate finding, consolidated into R24

A capable-model session wrote this independently the same day as R24, before knowing the R24 fix already existed — same VG 2026-07-13 incident, same root cause, same prescribed fix. No longer deferred: R24 documents the applied, tested, live fix. See R24 for the current, authoritative rule and fix details. Kept listed per R18 as a genuine independent discovery, not a mistaken rule.

same incident as R24, 2026-07-13

R32 [removed] REMOVED 2026-08-07 -- flat $100 max loss per trade

RETIRED by human directive ('allow the app to do whatever sizing it thinks makes sense'). R32 was the binding cap on the large majority of setups, so leaving it in would have made the new 10% per-name ceiling unreachable and the directive a no-op. WHAT THIS GIVES UP: a single trade's loss is no longer bounded by a flat dollar figure, and position size no longer varies with stop distance AT ALL -- R32 was the only cap that read the stop, so a 3%-wide stop now produces the same quantity as a 1%-wide one and therefore three times the loss. What still bounds a position: R21 (10% per name) and, across positions, R38's aggregate heat cap -- which is exactly why R38 was KEPT when R32 was dropped. sizing.risk_capped_qty() survives only so blocked_trade_analysis.py can recompute historical refusals from the permanent action log. Removal decision, evidence and downside analysis: [internal note]

human directive, 2026-07-28 ("add a rule that the max loss of $100 allowed"); opening-bell propagation auto-applied 2026-07-30. RETIRED 2026-08-07 by human directive; removal write-up cited in the rule text above.

R36 [removed] REMOVED 2026-08-07 -- quarter/half-Kelly position-size ceiling

RETIRED by human directive ('remove R36 and all of kelly'). Replaced by R44. The failure was structural, not mathematical: a fraction derived from a strategy's own history is a confirmed ZERO for exactly the strategies with a losing record, which sized them to zero shares, which made their R18 retest budget unspendable, which required close_deadlocked_retests() to exist purely to break the resulting deadlock, which in turn produced permanent retirements on budgets that could never be spent (kronos-momentum, rsi-dip, 2026-08-06/07). Every Kelly function, the HALF_KELLY_* gate set, HALF_KELLY_ENABLED, and close_deadlocked_retests() were deleted together. Kept as a tombstone per R18: never re-implement blind. Removal write-up: [internal note]; same-day sizing-directive context in [internal note]

human directive, 2026-08-01; rollout documentation completed by recurring Codex action-log repair session, 2026-08-01; original Kelly criterion: https://doi.org/10.1002/j.1538-7305.1956.tb03809.x; fractional/drawdown context: https://stanford.edu/~boyd/papers/kelly.html. RETIRED 2026-08-07 by human directive; removal write-up cited in the rule text above.

STRATEGY ROSTER (25)

idstrategystatus
st-flipSuperTrend FlipTESTING
squeeze-popSqueeze MomentumTESTING
ut-botUT Bot AlertsTESTING
vwap-bounceVWAP BounceTESTING (reactivated 2026-07-16 with live reclaim gate + half risk)
orb-retestOpening Range Breakout RetestTESTING
ema-stackEMA StackTESTING
macd-stMACD + SuperTrendTESTING
rsi-dipRSI-2 DipTESTING
wavetrendWaveTrendTESTING
pdh-breakPrev-Day-High BreakTESTING
3bar-rev3-Bar ReversalTESTING
fib-pocketGolden Pocket / Fib RetraceTESTING
gap-goGap & GoACTIVE
adx-diADX + DI CrossTESTING
chandelierChandelier Exit (exit overlay)TESTING
pm-breakOpening-Bell PMH BreakTESTING
tj-pmhThomas James PMH ReclaimTESTING
lux-smcSmart Money Concepts (LuxAlgo proxy)TESTING
vixfixCM Williams Vix FixTESTING
watchlist-momoWatchlist MomentumACTIVE
or-breakOpening Range Break (legacy)TESTING (reactivated 2026-07-16; separately journaled for R18 comparison)
inst-continuationInstitutional ContinuationTESTING
score80Score ≥80 Conviction (Tier 2)TESTING
score90Score ≥90 Conviction (Tier 1, first 30 min only)TESTING
rumor-momoRumor MomentumTESTING

CHANGELOG