Files
tradeing/SOURCE_ANALYSIS.md
chpark c4e6aab7b2 React + FastAPI 풀 마이그레이션 — Streamlit 제거
- backend/ — FastAPI + JWT + 모든 REST 엔드포인트
- frontend/ — Next.js 14 + Tailwind + 7페이지 (대시보드/트레이드/거래소/자동매매/설정/내정보/로그인)
- core_logic.py — 신호계산/알림 로직 분리 (기존 app_streamlit.py 에서 추출)
- users_db.py + bcrypt 인증, exchange_keys.py + Fernet 암호화
- trades_db.py — 진입/청산 lifecycle 추적, signal_events raw 로그
- settings_db.py — 모든 운영 파라미터 DB 영속 저장 (RSI/거래량/펀딩비 임계값 포함)
- docker-compose: frontend / backend / postgres + Traefik 라우팅
- assets/logo.svg — JUNGGOMOA 그라디언트 로고

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 17:27:11 +09:00

13 KiB
Raw Permalink Blame History

BTC/ETH Futures Dashboard — 소스 분석

Streamlit 기반 Binance Futures 실시간 모니터링 대시보드. 차트 시각화 + 다중 시간축 자동 알림 (Telegram) + 일일 신호 통계 리포트를 한 프로세스에서 처리한다.


1. 파일 구성

파일 역할
app_streamlit.py 메인 앱 — 데이터 수집 / 지표 계산 / 신호 생성 / 차트 빌드 / 알림 스레드 / 사이드바 메뉴 (대시보드 / 트레이드 이력 / 설정)
alert_state.py 멀티 rerun 환경에서 살아남는 mutable 상태 (sys.modules 캐싱 활용)
settings_db.py SQLite key-value 설정 영속 저장 (텔레그램 토큰, 심볼, 시간축, 쿨다운, 손절가 비율, 알림 ON/OFF)
trades_db.py PostgreSQL 트레이드 lifecycle — trades (진입→청산), signal_events (raw 신호 로그). DATABASE_URL 미설정 시 silent no-op
Dockerfile / docker-compose.yml python:3.11-slim 컨테이너 + Postgres 16 + Traefik labels (junggomoa.com)
DEPLOY.md 서버 배포 절차
requirements.txt streamlit, pandas, numpy, plotly, ta, requests, python-dotenv, urllib3, psycopg2-binary
assets/override.css 라이트모드 강제 CSS
.env.example 환경변수 템플릿 (TELEGRAM_TOKEN, TELEGRAM_CHAT_ID)

2. 아키텍처 전체 흐름

┌─────────────── Streamlit 메인 프로세스 ───────────────┐
│                                                         │
│   ┌── UI Thread (main()) ──┐    ┌── Background Threads ─┐
│   │  매 rerun 마다 실행:    │    │  daemon thread × 2    │
│   │   - build_chart()      │    │                       │
│   │   - st.plotly_chart    │    │  _alert_loop          │
│   │   - time.sleep + rerun │    │   (30초 주기)          │
│   └────────────────────────┘    │                       │
│             │                    │  _daily_report_loop  │
│             ▼                    │   (60초 주기, KST 자정)│
│      ┌─────────────┐             └───────┬───────────────┘
│      │ alert_state │ ◀───────────────────┘
│      │ (sys.modules│
│      │   캐싱 보존) │
│      └─────────────┘
│                                                         │
│   외부 호출: Binance Futures API + Telegram Bot API     │
└─────────────────────────────────────────────────────────┘

핵심 설계 결정: Streamlit 의 매 rerun 은 메인 스크립트를 새 namespace 에서 재실행해 모듈 최상단 globals 가 모두 초기화된다. mutable 상태 ( dedup, 진입 추적, 스레드 가드 ) 는 alert_state.py 라는 별도 모듈에 두어 sys.modules 캐싱으로 process lifetime 동안 보존되도록 분리.


3. 모듈 상세

3.1 alert_state.py — 보존 상태

변수 타입 용도
last_alert dict[(interval, key), float] 알림 cooldown (default 600s)
last_fired_candle dict[(interval, key), Timestamp] per-candle dedup
long_entry / short_entry dict[interval, record] 진입 추적 (손절/청산 권고용)
pending_groups list[dict] forming candle 발사 후 신호 재검증 큐
synced_intervals set[str] 재시작 직후 역사적 신호 burst 차단용 sync 플래그
signal_seen_count dict[(interval, sig), {candle_time, count}] forming candle 의 연속 True polling 카운트 (false alert 차단)
alert_lock threading.Lock UI ↔ alert thread 공유 변수 보호
alert_started / daily_report_started bool 스레드 중복 기동 가드

3.2 app_streamlit.py 섹션 분해

