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:
@@ -8,8 +8,13 @@ sys.path.insert(0, "/mnt/dolphinng5_predict")
|
||||
|
||||
import pytest
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
from prod.clean_arch.violet.cadence import Action, CadenceControlPlane, INSTA_Q_NS, SCAN_Q_NS
|
||||
from prod.clean_arch.violet.decision_engine import ShadowDecision, VioletDecisionEngine
|
||||
from prod.clean_arch.violet.decision_engine import (
|
||||
STABLECOIN_SYMBOLS, ShadowDecision, VioletDecisionEngine,
|
||||
)
|
||||
|
||||
LOOKBACK = 5
|
||||
|
||||
@@ -101,6 +106,32 @@ def test_engine_holds_no_venue_or_kernel():
|
||||
assert not hasattr(e, attr)
|
||||
|
||||
|
||||
def test_stablecoin_set_matches_blue_exactly():
|
||||
# Drift guard: VIOLET's exclusion set MUST equal BLUE's _STABLECOIN_SYMBOLS
|
||||
# (nautilus_event_trader.py), parsed from source (no heavy import).
|
||||
src = Path("/mnt/dolphinng5_predict/prod/nautilus_event_trader.py").read_text()
|
||||
m = re.search(r"_STABLECOIN_SYMBOLS\s*=\s*frozenset\(\{(.*?)\}\)", src, re.DOTALL)
|
||||
assert m is not None
|
||||
blue = set(re.findall(r"'([A-Z0-9]+)'", m.group(1)))
|
||||
assert STABLECOIN_SYMBOLS == blue
|
||||
|
||||
|
||||
def test_stablecoin_never_selected():
|
||||
# Even with a strong short signal, a stablecoin must never be picked (BLUE :3906).
|
||||
e = _engine()
|
||||
assets = ["USDCUSDT", "BBBUSDT", "CCCUSDT"]
|
||||
for s in range(8):
|
||||
# USDC trends down hardest (would rank top by IRP if not excluded)
|
||||
prices = [100.0 * (1 - 0.01 * s), 100.0 * (1 - 0.001 * s), 100.0 * (1 - 0.0005 * s)]
|
||||
e.observe({"assets": assets, "asset_prices": prices}, scan_number=s + 1)
|
||||
assert "USDCUSDT" not in e._history # never accumulated
|
||||
for k in range(3):
|
||||
d = e.decide(now_ns=10**12 + k * SCAN_Q_NS, scan_number=20 + k,
|
||||
capital=69_000.0, vel_div=-0.20)
|
||||
if d is not None:
|
||||
assert d.asset != "USDCUSDT"
|
||||
|
||||
|
||||
def test_determinism_same_inputs_same_decision():
|
||||
e1, e2 = _engine(), _engine()
|
||||
_warm(e1); _warm(e2)
|
||||
|
||||
Reference in New Issue
Block a user