Files
ai-trade/modules/config.py
gahusb 0aebca7ff0 v3.1 과매수 방지, 앙상블 학습, KRX 캘린더 기반 장중 전용 운영 구현
[잔고 관리]
- _today_buy_total 인스턴스 변수로 당일 누적 매수 추적 (KIS T+2 미차감 보완)
- MAX_BUY_PER_CYCLE, MAX_DAILY_BUY_RATIO 설정 추가
- available_deposit = max_daily_buy - effective_today_buy 계산

[앙상블 & 포지션 사이징]
- AdaptiveEnsemble 실제 연동 (하드코딩 가중치 제거)
- Kelly Criterion Half-Kelly 포지션 비중 계산
- SignalWeights.normalize() Water-Filling 알고리즘으로 경계 위반 해결
- _accuracy_weighted() 크기 가중 정확도로 통일
- ensemble_weights.json → ensemble_history.json 통합

[LLM 클라이언트]
- GeminiLLMClient 추가 (Gemini → Ollama 폴백 체인)
- _class_last_call_ts 클래스 변수로 워커 재시작 후에도 스로틀 유지
- Ollama 미실행 조기 감지 및 명확한 오류 메시지

[KIS API]
- 모든 requests.get/post에 timeout=Config.HTTP_TIMEOUT 적용
- get_balance()에 today_buy_amt 필드 추가

[장중 전용 운영]
- KRXCalendar: exchange_calendars 기반, 2024~2026 공휴일 하드코딩 폴백
- EOD 셧다운: 15:35에 전체 상태 저장 후 서버 자동 종료
- Watchdog: .eod_date 마커로 EOD 후 재시작 차단
- daily_launcher.py: 매일 08:30 실행, 휴장일 감지 후 봇 미시작
- Windows 작업 스케줄러 WebAI_DailyLauncher 등록

[텔레그램 스킬 수정]
- PYTHONIOENCODING=utf-8 서브프로세스 환경 설정 (cp949 이모지 오류 해결)
- /regime: IPC macro_indices 파싱 구현, --json 모드 input() 블로킹 제거
- /weights: ensemble_history.json 형식 파싱 업데이트
- /model_health: glob 패턴 *_v3.pt 수정
- /postmortem: 거래 없을 때 빈 JSON 출력으로 Telegram 오류 해결
- /macro: price=0 시 prev_close 폴백 표시

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 05:21:23 +09:00

119 lines
5.3 KiB
Python

