refactor: Git에서 데이터 제거, 설정·코드만 유지

파이프라인 산출물(data/, docs/)을 Git 추적에서 제외하고
히스토리를 단일 커밋으로 재구성해 저장소 용량을 경량화한다.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-12 10:01:43 +09:00
commit 741c949470
92 changed files with 12230 additions and 0 deletions

View File

@@ -0,0 +1,132 @@
"""2단계: 인과 기법 GT 정합 비교 리포트."""
from __future__ import annotations
import json
from datetime import datetime
from pathlib import Path
from typing import Any
from deepcoin.techniques.base import TechniqueResult
def build_comparison_report(
results: list[TechniqueResult],
gt_result: dict[str, Any],
symbol: str,
) -> dict[str, Any]:
"""기법 비교 요약 리포트를 생성한다."""
gt_meta = gt_result.get("meta", {})
gt_pnl = gt_result.get("pnl", {})
gt_summary = gt_result.get("summary", {})
rows: list[dict[str, Any]] = []
for result in results:
align = result.alignment or {}
buy = align.get("buy", {})
sell = align.get("sell", {})
legs = align.get("legs", {})
rows.append(
{
"technique_id": result.technique_id,
"technique_name": result.technique_name,
"category": result.category,
"causal": result.causal,
"leg_count": result.summary.get("leg_count", 0),
"tech_return_pct": result.pnl.get("total_return_pct", 0.0),
"buy_recall": buy.get("recall", 0.0),
"sell_recall": sell.get("recall", 0.0),
"leg_recall": legs.get("leg_recall", 0.0),
"return_capture_ratio": align.get("return_capture_ratio", 0.0),
"score": align.get("score", 0.0),
"avg_buy_offset": buy.get("avg_bar_offset", 0.0),
"avg_sell_offset": sell.get("avg_bar_offset", 0.0),
}
)
rows.sort(key=lambda r: r["score"], reverse=True)
return {
"generated_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"symbol": symbol,
"gt": {
"leg_count": gt_summary.get("leg_count", 0),
"return_pct": gt_pnl.get("total_return_pct", 0.0),
"interval_label": gt_meta.get("interval_label", ""),
"lookback_days": gt_meta.get("lookback_days", 365),
},
"ranking": rows,
}
def save_comparison_report(report: dict[str, Any], json_path: Path) -> Path:
"""비교 리포트 JSON을 저장한다."""
json_path.parent.mkdir(parents=True, exist_ok=True)
with json_path.open("w", encoding="utf-8") as fp:
json.dump(report, fp, ensure_ascii=False, indent=2)
return json_path
def render_comparison_html(report: dict[str, Any], html_path: Path) -> Path:
"""비교 리포트 HTML을 생성한다."""
html_path.parent.mkdir(parents=True, exist_ok=True)
rows = report.get("ranking", [])
gt = report.get("gt", {})
table_rows = ""
for idx, row in enumerate(rows, start=1):
table_rows += f"""
<tr>
<td>{idx}</td>
<td>{row['technique_name']}</td>
<td>{row['category']}</td>
<td>{'Y' if row['causal'] else 'N'}</td>
<td>{row['leg_count']}</td>
<td>{row['tech_return_pct']:+.1f}%</td>
<td>{row['buy_recall']*100:.1f}%</td>
<td>{row['sell_recall']*100:.1f}%</td>
<td>{row['leg_recall']*100:.1f}%</td>
<td>{row['return_capture_ratio']*100:.1f}%</td>
<td><strong>{row['score']*100:.1f}</strong></td>
</tr>"""
html = f"""<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>DeepCoin 2단계 — 인과 GT 정합</title>
<style>
body {{ font-family: "Malgun Gothic", Arial, sans-serif; margin: 24px; color: #333; background: #f5f5f5; }}
h1 {{ font-size: 20px; margin-bottom: 8px; }}
.meta {{ color: #666; margin-bottom: 20px; font-size: 14px; }}
table {{ border-collapse: collapse; width: 100%; background: #fff; }}
th, td {{ border: 1px solid #ddd; padding: 8px 10px; text-align: center; font-size: 13px; }}
th {{ background: #e8e8e8; }}
tr:nth-child(even) {{ background: #fafafa; }}
</style>
</head>
<body>
<h1>DeepCoin 2단계 — 인과 기법 Ground Truth 정합</h1>
<div class="meta">
생성: {report.get('generated_at', '')} |
{report.get('symbol', '')} |
GT: {gt.get('leg_count', 0)}레그, {gt.get('return_pct', 0):+.1f}% |
기간: 최근 {gt.get('lookback_days', 365)}
</div>
<table>
<thead>
<tr>
<th>순위</th><th>기법</th><th>유형</th><th>인과</th><th>레그</th>
<th>수익률</th><th>매수 Recall</th><th>매도 Recall</th><th>레그 Recall</th>
<th>수익 포착</th><th>종합 Score</th>
</tr>
</thead>
<tbody>{table_rows}
</tbody>
</table>
</body>
</html>"""
with html_path.open("w", encoding="utf-8") as fp:
fp.write(html)
return html_path