feat: propagate runtime session_id across decision and trade logs (#326)
This commit is contained in:
22
src/db.py
22
src/db.py
@@ -109,6 +109,7 @@ def init_db(db_path: str) -> sqlite3.Connection:
|
||||
stock_code TEXT NOT NULL,
|
||||
market TEXT NOT NULL,
|
||||
exchange_code TEXT NOT NULL,
|
||||
session_id TEXT DEFAULT 'UNKNOWN',
|
||||
action TEXT NOT NULL,
|
||||
confidence INTEGER NOT NULL,
|
||||
rationale TEXT NOT NULL,
|
||||
@@ -121,6 +122,27 @@ def init_db(db_path: str) -> sqlite3.Connection:
|
||||
)
|
||||
"""
|
||||
)
|
||||
decision_columns = {
|
||||
row[1]
|
||||
for row in conn.execute("PRAGMA table_info(decision_logs)").fetchall()
|
||||
}
|
||||
if "session_id" not in decision_columns:
|
||||
conn.execute("ALTER TABLE decision_logs ADD COLUMN session_id TEXT DEFAULT 'UNKNOWN'")
|
||||
conn.execute(
|
||||
"""
|
||||
UPDATE decision_logs
|
||||
SET session_id = 'UNKNOWN'
|
||||
WHERE session_id IS NULL OR session_id = ''
|
||||
"""
|
||||
)
|
||||
if "outcome_pnl" not in decision_columns:
|
||||
conn.execute("ALTER TABLE decision_logs ADD COLUMN outcome_pnl REAL")
|
||||
if "outcome_accuracy" not in decision_columns:
|
||||
conn.execute("ALTER TABLE decision_logs ADD COLUMN outcome_accuracy INTEGER")
|
||||
if "reviewed" not in decision_columns:
|
||||
conn.execute("ALTER TABLE decision_logs ADD COLUMN reviewed INTEGER DEFAULT 0")
|
||||
if "review_notes" not in decision_columns:
|
||||
conn.execute("ALTER TABLE decision_logs ADD COLUMN review_notes TEXT")
|
||||
|
||||
conn.execute(
|
||||
"""
|
||||
|
||||
@@ -19,6 +19,7 @@ class DecisionLog:
|
||||
stock_code: str
|
||||
market: str
|
||||
exchange_code: str
|
||||
session_id: str
|
||||
action: str
|
||||
confidence: int
|
||||
rationale: str
|
||||
@@ -47,6 +48,7 @@ class DecisionLogger:
|
||||
rationale: str,
|
||||
context_snapshot: dict[str, Any],
|
||||
input_data: dict[str, Any],
|
||||
session_id: str | None = None,
|
||||
) -> str:
|
||||
"""Log a trading decision with full context.
|
||||
|
||||
@@ -59,20 +61,22 @@ class DecisionLogger:
|
||||
rationale: Reasoning for the decision
|
||||
context_snapshot: L1-L7 context snapshot at decision time
|
||||
input_data: Market data inputs (price, volume, orderbook, etc.)
|
||||
session_id: Runtime session identifier
|
||||
|
||||
Returns:
|
||||
decision_id: Unique identifier for this decision
|
||||
"""
|
||||
decision_id = str(uuid.uuid4())
|
||||
timestamp = datetime.now(UTC).isoformat()
|
||||
resolved_session = session_id or "UNKNOWN"
|
||||
|
||||
self.conn.execute(
|
||||
"""
|
||||
INSERT INTO decision_logs (
|
||||
decision_id, timestamp, stock_code, market, exchange_code,
|
||||
action, confidence, rationale, context_snapshot, input_data
|
||||
session_id, action, confidence, rationale, context_snapshot, input_data
|
||||
)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
""",
|
||||
(
|
||||
decision_id,
|
||||
@@ -80,6 +84,7 @@ class DecisionLogger:
|
||||
stock_code,
|
||||
market,
|
||||
exchange_code,
|
||||
resolved_session,
|
||||
action,
|
||||
confidence,
|
||||
rationale,
|
||||
@@ -106,7 +111,7 @@ class DecisionLogger:
|
||||
query = """
|
||||
SELECT
|
||||
decision_id, timestamp, stock_code, market, exchange_code,
|
||||
action, confidence, rationale, context_snapshot, input_data,
|
||||
session_id, action, confidence, rationale, context_snapshot, input_data,
|
||||
outcome_pnl, outcome_accuracy, reviewed, review_notes
|
||||
FROM decision_logs
|
||||
WHERE reviewed = 0 AND confidence >= ?
|
||||
@@ -168,7 +173,7 @@ class DecisionLogger:
|
||||
"""
|
||||
SELECT
|
||||
decision_id, timestamp, stock_code, market, exchange_code,
|
||||
action, confidence, rationale, context_snapshot, input_data,
|
||||
session_id, action, confidence, rationale, context_snapshot, input_data,
|
||||
outcome_pnl, outcome_accuracy, reviewed, review_notes
|
||||
FROM decision_logs
|
||||
WHERE decision_id = ?
|
||||
@@ -196,7 +201,7 @@ class DecisionLogger:
|
||||
"""
|
||||
SELECT
|
||||
decision_id, timestamp, stock_code, market, exchange_code,
|
||||
action, confidence, rationale, context_snapshot, input_data,
|
||||
session_id, action, confidence, rationale, context_snapshot, input_data,
|
||||
outcome_pnl, outcome_accuracy, reviewed, review_notes
|
||||
FROM decision_logs
|
||||
WHERE confidence >= ?
|
||||
@@ -223,13 +228,14 @@ class DecisionLogger:
|
||||
stock_code=row[2],
|
||||
market=row[3],
|
||||
exchange_code=row[4],
|
||||
action=row[5],
|
||||
confidence=row[6],
|
||||
rationale=row[7],
|
||||
context_snapshot=json.loads(row[8]),
|
||||
input_data=json.loads(row[9]),
|
||||
outcome_pnl=row[10],
|
||||
outcome_accuracy=row[11],
|
||||
reviewed=bool(row[12]),
|
||||
review_notes=row[13],
|
||||
session_id=row[5] or "UNKNOWN",
|
||||
action=row[6],
|
||||
confidence=row[7],
|
||||
rationale=row[8],
|
||||
context_snapshot=json.loads(row[9]),
|
||||
input_data=json.loads(row[10]),
|
||||
outcome_pnl=row[11],
|
||||
outcome_accuracy=row[12],
|
||||
reviewed=bool(row[13]),
|
||||
review_notes=row[14],
|
||||
)
|
||||
|
||||
@@ -217,6 +217,7 @@ async def sync_positions_from_broker(
|
||||
price=avg_price,
|
||||
market=log_market,
|
||||
exchange_code=market.exchange_code,
|
||||
session_id=get_session_info(market).session_id,
|
||||
mode=settings.MODE,
|
||||
)
|
||||
logger.info(
|
||||
@@ -1368,10 +1369,12 @@ async def trading_cycle(
|
||||
"pnl_pct": pnl_pct,
|
||||
}
|
||||
|
||||
runtime_session_id = get_session_info(market).session_id
|
||||
decision_id = decision_logger.log_decision(
|
||||
stock_code=stock_code,
|
||||
market=market.code,
|
||||
exchange_code=market.exchange_code,
|
||||
session_id=runtime_session_id,
|
||||
action=decision.action,
|
||||
confidence=decision.confidence,
|
||||
rationale=decision.rationale,
|
||||
@@ -1636,6 +1639,7 @@ async def trading_cycle(
|
||||
pnl=0.0,
|
||||
market=market.code,
|
||||
exchange_code=market.exchange_code,
|
||||
session_id=runtime_session_id,
|
||||
mode=settings.MODE if settings else "paper",
|
||||
)
|
||||
logger.info("Order result: %s", result.get("msg1", "OK"))
|
||||
@@ -1690,6 +1694,7 @@ async def trading_cycle(
|
||||
pnl=trade_pnl,
|
||||
market=market.code,
|
||||
exchange_code=market.exchange_code,
|
||||
session_id=runtime_session_id,
|
||||
selection_context=selection_context,
|
||||
decision_id=decision_id,
|
||||
mode=settings.MODE if settings else "paper",
|
||||
@@ -2497,10 +2502,12 @@ async def run_daily_session(
|
||||
"pnl_pct": pnl_pct,
|
||||
}
|
||||
|
||||
runtime_session_id = get_session_info(market).session_id
|
||||
decision_id = decision_logger.log_decision(
|
||||
stock_code=stock_code,
|
||||
market=market.code,
|
||||
exchange_code=market.exchange_code,
|
||||
session_id=runtime_session_id,
|
||||
action=decision.action,
|
||||
confidence=decision.confidence,
|
||||
rationale=decision.rationale,
|
||||
@@ -2777,6 +2784,7 @@ async def run_daily_session(
|
||||
pnl=trade_pnl,
|
||||
market=market.code,
|
||||
exchange_code=market.exchange_code,
|
||||
session_id=runtime_session_id,
|
||||
decision_id=decision_id,
|
||||
mode=settings.MODE,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user