WLD DeepCoin 단계별 구조 재편 및 설정·문서 통합

로고스/루트 레거시를 제거하고 deepcoin 패키지·scripts 01~05 CLI·docs/reference로
데이터·GT·분석·매칭·운영 단계를 정리했다. config와 .env 기반 설정, trade_anaysis.html 동기화 포함.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-30 22:58:25 +09:00
parent e631a5701f
commit b52d61b777
76 changed files with 11552 additions and 4567 deletions

11
scripts/01_download.py Normal file
View File

@@ -0,0 +1,11 @@
#!/usr/bin/env python3
"""01단계: WLD 봉 데이터 다운로드 → data/coins.db"""
import runpy
from pathlib import Path
runpy.run_path(str(Path(__file__).resolve().parent / "_bootstrap.py"))
from deepcoin.data.downloader import download
if __name__ == "__main__":
download()

View File

@@ -0,0 +1,11 @@
#!/usr/bin/env python3
"""02단계: Ground Truth 매수·매도 타점 생성."""
import runpy
from pathlib import Path
runpy.run_path(str(Path(__file__).resolve().parent / "_bootstrap.py"))
from deepcoin.ground_truth.ground_truth import run_from_db
if __name__ == "__main__":
run_from_db()

View File

@@ -0,0 +1,11 @@
#!/usr/bin/env python3
"""03단계: 3분~일봉 전 기법 enrich (latest CSV)."""
import runpy
from pathlib import Path
runpy.run_path(str(Path(__file__).resolve().parent / "_bootstrap.py"))
from deepcoin.analysis.general_analysis_enrich_runner import main
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,11 @@
#!/usr/bin/env python3
"""03b단계: Ground Truth 타점 MTF 기술적 스냅샷 CSV."""
import runpy
from pathlib import Path
runpy.run_path(str(Path(__file__).resolve().parent / "_bootstrap.py"))
from deepcoin.analysis.general_analysis_runner import main
if __name__ == "__main__":
main()

11
scripts/04_match_rules.py Normal file
View File

@@ -0,0 +1,11 @@
#!/usr/bin/env python3
"""04단계: GT 근접 규칙 선택 (스텁)."""
import runpy
from pathlib import Path
runpy.run_path(str(Path(__file__).resolve().parent / "_bootstrap.py"))
from deepcoin.matching.match_rules import run_match_stub
if __name__ == "__main__":
run_match_stub()

13
scripts/05_chart_bb.py Normal file
View File

@@ -0,0 +1,13 @@
#!/usr/bin/env python3
"""05: 3분봉 BB 차트 HTML."""
import runpy
import sys
from pathlib import Path
runpy.run_path(str(Path(__file__).resolve().parent / "_bootstrap.py"))
from deepcoin.ops import simulation
if __name__ == "__main__":
sys.argv = [sys.argv[0]]
simulation.main()

13
scripts/05_chart_truth.py Normal file
View File

@@ -0,0 +1,13 @@
#!/usr/bin/env python3
"""05: Ground Truth 차트 + JSON."""
import runpy
import sys
from pathlib import Path
runpy.run_path(str(Path(__file__).resolve().parent / "_bootstrap.py"))
from deepcoin.ops import simulation
if __name__ == "__main__":
sys.argv = [sys.argv[0], "truth"]
simulation.main()

11
scripts/05_run_monitor.py Normal file
View File

@@ -0,0 +1,11 @@
#!/usr/bin/env python3
"""05단계: WLD 실시간 모니터 루프."""
import runpy
from pathlib import Path
runpy.run_path(str(Path(__file__).resolve().parent / "_bootstrap.py"))
from deepcoin.ops.monitor_coin import MonitorCoin
if __name__ == "__main__":
MonitorCoin(cooldown_file=None).run_schedule()

17
scripts/README.md Normal file
View File

@@ -0,0 +1,17 @@
# scripts — 단계별 CLI
프로젝트 루트에서 실행하세요. 각 스크립트는 `_bootstrap.py``.env``config`를 로드합니다.
```bash
python scripts/01_download.py
python scripts/02_ground_truth.py
python scripts/03_analyze_enrich.py
python scripts/03_analyze_trades.py
python scripts/04_match_rules.py # 스텁
python scripts/05_chart_truth.py
python scripts/05_chart_bb.py
python scripts/05_run_monitor.py
python scripts/verify_env.py
```
상세 구조: [docs/reference/STRUCTURE.md](../docs/reference/STRUCTURE.md)

11
scripts/_bootstrap.py Normal file
View File

