From 55debd98a41b9f58eb6dddd4eea7986685d938db Mon Sep 17 00:00:00 2001 From: kjh2064 Date: Sat, 13 Jun 2026 18:46:33 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=84=B1=EA=B3=BC=20=EB=AA=A8=EB=8B=88?= =?UTF-8?q?=ED=84=B0=EB=A7=81=20=EB=8C=80=EC=8B=9C=EB=B3=B4=EB=93=9C=20Exc?= =?UTF-8?q?el(xlsx)=20=EC=B6=9C=EB=A0=A5=20=EC=A3=BC=EC=9E=85=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EB=B3=B4=EC=99=84=20(2026-06-13)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 주요 변경 사항: - tools/build_continuous_evaluation_dashboard_v1.py 수정: * openpyxl을 사용해 JSON 대시보드 산출 결과를 GatherTradingData.xlsx의 evaluation_dashboard 시트에 실시간 기입하도록 연동 * 기존 데이터 자동 클리어 및 주간 스코어카드 테이블 D~H열 병렬 기입 구현 - 검증 결과: python tools/build_continuous_evaluation_dashboard_v1.py 정상 구동 및 Excel 저장 완료 Co-Authored-By: Antigravity AI --- ...uild_continuous_evaluation_dashboard_v1.py | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/tools/build_continuous_evaluation_dashboard_v1.py b/tools/build_continuous_evaluation_dashboard_v1.py index f7651df..877c025 100644 --- a/tools/build_continuous_evaluation_dashboard_v1.py +++ b/tools/build_continuous_evaluation_dashboard_v1.py @@ -156,6 +156,61 @@ def main() -> int: } save_json(args.out, result) + # ── Excel 파일 기입 (GatherTradingData.xlsx > evaluation_dashboard) ── + try: + import openpyxl + xlsx_path = ROOT / "GatherTradingData.xlsx" + if xlsx_path.exists(): + wb = openpyxl.load_workbook(xlsx_path) + sheet_name = "evaluation_dashboard" + + # 기존 시트 클리어 및 재생성 + if sheet_name in wb.sheetnames: + ws = wb[sheet_name] + ws.delete_rows(1, ws.max_row + 10) + else: + ws = wb.create_sheet(sheet_name) + + # 1. SUMMARY 섹션 기입 + ws.append(["Metric", "Value"]) + summary_metrics = [ + ("Generated At", result["generated_at"]), + ("Gate Status", result["gate"]), + ("Expectancy Pct", result["expectancy_pct"]), + ("Win Rate Pct", result["win_rate_pct"]), + ("Max Drawdown Pct", result["max_drawdown_pct"]), + ("Total Live Evaluated T+20", result["total_live_evaluated_t20"]), + ("Total Live Pending", result["total_live_pending"]), + ("Replay Record Count", result["replay_informational"]["replay_record_count"]), + ("Sufficient For Metrics", result["data_confidence"]["sufficient_for_metrics"]), + ("Min Required", result["data_confidence"]["min_required"]), + ("Current Live T+20", result["data_confidence"]["current_live_t20"]), + ("Gap", result["data_confidence"]["gap"]), + ("Estimated Ready", result["data_confidence"]["estimated_ready"]) + ] + for m, v in summary_metrics: + ws.append([m, v]) + + # 2. WEEKLY SCORECARD 섹션 기입 (오른쪽 열인 D열부터 시작) + ws.cell(row=1, column=4, value="Week") + ws.cell(row=1, column=5, value="Expectancy_Pct") + ws.cell(row=1, column=6, value="Win_Rate_Pct") + ws.cell(row=1, column=7, value="Max_Drawdown_Pct") + ws.cell(row=1, column=8, value="Trade_Count") + + for idx, w in enumerate(weekly_scorecard): + r_num = idx + 2 + ws.cell(row=r_num, column=4, value=w.get("week")) + ws.cell(row=r_num, column=5, value=w.get("expectancy_pct")) + ws.cell(row=r_num, column=6, value=w.get("win_rate_pct")) + ws.cell(row=r_num, column=7, value=w.get("max_drawdown_pct")) + ws.cell(row=r_num, column=8, value=w.get("trade_count")) + + wb.save(xlsx_path) + print(f"[EVALUATION_DASHBOARD] Saved evaluation_dashboard sheet to {xlsx_path.name}") + except Exception as e: + print(f"[EVALUATION_DASHBOARD][ERROR] Failed to save Excel sheet: {e}") + suffix = f"(need {max(0, MIN_T20_FOR_METRICS - live_t20_count)} more LIVE T+20)" if insufficient else "" print( f"[CONTINUOUS_EVALUATION_DASHBOARD_V1] gate={gate} "