VIOLET V3.1: BLUE stablecoin exclusion (parity fix)

Soak surfaced USDCUSDT being shorted. BLUE has a hardcoded exclusion gate around
its (muted-IRP) picking: _STABLECOIN_SYMBOLS removed from prices_dict pre-select
(nautilus_event_trader.py:24/3906). Replicate exactly: VioletDecisionEngine skips
the same 10 symbols in observe() so IRP never sees them. Following BLUE in all
regards (picking unchanged; this is BLUE's separate gate). Set-equality drift
guard vs BLUE source + never-selected test. 11 tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Codex
2026-06-14 21:51:09 +02:00
parent 02ecc55c16
commit a168d0bee5
2 changed files with 45 additions and 1 deletions

View File

@@ -31,6 +31,17 @@ from .cadence import Action, CadenceControlPlane
from .domain import StrictModel, Symbol, typed
# Stablecoins / pegged assets that must NEVER be selected as a trade asset.
# MUST equal nautilus_event_trader.py:_STABLECOIN_SYMBOLS (BLUE removes these from
# prices_dict before selection, :3906) — asserted by test_violet_decision_engine.
# Following BLUE in all regards: picking stays muted-IRP as BLUE, this is BLUE's
# separate exclusion gate around it.
STABLECOIN_SYMBOLS = frozenset({
"USDCUSDT", "BUSDUSDT", "FDUSDUSDT", "USDTUSDT", "TUSDUSDT",
"DAIUSDT", "FRAXUSDT", "USDDUSDT", "USTCUSDT", "EURUSDT",
})
class ShadowDecision(StrictModel):
"""One muted decision — what BLUE *would* do this scan. Never executed."""
@@ -107,6 +118,8 @@ class VioletDecisionEngine:
if px <= 0:
continue
sym = str(asset).upper()
if sym in STABLECOIN_SYMBOLS: # BLUE :3906 — never a trade asset
continue
hist = self._history.get(sym)
if hist is None:
hist = deque(maxlen=maxlen)