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:
32
prod/clean_arch/sim/__init__.py
Normal file
32
prod/clean_arch/sim/__init__.py
Normal file
@@ -0,0 +1,32 @@
|
||||
"""Mock stack and simulator for policy-level testing."""
|
||||
|
||||
from .fuzzer import FuzzConfig, FuzzReport, fuzz_stack, generate_snapshot_stream
|
||||
from .mock_stack import (
|
||||
ChaosProfile,
|
||||
MockClickHouse,
|
||||
MockExchange,
|
||||
MockHazelcast,
|
||||
MockLogSink,
|
||||
MockNetwork,
|
||||
MockTradingStack,
|
||||
SimulationResult,
|
||||
AnomalySensorState,
|
||||
NetworkProfile,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"FuzzConfig",
|
||||
"FuzzReport",
|
||||
"ChaosProfile",
|
||||
"MockClickHouse",
|
||||
"MockExchange",
|
||||
"MockHazelcast",
|
||||
"MockLogSink",
|
||||
"MockNetwork",
|
||||
"MockTradingStack",
|
||||
"SimulationResult",
|
||||
"AnomalySensorState",
|
||||
"NetworkProfile",
|
||||
"fuzz_stack",
|
||||
"generate_snapshot_stream",
|
||||
]
|
||||
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,
|
||||
)
|
||||
1127
prod/clean_arch/sim/mock_stack.py
Normal file
1127
prod/clean_arch/sim/mock_stack.py
Normal file
File diff suppressed because it is too large
Load Diff
74
prod/clean_arch/sim/run.py
Normal file
74
prod/clean_arch/sim/run.py
Normal file
@@ -0,0 +1,74 @@
|
||||
#!/usr/bin/env python3
|
||||
"""CLI for large-scale policy simulation and fuzzing."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
|
||||
from prod.clean_arch.sim.fuzzer import FuzzConfig, fuzz_stack
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description="Run clean-arch policy simulation/fuzzing.")
|
||||
parser.add_argument("--transactions", type=int, default=1_000_000)
|
||||
parser.add_argument("--seed", type=int, default=42)
|
||||
parser.add_argument("--bad-input-rate", type=float, default=0.01)
|
||||
parser.add_argument("--network-drop-rate", type=float, default=0.001)
|
||||
parser.add_argument("--network-duplicate-rate", type=float, default=0.001)
|
||||
parser.add_argument("--price-sigma", type=float, default=0.015)
|
||||
parser.add_argument("--capture-limit", type=int, default=2_000)
|
||||
parser.add_argument("--runtime-namespace", type=str, default="pink")
|
||||
parser.add_argument("--anomaly-sensor-key", type=str, default="")
|
||||
parser.add_argument("--mirror-legacy-sensor-key", action="store_true")
|
||||
parser.add_argument("--aggressive", action="store_true", help="Enable aggressive chaos/anomaly injection")
|
||||
parser.add_argument("--json", action="store_true", help="Emit JSON summary")
|
||||
args = parser.parse_args()
|
||||
|
||||
report = fuzz_stack(
|
||||
FuzzConfig(
|
||||
transactions=args.transactions,
|
||||
seed=args.seed,
|
||||
bad_input_rate=args.bad_input_rate,
|
||||
network_drop_rate=args.network_drop_rate,
|
||||
network_duplicate_rate=args.network_duplicate_rate,
|
||||
price_sigma=args.price_sigma,
|
||||
capture_limit=args.capture_limit,
|
||||
aggressive=args.aggressive,
|
||||
runtime_namespace=args.runtime_namespace,
|
||||
anomaly_sensor_key=(args.anomaly_sensor_key.strip() or None),
|
||||
mirror_legacy_sensor_key=args.mirror_legacy_sensor_key,
|
||||
)
|
||||
)
|
||||
|
||||
payload = {
|
||||
"transactions": report.transactions,
|
||||
"capital_final": report.capital_final,
|
||||
"equity_final": report.equity_final,
|
||||
"open_notional_final": report.open_notional_final,
|
||||
"policy_events": report.policy_events,
|
||||
"trade_events": report.trade_events,
|
||||
"account_events": report.account_events,
|
||||
"logs_emitted": report.logs_emitted,
|
||||
"network_dropped": report.network_dropped,
|
||||
"network_duplicated": report.network_duplicated,
|
||||
"anomaly_counts": report.anomaly_counts,
|
||||
"anomaly_origin_counts": report.anomaly_origin_counts,
|
||||
"injected_anomaly_counts": report.injected_anomaly_counts,
|
||||
"emergent_anomaly_counts": report.emergent_anomaly_counts,
|
||||
"anomaly_sensor_payload": report.anomaly_sensor_payload,
|
||||
"anomaly_samples": report.anomaly_samples,
|
||||
"sample_policy_events": report.sample_policy_events,
|
||||
}
|
||||
if args.json:
|
||||
print(json.dumps(payload, indent=2, sort_keys=True))
|
||||
else:
|
||||
print("Clean-arch policy simulation complete")
|
||||
for k, v in payload.items():
|
||||
if k != "sample_policy_events":
|
||||
print(f"{k}: {v}")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user