(1) 환경 설정 & 페이지 셋업 — L1L70

  • st.set_page_config (반드시 import 직후)
  • 라이트모드 강제 CSS inline
  • 텔레그램 토큰 / 채팅 ID 는 os.getenv 로 로드
  • 핵심 상수:
    • STOP_LOSS_PCT = 0.0075 — 10x 레버리지 기준 ROI -7.5%
    • LONG_SIGNALS / SHORT_SIGNALS — 신호 분류 set
    • TF_LABEL_MAP — 11개 시간축 한글 라벨

(2) 텔레그램 송신 + 알림 코어 — L74L263

SIG_DEFS (9종 신호):

  • strong_long_signal / strong_short_signal — 다중 필터 통과
  • long_signal / short_signal — 일반 진입
  • vol_long_signal / vol_short_signal — 볼륨 급등
  • reversal_long_signal / reversal_short_signal — 추세 꺾임 감지
  • short_caution_signal — 극단 펀딩비 + OI 하락 (숏 주의)

check_and_alert(df, symbol, interval) — 알림 코어 로직:

  1. Phase 0 — silent sync (재시작 후 첫 polling): synced_intervals 미포함 시 모든 last_fired_candle 만 채우고 알림 skip → 역사적 신호 burst 방지
  2. Phase 1 — pending 검증: forming candle 에서 발사된 알림은 매 polling 마다 신호 잔존 여부 확인. 사라지면 즉시 [취소 알림] 발사 (캔들 마감까지 기다리지 않음)
  3. Phase 2 — 신호 검사:
    • tail(3) 만 검사
    • cooldown (10분) + per-candle dedup
    • forming candle 안정성: 연속 2 polls True 만 발사 (signal_seen_count) — 깜빡임 false alert 차단
    • 닫힌 캔들은 즉시 발사 (data 확정)
  4. Phase 3 — group 발사: long / short / caution 그룹별로 한번에 묶어서 송신. 진입가 / 손절가 표시
  5. Phase 4 — 청산 권고: 30m / 1h 의 새 진입 신호만 반대 방향 진입에 대한 [반대 신호 감지 - 청산 권장] 트리거 (5m / 15m 은 노이즈 多 → 폭주 방지)
  6. Phase 5 — 손절가 알림: 현재가가 추적 중 진입의 stop 을 침범하면 [손절가알림] 송신

(3) Binance 데이터 수집 — L267L311

함수 엔드포인트 반환
get_klines /fapi/v1/klines OHLCV + taker buy/sell volume
get_funding_rate /fapi/v1/fundingRate FR (%, 100배 환산)
get_open_interest_history /futures/data/openInterestHist OI
get_long_short_ratio /futures/data/topLongShortPositionRatio 탑트레이더 L/S ratio
get_taker_buy_sell_ratio /futures/data/takerlongshortRatio (코드상 정의되나 차트엔 미사용)

모든 시각은 KST (+9h).

(4) 지표 + 신호 계산 — L315L450

compute_indicators(df, interval) — 표준 TA:

  • MA 7 / 25 / 99 / 200
  • BB (20, 2σ) — mid / upper / lower
  • RSI(14), StochRSI(14, 3, 3)
  • MACD(12, 26, 9) — line / signal / histogram
  • ATR(14)

compute_signals(df, interval) — 신호 정의:

신호 조건
long_signal bull_ma_2 (close > MA7 & MA25) & RSI<75 & MACD_hist↑ & close > BB_mid & body% ≥ +0.2%
short_signal bear_ma_2 & RSI>25 & MACD_hist↓ & close < BB_mid & body% ≤ -0.2%
strong_long_signal bull_ma_2 & RSI<65 & MACD_hist↑ & oi_up_2 & taker_buy_2 & fr_long_favor & 양봉
strong_short_signal bear_ma_2 & RSI>35 & MACD_hist↓ & oi_down_2 & taker_sell_2 & fr_short_favor & 음봉
vol_long_signal buy_net > avg×2 & taker_buy_vol > min × oi_active (interval 별 min 가변)
vol_short_signal sell_net 동일 미러
short_caution_signal oi_down_2 & FR ≤ -0.007% (극단 음수)
reversal_long/short_signal 직전 3봉 추세 반대 +
exhaustion_long/short 직전봉 거래량 spike (vol > avg×3) + 매도/매수 우세

쿨다운: 신호별로 rolling(N, sum).shift(1)==0 패턴으로 N봉 내 중복 차단.

MA 정렬 요구 완화: 추세 반전 직후엔 MA7>MA25 정렬이 늦게 형성되어 bull_ma (3중 정렬) 대신 bull_ma_2 (2중 정렬) 만 요구. (커밋 d49ac84)

(5) 차트 빌드 — L455L741

build_chart(symbol, interval, candle_limit):

  • 7-row Plotly subplot:
    1. 메인 — Candlestick + BB + MA7/25/99/200 + 모든 신호 마커 + Taker buy/sell 점 + L/S / FR / OI 오버레이
    2. Taker Buy/Sell Volume (Net Bar)
    3. Open Interest
    4. Funding Rate Bar (±0.5% / -0.7% 가이드 라인)
    5. Long/Short Ratio (탑트레이더)
    6. RSI / StochRSI (20/50/80 가이드)
    7. MACD (Line + Signal + Histogram)