@@ -0,0 +1,11 @@
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
# .env → config 일관 로드
from deepcoin.env_loader import load_project_env # noqa: E402
load_project_env()

219
scripts/verify_env.py Normal file
View File

@@ -0,0 +1,219 @@
#!/usr/bin/env python3
"""`.env` 완전성 및 config 로드 점검."""
from __future__ import annotations
import os
import re
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))
ENV_FILE = ROOT / ".env"
CONFIG_FILE = ROOT / "config.py"
# config.py에서 읽는 환경 변수 키 (코드 기본값이 있는 항목)
CONFIG_ENV_KEYS = {
"BITHUMB_API_URL",
"BITHUMB_API_CANDLE_COUNT",
"BITHUMB_MINUTE_INTERVALS",
"HTS_API_RETRY_SLEEP_SEC",
"SYMBOL",
"COIN_NAME",
"DAILY_INTERVAL_MIN",
"ENTRY_INTERVAL",
"TREND_INTERVAL_1H",
"TREND_INTERVAL_1D",
"ALL_INTERVALS",
"DOWNLOAD_INTERVALS",
"GENERAL_ANALYSIS_INTERVALS",
"TIMING_INTERVALS",
"TREND_INTERVALS",
"INTERVAL_PREFIX",
"BB_PERIOD",
"BB_STD",
"BB_MIN_WIDTH_PCT",
"RSI_PERIOD",
"DISPARITY_PERIODS",
"DISPARITY_OVERBOUGHT",
"DISPARITY_OVERSOLD",
"MACD_FAST",
"MACD_SLOW",
"MACD_SIGNAL",
"STOCH_K_PERIOD",
"STOCH_D_PERIOD",
"STOCH_SMOOTH_K",
"STOCH_OVERSOLD",
"STOCH_OVERBOUGHT",
"TREND_RANGE_MA_GAP_PCT",
"ALIGN_RSI_OVERSOLD",
"ALIGN_RSI_OVERBOUGHT",
"ALIGN_RSI_CONFLICT_TIMING_LOW",
"ALIGN_RSI_CONFLICT_TIMING_HIGH",
"ALIGN_RSI_CONFLICT_TREND_LOW",
"ALIGN_RSI_CONFLICT_TREND_HIGH",
"ALIGN_BB_POS_LOW",
"ALIGN_BB_POS_HIGH",
"DOWNLOAD_MONTHS",
"DOWNLOAD_MONTHS_1M",
"INCREMENTAL_OVERLAP_BARS",
"DOWNLOAD_BACKFILL_EXTRA_BARS",
"DOWNLOAD_MIN_INCREMENTAL_BARS",
"DOWNLOAD_DAILY_EXTRA_DAYS",
"CHART_LOOKBACK_DAYS",
"DB_READ_LIMIT_DEFAULT",
"DB_ROW_WARMUP_BARS",
"DB_ROW_MIN_DAILY_BARS",
"DB_ROW_DAILY_PADDING_DAYS",
"DB_PATH",
"GROUND_TRUTH_FILE",
"GT_UNLIMITED_CHRONOLOGICAL_DAYS",
"GT_MIN_SWING_PCT",
"GT_PIVOT_ORDER",
"GT_MIN_BARS_BETWEEN",
"GT_MAX_ROUND_TRIPS",
"GT_SELECTION_MODE",
"GT_MIN_LEG_PCT",
"GT_BUY_MIN_SWING_PCT",
"GT_BUY_BB_MAX",
"GT_BUY_MIN_BARS",
"GT_MAX_BUYS_PER_LEG",
"GT_MAX_SELLS_PER_LEG",
"GT_SELL_SPLIT_GAP_PCT",
"GT_MARKER_SIZE_MIN",
"GT_MARKER_SIZE_MAX",
"GT_INITIAL_CASH_KRW",
"TRADING_FEE_RATE",
"MONITOR_LOOP_SLEEP_SEC",
"MONITOR_POOL_WORKERS",
"MONITOR_DEFAULT_INTERVAL",
"MONITOR_API_RETRIES",
"MONITOR_API_BONG_COUNT",
"MONITOR_SLEEP_AFTER_REQUEST_SEC",
"MONITOR_SLEEP_RATE_LIMIT_SEC",
"MONITOR_SLEEP_BETWEEN_CHUNKS_SEC",
"MONITOR_API_CHUNK_BARS",
"MONITOR_MA_WINDOWS",
"MONITOR_NORM_WINDOW",
"MONITOR_TELEGRAM_BATCH_SIZE",
"GA_COL_PREFIX",
"LOOKBACK_BARS",
"CONTEXT_TAIL_ROWS",
"GA_DEFAULT_TAIL_EXPORT",
"GA_PATTERN_TOLERANCE_PCT",
"GA_VP_BINS",
"GA_VP_VALUE_AREA_PCT",
"GA_HV_ROLLING_BARS",
"GA_HV_PERCENTILE_WINDOW",
"GA_HV_ANNUALIZE_SQRT",
"GA_DIVERGENCE_LOOKBACK",
"GA_SMA_PERIODS",
"GA_EMA_SPANS",
"GA_ATR_PERIOD",
"GA_KELTNER_ATR_MULT",
"GA_AO_FAST",
"GA_AO_SLOW",
"GA_LINREG_WINDOW",
"GA_ADX_PERIOD",
"GA_ADX_TREND_THRESHOLD",
"GA_SUPERTREND_ATR_MULT",
"GA_VOL_SPIKE_MULT",
"GA_VOL_MA_WINDOW",
"GA_CCI_PERIOD",
"GA_WILLIAMS_PERIOD",
"GA_ROC_PERIOD",
"GA_MFI_PERIOD",
"GA_CMF_PERIOD",
"GA_DONCHIAN_PERIOD",
"GA_BB_SQUEEZE_WINDOW",
"GA_BB_SQUEEZE_QUANTILE",
"GA_PIVOT_ORDER",
"GA_PSAR_AF_START",
"GA_PSAR_AF_STEP",
"GA_PSAR_AF_MAX",
}
# 비어 있어도 되는 선택 항목 (현재는 모두 채움)
OPTIONAL_EMPTY = frozenset()
def parse_env_file(path: Path) -> dict[str, str]:
"""`.env` 키=값 파싱."""
out: dict[str, str] = {}
if not path.is_file():
return out
for line in path.read_text(encoding="utf-8").splitlines():
line = line.strip()
if not line or line.startswith("#"):
continue
if "=" not in line:
continue
key, _, val = line.partition("=")
out[key.strip()] = val.strip()
return out
def main() -> int:
errors: list[str] = []
if not ENV_FILE.is_file():
errors.append(f".env 없음: {ENV_FILE}")
for e in errors:
print(f"FAIL: {e}")
return 1
env_vars = parse_env_file(ENV_FILE)
empty = [k for k, v in env_vars.items() if v == "" and k not in OPTIONAL_EMPTY]
missing = sorted(CONFIG_ENV_KEYS - set(env_vars.keys()))
extra = sorted(set(env_vars.keys()) - CONFIG_ENV_KEYS - {
"BITHUMB_ACCESS_KEY",
"BITHUMB_SECRET_KEY",
"COIN_TELEGRAM_BOT_TOKEN",
"COIN_TELEGRAM_CHAT_ID",
})
if empty:
errors.append(f"빈 값: {', '.join(empty)}")
if missing:
errors.append(f"config 대비 .env 누락: {', '.join(missing)}")
if extra:
print(f"WARN: config 미사용 .env 키: {', '.join(extra)}")
from deepcoin.env_loader import env_status, load_project_env
loaded = load_project_env(override=True)
if not loaded:
errors.append("load_project_env: .env 로드 실패 (python-dotenv 확인)")
import config # noqa: E402
checks = [
("SYMBOL", config.SYMBOL, env_vars.get("SYMBOL")),
("DB_PATH", config.DB_PATH, env_vars.get("DB_PATH")),
("BITHUMB_ACCESS_KEY", bool(config.BITHUMB_ACCESS_KEY), bool(env_vars.get("BITHUMB_ACCESS_KEY"))),
("LOOKBACK_BARS[3]", config.LOOKBACK_BARS.get(3), 120),
]
for name, got, expected in checks:
if got != expected and expected is not None:
errors.append(f"config 불일치 {name}: got={got!r} expected={expected!r}")
status = env_status()
print("env_status:", status)
print(f".env 키 수: {len(env_vars)} (config 필수 {len(CONFIG_ENV_KEYS)})")
print(f"SYMBOL={config.SYMBOL} DB_PATH={config.DB_PATH}")
print(f"BITHUMB_KEY set={bool(config.BITHUMB_ACCESS_KEY)} TELEGRAM set={bool(config.COIN_TELEGRAM_BOT_TOKEN)}")
if errors:
print("\n=== 점검 실패 ===")
for e in errors:
print(f" - {e}")
return 1
print("\n=== 점검 통과: .env → config 로드 정상 ===")
return 0
if __name__ == "__main__":
raise SystemExit(main())