diff --git a/docs/ouroboros/80_implementation_audit.md b/docs/ouroboros/80_implementation_audit.md index 6fd4a30..c688777 100644 --- a/docs/ouroboros/80_implementation_audit.md +++ b/docs/ouroboros/80_implementation_audit.md @@ -111,6 +111,7 @@ Updated: 2026-03-02 - **위치**: `src/db.py` (`fx_pnl`, `strategy_pnl` 컬럼 존재) - **현 상태**: 런타임 SELL 경로에서 `strategy_pnl`/`fx_pnl` 분리 계산 및 전달을 적용함 (`#370`). +- **운영 메모**: `trading_cycle`은 scanner 기반 `selection_context`에 `fx_rate`를 추가하고, `run_daily_session`은 scanner 컨텍스트 없이 `fx_rate` 스냅샷만 기록한다. - **잔여**: 과거 BUY 레코드에 `fx_rate`가 없으면 해외 구간도 `fx_pnl=0` fallback으로 기록됨. - **영향**: USD 거래에서 환율 손익과 전략 손익이 분리되지 않아 성과 분석 부정확 - **요구사항**: REQ-V3-007 diff --git a/src/main.py b/src/main.py index 8771010..7c222fa 100644 --- a/src/main.py +++ b/src/main.py @@ -130,6 +130,9 @@ def _resolve_sell_qty_for_pnl(*, sell_qty: int | None, buy_qty: int | None) -> i def _extract_fx_rate_from_sources(*sources: dict[str, Any] | None) -> float | None: """Best-effort FX rate extraction from broker payloads.""" + # KIS overseas payloads expose exchange-rate fields with varying key names + # across endpoints/responses (price, balance, buying power). Keep this list + # centralised so schema drifts can be patched in one place. rate_keys = ( "frst_bltn_exrt", "bass_exrt", @@ -3392,10 +3395,13 @@ async def run_daily_session( sell_fx_rate=sell_fx_rate, ) if sell_fx_rate is not None and not market.is_domestic: + # Daily path does not carry scanner candidate metrics, so this + # context intentionally stores FX snapshot only. selection_context = {"fx_rate": sell_fx_rate} elif not market.is_domestic: snapshot_fx_rate = _extract_fx_rate_from_sources(balance_info, stock_data) if snapshot_fx_rate is not None: + # BUY/HOLD in daily path: persist FX snapshot for later SELL split. selection_context = {"fx_rate": snapshot_fx_rate} log_trade( conn=db_conn,