CWM (103): core mechanics, exhaustive edge cases, numba, exchange mechanics Replay (118): exhaustive verification, microstructure, trajectory Training (190): asset classification, phase0 extensive, pipeline, exhaustive DSL (102): v2 syntax, expanded, new features ASEx (33): validate-before-mutate, single-writer Planner (48): MCTS, alternatives, hooks Counterparties (19): 9 adversarial agent policies Clock (30): event-driven reactor BingX (28): venue adapter IPC (8): Zinc SHM Storage (9): ClickHouse Risk (4): hard invariants State (17): frozen dataclass invariants Integration: E2E, concurrency, sync/async seams, hypothesis, fuzz, adversarial
81 lines
2.5 KiB
Python
81 lines
2.5 KiB
Python
"""
|
|
ClickHouse persistence — store, retrieve, table creation.
|
|
"""
|
|
import json
|
|
import time
|
|
import pytest
|
|
from malkhut.storage.ch_store import MalkhutCHStore
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def store():
|
|
s = MalkhutCHStore()
|
|
s.ensure_tables()
|
|
return s
|
|
|
|
|
|
class TestClickHouseTables:
|
|
def test_tables_exist(self, store):
|
|
result = store.query("SHOW TABLES")
|
|
tables = result.strip().split("\n")
|
|
assert "replay_steps" in tables
|
|
assert "fulfilment_decisions" in tables
|
|
assert "self_play_episodes" in tables
|
|
assert "policy_snapshots" in tables
|
|
assert "live_discrepancies" in tables
|
|
|
|
def test_table_idempotent(self, store):
|
|
store.ensure_tables()
|
|
store.ensure_tables()
|
|
result = store.query("SHOW TABLES")
|
|
assert "replay_steps" in result
|
|
|
|
|
|
class TestClickHouseInsert:
|
|
def test_store_fulfilment_decision(self, store):
|
|
store.store_fulfilment_decision(
|
|
ts_ns=time.time_ns(), exchange="bingx", symbol="BTCUSDT",
|
|
intent_id="test_intent", state_hash="abc123",
|
|
selected_action="PLACE", root_distribution="[0.5, 0.5]",
|
|
risk_decision="True:approved", policy_version="v0.1",
|
|
latency_ms=5.0,
|
|
)
|
|
|
|
def test_store_episode(self, store):
|
|
store.store_episode(
|
|
policy_version="v0.1", scenario_id="test_scenario",
|
|
seed=42, pnl_bps=10.0, max_drawdown_bps=-5.0,
|
|
fill_ratio=0.8, adverse_fill_ratio=0.1,
|
|
avg_slippage_bps=1.5, liq_near_misses=0,
|
|
cancel_count=3, diagnostics="{}",
|
|
)
|
|
|
|
def test_store_policy_snapshot(self, store):
|
|
store.store_policy_snapshot(
|
|
version="v0.1_test", score=5.0,
|
|
params_str="test_params", evaluation_summary="{}",
|
|
)
|
|
|
|
def test_store_discrepancy(self, store):
|
|
store.store_discrepancy(
|
|
ts_ns=time.time_ns(), exchange="bingx", symbol="BTCUSDT",
|
|
predicted="PLACE", actual="FILL", severity="warning",
|
|
)
|
|
|
|
def test_store_replay_step(self, store):
|
|
store.store_replay_step(
|
|
symbol="BTCUSDT", ts_ns=time.time_ns(), step_index=0,
|
|
before="{}", action="{}", after="{}",
|
|
)
|
|
|
|
|
|
class TestClickHouseQuery:
|
|
def test_query_returns_string(self, store):
|
|
result = store.query("SELECT 1")
|
|
assert result.strip() == "1"
|
|
|
|
def test_query_with_format(self, store):
|
|
result = store.query("SELECT 1 AS val FORMAT JSONEachRow")
|
|
row = json.loads(result.strip())
|
|
assert row["val"] == 1
|