Files
upbit-trader/STRATEGY.md
joungmin 6580cda017 docs: update STRATEGY.md with F&G filter and project structure changes
- Add F&G filter section: FNG_MIN_ENTRY=41, 1-year backtest proof
  (no filter: +95K KRW → F&G>=41: +1.72M KRW over 1 year)
- Add F&G backtest result (section D) with adaptive param findings
- Update section E: rename velocity backtest (was D)
- Split file table into production core vs tests/ scripts
- Update simulation commands to use tests/ path prefix
- Update env config: add FNG_MIN_ENTRY=41
- Add changelog entries for F&G filter, project structure, ecosystem.config.js

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-03 16:14:50 +09:00

14 KiB
Raw Blame History

Volume Lead 전략 가이드

전략 개요

거래량 선행(Volume Lead) 매집 전략 — 가격이 횡보하는 중 거래량 급증이 발생하면 매집 신호로 기록하고, 이후 일정 수준 이상 상승 시 진입하는 선진입 전략.

핵심 아이디어: 대형 매수자는 가격을 올리지 않고 조용히 매집한다. 거래량이 먼저 급증하고, 가격 상승은 그 뒤에 따라온다.

캔들 단위: 40분봉 (Upbit minute10 API로 수신 후 인메모리 40분 리샘플링)


진입 조건 (2단계)

1단계: 매집 신호 감지

다음 두 조건 동시 충족 시 signal_price + vol_ratio 기록:

조건 파라미터 기본값
2h 가격 변동 < N% (횡보) PRICE_QUIET_PCT 2.0%
직전 40분봉 거래량 ≥ 로컬 5h(7봉) 평균 × M배 VOLUME_MULTIPLIER 2.0x
  • 신호 발생 시 텔레그램 알림 발송
  • SIGNAL_TIMEOUT_H 내 진입 조건 미달 시 신호 초기화 (기본: 8h)
  • 신호가 이하 하락 시 즉시 초기화 (매집 실패 판단)

2h 횡보 체크: Oracle DB에 저장된 실시간 가격 기록을 조회 (get_price_n_hours_ago) 거래량 체크: minute10 → 40분봉 resample → 직전 완성봉 vs 이전 7봉 평균

2단계: 추세 확인 후 진입 (거리 기반 OR 속도 기반 — 먼저 충족되는 조건으로 진입)

A. 거리 기반: signal_price 대비 +임계값% 이상 상승 시 매수 (vol_ratio에 따라 동적 조정)

vol_ratio 진입 임계값 설명
≥ 5.0x +1.0% 매우 강한 신호
≥ 3.5x +2.0% 강한 신호
≥ 2.5x +3.0% 중간 신호
< 2.5x +TREND_AFTER_VOL% 기본 임계값

B. 속도 기반 (조기 진입): 신호 후 가격 상승 속도가 VELOCITY_THRESHOLD 이상이면 즉시 진입

파라미터 기본값 설명
TREND_AFTER_VOL 4.8% 거리 기반 기본 임계값
VELOCITY_THRESHOLD 0.10%/분 속도 기준 (6%/h — 가파른 상승 감지)
VELOCITY_MIN_MOVE 0.5% 속도 체크 전 최소 이동 %
VELOCITY_MIN_AGE_M 5분 속도 체크 전 최소 경과 시간

예시 (BTC 23:20 신호): 23:30에 +1.26%/6분 = 0.21%/분 → 속도 기준 충족 → 조기 진입 실제 진입(00:34, 100,840,000) 대비 약 1시간 빠른 23:30(97,286,000) 진입 가능

신호 감시 스레드 (Fast Poll)

신호 감지 후 전체 스캔 60초를 기다리지 않고 해당 종목만 빠르게 폴링.

파라미터 기본값 설명
SCAN_INTERVAL 60초 전체 시장 스캔 주기
SIGNAL_POLL_INTERVAL 15초 신호 종목 집중 감시 주기
  • 신호 발생 시 별도 스레드(signal-fast-poll)가 15초마다 해당 종목만 체크
  • 목표 임계값(거리 or 속도) 도달 즉시 매수 → 60초 지연 제거

청산 조건

