gahusb 5dbb11ac83 fix(trade-monitor): sell_climax holdings_intel 정합
BE 회신(holdings_intel.py:109-118)에 맞춰 반전 기준을
price<day_open → price<day_high×climax_close_pct(윗꼬리)로 변경.
- kis_client.get_quote에 day_high(stck_hgpr) 추가
- monitor._build_ctx가 day_high를 ctx로 전달
- climax_vol_x·climax_close_pct를 monitor-set exit_params에서 읽기
  (fallback: TM_CLIMAX_VOL_MULT/0.97)
- 테스트 36/36 (climax exit_params 2건 추가)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N83vbXEA8h83GMXQcg8fxD
2026-07-03 11:15:27 +09:00

web-ai

Windows AI 머신(AMD 9800X3D + RTX 5070 Ti 16GB)에서 동작하는 두 영역의 서비스:

  1. ai_trade — Confidence Signal Pipeline V2. NAS stock 백엔드와 KIS Open API를 결합해 매수/매도 신호를 생성하는 FastAPI 워커.
  2. services — NAS↔Windows 분산 워커: 렌더링(인스타 카드 / 음악 / 영상 / 이미지) + task-watcher + trade-monitor(실시간 매매 알람).

상위 워크스페이스 컨텍스트는 ../CLAUDE.md, 본 디렉토리 상세는 CLAUDE.md, 운영 체크포인트는 CHECK_POINT.md 참조.


디렉토리 구조

경로 역할 포트
ai_trade/ 자동매매 메인. Chronos-bolt(또는 Chronos-2) + 분봉 모멘텀 + KIS WebSocket 호가 + 매수/매도 신호 생성기. :8001
services/_shared/ 4개 render worker 공통 모듈 (ReliableQueue — BLMOVE + ack/fail + recovery).
services/insta-render/ Instagram 카드 Playwright 렌더 워커. NAS Redis queue:insta-render 소비. :18710
services/music-render/ Suno + MusicGen 음악 생성 워커. queue:music-render 소비. :18711
services/video-render/ sora / veo / kling / seedance 4 provider 영상 생성 게이트웨이. queue:video-render 소비. :18712
services/image-render/ gpt_image / nano_banana / flux(ComfyUI 로컬) 3 provider. queue:image-render 소비. :18714
services/task-watcher/ 박재오 작업 시간대에 queue:paused 토글 → 워커 일시 정지. :18713
services/trade-monitor/ 실시간 매매 알람. monitor-set pull → KIS 시세 + TA 조건(§6 8종) → report + heartbeat(kind=trader). 무상태. :18715
legacy/signal_v1/ DEPRECATED (2026-05-19). LSTM 봇. 자동 실행 차단됨. OFF

ai_trade — Confidence Signal Pipeline V2

NAS stock 백엔드(:18500)에서 portfolio / news_sentiment / screener를 pull하고, KIS REST/WebSocket으로 분봉·호가를 보강한 뒤 Chronos 예측과 5분봉 모멘텀 분류로 매수/매도 신호를 생성한다.

매수 (screener Top-N + portfolio)

모두 충족 시 confidence 계산 → threshold 초과 시 emit:

  1. chronos.median > 0
  2. chronos.q90 - chronos.q10 < 0.6 (absolute spread)
  3. minute_momentum == strong_up
  4. asking_price.bid_ratio >= 0.6

종합 confidence = chronos_conf * 0.5 + minute_score * 0.3 + screener_norm * 0.2. > 0.7 시 emit.

매도 (portfolio only, 우선순위 stop_loss → anomaly → take_profit)

  • stop_loss: pnl_pct < -7% 즉시 (confidence=1.0)
  • anomaly: chronos.median < -1% + strong_down + bid_ratio < 0.4 + 종합 conf > 0.7
  • take_profit: pnl_pct > 15% 검토 (confidence=0.6)

핵심 파일

