106 lines
1.8 KiB
Python
106 lines
1.8 KiB
Python
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass, field
|
|
from typing import Any, Dict, List
|
|
|
|
|
|
@dataclass
|
|
class LocalEvent:
|
|
id: str
|
|
instrument: str
|
|
timestamp: float
|
|
data: Dict[str, Any] = field(default_factory=dict)
|
|
|
|
|
|
@dataclass
|
|
class SharedSignal:
|
|
id: str
|
|
signal_type: str
|
|
timestamp: float
|
|
value: Any
|
|
|
|
|
|
@dataclass
|
|
class PlanDelta:
|
|
id: str
|
|
decision: str
|
|
timestamp: float
|
|
latency_budget_ms: int = 0
|
|
|
|
|
|
@dataclass
|
|
class OrderEvent:
|
|
id: str
|
|
order_id: str
|
|
side: str
|
|
qty: int
|
|
price: float
|
|
timestamp: float
|
|
|
|
|
|
@dataclass
|
|
class FillEvent:
|
|
id: str
|
|
order_id: str
|
|
qty: int
|
|
price: float
|
|
timestamp: float
|
|
|
|
|
|
@dataclass
|
|
class RiskCheck:
|
|
id: str
|
|
check_name: str
|
|
result: bool
|
|
timestamp: float
|
|
|
|
|
|
@dataclass
|
|
class AuditLog:
|
|
id: str
|
|
entry: str
|
|
timestamp: float
|
|
signature: str # placeholder for crypto-signed payload
|
|
|
|
|
|
@dataclass
|
|
class PrivacyBudget:
|
|
id: str
|
|
venue: str
|
|
budget: float
|
|
consumed: float = 0.0
|
|
|
|
|
|
@dataclass
|
|
class Edge:
|
|
src: str
|
|
dst: str
|
|
label: str
|
|
|
|
|
|
@dataclass
|
|
class TraceGraph:
|
|
nodes: List[str] = field(default_factory=list)
|
|
edges: List[Edge] = field(default_factory=list)
|
|
|
|
def add_node(self, node_id: str) -> None:
|
|
if node_id not in self.nodes:
|
|
self.nodes.append(node_id)
|
|
|
|
def add_edge(self, src: str, dst: str, label: str) -> None:
|
|
self.edges.append(Edge(src=src, dst=dst, label=label))
|
|
|
|
|
|
def build_graph_from_events(events: List[Dict[str, Any]]) -> TraceGraph:
|
|
graph = TraceGraph()
|
|
for e in events:
|
|
nid = e.get("id")
|
|
if not nid:
|
|
continue
|
|
graph.add_node(nid)
|
|
parent = e.get("parent_id")
|
|
if parent:
|
|
graph.add_node(parent)
|
|
graph.add_edge(parent, nid, e.get("type", "child"))
|
|
return graph
|