트레일링 스탑 (ATR 기반)

  • minute10 → 40분봉 resample 후 최근 7봉(≈5h)의 평균 진폭 계산
  • ATR = 평균진폭 × 1.5 계수 → 동적 손절폭 산출
  • 최소 1.0% / 최대 2.0% 범위 내 자동 조정
  • 최고가 대비 손절폭 이하 하락 시 즉시 청산
  • ATR 캐시: 40분마다 갱신 (캐시 TTL=2400초)

타임 스탑

  • 보유 TIME_STOP_HOURSh 경과 후 수익률 < TIME_STOP_MIN_GAIN_PCT% 이면 청산
  • 기본값: 8시간 경과 / 수익률 3% 미만

진입 사전 필터

F&G (공포탐욕지수) 필터 — core/fng.py

alternative.me API 기반 일일 공포탐욕지수(0~100) 조회. 극공포·공포 구간에서는 신규 매수를 전면 차단한다.

F&G 구간 레이블 진입 여부
76 ~ 100 극탐욕 허용
56 ~ 75 탐욕 허용
46 ~ 55 중립 허용
41 ~ 45 약공포 허용
26 ~ 40 공포 차단
0 ~ 25 극공포 차단
  • 환경변수 FNG_MIN_ENTRY=41 (기본값) — 이 값 미만이면 스캔 전체 스킵
  • API는 하루 1회 KST 09:00 업데이트 → 캐시 TTL 24시간
  • API 실패 시 폴백: 50 (중립) — 안전하게 진입 허용
  • BEAR 레짐 차단과 독립적으로 동작 (둘 다 통과해야 스캔 진행)

1년 백테스트 검증 결과 (2025-03-03 ~ 2026-03-03, 18종목 1h봉):

구성 거래수 승률 평균PnL 누적PnL(KRW)
필터 없음 820건 32.7% +0.012% +95,743원
F&G≥41 372건 39.5% +0.462% +1,719,047원
  • 차단 거래 452건 평균 PnL: -0.372% → 손실 거래 제거 효과
  • 극공포 구간(0~25): 23.5% 승률, -0.540%/건 → 파라미터 조정으로 개선 불가 (검증됨)

리스크 관리

Walk-Forward (WF) 필터

파라미터 기본값 설명
WF_WINDOW 4 이력 윈도우 (직전 N건) — 4연패 시 차단
WF_MIN_WIN_RATE 0.01 최소 승률 임계값 (1%)
WF_SHADOW_WINS 2 차단 해제 조건 (가상 N연승)
  • 직전 4건 승률 < 1% → 해당 종목 진입 차단
  • 차단 후 가상 추적으로 2연승 달성 시 자동 복귀
  • WF 차단 상태는 Oracle DB(wf_state 테이블)에 영속 저장 → 재시작 후에도 복원

예산 관리 (복리)

  • 수익 발생 시: 운용예산 = 초기예산 + 누적수익 (복리 증가)
  • 손실 발생 시: 운용예산 = 초기예산 + 누적수익 (차감)
  • 하한선: 초기예산의 30% (기본: 4,500,000원)
  • 포지션당 크기: 운용예산 / MAX_POSITIONS

시장 레짐 적응

BTC·ETH·SOL·XRP 가중평균 2h 추세 score로 레짐 결정.

종목 가중치
KRW-BTC 40%
KRW-ETH 30%
KRW-SOL 15%
KRW-XRP 15%
레짐 score 기준 vol_mult 신규 진입
BULL ≥ +1.5% 1.5x 허용
NEUTRAL -0.5% ~ +1.5% 2.0x 허용
BEAR < -0.5% 3.5x 전면 차단
  • BEAR 레짐 감지 시 신규 매수 전면 차단 (기존 포지션 청산은 정상 진행)
  • 레짐 캐시 TTL: 10분 (API 호출 최소화)
  • 현재가는 매 레짐 계산 시 Oracle DB(price_history)에 저장 → 2h 전 가격 조회에 재활용

2026-03-03 조정: BEAR 기준 -1.0% → **-0.5%**로 강화 완만한 하락장(score ≈ -0.4%)에서 NEUTRAL로 오판하던 문제 수정


운용 설정 (.env)