파일 책임
main.py FastAPI app + lifespan (의존성 wiring) + poll_loop task 생성
config.py Settings dataclass — 환경변수 로드
state.py PollState (process-wide singleton) — portfolio·screener·signals 등 + get_active_signals / purge_expired_signals
stock_client.py NAS stock 백엔드 pull (X-WebAI-Key + 메모리 캐시)
kis_client.py KIS REST 분봉/호가 + asyncio.Lock 직렬화 + 지수 backoff
kis_websocket.py KIS WebSocket 호가 + approval_key + 재연결
chronos_predictor.py HuggingFace Chronos zero-shot 분위수 예측 (FP32 강제)
minute_momentum.py 5분봉 → strong_up / weak_up / neutral / weak_down / strong_down
signal_generator.py 매수/매도 룰 엔진. cycle_id + expires_at 부착
pull_worker.py asyncio cron — 시간대별 분기 + post-close 트리거 + signal 생성 + expired purge
scheduler.py 폴링 윈도우 판정 (KST 캘린더 + 휴장일)
rate_limit.py 초당 N회 token bucket + SignalDedup SQLite WAL

시작

cd ai_trade
start.bat

Uvicorn running on http://0.0.0.0:8001, poll_loop started.

휴장일/장 외 시간엔 poll_loop만 idle.

헬스 / 로그

curl http://localhost:8001/health
Get-Content logs\ai_trade.log -Wait
nvidia-smi

services — NAS↔Windows 분산 워커

NAS측 lab 서비스(insta-lab / music-lab / video-lab / image-render NAS측)가 queue:<worker>-render 에 LPUSH로 작업을 enqueue. Windows worker가 BLMOVE로 atomic dequeue 후 처리, 완료 시 NAS internal webhook으로 결과 통지.

신뢰성 패턴 (_shared.ReliableQueue)

  • dequeue: BLMOVE main → processing:<queue>:<worker_id> (atomic).
  • ack: LREM processing 1 raw (성공).
  • fail: LREM processingattempts++ 후 main 재큐 또는 max_attempts 도달 시 dead_letter:<queue> 이동.
  • recover: startup 시 자신의 processing list orphan을 main queue로 (attempts 증가).

시작 (NAS, WSL2 Docker)

cd services
docker compose up -d insta-render music-render video-render image-render task-watcher

build context는 services/ 루트. 각 Dockerfile은 _shared 모듈을 함께 COPY하고 PYTHONPATH=/app.

운영 조작

# 워커 일시 정지 / 재개
redis-cli -h 192.168.45.54 SET queue:paused 1
redis-cli -h 192.168.45.54 DEL queue:paused

# 큐 / dead-letter 점검
redis-cli -h 192.168.45.54 LLEN queue:insta-render
redis-cli -h 192.168.45.54 LLEN dead_letter:queue:insta-render
redis-cli -h 192.168.45.54 KEYS 'processing:*'

환경 변수

