repo hygiene: track the PINK launcher import closure
67 production .py modules that the running PINK service imports but which were never committed: prod/bingx/ (HTTP client, market/user streams, journal, config), prod/clean_arch/ adapters/persistence/runtime/dita/dita_v2 production modules and their co-located tests. Rule going forward: every module imported by launch_dolphin_pink.py / pink_direct.py must appear in git ls-files. Excludes _backup dirs, __pycache__, and non-code files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
202
prod/clean_arch/sim/fuzzer.py
Normal file
202
prod/clean_arch/sim/fuzzer.py
Normal file
@@ -0,0 +1,202 @@
|
||||
"""Fuzz generation for the mock stack."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime, timedelta, timezone
|
||||
import math
|
||||
import random
|
||||
from typing import Iterable, Iterator, List, Optional
|
||||
|
||||
from prod.clean_arch.ports.data_feed import MarketSnapshot
|
||||
from prod.clean_arch.dita import DecisionConfig, DecisionEngine, IntentEngine, DitaObservabilityNamespace
|
||||
|
||||
from .mock_stack import ChaosProfile, MockClickHouse, MockHazelcast, MockLogSink, MockNetwork, MockTradingStack, NetworkProfile
|
||||
|
||||
|
||||
DEFAULT_SYMBOLS = (
|
||||
"BTCUSDT",
|
||||
"ETHUSDT",
|
||||
"BNBUSDT",
|
||||
"SOLUSDT",
|
||||
"XRPUSDT",
|
||||
"ADAUSDT",
|
||||
"DOGEUSDT",
|
||||
"TRXUSDT",
|
||||
)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class FuzzConfig:
|
||||
"""High-volume fuzz config."""
|
||||
|
||||
transactions: int = 1_000_000
|
||||
seed: int = 42
|
||||
bad_input_rate: float = 0.01
|
||||
network_drop_rate: float = 0.001
|
||||
network_duplicate_rate: float = 0.001
|
||||
price_sigma: float = 0.015
|
||||
symbol_pool: tuple[str, ...] = DEFAULT_SYMBOLS
|
||||
capture_limit: int = 2_000
|
||||
aggressive: bool = False
|
||||
hang_entry_rate: float = 0.0
|
||||
hang_exit_rate: float = 0.0
|
||||
stale_account_rate: float = 0.0
|
||||
duplicate_terminal_rate: float = 0.0
|
||||
missing_terminal_rate: float = 0.0
|
||||
orphan_close_rate: float = 0.0
|
||||
reorder_account_rate: float = 0.0
|
||||
runtime_namespace: str = "pink"
|
||||
anomaly_sensor_key: str | None = None
|
||||
mirror_legacy_sensor_key: bool = False
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class FuzzReport:
|
||||
"""Summary of a fuzz run."""
|
||||
|
||||
transactions: int
|
||||
capital_final: float
|
||||
equity_final: float
|
||||
open_notional_final: float
|
||||
policy_events: int
|
||||
trade_events: int
|
||||
account_events: int
|
||||
logs_emitted: int
|
||||
network_dropped: int
|
||||
network_duplicated: int
|
||||
anomaly_counts: dict
|
||||
anomaly_origin_counts: dict
|
||||
injected_anomaly_counts: dict
|
||||
emergent_anomaly_counts: dict
|
||||
anomaly_sensor_payload: dict
|
||||
anomaly_samples: List[dict]
|
||||
sample_policy_events: List[dict]
|
||||
|
||||
|
||||
def generate_snapshot_stream(cfg: FuzzConfig) -> Iterator[MarketSnapshot]:
|
||||
"""Stream randomized snapshots with occasional poison inputs."""
|
||||
rng = random.Random(cfg.seed)
|
||||
price_map = {sym: 100.0 + 25.0 * i for i, sym in enumerate(cfg.symbol_pool)}
|
||||
ts = datetime.now(timezone.utc)
|
||||
|
||||
for i in range(cfg.transactions):
|
||||
symbol = rng.choice(cfg.symbol_pool)
|
||||
base = price_map[symbol]
|
||||
drift = rng.gauss(0.0, cfg.price_sigma)
|
||||
price = max(0.01, base * (1.0 + drift))
|
||||
price_map[symbol] = price
|
||||
|
||||
vdiv = rng.uniform(-0.2, 0.1)
|
||||
irp = rng.uniform(-1.0, 1.0)
|
||||
eigenvalues = [1.0, 0.9, 0.8]
|
||||
|
||||
if rng.random() < cfg.bad_input_rate:
|
||||
poison = rng.choice(["nan", "inf", "-inf", "zero", "none", "unicode"])
|
||||
if poison == "nan":
|
||||
price = float("nan")
|
||||
elif poison == "inf":
|
||||
price = float("inf")
|
||||
elif poison == "-inf":
|
||||
price = float("-inf")
|
||||
elif poison == "zero":
|
||||
price = 0.0
|
||||
elif poison == "none":
|
||||
vdiv = None # type: ignore[assignment]
|
||||
elif poison == "unicode":
|
||||
symbol = symbol + "🐬"
|
||||
|
||||
yield MarketSnapshot(
|
||||
timestamp=ts + timedelta(milliseconds=i),
|
||||
symbol=symbol,
|
||||
price=price,
|
||||
bid=price * 0.9995 if math.isfinite(price) else price,
|
||||
ask=price * 1.0005 if math.isfinite(price) else price,
|
||||
eigenvalues=eigenvalues,
|
||||
eigenvectors=None,
|
||||
velocity_divergence=vdiv,
|
||||
irp_alignment=irp,
|
||||
scan_number=i,
|
||||
source="fuzz",
|
||||
)
|
||||
|
||||
|
||||
def fuzz_stack(cfg: Optional[FuzzConfig] = None) -> FuzzReport:
|
||||
"""Run the full mocked stack against fuzzed market snapshots."""
|
||||
cfg = cfg or FuzzConfig()
|
||||
if cfg.aggressive:
|
||||
cfg = FuzzConfig(
|
||||
transactions=cfg.transactions,
|
||||
seed=cfg.seed,
|
||||
bad_input_rate=max(cfg.bad_input_rate, 0.08),
|
||||
network_drop_rate=max(cfg.network_drop_rate, 0.03),
|
||||
network_duplicate_rate=max(cfg.network_duplicate_rate, 0.03),
|
||||
price_sigma=max(cfg.price_sigma, 0.05),
|
||||
symbol_pool=cfg.symbol_pool,
|
||||
capture_limit=cfg.capture_limit,
|
||||
aggressive=cfg.aggressive,
|
||||
hang_entry_rate=max(cfg.hang_entry_rate, 0.01),
|
||||
hang_exit_rate=max(cfg.hang_exit_rate, 0.03),
|
||||
stale_account_rate=max(cfg.stale_account_rate, 0.03),
|
||||
duplicate_terminal_rate=max(cfg.duplicate_terminal_rate, 0.03),
|
||||
missing_terminal_rate=max(cfg.missing_terminal_rate, 0.015),
|
||||
orphan_close_rate=max(cfg.orphan_close_rate, 0.015),
|
||||
reorder_account_rate=max(cfg.reorder_account_rate, 0.02),
|
||||
)
|
||||
policy = DecisionEngine(DecisionConfig())
|
||||
intent = IntentEngine(DecisionConfig())
|
||||
stack = MockTradingStack(
|
||||
decision_engine=policy,
|
||||
intent_engine=intent,
|
||||
capital=25_000.0,
|
||||
runtime_namespace=cfg.runtime_namespace,
|
||||
strategy_namespace=cfg.runtime_namespace,
|
||||
event_namespace=cfg.runtime_namespace,
|
||||
observability=DitaObservabilityNamespace(
|
||||
runtime_namespace=cfg.runtime_namespace,
|
||||
anomaly_sensor_key=cfg.anomaly_sensor_key,
|
||||
mirror_legacy_key=cfg.mirror_legacy_sensor_key,
|
||||
state_map=f"DOLPHIN_STATE_{cfg.runtime_namespace.upper()}" if cfg.runtime_namespace.lower() != "pink" else "DOLPHIN_STATE_PINK",
|
||||
),
|
||||
network=MockNetwork(
|
||||
NetworkProfile(
|
||||
drop_rate=cfg.network_drop_rate,
|
||||
duplicate_rate=cfg.network_duplicate_rate,
|
||||
),
|
||||
seed=cfg.seed,
|
||||
),
|
||||
hazelcast=MockHazelcast(),
|
||||
clickhouse=MockClickHouse(capture_limit=cfg.capture_limit),
|
||||
logs=MockLogSink(capture_limit=cfg.capture_limit),
|
||||
chaos=ChaosProfile(
|
||||
hang_entry_rate=cfg.hang_entry_rate,
|
||||
hang_exit_rate=cfg.hang_exit_rate,
|
||||
stale_account_rate=cfg.stale_account_rate,
|
||||
duplicate_terminal_rate=cfg.duplicate_terminal_rate,
|
||||
missing_terminal_rate=cfg.missing_terminal_rate,
|
||||
orphan_close_rate=cfg.orphan_close_rate,
|
||||
reorder_account_rate=cfg.reorder_account_rate,
|
||||
),
|
||||
)
|
||||
for snapshot in generate_snapshot_stream(cfg):
|
||||
stack.step(snapshot)
|
||||
result = stack.summary(cfg.transactions)
|
||||
return FuzzReport(
|
||||
transactions=result.steps,
|
||||
capital_final=result.capital_final,
|
||||
equity_final=result.equity_final,
|
||||
open_notional_final=result.open_notional_final,
|
||||
policy_events=result.decision_events,
|
||||
trade_events=result.trade_events,
|
||||
account_events=result.account_events,
|
||||
logs_emitted=result.logs_emitted,
|
||||
network_dropped=result.network_dropped,
|
||||
network_duplicated=result.network_duplicated,
|
||||
anomaly_counts=result.anomaly_counts,
|
||||
anomaly_origin_counts=result.anomaly_origin_counts,
|
||||
injected_anomaly_counts=result.injected_anomaly_counts,
|
||||
emergent_anomaly_counts=result.emergent_anomaly_counts,
|
||||
anomaly_sensor_payload=result.anomaly_sensor_payload,
|
||||
anomaly_samples=result.anomaly_samples,
|
||||
sample_policy_events=result.sample_policy_events,
|
||||
)
|
||||
Reference in New Issue
Block a user