# 핵심 전략
PRICE_QUIET_PCT=2.0       # 2h 횡보 기준 (%)
TREND_AFTER_VOL=4.8       # 진입 임계값 (신호가 대비 %)
SIGNAL_TIMEOUT_H=8.0      # 신호 유효 시간 (h)
VOLUME_MULTIPLIER=2.0     # 거래량 배수 기준

# 속도 기반 조기 진입
VELOCITY_THRESHOLD=0.10   # %/분 (0.10 = 6%/h)
VELOCITY_MIN_MOVE=0.5     # 최소 이동 % (잡음 제거)
VELOCITY_MIN_AGE_M=5.0    # 최소 경과 시간 (분)

# 청산
TIME_STOP_HOURS=8         # 타임스탑 보유 시간
TIME_STOP_MIN_GAIN_PCT=3  # 타임스탑 최소 수익률

# 포트폴리오
MAX_BUDGET=15000000       # 초기 운용 예산
MAX_POSITIONS=3           # 최대 동시 보유 종목

# 감시 주기
SIGNAL_POLL_INTERVAL=15   # 신호 종목 빠른 감시 (초)

# WF 필터
WF_WINDOW=4
WF_MIN_WIN_RATE=0.01
WF_SHADOW_WINS=2

# F&G 필터
FNG_MIN_ENTRY=41          # 이 값 미만(공포/극공포) 시 신규 매수 전면 차단

백테스트 결과 요약

A. 365일 — 1h봉, WF 적용 (sim_365.py)

기간: 2025-03-02 ~ 2026-03-02 / 데이터: Oracle DB 1h OHLCV / 20종목

항목
초기 예산 15,000,000원
최종 자산 29,996,109원
수익률 +100%
최대 낙폭 -3.81% (-57만원)
거래수 190건 (WF 183건 차단)
승률 46%
월평균 수익 약 115만원

B. 45일 — 40분봉, WF + 복리 적용 (sim_45m40.py)

기간: 2026-01-20 ~ 2026-03-02 / 데이터: Upbit minute10 캐시 40분 리샘플링 / 20종목

항목
초기 예산 15,000,000원
최종 자산 21,684,574원
수익률 +44.56%
최대 낙폭 -3.90% (-585,102원)
거래수 87건 (WF 3건 차단 / MAX_POS 1건 스킵)
승률 47.1%
월평균 수익 약 2,228,000원
거래 승률 월수익 누적수익
2026-01 17건 29% -160,000원 -160,000원
2026-02 61건 49% +6,217,000원 +6,057,000원
2026-03 9건 67% +627,000원 +6,685,000원

참고 — 봉 단위별 단순 PnL 합산 비교 (WF 미적용, interval_sweep.py)

봉 단위 거래수 승률 누적PnL 최대낙폭
10분 180 33.9% +15.8% -32.6%
20분 120 36.7% +31.0% -16.7%
30분 91 48.4% +81.7% -12.9%
40분 91 48.4% +119.4% -11.2% ← 채택
50분 83 50.6% +94.7% -17.1%
60분 65 50.8% +88.3% -11.9%

C. ATR_MAX_STOP 스윕 — 1h봉 기준 (atr_sweep.py)

데이터: Oracle DB 1h OHLCV / 20종목

ATR_MAX 승률 누적PnL 최대낙폭 평균스탑
1.5% 52.3% +442% -3.2% 1.49%
2.0% 50.8% +299% -4.1% 1.49% ← 현재 채택
2.5% 50.8% +256% -5.3% 1.77%
4.0% 45.9% -52% -29.1% 3.11%

D. F&G 필터 효과 비교 — 1h봉 (tests/fng_sim_comparison.py)

기간: 2025-03-03 ~ 2026-03-03 / 데이터: Oracle DB 1h OHLCV / 18종목

구성 거래수 승률 평균PnL 누적(KRW)
필터 없음 820건 32.7% +0.012% +95,743원
F&G≥41 372건 39.5% +0.462% +1,719,047원
  • 차단 452건 평균 PnL -0.372% → 약 168만원 손실 방지
  • 극공포 적응 파라미터 테스트(tests/fng_adaptive_backtest.py): 어떤 파라미터도 극공포 성과 개선 불가 → 진입 차단이 유일한 해결책

E. 속도 진입 효과 비교 — 10분봉 (tests/velocity_backtest.py)

기간: 2026-01-19 ~ 2026-03-02 / 10분봉 캐시 / 20종목

