Atomic mv of root V1 assets (main_server.py + modules/ + data/ + tests/ + entry scripts + docs + logs) into signal_v1/ subdirectory. load_dotenv() updated to load web-ai/.env explicitly via Path. Adds web-ai/CLAUDE.md (workspace guide) and web-ai/start.bat (signal_v1 entry wrapper). Prepares for signal_v2/ Phase 2. Tests: signal_v1/tests/unit baseline preserved (no regression). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
31 KiB
31 KiB
🤖 AI Trading Bot — 프로젝트 설계 문서 (CLAUDE.md)
최종 갱신: 2026-03-19 런타임: Windows (Python 3.x, PyTorch CUDA, FastAPI, Ollama)
하드웨어: AMD 9800X3D + RTX 5070 Ti (16 GB VRAM)
1. 시스템 아키텍처 개요
┌──────────────────────────────────────────────────────────────────┐
│ main_server.py │
│ FastAPI (uvicorn, port 8000) — 프로세스 매니저 & REST API 서버 │
│ ┌──────────────┐ ┌─────────────────┐ ┌──────────────────────┐ │
│ │ Trading Bot │ │ Telegram Bot │ │ ProcessWatchdog │ │
│ │ (Process #1) │ │ (Process #2) │ │ (Daemon Thread) │ │
│ └──────┬───────┘ └────────┬────────┘ └──────────┬───────────┘ │
│ │ │ │ │
│ └─── Shared Memory (IPC) ───┘ Health Check / Restart │
│ + Command Queue │
└──────────────────────────────────────────────────────────────────┘
1.1 멀티 프로세스 구성
| 프로세스 | 역할 | 진입점 |
|---|---|---|
| Main Server (Uvicorn) | FastAPI REST API 서버, 프로세스 오케스트레이터 | main_server.py |
| Trading Bot | 자동매매 메인 루프 (스케줄러, 분석, 주문) | modules/bot.py → AutoTradingBot.loop() |
| Telegram Bot | 사용자 인터랙션 (명령어 처리, 알림) | modules/services/telegram_bot/runner.py |
| ProcessWatchdog | 자식 프로세스 헬스체크 & 자동 재시작 (30초 간격) | modules/utils/process_tracker.py |
1.2 프로세스 간 통신 (IPC)
┌─────────────┐ SharedMemory (128KB) ┌──────────────┐
│ Trading Bot │ ─── write_status() ───────► │ Telegram Bot │
│ │ ◄── read_status() ──────── │ │
│ │ │ │
│ │ multiprocessing.Queue │ │
│ │ ◄── send_command() ──────── │ │
│ │ (텔레그램 → 봇 명령) │ │
└─────────────┘ └──────────────┘
- SharedMemory (
web_ai_bot_ipc, 128KB): 메인 봇이 상태 데이터(잔고, GPU, 매크로 지표 등)를 JSON으로 기록, 텔레그램 봇이 읽기 - Command Queue (
multiprocessing.Queue): 텔레그램 → 메인 봇 양방향 명령 채널 (restart,evaluate등) - Lock (
multiprocessing.Lock): SharedMemory 동시 접근 보호 - IPC Staleness: 600초 (10분 이상 오래된 데이터는 무시)
1.3 서버 생명주기 (Lifespan)
# main_server.py > lifespan()
1. Config.validate() # 환경변수 검증
2. ProcessTracker.check_and_kill_zombies() # 좀비 프로세스 정리
3. 전역 객체 초기화 (OllamaManager, KISClient, NewsCollector)
4. Shared Resources 생성 (Lock, Queue, Event)
5. Trading Bot 프로세스 생성 & 시작
6. Telegram Bot 프로세스 생성 & 시작
7. ProcessWatchdog 시작 (30초 간격 헬스체크)
8. → yield (서버 정상 운영)
9. [종료] shutdown_event 설정 → 자식 종료 → SharedMemory 해제
2. 디렉토리 구조
web-ai/
├── main_server.py # [Entry Point] FastAPI + 프로세스 매니저
├── warmup_and_restart.py # LSTM 사전학습 + 봇 자동 시작 스크립트
├── watchlist_manager.py # 뉴스 기반 일일 Watchlist 자동 업데이트
├── backtester.py # 전략 백테스팅 CLI
├── theme_manager.py # 종목별 테마/섹터 관리
├── .env # 환경변수 (KIS, Telegram, Ollama 등)
│
├── modules/
│ ├── __init__.py
│ ├── config.py # [Config] 환경변수 & 상수 정의
│ ├── bot.py # [Core] AutoTradingBot (상태 머신 & 스케줄러)
│ │
│ ├── analysis/ # [AI Brain] 분석 엔진
│ │ ├── deep_learning.py # Attention-LSTM (7D 피처, PyTorch GPU)
│ │ ├── technical.py # 기술적 지표 (RSI, MACD, BB, ADX, OBV...)
│ │ ├── macro.py # 거시경제 분석 (KOSPI/KOSDAQ/MSI)
│ │ ├── ensemble.py # 적응형 앙상블 (3신호 가중치 자동조정)
│ │ ├── evaluator.py # 주간 성과 평가 + LLM 전문가 패널
│ │ └── backtest.py # 백테스팅 프레임워크 (Sharpe, MDD 등)
│ │
│ ├── strategy/ # [Decision] 매매 의사결정
│ │ └── process.py # 워커 프로세스용 분석 함수 (병렬 처리)
│ │
│ ├── services/ # [I/O] 외부 서비스 연동
│ │ ├── kis.py # 한국투자증권 REST API (동기 + 비동기)
│ │ ├── ollama.py # Ollama LLM 인터페이스 (GPU 충돌 방지)
│ │ ├── news.py # Google News RSS 크롤링 (동기 + 비동기)
│ │ ├── telegram.py # 텔레그램 메시지 발송 (Fire-and-forget)
│ │ └── telegram_bot/
│ │ ├── server.py # 텔레그램 봇 서버 (명령어 핸들러)
│ │ └── runner.py # 텔레그램 봇 독립 프로세스 실행기
│ │
│ └── utils/ # [Util] 유틸리티
│ ├── ipc.py # SharedMemory + Command Queue IPC
│ ├── process_tracker.py # PID 추적 & 좀비 정리 & Watchdog
│ ├── monitor.py # CPU/GPU/RAM 서킷 브레이커
│ └── performance_db.py # 일별 스냅샷 & 매매 기록 영구 저장
│
├── data/ # [Runtime Data]
│ ├── watchlist.json # 현재 감시 종목 리스트
│ ├── daily_trade_history.json # 일일 매매 기록
│ ├── kis_token.json # KIS OAuth 토큰 캐시
│ ├── peak_prices.json # 트레일링 스탑용 최고가
│ ├── ensemble_history.json # AdaptiveEnsemble 가중치 + 매매 히스토리 (종목별)
│ ├── models/ # LSTM 체크포인트 (종목별 .pt 파일)
│ └── performance/ # 성과 데이터 (daily_snapshots, trade_records)
│
└── tests/ # 테스트
3. 핵심 모듈 상세
3.1 AutoTradingBot (modules/bot.py)
메인 트레이딩 루프 — 장 시작(09:00) ~ 장 마감(15:30) 사이에 자동 실행
[v3.1 주요 기능]
├── ATR 기반 동적 손절/익절 + 트레일링 스탑
├── Kelly Criterion 포지션 사이징 (실전 승률·손익비 기반, Half-Kelly)
├── AdaptiveEnsemble 연동 (매도 후 가중치 자동 학습)
├── 당일 누적 매수 추적 (_today_buy_total) - KIS T+2 미차감 보완
├── 사이클당 최대 매수 종목 수 제한 (MAX_BUY_PER_CYCLE)
├── ProcessPoolExecutor 병렬 분석 (워커 1개, OOM 대응 자동 재시작)
├── 일별 자산 스냅샷 (09:05~09:15)
├── 주간 성과 평가 (월요일 아침)
├── CPU 서킷 브레이커 연동
└── IPC Command Queue 폴링 (텔레그램 명령 처리)
잔고 추적 로직 (v3.1 — 과매수 방지):
KIS get_balance() → raw_deposit (dnca_tot_amt)
↓
max_daily_buy = raw_deposit × MAX_DAILY_BUY_RATIO (80%)
tracking_deposit = max_daily_buy - effective_today_buy
↑
max(kis_today_buy, self._today_buy_total)
(KIS thdt_buy_amt vs 로컬 누적 중 큰 값)
_today_buy_total: 인스턴스 변수, 사이클 간 유지 (09:00 리셋)_buy_scores: BUY 시 신호 점수 저장 → SELL 시record_trade()전달
run_cycle() 흐름:
- 시스템 헬스 체크 (CPU/GPU/RAM)
- 거시경제 분석 (KOSPI/KOSDAQ/MSI)
- 위험 상태별 분기 (SAFE/CAUTION/DANGER)
- Watchlist 종목 OHLCV 수집 (KIS 비동기 배치)
- 잔고 조회 + 당일 누적 매수 차감 → 실제 가용 예수금 계산
ProcessPoolExecutor로 종목 병렬 분석 (Kelly Criterion + Ensemble 가중치)- 앙상블 점수 기반 매수/매도 판단 (사이클당 MAX_BUY_PER_CYCLE 제한)
- 주문 실행 & 결과 텔레그램 알림
- 매도 시
record_trade()→ Ensemble 가중치 학습 - IPC 상태 갱신
3.2 AI 분석 파이프라인
┌─────────────────────┐
│ analyze_stock_ │
│ process() │
│ (strategy/process)│
└─────────┬───────────┘
│
┌─────────────────────┼────────────────────┐
▼ ▼ ▼
┌───────────────┐ ┌────────────────┐ ┌─────────────────┐
│ Technical │ │ Deep Learning │ │ LLM (Ollama) │
│ Analyzer │ │ LSTM │ │ Sentiment │
│ (기술적 지표) │ │ (주가 예측) │ │ (뉴스 감성분석) │
├───────────────┤ ├────────────────┤ ├─────────────────┤
│ RSI 25% │ │ Attention-LSTM │ │ qwen2.5:7b │
│ 이격도 15% │ │ 4L×512H │ │ JSON 포맷 요청 │
│ MACD 15% │ │ 7차원 피처 │ │ 뉴스+지표 통합 │
│ Stochastic 5% │ │ 60일 시퀀스 │ │ 감성+신뢰도 │
│ BB 15% │ │ GPU 가속 │ │ │
│ ADX 15% │ │ 종목별 모델 │ │ │
│ MTF 10% │ │ (ModelRegistry)│ │ │
│ OBV ±보너스 │ │ │ │ │
└───────┬───────┘ └───────┬────────┘ └───────┬─────────┘
│ │ │
└──────────┬────────┘ │
▼ │
┌─────────────────┐ │
│ AdaptiveEnsemble│ ◄───────────────────┘
│ (학습형 가중치) │
├─────────────────┤
│ get_weights() │ ← 과거 매매 결과 반영
│ (ADX+macro+conf)│ 크기 가중 정확도 기준
│ 경계: 0.10~0.65 │ Water-Filling 정규화
│ Kelly Fraction │ ← 승률·손익비 기반
└────────┬────────┘
▼
┌────────────────┐
│ 매수/매도/홀드 │
│ 최종 판단 │
└────────────────┘
3.2.1 Deep Learning — Attention-LSTM (analysis/deep_learning.py)
| 항목 | 값 |
|---|---|
| 아키텍처 | 4-Layer Stacked LSTM + Attention + FC |
| Hidden Size | 512 |
| Input Features | 7 (close, open, high, low, volume_norm, rsi_14, macd_hist) |
| 시퀀스 길이 | 60일 |
| 학습 에포크 | 최대 200 (Early Stopping patience=15) |
| 빠른 재학습 | 30 에포크 (체크포인트 존재 시) |
| 쿨다운 | 1200초 (20분, 동일 종목 재학습 방지) |
| ModelRegistry | LRU 방식, 최대 5개 모델 동시 적재 |
| 체크포인트 | data/models/{ticker}_v3.pt |
| GPU 관리 | LSTM 학습 시 Ollama 자동 언로드/리로드 |
3.2.2 기술적 분석 (analysis/technical.py)
TechnicalAnalyzer.get_technical_score() → 0.0 ~ 1.0 통합 점수
| 지표 | 비중 | 설명 |
|---|---|---|
| RSI (14일) | 25% | Wilder 방식, 30 이하 과매도/70 이상 과매수 |
| 이동평균 이격도 | 15% | 20일 MA 대비 현재가 위치 |
| MACD | 15% | 12/26/9, 히스토그램 방향 |
| Stochastic | 5% | Fast %K/%D (14/3/3) |
| Bollinger Bands | 15% | 20일/2σ, %B 위치 + 밴드폭 |
| ADX | 15% | 추세 강도 (>25 강한 추세) |
| Multi-Timeframe | 10% | 5일/20일/60일 추세 일관성 |
| OBV | ±0.1 보너스 | 거래량 기반 매집/분산 감지 |
추가 기능:
calculate_atr()→ ATR 기반 동적 손절/익절calculate_dynamic_sl_tp()→ 변동성 적응형 SL/TPcalculate_obv()→ 스마트 머니 다이버전스 감지
3.2.3 거시경제 분석 (analysis/macro.py)
MacroAnalyzer.get_macro_status(kis_client) → {
"status": "SAFE" | "CAUTION" | "DANGER",
"risk_score": int,
"indicators": {
"KOSPI": {"price", "change", "high", "low", "prev_close", "volume"},
"KOSDAQ": {"price", "change", ...},
"KOSPI200":{"price", "change", ...},
"MSI": float # Market Stress Index (0~100)
}
}
- SAFE (risk_score < 1): 정상 매매
- CAUTION (1 ≤ risk_score < 3): 매수 규모 축소
- DANGER (risk_score ≥ 3): 매수 중단, 보유분만 관리
3.2.4 앙상블 (analysis/ensemble.py)
AdaptiveEnsemble — 과거 매매 결과 기반 가중치 자동 조정 + Kelly Criterion:
가중치 학습 흐름:
BUY 체결 → bot._buy_scores[ticker] = {tech, sentiment, lstm} 저장
SELL 체결 → ensemble.record_trade(ticker, ..., outcome_pct=yld)
→ _update_weights() → EMA(alpha=0.10) 가중치 점진 조정
→ _save() → data/ensemble_history.json
워커 프로세스 → reload_if_stale() → 파일 mtime 감지 시 재로드
주요 메서드:
get_weights(ticker, adx, macro_state, ai_confidence)→SignalWeights- 시장 컨텍스트 (strong_trend/sideways/danger/default) 별 기본 가중치
- 종목별 최근 10거래 크기 가중 정확도 반영
- ai_confidence >= 0.75 → LSTM 가중치 +25% (confidence 상한 0.80 반영)
get_kelly_fraction(ticker, half_kelly=True)→ 0.03~0.25 범위 투자 비중- f* = (p·b - q) / b (p=승률, b=손익비)
- 거래 데이터 < 10건 → 보수적 기본값 8%
- Half-Kelly 적용으로 변동성 과대추정 보완
compute_ensemble_score(tech, sentiment, lstm, investor, weights)→ 통합 점수reload_if_stale()→ 파일 mtime 기반 cross-process 동기화
SignalWeights.normalize() — Water-Filling 알고리즘:
- 경계(0.10~0.65) 위반 시 해당 값을 경계에 고정, 나머지에 잔여 비중 비례 배분
- 2차 정규화(합=1 보장)와 경계 클램핑이 상충하는 문제 해결
- 영구 저장:
data/ensemble_history.json(가중치 + 매매 히스토리 통합)
3.2.5 성과 평가 (analysis/evaluator.py)
PerformanceEvaluator.generate_weekly_report():
- 핵심 지표: 총수익률, Sharpe Ratio, MDD, 승률, 평균손익비, KOSPI 상관도
- S/A/B/C/D/F 등급 산출
- 5명 전문가 LLM 패널 (Ollama): 각각 다른 관점으로 평가
- HTML 포맷 텔레그램 주간 보고서 자동 생성
4. 외부 서비스 연동
4.1 한국투자증권 KIS API (services/kis.py)
인증
KISClient.ensure_token()
# OAuth 2.0 → access_token 발급 → data/kis_token.json에 캐시
# 토큰 만료 시 자동 갱신 (_request_api에서 처리)
| 설정 | 모의투자 | 실전투자 |
|---|---|---|
| Base URL | openapivts.koreainvestment.com:29443 |
openapi.koreainvestment.com:9443 |
| 환경변수 | KIS_VIRTUAL_APP_KEY/SECRET/ACCOUNT |
KIS_REAL_APP_KEY/SECRET/ACCOUNT |
| 전환 | .env → KIS_ENV_TYPE=virtual |
.env → KIS_ENV_TYPE=real |
API 스로틀링
- 초당 2회 제한 (
_throttle()— 0.5초 딜레이) - 토큰 만료 시 자동 갱신 (403 → retry with new token)
주요 API 엔드포인트 매핑
| 기능 | KISClient 메서드 | KIS TR_ID |
|---|---|---|
| 잔고 조회 | get_balance() → {holdings, total_eval, deposit, today_buy_amt} |
VTTC8434R (모의) / TTTC8434R (실전) |
| 주문 (매수/매도) | order() |
VTTC0802U / VTTC0801U (모의) |
| 현재가 조회 | get_current_price() |
FHKST01010100 |
| 일봉 OHLCV | get_daily_ohlcv() → _get_daily_ohlcv_by_range() |
FHKST03010100 |
| 일봉 종가 | get_daily_price() → _get_daily_price_by_range() |
FHKST03010100 |
| 거래량 순위 | get_volume_rank() |
FHPST01710000 |
| 지수 현재가 | get_current_index() |
FHPUP02100000 |
| 지수 일봉 | get_daily_index_price() |
FHKUP03500100 |
| 투자자 동향 | get_investor_trend() |
FHKST01010900 |
| Hash Key | get_hash_key() |
- |
비동기 클라이언트 (KISAsyncClient)
aiohttp 기반 — 다중 종목 동시 수집용:
get_daily_price_batch()— 여러 종목 일봉 병렬 수집get_daily_ohlcv_batch()— 여러 종목 OHLCV 병렬 수집get_investor_trends_batch()— 여러 종목 투자자 동향 병렬 수집
4.2 Ollama LLM (services/ollama.py)
| 설정 | 값 |
|---|---|
| 모델 | qwen2.5:7b-instruct-q4_K_M (VRAM ~4GB) |
| API URL | http://localhost:11434 |
| Context Window | 4096 토큰 |
| Max Output | 200 토큰 |
| Temperature | 0.1 (결정론적, JSON 안정성) |
| Keep Alive | 5분 (비활성 시 자동 언로드) |
| Timeout | 90초 |
| CPU Threads | 8 (9800X3D 최적화) |
| 응답 포맷 | JSON (format: "json") |
GPU 충돌 방지:
- LSTM 학습 중 → Ollama 추론 최대 60초 대기
- VRAM > 12GB → 모델 즉시 언로드 (
keep_alive=0) - LSTM 학습 전 → Ollama 자동 언로드, 학습 후 → 자동 리로드
4.3 뉴스 수집 (services/news.py)
- 소스: Google News RSS (
news.google.com/rss/search) - 동기:
NewsCollector.get_market_news()— 시장 일반 뉴스 5건 - 비동기:
AsyncNewsCollectorget_market_news_async()— 시장 뉴스 (5분 캐시)get_stock_news_async()— 종목별 뉴스 (5분 캐시)
5. 웹 백엔드 서버 API (FastAPI)
5.1 서버 정보
| 항목 | 값 |
|---|---|
| 프레임워크 | FastAPI + Uvicorn |
| 호스트 | 0.0.0.0:8000 |
| NAS 백엔드 | http://192.168.45.54:18500 (웹 프론트엔드 서버) |
5.2 API 엔드포인트
GET / — 서버 상태
{
"status": "online",
"gpu_vram": 4.2,
"service": "Windows AI Server (Refactored)"
}
GET /trade/balance | GET /api/trade/balance — 잔고 조회
KIS API를 통해 현재 계좌 잔고(예수금, 보유종목, 평가금액) 조회.
{
"total_eval": 10500000,
"deposit": 5000000,
"holdings": [
{
"ticker": "005930",
"name": "삼성전자",
"qty": 10,
"avg_price": 72000,
"current_price": 73500,
"profit_rate": 2.08
}
]
}
POST /trade/order | POST /api/trade/order — 수동 주문
// Request Body
{
"ticker": "005930",
"action": "BUY", // "BUY" | "SELL"
"quantity": 10
}
// Response
{
"status": "executed",
"kis_result": { ... }
}
POST /analyze/portfolio | POST /api/analyze/portfolio — AI 포트폴리오 분석
현재 잔고 + 최신 뉴스를 종합하여 Ollama LLM으로 포트폴리오 분석.
{
"analysis": "... AI 분석 결과 (한국어) ..."
}
5.3 NAS 서버와의 통신 흐름
┌──────────────┐ HTTP Request ┌────────────────────┐
│ NAS Backend │ ─────────────────────► │ Windows AI Server │
│ (웹 프론트) │ │ (FastAPI:8000) │
│ :18500 │ ◄──────────────────── │ │
│ │ JSON Response │ │
└──────────────┘ └────────────────────┘
[통신 시나리오]
1. 웹 → /api/trade/balance → 잔고 데이터 표시
2. 웹 → /api/trade/order → 수동 매수/매도 실행
3. 웹 → /api/analyze/portfolio → AI 분석 결과 표시
4. 웹 → / → 서버 상태 및 GPU 정보
- NAS 서버 (
192.168.45.54:18500): 웹 프론트엔드 호스팅, 사용자 인터페이스 제공 - Windows AI 서버 (
0.0.0.0:8000): GPU 연산, KIS API 통신, AI 분석 처리 - 내부 네트워크 (LAN) 통신, 외부 노출 없음
6. 텔레그램 봇 설정 & 명령어
6.1 환경변수
TELEGRAM_BOT_TOKEN=8546032918:AAF5GJcP92DrtpSoQdaimMIZe7bz_xtGGPo
TELEGRAM_CHAT_ID=7388056964
6.2 봇 프로세스 아키텍처
runner.py
└── run_telegram_bot_standalone()
├── SharedIPC 초기화 (lock, queue, shutdown_event)
├── TelegramBotServer 생성
├── IPC에서 초기 데이터 로드
├── bot_server.run() (python-telegram-bot polling)
└── Conflict 감지 시 백오프 재시도 (최대 10회)
- 라이브러리:
python-telegram-bot(Application, CommandHandler) - 메시지 포맷: HTML (
parse_mode="HTML") - 동시 업데이트:
concurrent_updates=True - 로깅:
telegram_bot.log(파일 + 콘솔)
6.3 명령어 목록
| 명령어 | 설명 | 데이터 소스 |
|---|---|---|
/start |
봇 시작 & 전체 명령어 안내 | - |
/status |
봇 상태, 시장 지수, AI 모델 상태 | IPC (SharedMemory) |
/portfolio |
보유 종목 & 수익률 조회 | IPC → FakeKIS.get_balance() |
/watchlist |
현재 감시 종목 리스트 | IPC → watchlist 데이터 |
/update_watchlist |
Watchlist 즉시 업데이트 요청 | Command Queue → 메인 봇 |
/macro |
거시경제 분석 (KOSPI/KOSDAQ/MSI) | IPC → macro_indices |
/system |
CPU/GPU/RAM 시스템 상태 | IPC → gpu_status + psutil |
/ai |
AI 모델 상태 (VRAM, 학습 여부) | IPC → gpu_status |
/restart |
메인 봇 재시작 명령 | Command Queue |
/stop |
봇 종료 | shutdown_event.set() |
/exec <cmd> |
서버 쉘 명령어 직접 실행 | subprocess (10초 타임아웃) |
/evaluate |
즉시 성과 평가 보고서 생성 | PerformanceEvaluator |
6.4 TelegramMessenger (services/telegram.py)
단방향 알림 전용 (메인 봇 → 사용자):
- 비동기 전송:
threading.Thread(daemon=True)— Fire-and-forget - HTML 파싱: 마크다운 에러 방지
- 매매 실행, 서버 시작/종료, 에러 알림 등에 사용
6.5 Conflict 처리
텔레그램 봇 API는 동시에 하나의 polling 인스턴스만 허용:
Conflict에러 감지 시 지수 백오프 (5s → 10s → ... → 30s)- 최대 10회 재시도 후 프로세스 종료
- Watchdog가 감지하여 자동 재시작
7. 환경 설정 (modules/config.py)
7.1 주요 설정 상수
| 그룹 | 키 | 값 | 설명 |
|---|---|---|---|
| 매매 | MAX_INVESTMENT_PER_STOCK |
3,000,000원 | 종목당 최대 투자금 |
| 매매 | MAX_BUY_PER_CYCLE |
2 | 사이클당 최대 매수 종목 수 (env: MAX_BUY_PER_CYCLE) |
| 매매 | MAX_DAILY_BUY_RATIO |
0.80 | 예수금 대비 일일 최대 매수 비율 (env: MAX_DAILY_BUY_RATIO) |
| IPC | SHM_NAME |
web_ai_bot_ipc |
SharedMemory 이름 |
| IPC | SHM_SIZE |
131,072 (128KB) | SharedMemory 크기 |
| IPC | IPC_STALENESS |
600초 | 데이터 유효 기간 |
| GPU | VRAM_WARNING_THRESHOLD |
12.0 GB | VRAM 경고 임계값 |
| 프로세스 | WATCHDOG_INTERVAL |
30초 | 헬스체크 간격 |
| 프로세스 | MAX_RESTART_COUNT |
3 | 최대 자동 재시작 횟수 |
| LSTM | LSTM_COOLDOWN |
1,200초 | 동일 종목 재학습 방지 |
| LSTM | LSTM_FAST_EPOCHS |
30 | 빠른 재학습 에포크 |
| CPU | CPU_CIRCUIT_BREAKER_THRESHOLD |
92% | 서킷 브레이커 임계값 |
| CPU | CPU_CIRCUIT_BREAKER_CONSECUTIVE |
2회 | 연속 초과 시 발동 |
| Ollama | OLLAMA_NUM_CTX |
4,096 | 컨텍스트 윈도우 |
| Ollama | OLLAMA_NUM_PREDICT |
200 | 최대 출력 토큰 |
| Ollama | OLLAMA_NUM_THREAD |
8 | CPU 스레드 수 |
| Network | HTTP_TIMEOUT |
10초 | 기본 HTTP 요청 타임아웃 |
7.2 .env 파일 구조
# NAS Backend (웹 프론트엔드 서버)
NAS_API_URL=http://192.168.45.54:18500
# Ollama LLM
OLLAMA_API_URL=http://localhost:11434
OLLAMA_MODEL=qwen2.5:7b-instruct-q4_K_M
# KIS API (virtual/real 전환)
KIS_ENV_TYPE=virtual
KIS_REAL_APP_KEY=...
KIS_REAL_APP_SECRET=...
KIS_REAL_ACCOUNT=XXXXXXXX-XX
KIS_VIRTUAL_APP_KEY=...
KIS_VIRTUAL_APP_SECRET=...
KIS_VIRTUAL_ACCOUNT=XXXXXXXX-XX
# Telegram Bot
TELEGRAM_BOT_TOKEN=...
TELEGRAM_CHAT_ID=...
8. 운영 가이드
8.1 시작 방법
# 일반 시작
python main_server.py
# LSTM 사전학습 후 자동 시작
python warmup_and_restart.py
# 텔레그램 봇만 단독 실행 (디버깅용)
python -m modules.services.telegram_bot.runner
8.2 좀비 프로세스 관리
main_server.py실행 시 자동으로 이전 좀비 프로세스 정리pids.txt기반 → 메모리 기반 PID 추적으로 전환 완료- 수동 확인:
Get-Process python(PowerShell)
8.3 로그 파일
| 파일 | 용도 |
|---|---|
server.log |
Uvicorn 서버 로그 |
telegram_bot.log |
텔레그램 봇 로그 |
warmup.log |
LSTM 사전학습 진행 로그 |
bot_output.log |
트레이딩 봇 출력 로그 |
8.4 트러블슈팅
| 증상 | 원인 | 해결 |
|---|---|---|
| KIS 403 Forbidden | 토큰 만료 또는 Rate Limit | data/kis_token.json 삭제 후 재시작 |
| Telegram Conflict | 이전 봇 프로세스 미종료 | main_server.py 재시작 (자동 정리) |
| GPU OOM | LSTM + Ollama 동시 적재 | VRAM_WARNING_THRESHOLD 낮추기 |
| CPU 100% 고정 | 좀비 워커 프로세스 | main_server.py 재시작 |
| IPC 데이터 오래됨 | 메인 봇 크래시 | Watchdog 자동 재시작 확인, 수동 재시작 |
| 예수금 초과 매수 | KIS 모의투자 T+2 미차감 | MAX_DAILY_BUY_RATIO / MAX_BUY_PER_CYCLE 조정 |
| Kelly 비중이 너무 낮음 | 거래 기록 부족 (< 10건) | 초기에는 기본값 8% 사용, 거래 누적 후 자동 조정 |
| 앙상블 가중치 갱신 안 됨 | 매도 체결 없음 또는 _buy_scores 누락 |
봇 재시작 전 매도 완료 확인; data/ensemble_history.json 확인 |
9. 데이터 흐름 요약
[시장 개장 전]
WatchlistManager → 뉴스 분석 → Watchlist 갱신
[장중 사이클 (≈5분 간격)]
1. SystemMonitor.check_health() → CPU/GPU 확인
2. MacroAnalyzer.get_macro_status() → 시장 상태 판단
3. KIS → get_balance() → raw_deposit - today_buy_total = 가용 예수금
4. KIS → get_daily_ohlcv_batch() → OHLCV 수집
5. ProcessPool → analyze_stock_process() × N종목
├── ensemble.reload_if_stale() → 파일 mtime 감지 시 가중치 재로드
├── TechnicalAnalyzer → 기술적 점수
├── PricePredictor → LSTM 예측
├── OllamaManager → LLM 감성 분석
├── AdaptiveEnsemble.get_weights() → 학습된 동적 가중치
└── calculate_position_size() → Kelly Criterion 수량 산출
6. 매수 판단 → 예수금 확인 → KIS 주문
├── _buy_scores[ticker] 저장 (앙상블 학습용)
├── _today_buy_total += 매수금액
└── buys_this_cycle++ (MAX_BUY_PER_CYCLE 제한)
7. 매도 판단 → KIS 주문
└── ensemble.record_trade() → 가중치 학습 + ensemble_history.json 저장
8. SharedIPC.write_status() → 텔레그램 봇에 공유
9. TelegramMessenger → 결과 알림
[장 마감 후]
PerformanceDB.save_daily_snapshot() → 일별 자산 기록
Evaluator → 주간 보고서 (월요일)
10. 버전 변경 이력
v3.1 (2026-03-19) — 잔고 관리 & 앙상블 학습 완성
버그 수정:
tracking_deposit사이클 간 초기화 문제 →_today_buy_total인스턴스 변수로 누적 추적- KIS 모의투자 T+2 미차감으로 인한 예수금 초과 매수 방지
ai_confidence >= 0.85임계값 버그 (LSTM confidence 상한 0.80 미반영) → 0.75로 수정- OHLCV 피처 누락 시 silent fallback → 경고 로그 출력
신규 기능:
MAX_BUY_PER_CYCLE: 사이클당 최대 매수 종목 수 제한 (기본 2)MAX_DAILY_BUY_RATIO: 예수금 대비 일일 최대 매수 비율 (기본 80%)kis.get_balance()→today_buy_amt필드 추가 (thdt_buy_amt)
앙상블 (analysis/ensemble.py):
AdaptiveEnsemble을process.py에 실제 연동 (하드코딩 가중치 제거)get_kelly_fraction(): Half-Kelly Criterion 포지션 비중 계산 추가SignalWeights.normalize(): Water-Filling 알고리즘으로 경계 위반 문제 해결_accuracy()이진 지표 제거 →_accuracy_weighted()(크기 가중) 통일reload_if_stale(): 파일 mtime 기반 cross-process 동기화
포지션 사이징 (strategy/process.py):
calculate_position_size(): 하드코딩 10% → Kelly Criterion (과거 승률·손익비 기반)bot.py중복 계산 제거 → 워커의suggested_qty직접 사용
앙상블 학습 루프 (bot.py):
- BUY 체결 시
_buy_scores[ticker]신호 점수 저장 - SELL 체결 시
ensemble.record_trade()→ensemble_history.json갱신 - 워커 프로세스는
reload_if_stale()로 자동 반영