변수 용도
REDIS_URL NAS Redis (redis://192.168.45.54:6379)
NAS_BASE_URL NAS 대상 서비스 URL (insta-lab :18700, music-lab :18600, video-lab :18801, image-render NAS측 :18802)
INTERNAL_API_KEY NAS internal webhook 인증
WORKER_ID (권장) <service>-prod-1 등 영속 ID. hostname 기반 default는 컨테이너 재기동 시 바뀌어 orphan 추적 불가
OPENAI_API_KEY / GEMINI_API_KEY / KLING_* / SEEDANCE_API_KEY / SUNO_API_KEY 각 provider 인증
COMFYUI_URL image-render FLUX 로컬 ComfyUI (http://host.docker.internal:8188)
FLUX_BLOCK_TRADING_HOURS 1 이면 장중(09:00~15:30) FLUX 차단 (Chronos GPU 보호)

trade-monitor — 실시간 매매 알람 워커 (신규 2026-07-03)

NAS stock 백엔드(:18500)에서 monitor-set을 60초마다 pull하고, KIS 실시간/일봉 시세로 TA 조건을 평가해 발화집합을 report로 전송. NAS가 edge diff로 신규 알림만 텔레그램/프론트에 노출. 워커 무상태(dedup은 NAS 영속). 포트 :18715, WSL2 Docker. 상세 설계·조건 규칙은 services/trade-monitor/DESIGN.md.

루프 (1분)

  1. GET /api/webai/trade-alert/monitor-set (X-WebAI-Key) → buy_targets(watchscreener) + sell_targets(보유 avg_price/qty/holding_high) + buy_params/exit_params + session.
  2. session=="closed"면 KIS 호출 0, idle. 비-KRX(알파벳) 티커 skip(워커 책임).
  3. KIS quote + 일봉 250봉 → 지표 계산 → 조건 평가(종목 단위 실패 격리).
  4. POST /api/webai/trade-alert/report {as_of, firing:[...]} — 빈 배열도 전송(edge clear).
  5. heartbeat worker:trade-monitor:heartbeat EX45 (kind=trader, state=market_open|market_closed|idle + last_alert_at). 60초 루프 > TTL45 만료갭 회피 위해 15초 독립 태스크.

조건 (§6 — condition 문자열이 FE 라벨/뱃지로 그대로 매핑됨)

  • 매수: buy_ma20_pullback(정배열 + ma20 근접 반등), buy_breakout(20봉 고점 돌파 + 거래량 배수), buy_rsi_bounce(RSI 과매도 반등, 무상태).
  • 매도: sell_stop_loss, sell_take_profit, sell_trailing_stop, sell_ma_break(ma50/ma200 severity), sell_climax(거래량 급증 + 윗꼬리 — holdings_intel 정합 예정).

핵심 파일

파일 책임
config.py Settings (TM_ 접두사, ai_trade와 분리)
indicators.py 순수: sma / rsi_series(Wilder) / highest_high
conditions.py 순수 §6: evaluate_buy / evaluate_sell
kis_client.py KIS 자체 OAuth 토큰 + get_quote + get_daily_ohlcv + 0.5s throttle
nas_client.py monitor-set / report (X-WebAI-Key + retry)
monitor.py run_cycle / monitor_loop / make_state_fn
main.py FastAPI lifespan + _shared.heartbeat_loop 배선 + /health

환경 변수

변수 기본 설명
NAS_BASE_URL http://192.168.45.54:18500 stock 백엔드
WEBAI_API_KEY (필수) X-WebAI-Key
REDIS_URL redis://192.168.45.54:6379 heartbeat
TM_KIS_APP_KEY / TM_KIS_APP_SECRET / TM_KIS_ACCOUNT (필수) KIS 전용 자체 토큰(ai_trade와 분리 발급 → 토큰 상호 무효화·EGW00201 회피)
TM_KIS_IS_VIRTUAL 0 실전/모의
TM_LOOP_INTERVAL 60 루프 주기(초)
TM_CLIMAX_VOL_MULT 3.0 sell_climax 거래량 배수 (→ monitor-set exit_params.climax_vol_x로 중앙화 예정)

상태

구현·머지 완료(테스트 34/34), 미배포. 배포 전: ① 전용 KIS 앱키 발급·주입(박재오 진행 중) ② sell_climax holdings_intel 정합(price < day_high × 0.97 + exit_params 파라미터화) ③ 첫 운영 KIS 필드 검증. BE가 node_monitor.WORKER_REGISTRY에 등재 완료 → 배포 시 /api/agent-office/nodes·web-ui /infra에 trader 노드 자동 노출(미배포 동안 down, 무경보).

시작 (NAS, WSL2 Docker)

cd services
docker compose up -d trade-monitor

환경 변수 (ai_trade)

변수 기본 설명
STOCK_API_URL (필수) NAS stock 백엔드 base URL
WEBAI_API_KEY (필수) stock 백엔드 호출 시 X-WebAI-Key
SIGNAL_V2_PORT 8001 uvicorn 포트
KIS_ENV_TYPE virtual virtual / real
KIS_REAL_APP_KEY / KIS_REAL_APP_SECRET / KIS_REAL_ACCOUNT KIS 실계좌
KIS_VIRTUAL_APP_KEY / KIS_VIRTUAL_APP_SECRET / KIS_VIRTUAL_ACCOUNT KIS 모의계좌
V1_TOKEN_PATH legacy/signal_v1/data/kis_token.json KIS 토큰 파일 (V1 토큰 read-only 공유)
CHRONOS_MODEL amazon/chronos-2 Chronos 모델 ID
STOP_LOSS_PCT -0.07 손절 임계
TAKE_PROFIT_PCT 0.15 익절 임계
CHRONOS_SPREAD_THRESHOLD 0.6 매수 hard gate spread 상한
ASKING_BID_RATIO_THRESHOLD 0.6 매수 hard gate 호가 비율
CONFIDENCE_THRESHOLD 0.7 매수 종합 confidence 하한
MIN_MOMENTUM_FOR_BUY strong_up 매수 hard gate 모멘텀 단계
SIGNAL_TTL_SECONDS 300 emit signal expires_at TTL

.env 는 web-ai 루트 (이 디렉토리)에 둔다. 절대 커밋 금지.


테스트

# ai_trade
python -m pytest ai_trade/tests -q

# services/_shared 공통 모듈
cd services/_shared && python -m pytest tests/ -q

# 각 worker
cd services/insta-render && python -m pytest tests/ -q
cd services/music-render && python -m pytest tests/ -q
cd services/video-render && python -m pytest tests/ -q
cd services/image-render && python -m pytest tests/ -q
cd services/trade-monitor && python -m pytest tests/ -q   # 34 tests

.venv 한글 사용자 경로 깨짐으로 시스템 Python(C:\Users\jaeoh\AppData\Local\Programs\Python\Python312\python.exe) 사용 권장. 또는 py -3.12 -m pytest ….


알려진 함정

  1. KIS rate limit (EGW00201) — V1+V2 동시 실행 시 충돌. V1은 legacy/로 격리. ai_trade는 asyncio.Lock으로 throttle 직렬화 (kis_client.py).
  2. .venv 한글 경로 — 시스템 Python 사용.
  3. Chronos FP16 overflow — 한국 주가 5만원+ 시 inf. FP32 강제됨.
  4. post-close 트리거 — 상태기반(last_post_close_date)으로 변경됨. 16:00 이후 + 오늘 미실행이면 trigger.
  5. services worker_id — env로 명시 권장. hostname 기반 default는 컨테이너 재기동 시 바뀌어 orphan 분실 위험.
  6. dead-letter 누적redis-cli LLEN dead_letter:* 정기 점검 필요.
  7. Dockerfile build contextservices/ 루트 (각 worker 디렉토리 아님). compose 변경 동반.
  8. 분산 워커 /infra 관측 필수 (팀 규칙) — 모든 WSL docker 워커는 heartbeat(worker:<name>:heartbeat EX45) + BE node_monitor.WORKER_REGISTRY 등재 + /infra 노출이 필수. trade-monitor는 kind=trader로 등재됨.
  9. trade-monitor KIS 앱키 분리 — ai_trade와 다른 전용 app_key(TM_KIS_*) 사용. 같은 app_key 공유 시 토큰 상호 무효화 + EGW00201. 실전 최대 89앱 발급 가능.

Phase 진행 상태 (Confidence Signal Pipeline V2)

Phase 내용 상태
0 Architecture & contract spec
1 stock 백엔드 WebAI API 보강 (NAS)
1.5 V1 → signal_v1/ rename → legacy/ 격리
2 ai_trade pull worker + signal API client + scheduler
3a KIS REST 분봉 + WebSocket 호가 + NXT 스케줄
3b Chronos-bolt-base 추론 + 5분봉 모멘텀 분류기
4 Signal Generator + 로깅
4.5 코드 리뷰 F1-F6 hotfix (토큰 경로 / throttle Lock / post-close 상태기반 / Chronos abs / state.signals lifecycle / render queue 신뢰성)
5 agent-office /signal + Ollama Qwen3 14B + 이중 텔레그램
6 signal_v1 deprecation (legacy 완료, 아카이브만 남음) 일부
7 운영 모니터링 + 4주 IC 검증

상세 spec/plan은 ../web-ui/docs/superpowers/specs/ / ../web-ui/docs/superpowers/plans/ (별도 repo).


라이선스 / 사용

비공개. 박재오 개인 웹 플랫폼.

Description
No description provided
Readme 12 MiB
Languages
Python 95.7%
Jinja 3.8%
Dockerfile 0.5%