설정 속도진입 승률 수익률 최대낙폭
A: 거리 기반만 0건 34.7% +8.83% -8.35%
B: +속도(0.10) 89건 33.6% +13.36% -4.50%
B: +속도(0.15) 39건 35.7% +17.19% -7.84%
  • 0.10 채택: 낙폭 -8.35% → -4.50% 개선, 수익률 +4.5%p
  • 속도진입 BTC 예시: 0.21%/분 → 0.10 기준 충족 (0.20도 아슬하게 충족)

주요 파일

프로덕션 코어

파일 역할
core/strategy.py 진입 신호 로직 (40분봉 vol-lead + 속도 기반 조기 진입)
core/fng.py F&G 필터 (alternative.me API, 24h 캐시)
core/monitor.py ATR 트레일링 스탑 + 타임스탑 (40분봉 ATR)
core/trader.py 주문 실행 + 복리 예산 관리
core/market_regime.py 시장 레짐 감지 (BTC/ETH/SOL/XRP 가중 2h 추세)
core/price_db.py 가격 DB + WF 상태 영속화
core/notify.py 텔레그램 알림 (매수/매도/신호/상태)
daemon/runner.py 전체 스캔 루프 + 신호 종목 fast-poll 스레드
main.py 진입점 (스레드 시작 + pm2)
ecosystem.config.js pm2 설정 (로그 경로 logs/)

백테스트 / 분석 (tests/)

파일 역할
tests/fng_sim_comparison.py F&G 필터 적용 전후 수익 비교 (1년)
tests/fng_1y_backtest.py F&G 구간별 성과 분석 (7개 구간, 1년)
tests/fng_adaptive_backtest.py F&G 구간별 적응 파라미터 테스트
tests/sim_365.py 365일 복리 시뮬레이션 (1h봉, DB)
tests/sim_45m40.py 45일 복리 시뮬레이션 (40분봉, 캐시)
tests/velocity_backtest.py 속도 진입 효과 비교 백테스트
tests/atr_sweep.py ATR_MAX_STOP 파라미터 스윕
tests/interval_sweep.py 봉 단위별 성과 비교
tests/backtest_db.py 백테스트 결과 Oracle DB 저장
tests/ohlcv_db.py OHLCV 시계열 DB 캐시 관리

시뮬레이션 실행

# F&G 필터 효과 비교 (필터 없음 vs F&G≥41)
python tests/fng_sim_comparison.py

# F&G 구간별 성과 분석 (7개 구간, 1년)
python tests/fng_1y_backtest.py

# 45일 복리 시뮬 — 40분봉 (현재 전략 기준)
python tests/sim_45m40.py

# 365일 복리 시뮬 — 1h봉 (DB에서 로드)
python tests/sim_365.py

# 속도 진입 효과 비교
python tests/velocity_backtest.py

# 봉 단위별 비교 (10m 캐시 필요)
python tests/interval_sweep.py

# ATR_MAX_STOP 스윕 (DB에서 로드)
python tests/atr_sweep.py

# OHLCV DB 상태 확인 / 업데이트
python tests/ohlcv_db.py status
python tests/ohlcv_db.py update

변경 이력

날짜 변경 내용
2026-03-03 F&G 필터 추가 (FNG_MIN_ENTRY=41) — 1년 백테스트로 검증, 수익 +95K→+1.72M원
2026-03-03 F&G 정보 텔레그램 알림 통합 (매수/신호/상태 리포트)
2026-03-03 F&G API 캐시 TTL 24시간 (하루 1회 KST 09:00 업데이트)
2026-03-03 프로젝트 구조 정리: tests/ data/ logs/ 폴더 분리
2026-03-03 ecosystem.config.js 추가 — pm2 로그 경로 logs/ 통일
2026-03-03 BEAR_THRESHOLD -1.0% → -0.5% 강화 (완만한 하락장 오판 수정)
2026-03-03 속도 기반 조기 진입 추가 (VELOCITY_THRESHOLD=0.10%/분)
2026-03-03 신호 종목 fast-poll 스레드 추가 (SIGNAL_POLL_INTERVAL=15s)
2026-03-03 vol_ratio 강도별 진입 임계값 티어 추가 (5x→1%, 3.5x→2%, 2.5x→3%)