REDIS_URL의 socket_timeout(<5s)이 ReliableQueue BLMOVE 5초 블록보다 짧아 idle dequeue마다 "Timeout reading"으로 잡을 못 꺼내 슬레이트가 draft에 정지(~2026-05-22~). 큐 연결을 socket_timeout=None + socket_keepalive로 생성(make_queue_redis)해 정상화. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
web-ai
Windows AI 머신(AMD 9800X3D + RTX 5070 Ti 16GB)에서 동작하는 두 영역의 서비스:
- ai_trade — Confidence Signal Pipeline V2. NAS stock 백엔드와 KIS Open API를 결합해 매수/매도 신호를 생성하는 FastAPI 워커.
- services — NAS↔Windows 분산 렌더링 워커(인스타 카드 / 음악 / 영상 / 이미지) + task-watcher.
상위 워크스페이스 컨텍스트는 ../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 |
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:
chronos.median > 0chronos.q90 - chronos.q10 < 0.6(absolute spread)minute_momentum == strong_upasking_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 processing→attempts++후 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 보호) |
환경 변수 (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
.venv 한글 사용자 경로 깨짐으로 시스템 Python(C:\Users\jaeoh\AppData\Local\Programs\Python\Python312\python.exe) 사용 권장. 또는 py -3.12 -m pytest ….
알려진 함정
- KIS rate limit (EGW00201) — V1+V2 동시 실행 시 충돌. V1은
legacy/로 격리. ai_trade는asyncio.Lock으로 throttle 직렬화 (kis_client.py). .venv한글 경로 — 시스템 Python 사용.- Chronos FP16 overflow — 한국 주가 5만원+ 시 inf. FP32 강제됨.
- post-close 트리거 — 상태기반(
last_post_close_date)으로 변경됨. 16:00 이후 + 오늘 미실행이면 trigger. - services worker_id — env로 명시 권장. hostname 기반 default는 컨테이너 재기동 시 바뀌어 orphan 분실 위험.
- dead-letter 누적 —
redis-cli LLEN dead_letter:*정기 점검 필요. - Dockerfile build context —
services/루트 (각 worker 디렉토리 아님). compose 변경 동반.
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).
라이선스 / 사용
비공개. 박재오 개인 웹 플랫폼.