import os
import sys
from dotenv import load_dotenv
# .env 파일 로드
load_dotenv()
class Config:
# 1. 기본 설정
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# 2. NAS 및 AI 서버
NAS_API_URL = os.getenv("NAS_API_URL", "http://192.168.45.54:18500")
OLLAMA_API_URL = os.getenv("OLLAMA_API_URL", "http://localhost:11434")
# [최적화] qwen2.5:7b-instruct-q4_K_M: JSON 정확도↑, 속도↑, VRAM 4GB
# 14B 원하면: qwen2.5:14b-instruct-q4_K_M (VRAM ~9GB, 품질 더 좋음)
OLLAMA_MODEL = os.getenv("OLLAMA_MODEL", "qwen2.5:7b-instruct-q4_K_M")
OLLAMA_NUM_CTX = int(os.getenv("OLLAMA_NUM_CTX", "4096")) # 8192→4096 (2배 속도)
OLLAMA_NUM_PREDICT = int(os.getenv("OLLAMA_NUM_PREDICT", "200")) # 응답 토큰 제한
OLLAMA_NUM_THREAD = int(os.getenv("OLLAMA_NUM_THREAD", "8")) # CPU 스레드 (9800X3D 최적화)
# 2-1. Gemini API (Primary LLM — Ollama 폴백)
# API 키: https://aistudio.google.com/apikey 에서 무료 발급
# 무료 티어: 15 RPM / 1,500 RPD (봇 필요량 ~240/일 → 여유 충분)
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY", "")
GEMINI_MODEL = os.getenv("GEMINI_MODEL", "gemini-2.5-flash")
# 3. KIS 한국투자증권
KIS_ENV_TYPE = os.getenv("KIS_ENV_TYPE", "virtual").lower()
if KIS_ENV_TYPE == "real":
KIS_APP_KEY = os.getenv("KIS_REAL_APP_KEY")
KIS_APP_SECRET = os.getenv("KIS_REAL_APP_SECRET")
KIS_ACCOUNT = os.getenv("KIS_REAL_ACCOUNT")
KIS_IS_VIRTUAL = False
KIS_BASE_URL = "https://openapi.koreainvestment.com:9443"
else:
KIS_APP_KEY = os.getenv("KIS_VIRTUAL_APP_KEY")
KIS_APP_SECRET = os.getenv("KIS_VIRTUAL_APP_SECRET")
KIS_ACCOUNT = os.getenv("KIS_VIRTUAL_ACCOUNT")
KIS_IS_VIRTUAL = True
KIS_BASE_URL = "https://openapivts.koreainvestment.com:29443"
# 4. 텔레그램
TELEGRAM_BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
TELEGRAM_CHAT_ID = os.getenv("TELEGRAM_CHAT_ID")
# 5. 매매 설정 (상수)
MAX_INVESTMENT_PER_STOCK = 3000000 # 종목당 최대 300만원
MAX_BUY_PER_CYCLE = int(os.getenv("MAX_BUY_PER_CYCLE", "2")) # 사이클당 최대 매수 종목 수
EOD_SHUTDOWN_BUFFER_MIN = int(os.getenv("EOD_SHUTDOWN_BUFFER_MIN", "5")) # 장 마감 후 EOD 처리까지 대기 분
MAX_DAILY_BUY_RATIO = float(os.getenv("MAX_DAILY_BUY_RATIO", "0.80")) # 예수금 대비 일일 최대 매수 비율
# 6. 데이터 경로
DATA_DIR = os.path.join(BASE_DIR, "data")
if not os.path.exists(DATA_DIR):
os.makedirs(DATA_DIR, exist_ok=True)
HISTORY_FILE = os.path.join(DATA_DIR, "daily_trade_history.json")
WATCHLIST_FILE = os.path.join(DATA_DIR, "watchlist.json")
# 모델 체크포인트 디렉토리
MODEL_DIR = os.path.join(DATA_DIR, "models")
if not os.path.exists(MODEL_DIR):
os.makedirs(MODEL_DIR, exist_ok=True)
# 7. IPC 설정
SHM_NAME = "web_ai_bot_ipc"
SHM_SIZE = 131072 # 128KB
IPC_STALENESS = 600 # 600초 (LSTM 분석 사이클이 길어도 portfolio 명령어 정상 작동)
# 8. GPU 설정
VRAM_WARNING_THRESHOLD = 12.0 # GB (14 → 12로 조기 경고)
# 9. 프로세스 관리
WATCHDOG_INTERVAL = 30 # 헬스체크 간격(초)
MAX_RESTART_COUNT = 3 # 최대 자동 재시작 횟수
# 10. 타임아웃 등
HTTP_TIMEOUT = 10
# 11. LSTM 학습 최적화
# 동일 종목을 이 시간(초) 내에 재학습하지 않음 → CPU/GPU 절약
LSTM_COOLDOWN = int(os.getenv("LSTM_COOLDOWN", "1200")) # 20분
# 체크포인트가 있을 때 빠른 재학습 에포크 수 (기존 50 → 30)
LSTM_FAST_EPOCHS = int(os.getenv("LSTM_FAST_EPOCHS", "30"))
# 12. CPU 서킷 브레이커
CPU_CIRCUIT_BREAKER_THRESHOLD = 92 # CPU% 이상 시 분석 스킵
CPU_CIRCUIT_BREAKER_CONSECUTIVE = 2 # 연속 N회 초과 시 발동
# 13. AI 전문가 회의 (AICouncil) 설정
# True: 매 분석 사이클에 회의 통합 (느림), False: 수동 호출만 허용
AI_COUNCIL_ENABLED = os.getenv("AI_COUNCIL_ENABLED", "false").lower() == "true"
# True: 의장 AI 단독 판단 (1회 LLM 호출), False: 전문가 4명 + 의장 (5회)
AI_COUNCIL_FAST_MODE = os.getenv("AI_COUNCIL_FAST_MODE", "true").lower() == "true"
# 종목당 최소 회의 간격(초) - 동일 종목 과다 호출 방지
AI_COUNCIL_MIN_INTERVAL = int(os.getenv("AI_COUNCIL_MIN_INTERVAL", "3600")) # 1시간
# 14. 시장 레짐 / 코스피 목표 수준 설정
# 코스피 레짐 감지 활성화 (process.py 임계값/포지션 자동 조정)
MARKET_REGIME_ENABLED = os.getenv("MARKET_REGIME_ENABLED", "true").lower() == "true"
# 모델 검증 활성화 (일일 1회 레짐 보고서 생성)
MODEL_VALIDATION_ENABLED = os.getenv("MODEL_VALIDATION_ENABLED", "true").lower() == "true"
# 코스피 목표/기준 수준 (레짐 전환 알림 기준)
KOSPI_REFERENCE_LEVEL = float(os.getenv("KOSPI_REFERENCE_LEVEL", "2600"))
@staticmethod
def validate():
"""필수 설정 검증"""
missing = []
if not Config.KIS_APP_KEY: missing.append("KIS_APP_KEY")
if not Config.KIS_APP_SECRET: missing.append("KIS_APP_SECRET")
if missing:
print(f"⚠️ [Config] Missing Env Params: {', '.join(missing)}")
return False
return True