# Bithumb 빗썸 KRW 마켓 암호화폐 캔들 수집 및 **현물(spot)** 매매 전략 파이프라인. - **기본 축:** 3분봉 BTC, 최근 **10년** 캔들 (`DOWNLOAD_DAYS=3650`) - **데이터·문서:** `data/common` (공유 DB) · `data/spot` / `docs/spot` (현물) - **현재 live 운영:** `fractal_swing`, MTF off, ledger + exchange reconcile + 5분 watch --- ## 목차 1. [파이프라인 개요](#파이프라인-개요) 2. [단계별 요약 (0~3단계)](#단계별-요약-03단계) 3. [수익률 정리](#수익률-정리) 4. [3단계 live 운영](#3단계-live-운영) 5. [설치·실행](#설치실행) 6. [폴더 구조](#폴더-구조) 7. [환경 변수](#환경-변수) 8. [소스 모듈](#소스-모듈) 9. [39종 인과 기법](#39종-인과-기법) 10. [변경 이력](#변경-이력) --- ## 파이프라인 개요 ```mermaid flowchart LR A[common
캔들 수집] --> B[0단계 GT] B --> C[1단계 GT sim] C --> D[2단계 39종 기법] D --> E[3단계 paper/live] F[watch 5분] -.->|감시·조치| E ``` | 단계 | 목적 | 미래 데이터 | 실거래 | |------|------|-------------|--------| | **common** | SQLite 캔들 DB 구축·증분 갱신 | — | — | | **spot 0단계** | GT v3 사후 최적 타점 (정답지) | 사용 (연구용) | 불가 | | **spot 1단계** | GT 타점 완벽 추종 sim 상한선 | GT 자체가 사후 | 불가 | | **spot 2단계** | 39종 인과 기법 평가·MTF 규칙 | 미사용 | 불가 | | **spot 3단계** | paper/live tick 운영 | 미사용 | **가능** | **핵심 원칙** - 0~1단계는 **연구·벤치마크** (사후 GT 포함). - 2단계는 **인과 기법**만으로 GT 재현도·sim을 비교. - 3단계는 2단계에서 선택한 기법을 **실시간 tick**으로 체결. 백테스트와 **동일 sim 엔진**(`ground_truth/pnl.py`) 사용. --- ## 단계별 요약 (0~3단계) ### common — 캔들 수집 | 항목 | 내용 | |------|------| | 스크립트 | `scripts/00_download.py` (별칭 `00_download_candles.py`) | | DB | `data/common/coins.db` | | TF | 11개 (1,3,5,10,15,30,60,240,1440,10080,43200분) | | 모드 | 증분(기본) / `--full` 전체 재수집 | | 테이블 | `{SYMBOL}_{분}` (예: `BTC_3`, `BTC_1440`) | 3단계 tick에서는 `sync_ops_candles()`가 in-process로 동일 DB에 증분 INSERT (`OPS_SYNC_CANDLES=true`). --- ### spot 0단계 — Ground Truth (GT) 타점 **목적:** 10년 3분봉에서 **사후적으로** 도출한 “이론적 최적” 매수·매도 타점. 이후 단계의 **정답지·벤치마크**. | 스크립트 | `scripts/0_ground_truth.py` | |----------|----------------------------| | 기간 | `GT_LOOKBACK_DAYS=3650` (10년) | | 봉 | `GT_INTERVAL_MIN=3` | **GT v3 신호 체계** | 코드 | 유형 | 10년 GT 건수(대략) | |------|------|-------------------| | B | 스윙 저점 매수 | 944 | | B* | 눌림목 | 406 | | B^ | 돌파 | 122 | | Bd | 상승 다이버전스 | 115 | | S | 스윙 고점 매도 | 944 | | Sd | 하락 다이버전스 | 144 | **티어** | 티어 | 포함 신호 | |------|-----------| | v1 | B / S | | v2 | + B* | | v3 | + B^ / Bd / Sd | **산출물** - `data/spot/ground_truth/ground_truth_trades_v{1,2,3}.json` - `docs/spot/0_ground_truth/ground_truth_chart_v*.html` --- ### spot 1단계 — GT sim (수익 상한선) **목적:** GT v3 타점을 **그대로** sim했을 때 3년 수익률. “이론적 상한” 벤치마크. | 스크립트 | `scripts/1_ground_truth_sim.py` | |----------|--------------------------------| | sim 기간 | `GT_SIM_LOOKBACK_DAYS=1095` (3년) | | 초기 자본 | `GT_INITIAL_CASH_KRW=200,000` | | 엔진 | `simulate_gt_signals_pnl` (슬리피지 없음) | **산출물:** `docs/spot/1_simulation/ground_truth_chart_sim_v*.html` **참고:** GT는 사후 타점이므로 **실거래 불가**. 1단계 수익률은 “최적 타점을 보수적으로 따라갔을 때”의 기준선. --- ### spot 2단계 — 인과 기법 분석 (39종) **목적:** 미래 데이터 **없이** GT v3를 얼마나 재현하는지 39종 기법을 평가. 3단계 전략 선택 근거. | 순서 | 스크립트 | 산출물 | |------|----------|--------| | 2-1 | `2_run_techniques.py` | `data/spot/techniques/*.json`, `comparison_report.html` | | 2-2 | `2_run_causal_sim.py` | `causal_sim_report.html` | | 2-3 | `2_run_signal_type_align.py` | `signal_type_report.html` | | 2-4 | `2_run_mtf_analysis.py` | `mtf_rules_v3.json`, `mtf_correlation_report.html` | | 일괄 | `bash scripts/2_run_stage2_all.sh` | 위 전체 | **GT 정합 score 상위 (10년, ±480봉 허용)** | 순위 | 기법 | score | 비고 | |------|------|-------|------| | 1 | **fractal_swing** | 0.914 | buy/sell recall 100%, **현재 live 운영** | | 2 | pivot_swing | 0.911 | | | 3 | minor_swing | 0.864 | | | 4 | local_extrema | 0.839 | | | 5 | zigzag_causal | 0.776 | 스윙 특화, 저빈도 | | … | composite_v3 | 0.546 | leg recall 22.9% | **문서** - 설계: [`docs/spot/2_analysis/stage2_design_guide.md`](docs/spot/2_analysis/stage2_design_guide.md) - 결과 해석: [`docs/spot/2_analysis/stage2_final_summary.md`](docs/spot/2_analysis/stage2_final_summary.md) --- ### spot 3단계 — paper / live 운영 **목적:** 선택 기법(`fractal_swing`)을 3분봉 tick으로 paper 또는 live 체결. | 스크립트 | 역할 | |----------|------| | `3_run_filtered_backtest.py` | 운영 조건 3년 sim | | `3_run_fractal_realistic_backtest.py` | 슬리피지·일 상한 시나리오 | | `3_render_live_chart.py` | `docs/live/` 매매 차트 | | `3_run_operations.py` | paper/live tick (loop 180초) | | `3_preflight_live.py` / `3_init_live_state.py` | live 사전 점검·상태 초기화 | | `3_reconcile_signals.py` | backlog inspect / execute | | `3_audit_ops_safety.py` | 놓침·중복 종합 점검 | | `3_watch_ops.py` | read-only 감시 + 불일치 조치 | | `3_run_watch_cron.sh` | cron 5분용 래퍼 | | `bash scripts/3_run_fractal_live.sh` | preflight → init → live loop | **설계:** [`docs/spot/3_operations/stage3_design_guide.md`](docs/spot/3_operations/stage3_design_guide.md) (초版은 composite_v3 중심 — **현재 `.env` 기본은 fractal_swing**) --- ## 수익률 정리 **공통 조건:** BTC · 3분봉 · sim 기간 **최근 3년(1095일)** · 초기 자본 **200,000원** · 편도 수수료 **0.05%** (`GT_TRADING_FEE_RATE`) > sim 수익률은 **과거 데이터 재생** 결과입니다. live는 슬리피지·체결 지연·유동성·운영 오류로 **달라질 수 있으며**, 특히 고빈도 전략은 슬리피지에 극도로 민감합니다. ### 1단계 — GT v3 벤치마크 | 항목 | 값 | |------|-----| | 3년 수익률 | **+94,154%** | | 최종 평가 | 약 1.89억 원 | | 매수/매도 체결 | 239 / 151 | | 의미 | 사후 최적 타점을 보수적으로 sim | ### 2단계 — 인과 sim (슬리피지 0, 일 상한 없음) | 기법 | 3년 수익률 | 최종 평가(약) | 매수/매도 체결 | 일평균 매수 | |------|-----------|--------------|---------------|------------| | **fractal_swing** | **+7,560,826%** | 151억 | 56,893 / 56,892 | **~52회** | | pivot_swing | +4,687,495% | 94억 | 12,656 / 12,658 | ~12회 | | minor_swing | +286,537% | 5.7억 | 831 / 887 | ~0.8회 | | zigzag_causal | +92,711% | 1.86억 | 97 / 97 | ~0.09회 | | composite_v3 | **-97.5%** | ~5,000원 | 1,885 / 1,237 | — | | composite_v3 + MTF (3단계 필터) | +3.37% | — | — | — | 출처: `docs/spot/2_analysis/stage2_final_summary.md`, `stage2_parity_sweep.json` ### 3단계 — fractal_swing 운영 백테스트 (슬리피지 반영) | 시나리오 | 슬리피지 | 일 체결 상한 | 3년 수익률 | 매수 체결 | 비고 | |----------|---------|-------------|-----------|----------|------| | **stage2 ideal** | 0% | 없음 | **+7,560,826%** | 56,893 | 2단계와 동일 | | **ops_default** | 0.05% | 100 | **+1,873,140%** | 53,589 | sizing_rules 100% (cluster1) | | **ops + sizing 튜닝** | 0.05% | 10,000 | **+2,307,905%** | 56,773 | cluster 100% (`sizing_rules.json`) | | slippage 0.1% | 0.1% | 100 | **-97.5%** | 3,964 | **실거래 리스크** | | slippage 0.1% (상한 없음) | 0.1% | 없음 | -97.5% | 3,962 | 동일 | 출처: `fractal_realistic_backtest.json`, `fractal_filtered_backtest_report.json` (2026-06-14) **해석** - 2단계 ideal 대비 ops_default는 약 **24.8%** 수준 (`fractal_ops_vs_stage2.json`) — 슬리피지·일 상한·분할 매매 반영. - 슬리피지 **0.05% → 0.1%**만 올려도 sim은 **-97.5%**로 붕괴 → live에서 체결가·수수료 관리가 핵심. - `1_tune_order_sizing.py`로 cluster별 100% sizing 튜닝 시 sim **+2,307,905%** (`sizing_rules.json` + `.env` `OPS_*_PCT=1.0`). ### live vs 백테스트 | 구분 | 백테스트 | live | |------|---------|------| | 실행 | 3년 일괄 재생 | 180초 tick 누적 | | 체결가 | 모델 슬리피지 | 빗썸 시장가 + 실제 스프레드 | | 신호 | 캐시+tail | 동일 파이프라인 + ledger | | 기대 | sim 수치 | sim **이하**가 정상 | --- ## 3단계 live 운영 ### tick 아키텍처 ```mermaid flowchart TD subgraph loop["3_run_operations.py --loop 180"] A[sync_ops_candles] --> B[generate_raw_signals
force_tail_refresh] B --> C[filter_signals_for_ops] C --> D[exchange reconcile] D --> E[stale backlog 정산] E --> F[ledger pending 체결] F --> G[state.json + report] end subgraph watch["3_watch_ops.py (cron 5분)"] H[불일치 감지] --> I{조치} I -->|lock 획득| J[remediation tick] I -->|tick stale| K[loop 재시작] I --> T[텔레그램] end L[ops.tick.lock] --- loop L --- watch ``` ### 신호 누락·중복 방어 (2026-06-14) | 기능 | 설명 | |------|------| | **ledger pending** | `trade_history` 기준 미정산 신호 추적 (커서와 분리) | | **force_tail_refresh** | live에서 tail 800봉 신호 재계산 | | **catchup 480봉** | 최근 구간 재시도 | | **max_age 45분** | 과거 backlog 현재가 재체결 차단 (수수료 churn 방지) | | **exchange reconcile** | 거래소 done 주문 ↔ 신호 대조, **재주문 없이** 원장 반영 | | **ops.tick.lock** | loop·watch tick 동시 실행 방지 | | **watch 5분** | 불일치 시 remediation tick 또는 loop 재시작 + 텔레그램 | ### live 시작 ```bash conda activate ncue # 또는 xavis export PYTHONPATH=src # 1) 백테스트 확인 python scripts/3_run_filtered_backtest.py # 2) live (preflight + init + loop) bash scripts/3_run_fractal_live.sh # 또는 직접 python scripts/3_run_operations.py --mode live --loop 180 ``` ### watch cron (5분) ```bash crontab -e # 추가: */5 * * * * /Users/dsyoon/workspace/bithumb/scripts/3_run_watch_cron.sh >> /Users/dsyoon/workspace/bithumb/data/spot/operations/watch_cron.log 2>&1 ``` ### vol_breakout cron (다운로드 + tick + 모니터) TRX/NEAR/WLD 15m flip 운영용. 한 번에 등록: ```bash bash scripts/install_crontab.sh --apply crontab -l # 확인 ``` | cron | 주기 | 스크립트 | 로그 | |------|------|----------|------| | 캔들 증분 | 1분 | `00_run_download_cron.sh` | `data/common/download_cron.log` | | vol tick | 1분 | `3_run_vol_breakout_cron.sh` | `data/spot/operations/vol_breakout_cron.log` | | 모니터 JSON | 5분 | `3_run_vol_monitor_cron.sh` | `data/spot/operations/vol_monitor_cron.log` | - hung 프로세스: 다운로드 20분·vol tick 10분 초과 시 자동 종료 후 lock 정리 (`scripts/_cron_env.sh`) - Python: `coin` / `ncue` conda 우선. 다른 환경이면 `.env` 또는 crontab에 `BITHUMB_PYTHON=...` 설정 - 모니터 UI (8766): ```bash bash scripts/install_vol_monitor_launchd.sh --install # 권장 — 로그인·재부팅 후 자동 기동 bash scripts/3_run_vol_monitor_serve.sh # 수동 1회 기동 bash scripts/install_vol_monitor_launchd.sh --status # 상태 확인 ``` → http://127.0.0.1:8766/vol_live_monitor.html Binance 모니터는 **8765** — 포트가 다릅니다. HTTP 서버(8766)는 **별도 터미널에서 수동 실행**: ```bash python scripts/3_run_vol_monitor.py ``` 점검: ```bash tail -f data/common/download_cron.log tail -f data/spot/operations/vol_breakout_cron.log bash scripts/00_run_download_cron.sh # 수동 1회 bash scripts/3_run_vol_breakout_cron.sh ``` ### fractal watch 점검 ```bash python scripts/3_audit_ops_safety.py # PASS 목표 python scripts/3_reconcile_signals.py --dry-run # pending 0 목표 python scripts/3_watch_ops.py --inspect-only ``` ### live 체크리스트 1. `.env`: `OPS_MODE=live`, API 키, `OPS_EXCHANGE_RECONCILE=true` 2. `3_run_filtered_backtest.py` 수익률 확인 3. paper 1~2일 또는 소액 live 모니터링 4. `fractal_ops_report.json` — tick duration, `ledger_pending_count`, `exchange_reconciled_count` 5. 텔레그램 체결·WATCH 알림 확인 --- ## 설치·실행 ### 요구사항 - Python 3.10+ - Conda `ncue` 또는 `xavis` ### 설치 ```bash cd bithumb conda activate ncue pip install -r requirements.txt cp .env.example .env # API 키·텔레그램 등 ``` ### 전체 파이프라인 (최초 1회) ```bash export PYTHONPATH=src python scripts/00_download.py --full python scripts/0_ground_truth.py --interval 3 --days 3650 --tier all python scripts/1_ground_truth_sim.py --tier all bash scripts/2_run_stage2_all.sh python scripts/3_run_filtered_backtest.py python scripts/3_render_live_chart.py ``` ### fractal 운영 (일상) ```bash bash scripts/3_run_fractal_ops.sh # backtest + paper loop python scripts/3_run_operations.py --loop 180 --mode live bash scripts/3_run_watch_cron.sh # 감시 1회 (또는 cron) ``` --- ## 폴더 구조 ```text bithumb/ ├── src/bithumb/ │ ├── api/ # Public·Private REST │ ├── data/ # 캔들 수집·DB │ ├── ground_truth/ # GT·sim·pnl 엔진 │ ├── techniques/ # 39종 인과 기법 │ ├── mtf/ # MTF 필터·규칙 │ ├── evaluation/ # 2단계 리포트 │ ├── operations/ # runner·executor·ledger·watch·reconcile │ └── notifications/ # 텔레그램 ├── scripts/ # 단계별 CLI·shell ├── data/ │ ├── common/coins.db │ └── spot/ │ ├── ground_truth/ │ ├── techniques/ │ ├── mtf/ │ └── operations/ # state·sizing·lock·pid └── docs/ ├── live/ # 운영 백테스트 차트 └── spot/ ├── 0_ground_truth/ ├── 1_simulation/ ├── 2_analysis/ └── 3_operations/ ``` --- ## 환경 변수 전체: `.env.example`. 카테고리별 요약. ### 공통·GT | 변수 | 설명 | 기본 | |------|------|------| | `SYMBOL` | 코인 | `BTC` | | `DB_PATH` | 캔들 DB | `data/common/coins.db` | | `DOWNLOAD_DAYS` | 수집·GT 기간(일) | `3650` | | `GT_INTERVAL_MIN` | GT·운영 봉(분) | `3` | | `GT_SIM_LOOKBACK_DAYS` | sim·백테스트(일) | `1095` | | `GT_INITIAL_CASH_KRW` | sim 초기 자본 | `200000` | | `GT_TRADING_FEE_RATE` | 편도 수수료 | `0.0005` | ### 3단계 운영 (fractal live) | 변수 | 설명 | 기본 | |------|------|------| | `OPS_MODE` | `paper` / `live` | `paper` | | `OPS_TECHNIQUE_ID` | 기법 | `fractal_swing` | | `OPS_MTF_ENABLED` | MTF 필터 | `false` | | `OPS_SLIPPAGE_RATE` | 편도 슬리피지 | `0.0005` | | `OPS_DAILY_MAX_TRADES` | 일 체결 상한 | `100` (live `.env`는 10000) | | `OPS_CATCHUP_BARS` | catchup 봉 | `480` | | `OPS_LEDGER_LOOKBACK_DAYS` | ledger 스캔 | `1` | | `OPS_LEDGER_EXECUTE_MAX_AGE_MINUTES` | backlog API 허용 | `45` | | `OPS_LIVE_FORCE_TAIL_REFRESH` | live tail 재계산 | `true` | | `OPS_EXCHANGE_RECONCILE` | 거래소 대조 | `true` | | `OPS_TICK_LOCK_PATH` | tick flock | `ops.tick.lock` | | `OPS_LOOP_PID_FILE` | loop PID | `ops_loop.pid` | | `OPS_WATCH_SIGNAL_GRACE_MIN` | 감시 grace | `5` | | `OPS_WATCH_TICK_STALE_MIN` | tick stale → 재시작 | `12` | | `OPS_WATCH_AUTO_REMEDIATE` | 조치 tick | `true` | | `OPS_WATCH_AUTO_RESTART` | loop 재시작 | `true` | | `COIN_TELEGRAM_*` | 체결·WATCH 알림 | — | | `BITHUMB_ACCESS_KEY` / `SECRET` | live API | — | ### composite_v3 대안 프로필 ```env OPS_TECHNIQUE_ID=composite_v3 OPS_MIN_SCORE=2.5 OPS_MTF_ENABLED=true OPS_TREND_GATE_ENABLED=true OPS_DAILY_MAX_TRADES=20 ``` --- ## 소스 모듈 | 모듈 | 역할 | |------|------| | `operations/runner.py` | tick·ledger·stale·watchdog | | `operations/exchange_reconcile.py` | 거래소 체결 ↔ 원장 | | `operations/watch_ops.py` | 5분 감시·조치 | | `operations/ops_lock.py` | flock | | `operations/candle_sync.py` | 증분 캔들 sync | | `operations/signal_pipeline.py` | 신호 tail·MTF | | `operations/executor.py` | paper/live 체결 | | `operations/trade_engine.py` | 사이징·포트폴리오 | | `operations/backtest.py` | 3년 sim | | `ground_truth/pnl.py` | sim 엔진 (2·3단계 공용) | | `api/bithumb_private.py` | 잔고·주문·done 조회 | | `notifications/telegram.py` | 체결·오류·WATCH | --- ## 39종 인과 기법 `src/bithumb/techniques/` — 단일 33 + 복합 6, **미래 데이터 미사용**. | ID | 기법 | 유형 | |----|------|------| | `fractal_swing` | 프랙탈 스윙 | 스윙 (**live**) | | `zigzag_causal` | 인과 ZigZag | 스윙 | | `pivot_swing` | 피벗 스윙 | 스윙 | | `minor_swing` | 소형 스윙 | 하이브리드 | | `local_extrema` | 국소 극값 | 스윙 | | `composite_v3` | v3 통합 | 복합 | | … | (전체 39종) | `techniques/registry.py` 참고 | --- ## 변경 이력 - **2026-06-14:** ledger pending, exchange reconcile, max_age backlog, watch 5분 감시·조치, ops.tick.lock, README 전면 갱신 - **2026-06-13:** fractal_swing live — 슬리피지·sync·tail·텔레그램; ops_default sim **+1,873,140%** - **2026-06-13:** 프로젝트명 Bithumb, 선물 파이프라인 제거 - **2026-06-12:** data/docs common·spot 구조, 2단계 39종 완료, 3단계 초기 (composite_v3) - **2026-06-08:** GT v1/v2/v3 - **2026-06-07:** 캔들 수집 모듈