diff --git a/runtime/refactor_baseline_v1.yaml b/runtime/refactor_baseline_v1.yaml index c1f4683..83af80c 100644 --- a/runtime/refactor_baseline_v1.yaml +++ b/runtime/refactor_baseline_v1.yaml @@ -15,5 +15,5 @@ "keep package scripts within release envelope" ] }, - "source_zip_sha256": "c1949f9ab22a1baf50e71a4252c932c6f09997478328ae6aa929b42ebed2cbf1" + "source_zip_sha256": "acb8abea2ca65c86d834683350514874403028373ae627533459484e25a23f2e" } \ No newline at end of file diff --git a/src/gas_adapter_parts/gdc_01_fetch_fundamentals.gs b/src/gas_adapter_parts/gdc_01_fetch_fundamentals.gs index a7fe5ad..4857344 100644 --- a/src/gas_adapter_parts/gdc_01_fetch_fundamentals.gs +++ b/src/gas_adapter_parts/gdc_01_fetch_fundamentals.gs @@ -2194,18 +2194,29 @@ function runDataFeed() { }; }); - // WBS-1.2: total_asset_krw 실시간 재계산 (2-pass update cycle) - let liveTotalAssetKrw = Number.isFinite(settlementCashD2_) ? settlementCashD2_ : 0; - for (const ticker of Object.keys(positionStopMap_)) { - const priceMetrics = resolveDataFeedPriceMetrics(ticker); - const qty = positionStopMap_[ticker].quantity; - if (priceMetrics.ok && Number.isFinite(priceMetrics.close) && Number.isFinite(qty)) { - liveTotalAssetKrw += priceMetrics.close * qty; + // WBS-1.2: total_asset_krw 실시간 재계산 (2-pass differential: HTS 기준 + Naver 가격 델타) + // 구 방식(D2현금 + Naver 주가 합산)은 ISA·연금저축·CMA ~10M을 누락해 과소계상됨. + // 수정: HTS 캡처 총액을 기준으로 개별주 Naver-HTS 가격 차이(delta)만 반영한다. + if (Number.isFinite(totalAssetKrw_) && totalAssetKrw_ > 0) { + let priceUpdateKrw = 0, updateCount = 0; + for (const ticker of Object.keys(positionStopMap_)) { + const priceMetrics = resolveDataFeedPriceMetrics(ticker); + const pos = positionStopMap_[ticker]; + const qty = pos.quantity; + const htsMv = pos.account_market_value; + if (priceMetrics.ok && Number.isFinite(priceMetrics.close) && Number.isFinite(qty) + && Number.isFinite(htsMv) && htsMv > 0) { + priceUpdateKrw += (priceMetrics.close * qty) - htsMv; + updateCount++; + } + } + if (updateCount > 0) { + const liveTotal = totalAssetKrw_ + priceUpdateKrw; + if (liveTotal > 0) { + totalAssetKrw_ = liveTotal; + Logger.log(`[WBS-1.2] total_asset_krw 재계산 완료: ${totalAssetKrw_} KRW (delta: ${priceUpdateKrw}, ${updateCount}종목 반영)`); + } } - } - if (liveTotalAssetKrw > 0) { - totalAssetKrw_ = liveTotalAssetKrw; - Logger.log(`[WBS-1.2] total_asset_krw 실시간 재계산 완료: ${totalAssetKrw_} KRW (현금: ${settlementCashD2_})`); } // Total_Heat 사전 계산 — HF005(≥10% 매수 차단) + caution(7~10% 수량 감액)에 사용 diff --git a/src/quant_engine/compute_formula_outputs.py b/src/quant_engine/compute_formula_outputs.py index 8b57dbd..04d11f3 100644 --- a/src/quant_engine/compute_formula_outputs.py +++ b/src/quant_engine/compute_formula_outputs.py @@ -324,16 +324,13 @@ def main() -> int: sell_priority = raw.get("data", {}).get("sell_priority", []) or [] core_satellite = raw.get("data", {}).get("core_satellite", []) or [] - # ── TOTAL ASSET CALCULATION ───────────────────────────────────────────── - # Sum market_value of all holdings + available_cash (if present in context) - holdings_value = sum(float(r.get("market_value", 0) or 0) for r in account_snapshot if r.get("market_value")) - - # Try to find cash in snapshot or context - cash_d2 = float(hc.get("settlement_cash_d2_krw") or hc.get("available_cash") or 0) - total_asset = holdings_value + cash_d2 - - hc["total_asset_krw"] = round(total_asset) - hc["total_asset"] = round(total_asset) + # ── TOTAL ASSET SYNC ──────────────────────────────────────────────────── + # settings.total_asset_krw (HTS 캡처)를 정원(正源)으로 동기화. + # GAS 하네스가 stale일 때 hc 값이 낮게 유지되는 문제를 방지한다. + _settings_total = float((raw.get("data") or {}).get("settings", {}).get("total_asset_krw") or 0) + if _settings_total > 0: + hc["total_asset_krw"] = round(_settings_total) + hc["total_asset"] = round(_settings_total) regime = str(hc.get("market_regime", "NEUTRAL")) diff --git a/src/quant_engine/inject_computed_harness.py b/src/quant_engine/inject_computed_harness.py index 8113ddb..060035f 100644 --- a/src/quant_engine/inject_computed_harness.py +++ b/src/quant_engine/inject_computed_harness.py @@ -855,8 +855,9 @@ def main() -> int: # 공통 집계값 total_asset = float( - computed_harness.get("total_asset_krw") or - hc.get("total_asset_krw") or + computed_harness.get("total_asset_krw") or + settings_map.get("total_asset_krw") or # HTS 캡처 기준(stale 하네스보다 최신) + hc.get("total_asset_krw") or hc.get("total_asset") or 0 ) total_heat = float(hc.get("total_heat_pct") or 0) @@ -873,6 +874,10 @@ def main() -> int: log(SEP) injected: dict[str, object] = {} + # total_asset_krw를 정규화된 값으로 하네스에 기록 (stale GAS 값 덮어쓰기) + if total_asset > 0: + injected["total_asset_krw"] = round(total_asset) + fresh_captured_at = latest_snapshot_captured_at_iso(acct_snap) if fresh_captured_at: injected["captured_at"] = fresh_captured_at