57 lines
1.4 KiB
Python
57 lines
1.4 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Any, Dict, List
|
|
from datetime import datetime, timezone
|
|
import threading
|
|
|
|
|
|
class DecisionStore:
|
|
def __init__(self) -> None:
|
|
self._lock = threading.Lock()
|
|
self._items: List[Dict[str, Any]] = []
|
|
|
|
def add(self, item: Dict[str, Any]) -> None:
|
|
with self._lock:
|
|
self._items.append(item)
|
|
if len(self._items) > 1000:
|
|
# keep last 1000
|
|
self._items = self._items[-1000:]
|
|
|
|
def latest(self, limit: int = 50) -> List[Dict[str, Any]]:
|
|
with self._lock:
|
|
return list(reversed(self._items[-limit:]))
|
|
|
|
|
|
# singleton store
|
|
store = DecisionStore()
|
|
|
|
|
|
def log_decision(
|
|
*,
|
|
symbol: str,
|
|
timeframe: str,
|
|
style: str,
|
|
recommendation: str,
|
|
confidence: float,
|
|
risk_level: str,
|
|
rationale: str,
|
|
inputs_hash: str | None = None,
|
|
cost: Dict[str, Any] | None = None,
|
|
) -> Dict[str, Any]:
|
|
now = datetime.now(timezone.utc).isoformat()
|
|
item = {
|
|
"id": f"dec_{int(datetime.now(timezone.utc).timestamp()*1000)}",
|
|
"time": now,
|
|
"symbol": symbol,
|
|
"timeframe": timeframe,
|
|
"style": style,
|
|
"recommendation": recommendation,
|
|
"confidence": confidence,
|
|
"risk_level": risk_level,
|
|
"rationale": rationale,
|
|
"inputs_hash": inputs_hash,
|
|
"cost": cost or {},
|
|
}
|
|
store.add(item)
|
|
return item
|