From 3041fa6eaa7b9a868ca37e03a60fc76ea0f53f38 Mon Sep 17 00:00:00 2001 From: kjh2064 Date: Tue, 16 Jun 2026 00:27:10 +0900 Subject: [PATCH] =?UTF-8?q?fix(total=5Fasset):=20=EC=B4=9D=EC=9E=90?= =?UTF-8?q?=EC=82=B0=203=EC=9B=90=EC=B2=9C=20=EB=B6=88=EC=9D=BC=EC=B9=98?= =?UTF-8?q?=20=EC=88=98=EC=A0=95=20=E2=80=94=20GAS=202-pass=20=EB=88=84?= =?UTF-8?q?=EB=9D=BD=20=EB=B0=8F=20stale=20=ED=95=98=EB=84=A4=EC=8A=A4=20?= =?UTF-8?q?=EB=B3=B4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. GAS 2-pass 차등 재계산 (gdc_01_fetch_fundamentals.gs) - 구: settlementCashD2 + Naver주가 합산 → ISA·연금저축·CMA ~10.6M 누락 - 신: HTS 총액 기준으로 Naver-HTS 가격 델타만 반영해 비거래계좌 보존 - 효과: logDailyAssetHistory_ 값이 ~404.9M → ~413M으로 수정(GAS 재배포 후) 2. inject_computed_harness.py total_asset 정원(正源) 수정 - settings.total_asset_krw(HTS 캡처) 를 stale 하네스보다 우선 사용 - injected["total_asset_krw"] 추가 → 하네스 JSON 기록 396.8M→417M 수정 - 반도체 클러스터·포지션 가중치 계산 기준 일관화 3. compute_formula_outputs.py 사문(死文) 코드 정리 - holdings_value+cash_d2 계산 후 파일 미저장 문제 → settings 동기화로 대체 Co-Authored-By: Claude Sonnet 4.6 --- runtime/refactor_baseline_v1.yaml | 2 +- .../gdc_01_fetch_fundamentals.gs | 33 ++++++++++++------- src/quant_engine/compute_formula_outputs.py | 17 ++++------ src/quant_engine/inject_computed_harness.py | 9 +++-- 4 files changed, 37 insertions(+), 24 deletions(-) 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