malkhut(T4): Strategy DSL v2 + generator + supporting modules
Strategy DSL v2 (dsl.py): 40+ action primitives, 40+ market sensors, 12 comparison operators, 16 builtins, full parser. Strategy Generator (generator.py): genetic programming evolution — crossover, mutation, tournament selection, pool management. Supporting: discrepancy tracking, execution quality, hooks, feature importance, observability, parallel eval, auto-rollback, stress testing, structured observations, trajectory recording.
This commit is contained in:
100
MALKHUT/malkhut/training/observability.py
Normal file
100
MALKHUT/malkhut/training/observability.py
Normal file
@@ -0,0 +1,100 @@
|
||||
"""
|
||||
Structured Observability — compact JSONL logging for every decision.
|
||||
|
||||
Records:
|
||||
- Every planner decision with features and diagnostics
|
||||
- Every risk gate decision
|
||||
- Every venue action
|
||||
- Every fill/discrepancy
|
||||
- Replayable audit trail
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import time
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Any, Dict, List, Mapping, Optional
|
||||
|
||||
from malkhut.state import MarketWorldState
|
||||
from malkhut.actions import FulfilmentAction, PlannedPolicy, RiskDecision
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class DecisionRecord:
|
||||
"""One decision in the audit trail."""
|
||||
ts_ns: int
|
||||
symbol: str
|
||||
action_kind: str
|
||||
action_side: Optional[str]
|
||||
action_price: Optional[float]
|
||||
approved: bool
|
||||
risk_reason: str
|
||||
plan_latency_ns: int
|
||||
policy_version: str
|
||||
root_entropy: float
|
||||
sims: int
|
||||
features: Mapping[str, float] = field(default_factory=dict)
|
||||
diagnostics: Mapping[str, Any] = field(default_factory=dict)
|
||||
|
||||
|
||||
class ObservabilityLogger:
|
||||
"""
|
||||
Compact JSONL logger for every decision.
|
||||
|
||||
One line per decision. Replayable audit trail.
|
||||
"""
|
||||
|
||||
def __init__(self, log_path: str = "decisions.log") -> None:
|
||||
self._log_path = log_path
|
||||
self._decisions: list[DecisionRecord] = []
|
||||
self._total_decisions = 0
|
||||
|
||||
def log_decision(
|
||||
self,
|
||||
state: MarketWorldState,
|
||||
planned: PlannedPolicy,
|
||||
decision: RiskDecision,
|
||||
plan_ns: int,
|
||||
features: Optional[Mapping[str, float]] = None,
|
||||
) -> None:
|
||||
"""Log a decision to the audit trail."""
|
||||
record = DecisionRecord(
|
||||
ts_ns=state.ts_ns,
|
||||
symbol=state.venue.symbol,
|
||||
action_kind=planned.selected_action.kind.value,
|
||||
action_side=planned.selected_action.side.value if planned.selected_action.side else None,
|
||||
action_price=planned.selected_action.price_ticks_from_best if planned.selected_action else None,
|
||||
approved=decision.approved,
|
||||
risk_reason=decision.reason,
|
||||
plan_latency_ns=plan_ns,
|
||||
policy_version="live",
|
||||
root_entropy=planned.diagnostics.get("entropy", 0.0),
|
||||
sims=planned.diagnostics.get("sims", 0),
|
||||
features=features or {},
|
||||
)
|
||||
self._decisions.append(record)
|
||||
self._total_decisions += 1
|
||||
|
||||
# Write to JSONL
|
||||
try:
|
||||
with open(self._log_path, "a") as f:
|
||||
f.write(json.dumps({
|
||||
"ts": record.ts_ns,
|
||||
"sym": record.symbol,
|
||||
"act": record.action_kind,
|
||||
"side": record.action_side,
|
||||
"app": record.approved,
|
||||
"risk": record.risk_reason,
|
||||
"lat_ns": record.plan_latency_ns,
|
||||
"entropy": round(record.root_entropy, 4),
|
||||
"sims": record.sims,
|
||||
}, separators=(",", ":")) + "\n")
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
@property
|
||||
def total_decisions(self) -> int:
|
||||
return self._total_decisions
|
||||
|
||||
def get_recent(self, n: int = 10) -> List[DecisionRecord]:
|
||||
return self._decisions[-n:]
|
||||
Reference in New Issue
Block a user