데이터 머지: OI / FR / L/S 는 시간 정렬 후 floor() + merge + ffill. FR 은 1h 기준, 나머지는 interval (혹은 5m fallback) 기준.

1시간 추세 컨텍스트: 비-1h 시간축에서 별도로 1h 캔들 가져와 h1_bull/bear 컬럼을 생성, 같은 일자 안에서 ffill 로 채움 (현재 코드에선 차트 표시 X — 보존만).

신호 마커:

  • 롱 → low × 0.9998 위치, 위 화살표
  • 숏 → high × 1.0002 위치, 아래 화살표
  • caution → diamond, exhaustion → star

축 자동 스케일: tight() + 분위수 기반.

(6) 알림 백그라운드 스레드 — L774L786

ALERT_TIMEFRAMES = ["5m", "15m", "30m", "1h"]
def _alert_loop():
    while True:
        for interval in ALERT_TIMEFRAMES:
            df = _build_signal_df(symbol, interval, 200)
            check_and_alert(df, symbol, interval)
        time.sleep(30)

UI 에서 선택한 symbol 만 추적 (alert_state.alert_symbol, lock 으로 보호). 4개 시간축 모두 동시 모니터링.

(7) 일일 리포트 — L791L1005

KST 자정 통과 감지 시 4종 텔레그램 메시지 발송:

  1. 24h 신호 통계 (1배 시간) — 다음 봉에 반대 신호 떴는지 T/F 카운트 + 승률
  2. 24h 신호 통계 (2배 시간) — 2번째 봉 검증
  3. 손절가 터치 횟수 — 진입 시 ±STOP_LOSS_PCT 가격이 이후 3봉 안에 터치됐는지
  4. 추세 꺾임 감지 통계 — 3봉 후 close 가 의도한 방향으로 갔는지

리포트 시간축: ["5m", "15m", "30m", "1h", "4h"]. 각 시간축 별 DAILY_REPORT_KLINES_LIMIT 만큼 가져와 24h 윈도우 분석.

(8) 메인 UI — L1010L1085

  • 5-column 헤더: 심볼 / 시간축 / 갱신주기(초) / 새로고침·자동갱신·범례·모바일 토글
  • Candle 수: 데스크톱 53, 모바일 14 (mobile_mode 토글)
  • 펀딩비 경고 배너 (≤-0.7% 위험 / ≤-0.5% 경보 / ≥+0.5% 롱 과열)
  • Plotly 차트: scrollZoom, doubleClick reset
  • auto 활성화 시 time.sleep(refresh_sec) + st.rerun()

4. 동시성 / 안전성 설계

위험 요소 대응
Streamlit rerun 마다 globals 초기화 alert_state 모듈 분리 (sys.modules 캐싱)
스레드 중복 기동 alert_started / daily_report_started bool 가드
UI ↔ alert thread 변수 충돌 alert_state.alert_lock
재시작 직후 역사적 신호 burst synced_intervals silent sync (첫 polling 은 dedup 만 채우고 alert 미발사)
forming candle 깜빡임 false alert signal_seen_count 연속 2 polls True 요구
forming candle 발사 후 신호 사라짐 pending_groups Phase 1 검증 → [취소 알림] 즉시 발사
청산 권고 폭주 (변동성 큰 날) 30m / 1h 만 트리거
Binance API 일시 오류 try/except 로 모든 보조 API 감싸고 pass (메인 klines 만 필수)

5. 환경 / 실행

pip install -r requirements.txt
cp .env.example .env  # TELEGRAM_TOKEN, TELEGRAM_CHAT_ID 채우기
streamlit run app_streamlit.py

기본 포트 8501. 환경변수 미설정 시 알림은 silent fail (콘솔에만 에러 출력).


6. 개선 가능 지점 (관찰만)

  • 신호 컬럼 마커 분기 로직 (L604–L641)pd.Series([False]*len(df)) fallback 패턴 반복. helper 추출 가능.
  • OI / FR / L/S 머지 로직 (L479L510, L750L770) — 4번 비슷하게 반복. merge_external_metric() 함수로 추출 가능.
  • get_taker_buy_sell_ratio — 정의돼 있으나 호출처 없음 (dead code).
  • exhaustion_long/shortcompute_signals 에서 계산되나 SIG_DEFS / 알림 대상엔 미포함 (차트 마커로만 표시).
  • h1_bull/bear 컨텍스트 — 계산되나 차트/신호에서 사용 X.
  • requests.get(verify=False) + urllib3.disable_warnings — TLS 검증 비활성. 운영 환경에선 검토 필요.
  • recent = df.tail(3) — 30초 폴링 + N분 캔들이라 충분하지만, 순간적 네트워크 지연 시 초과 시간축에서는 신호 누락 가능.