Files
trading/CLAUDE.md
T
kyu 97cf5aecb0
trading/pipeline/head This commit looks good
chore: 누적 미커밋 작업분 일괄 커밋
이번 세션 외 그간 쌓인 변경 일괄 저장:
- bareunaapi: finance_dict 금융용어 / stock_loader 종목 로더 보강
- kis-api: 키움 토큰·수집 로직
- us-market / dart-collector: 수집 보강
- docker-compose: GEMINI_API_KEY 등 환경변수 추가
- score-engine/news-collector requirements, CLAUDE.md
- 신규: PROJECT.md, news-collector/sentiment_rules.py

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 01:24:16 +09:00

28 KiB
Raw Blame History

Trading AI — Claude Code 프로젝트 가이드

역할: 워렌 버핏 스타일 한국 주식 AI 투자 분석 전문가로 행동할 것. 가치투자 관점(ROE·영업이익률·부채비율·FCF)을 최우선으로 판단한다. 이 파일은 매 대화 시작 시 자동 로드됨 — 파일 탐색 없이 이 내용만으로 작업 시작.


Claude 행동 원칙

1. 먼저 생각, 그 다음 코딩

  • 가정은 명시적으로 밝힐 것. 불확실하면 질문.
  • 해석이 여러 개면 나열하고 고를 것 — 혼자 결정 금지.
  • 더 단순한 방법이 있으면 말할 것. 불필요한 복잡성에 반론.

2. 단순함 우선

  • 요청한 것만 구현. 추측성 기능·추상화·유연성 추가 금지.
  • "나중에 필요할 수도" 코드 금지. 200줄이 50줄로 가능하면 다시 짤 것.
  • 불가능한 시나리오를 위한 에러 핸들링 금지.

3. 정밀한 변경

  • 요청한 부분만 수정. 인접 코드 "개선" 금지.
  • 기존 스타일 유지 (내 방식이 달라도).
  • 내 변경으로 생긴 불필요한 import/변수/함수만 제거. 기존 dead code는 언급만.

4. 검증 기준 명시

  • 다단계 작업 시 각 단계 완료 조건을 먼저 정의.
  • Docker 서비스 변경 → 로그 확인 필수.
  • DB 변경 → 쿼리로 확인 필수.

이 프로젝트 특이사항

  • sudo 비밀번호 입력 불가 → sudo 필요 작업은 ! sudo <cmd> 형태로 유저에게 요청.
  • n8n 마이그레이션 충돌 이력 있음 → n8n 스키마 변경 시 반드시 백업 먼저.
  • NAS fstab은 한 줄 유지 필수 (nfsvers=3).
  • 상장폐지 필터(is_active=true) 빠지면 추천 결과 오염됨.

시스템 개요

뉴스 수집 → 형태소분석 → 임베딩 → 중복제거 → AI분석 → 재무스코어링 → 기술분석 → 매수/매도 추천 → 텔레그램 알림


인프라

항목
서버 OS Ubuntu 22.04
GPU GPU0: RTX 3060 12GB (EXAONE 추론) / GPU1: RTX 3070 8GB (bge-m3 임베딩)
NAS 192.168.0.36:/volume1/trading → /mnt/nas (nfsvers=3 필수)
DB 연결 postgres:5432, DB명 trading_ai, user kyu
환경변수 /home/kyu/trading/.env
Docker docker compose (파일: /home/kyu/trading/docker-compose.yml)
PostgreSQL 데이터 /mnt/nas/postgresql/data (NAS 저장)

서비스 목록

서비스 컨테이너 포트 내부IP 역할
news-collector trading-news-collector 8787 172.30.0.16 뉴스수집+형태소+임베딩+Ollama분석
bareunaapi trading-bareunaapi 5757 172.30.0.12 한국어 형태소분석 FastAPI 래퍼
bareun trading-bareun 5656/9902 172.30.0.15 바른 NLP gRPC 서버
dart-collector trading-dart-collector 8888 172.30.0.17 DART 공시/재무제표 수집
score-engine trading-score-engine 8686 172.30.0.19 종합 투자 스코어 계산+텔레그램
ta-engine trading-ta-engine 8484 172.30.0.23 기술적분석 (MA/RSI/MACD/볼밴/스토캐스틱)
dashboard-api trading-dashboard-api 8989 172.30.0.22 대시보드 REST API
kis-api trading-kis-api 8585 172.30.0.18 네이버모바일 주가수집 + 매매시그널
ollama trading-ollama 11434 172.30.0.13 EXAONE 3.5 7.8B 추론(GPU0) + bge-m3 임베딩(GPU1)
n8n trading-n8n 5678 172.30.0.20 워크플로우 자동화
n8n-worker trading-n8n-worker - 172.30.0.21 n8n Queue Worker
postgres trading-postgres 5432 - 메인 DB
redis trading-redis 6379 172.30.0.10 캐시/중복제거
qdrant trading-qdrant 6333 172.30.0.11 뉴스 벡터 유사도 필터
aux-signal trading-aux-signal 8282 172.30.0.25 보조 데이터: 네이버 컨센서스·기관/외국인 수급 + ECOS 매크로(USD/KRW, 국고채10년)
us-market trading-us-market 8383 172.30.0.24 미증시→한국 동조 시그널 (섹터ETF 14개 ±5점, 개별 페어 회귀 ±10점, 자동 페어발굴)
graph-engine trading-graph-engine 9090 172.30.0.27 GAT 그래프 신경망 (12피처 노드 × 가격상관/섹터/뉴스공기 엣지) → graph_score
telegram-bot trading-telegram-bot - 172.30.0.26 텔레그램 명령 처리 (/buy /sell /stock /deep /market)

파일 구조 & 핵심 함수

/home/kyu/trading/news-collector/main.py (21KB)

뉴스 수집 + AI 분석 파이프라인. 포트 8787.

함수/클래스 역할
class S 전역 상태 (DB pool, Redis, Qdrant client)
nhash(title, url) SHA256[:16] 뉴스 중복 해시
is_korean(text) 한글 포함 여부 체크
parse_rss_date(date_str) RSS pubDate → ISO timestamp
@app.post("/collect/market") 네이버 금융 메인 뉴스 수집
@app.post("/collect/stocks") 종목별 네이버 뉴스 수집
@app.post("/collect/rss") 18개 RSS 피드 수집
@app.get("/sources") RSS 소스 목록

파이프라인 순서 (함수 내부):

  1. 바른API /analyze → 형태소분석 + 종목감지
  2. Ollama bge-m3 → 1024차원 임베딩
  3. Qdrant → 코사인 유사도 ≥0.92 중복 제거
  4. Ollama exaone3.5:7.8b (GPU0) → 호재/악재/중립 + intensity(1~5) + catalyst분류
  5. PostgreSQL news_analysis 저장

EXAONE 프롬프트: 버핏 관점 (실적/수주/배당/리스크/모멘텀/기타 catalyst 분류)

RSS 소스 (28개): 한국경제, 매일경제, 머니투데이, 이데일리, 연합뉴스, 조선비즈, 헤럴드경제, 아시아경제, 파이낸셜뉴스, SBS Biz, 뉴스1, 뉴시스 등 + 네이버금융 직접 크롤링

스케줄러:

  • 평일 RSS: 8-18시 5분마다 (rss_weekday)
  • 주말 RSS: 8-22시 15분마다 (rss_weekend) — 누적 학습용
  • 평일 마켓: 9-17시 10분마다 (market, 네이버 금융 메인)
  • raw 분석: 24시간 30분마다 200건 batch (process_raw) — 백로그 소화용으로 확장
  • 주간 raw 백필: 일요일 02:00 전체 종목 × 50페이지 (historical_raw_weekly)

수집/분석 분리 (대규모 백필용):

  • POST /collect/historical-raw?count=0&max_pages=100 — raw만 빠르게 수집 (LLM 스킵)
  • POST /process/raw?batch_size=200 — news_raw → news_analysis 점진 분석
  • GET /raw/stats — 백필 진행률 (total/unprocessed/processed)

/home/kyu/trading/bareunaapi/main.py (9.5KB)

한국어 형태소분석 FastAPI 래퍼. 포트 5757.

함수/클래스 역할
class AppState bareun gRPC stub + Redis + 종목사전
class AnalyzeRequest / AnalyzeResponse 분석 요청/응답 모델
news_hash(title, url) Redis 중복제거용 해시
extract_morphemes(text) 바른API → 명사 추출
extract_stocks(text) 텍스트에서 종목코드 감지
build_filtered(nouns, stocks) 필터링된 텍스트 구성
scan_finance_terms(text) finance_dict.py 금융용어 매칭
_analyze(req) 핵심 분석 로직
@app.post("/analyze") 단건 분석
@app.post("/analyze/batch") 배치 분석
@app.get("/stocks") 로드된 종목 목록
@app.post("/stocks/refresh") KRX→Naver 종목 새로고침
@app.delete("/dedup/flush") Redis 중복제거 캐시 초기화

관련 파일:

  • bareunaapi/finance_dict.py — 주식/금융 전문 용어 사전
  • bareunaapi/stock_loader.py — KRX→Naver 폴백, ~3768 종목 로드

/home/kyu/trading/dart-collector/main.py (34KB)

DART 공시/재무제표 수집. 포트 8888.

함수/클래스 역할
class Stats 수집 통계
get_corp_code(stock_code) 종목코드 → DART corp_code 변환
get_corp_name(stock_code) 종목코드 → 기업명
calc_financial_ratios(key_items, prev_revenue) ROE/영업이익률/부채비율/FCF/매출성장률 계산
@app.post("/collect/disclosures") 공시 수집
@app.post("/collect/financials") 재무제표 수집 (300개 종목)
@app.post("/collect/major") 주요 대형주 수집
@app.post("/collect/corps") DART 기업목록 갱신
@app.get("/corps") 기업목록 조회
@app.get("/corps/{stock_code}") 특정 기업 조회
@app.get("/financials/{stock_code}") 종목 재무데이터
@app.get("/stats") 수집 통계

/home/kyu/trading/score-engine/main.py (27KB)

종합 투자 스코어 계산 + 텔레그램 알림. 포트 8686.

함수/클래스 역할
get_recommendation(score) 점수→등급 변환
calc_fundamental_score(fin, per, pbr) 재무점수 산출 (-100~100)
calc_magic_formula(fin, market_cap) 그린블라트 매직 포뮬러 (ROC + EY) 0~30점
calc_piotroski_score(curr, prev) 피오트로스키 F-Score 7신호 → -15~+15
calc_altman_z(fin, market_cap) 알트만 Z-Score 단순화 → 매수/매도/관망 신호
calc_peg(curr, prev, per) 린치 GARP — PER/이익성장률 → 신호
calc_momentum(conn, code) AQR 12-1개월 가격 모멘텀 → 신호
calc_beneish_simplified(curr, prev) Beneish M-Score 단순화 (분식 의심도)
aggregate_signals(signals) 6공식 보팅 다수결 → (요약, 카운트)
calc_trend_score(conn, code) 5년 ROE 일관성·추세 -30~+30
calc_dcf(fin, market_cap) 간이 DCF 내재가치 + 안전마진
calc_earnings_quality(fin) CFO/영업이익 비율 (분식의심 패널티)
is_value_investable(fin, per, pbr, market_cap) 버핏 필터 통과 여부
@app.post("/score/calculate") 종목 점수 계산 실행
@app.post("/briefing/send") 텔레그램 브리핑 전송
@app.get("/ranking") 전체 종목 랭킹
@app.get("/recommendations") 추천 종목 목록
@app.get("/stock/{code}") 특정 종목 점수 상세
@app.get("/backtest") 추천 성과 백테스트 (수익률/승률/샤프/MDD/알파)
@app.post("/learn-weights") 공식별 신호 → 7d 수익률 회귀로 가중치 학습
@app.get("/learn-weights") 현재 적용 중인 공식 가중치 조회
@app.post("/learn-pricing") D+E: 점수→30d 수익률 선형회귀 + Random Forest 학습
@app.get("/predict-price/{code}") 학습된 모델로 종목 30일 후 예상 수익률·가격
@app.get("/sector/concentration") 섹터 집중도 + 30% 초과 경고

스코어링 공식 (실제 가중치):

종합점수 = 펀더멘털통합×0.24 + 뉴스(catalyst가중)×0.18 + 기술×0.15
        + DART공시×0.10 + 외국인수급×0.14 + 공매도×0.06
        + 가격모멘텀×0.03 + DCF안전마진×0.10
        + 시장레짐 보정(±5~10)
        + 앙상블 보팅(±18) ← 6공식 매수/매도 합 × 학습가중치

10공식 앙상블 보팅 — 각 공식이 독립 신호 발신, 학습 가중치로 결합:

공식 출처/논문 데이터 매수 신호
매직포뮬러 Greenblatt ROC + EY magic_score ≥ 20
F-Score Piotroski 2000 7신호 (전년 대비) f_score ≥ 6
알트만 Z Altman 1968 6.72×ROA + 1.05×(시총/부채) Z ≥ 2.6
PEG Lynch GARP PER / 이익성장률 PEG ≤ 1.5
12-1 모멘텀 AQR (Carhart 1997) (P_-21 / P_-252) - 1 ≥ 10%
Beneish Beneish 1999 TATA·SGI·CFO/NI 의심도 < 50 + CFO/NI > 1
GP/A Novy-Marx 2013 영업이익/총자산 (대체) ≥ 15%
G-Score Mohanram 2005 5신호 vs 섹터 중앙값 ≥ 4
Amihud Amihud 2002 avg(|return|/거래대금) ≥ 100 (소형 알파)
베타(BAB) Frazzini-Pedersen 2014 종목 vs KOSPI 60일 회귀 β < 0.7 (저베타 알파)

학습 가중치 (weight_config 테이블):

  • POST /learn-weights?days=90 — 백테스트로 공식별 매수vs매도 그룹 7d 수익률 차이(edge) 측정
  • edge가 큰 공식일수록 가중치 ↑ (정규화 후 합 = 6, 균등 시 각 1.0)
  • 다음 점수 계산부터 자동 적용. 표본 부족 시 default(균등 1.0)

펀더멘털통합 = clip(buffett_score + trend_score + earnings_quality + magic_score + f_score_adj, -100, 100)

  • buffett_score: ROE / 영업이익률 / 부채비율 / 매출성장 / PER / PBR / FCF / 배당
  • trend_score: 5년 ROE 일관성·추세 (-30~+30)
  • earnings_quality: CFO/영업이익 ≥1 가산, <0.7 분식의심 패널티
  • magic_score: ROC(영업이익/총자산) + EY(영업이익/EV) 임계값 합산 (0~30)
  • f_score_adj: F-Score ≥6 +15, 5 +8, 4 +3, ≤2 -15 (가치함정 회피)

매직 포뮬러 임계값 (한국 시장 보정):

  • ROC: ≥25% +15 / ≥15% +10 / ≥8% +5
  • EY: ≥15% +15 / ≥10% +10 / ≥6% +5

피오트로스키 F-Score 7신호 (현재/전년 사업보고서 비교, 9중 2개는 데이터 부재로 생략):

  1. ROA(NI/총자산) > 0 2. CFO > 0 3. ΔROA > 0 4. CFO > NI
  2. Δ부채비율 < 0 6. Δ영업이익률 > 0 7. Δ자산회전율 > 0

추천 등급 (점수 + 다수공식 동의 강제):

  • 강력매수: 점수 ≥70 AND 매수보팅 ≥3
  • 매수관심: 점수 ≥40 AND 매수보팅 ≥1 AND 매도보팅 <2
  • 매도관심: 점수 ≤-30 OR 매도보팅 ≥3
  • 강력매도: 점수 ≤-60 OR 매도보팅 ≥4
  • 관망: 그 외

버핏 가치투자 필터 (is_value_investable):

  • operating_profit > 0 영업적자 제외
  • ROE ≥ 10%
  • 부채비율 ≤ 200%
  • PER ≤ 60
  • 시총 ≥ 100억
  • dart_corps.is_active=true (상장폐지 제외)

/home/kyu/trading/ta-engine/main.py (37KB)

기술적 분석 엔진. 포트 8484.

함수/클래스 역할
_ema_series(values, period) EMA 계산
_ma(closes, n) 단순이동평균
_rsi(closes, period=14) RSI
_macd(closes) MACD (12/26/9)
_bollinger(closes, period=20) 볼린저밴드
_stochastic(highs, lows, closes, period=14) 스토캐스틱 K/D
_vol_ratio(volumes, period=20) 거래량비율
calc_indicators(ohlcv) 전체 지표 계산
calc_tech_score(ind) 기술점수 (-100~100)
calc_price_targets(price, ind, sig) 목표가/손절가 계산
analyze_position(price, buy_price, qty, ...) 포지션 분석
@app.get("/technical/{code}") 종목 기술분석
@app.get("/ranking") 기술점수 랭킹
@app.get("/buy-candidates") 매수 후보
@app.post("/analyze/all") 전체 종목 분석
@app.post("/analyze/{code}") 특정 종목 분석
@app.post("/position") 포지션 분석
@app.get("/report/{code}") 종합 리포트

목표가 계산:

  • 진입가: min(현재가, MA20×0.99)
  • T1: max(볼밴상단, 현재가×1.05)
  • T2: max((현재가+52주고가)/2, 현재가×1.10)
  • T3: max(52주고가×0.97, 현재가×1.20)
  • 손절가: min(MA60×0.98, 현재가×0.95)

/home/kyu/trading/dashboard-api/main.py (19KB)

대시보드 REST API. 포트 8989.

엔드포인트 역할
GET /api/summary 전체 요약 통계
GET /api/recent 최근 뉴스 분석
GET /api/ranking 종합 랭킹
GET /api/recommendations 추천 종목
GET /api/avoid 회피 종목
GET /api/signals 매매 시그널
GET /api/technical/{code} 기술분석 데이터
GET /api/buy-candidates 매수 후보
GET /api/alerts 알림 목록
GET /api/timeline 타임라인
GET /api/stock/{code} 종목 상세
GET /api/search 종목 검색
POST /api/position 포지션 등록
GET /api/report/{code} 종목 리포트
GET /api/fundamentals 전체 재무데이터
GET /api/fundamentals/{code} 종목 재무데이터
GET /api/name/{code} 종목명 조회
GET / 대시보드 HTML

/home/kyu/trading/kis-api/main.py (11KB)

네이버 모바일 주가수집 + 매매시그널. 포트 8585.

함수/엔드포인트 역할
class Stats 수집 통계
calc_signal(p, news_sc, dart_sc) 뉴스+공시점수 → 매매시그널
GET /price/{code} 단일 종목 주가
GET /prices 전체 주가 목록
GET /signals 전체 시그널
GET /signals/{code} 종목별 시그널
POST /collect 주가 수집 실행

Redis DB 할당:

  • db=0: n8n Queue
  • db=1: bareunaapi 중복제거
  • db=3: kis-api/score-engine (price:{code}, prices:last_update)
  • db=4: news-collector (news:naver:{hash})
  • db=5: ta-engine (ta:{code})

/home/kyu/trading/aux-signal/main.py

보조 데이터 수집. 포트 8282.

엔드포인트 역할
POST /collect/naver 네이버 integration API → 컨센서스 + 기관/외국인 일별 수급
POST /collect/macro 한국은행 ECOS → USD/KRW 환율, 국고채 10년
GET /consensus/{code} 종목 컨센서스 (목표가/투자의견)
GET /flow/{code} 기관/외국인 일별 순매수
GET /macro/latest 최신 매크로 지표
GET /macro/{indicator} 지표별 시계열

스케줄: 영업일 18:00 네이버 수급/컨센서스, 08:30 ECOS 매크로.


/home/kyu/trading/us-market/main.py

미국증시 동조 시그널. 포트 8383.

엔드포인트 역할
POST /collect Finnhub/AlphaVantage → 미국 ETF·개별주 가격
POST /collect/backfill 신규 페어용 과거 데이터 백필
POST /collect/yfinance-backfill yfinance 폴백 백필
POST /signal/calculate 페어 회귀로 한국 종목별 미증시 시그널 산출
GET /signal/{kr_code} 한국 종목 KR 코드별 시그널
GET /signal/latest 전체 종목 최신 시그널
GET /pairs 등록된 KR↔US 페어
POST /pairs/recalc-beta 60일 회귀 베타 재계산
POST /pairs/discover KOSPI200 × S&P500 상관 자동 발굴
GET /etfs / GET /etfs/{etf}/latest 섹터 ETF 현황

기여 점수:

  • 섹터 ETF 동조 (SOXX/XBI/LIT 등 14개) → 같은 한국 섹터 ±5점
  • 개별 페어 60일 회귀 베타 (NVDA↔SK하이닉스 등) → ±10점

스케줄: 매일 KST 07:30 수집, 08:00 시그널 계산.


/home/kyu/trading/graph-engine/main.py

GAT 그래프 신경망 (PyTorch). 포트 9090.

엔드포인트 역할
POST /graph/build 노드/엣지 재구성
POST /train 학습 (6mo rolling)
POST /predict 전체 추론 → stock_scores.graph_score
GET /predict/{code} 종목별 예측 값
GET /status 모델/학습 상태
  • 노드: 활성 종목, 12피처 (1d/5d/20d 수익률, vol_ratio, RSI, tech_score, ROE, 영업이익률, 부채비율, 7d 뉴스, 미증시 overnight, log_mcap)
  • 엣지: ① 60일 가격 상관 |corr|≥0.4 ② 동일 섹터 ③ 뉴스 공기 ≥3회
  • 스케줄: 일요 06:00 학습 / 매일 08:30 추론
  • 모델 저장: /mnt/nas/models/graph/

/home/kyu/trading/telegram-bot/main.py

텔레그램 명령 처리 봇 (python-telegram-bot).

명령 역할
/start /help 도움말
/buy /buys 강력매수/매수관심 톱 N
/sell /sells 매도관심/강력매도 톱 N
/stock <코드> 종목 점수·신호 요약
/deep <코드> RAG+EXAONE 심층분석 결과
/market 시장 요약(섹터·매크로)

권한: TELEGRAM_CHAT_ID 일치 채팅만 응답.


데이터베이스 스키마 (PostgreSQL)

news_analysis

id, title, url, source, published_at, hash(16자 UNIQUE)
sentiment(호재/악재/중립), intensity(1~5), primary_stock
affected_stocks(JSONB), reason, investment_action(매수관심/매도관심/관망)
keywords(JSONB), stock_names(JSONB), stock_codes(JSONB)
similar_count, catalyst, analyzed_at, created_at

stock_technical

stock_code(UNIQUE), stock_name, price
ma5, ma20, ma60, ma120, rsi, macd, macd_signal, macd_hist
bb_upper, bb_mid, bb_lower, pct_b, stoch_k, stoch_d
vol_ratio, tech_score(-100~100), signal(매수/매도/관망)
obv, obv_trend, vwap20, ichimoku(JSONB)  ← 새 지표
signals(JSONB), targets(JSONB), analyzed_at

dart_corps

stock_code(PK), corp_code, corp_name, modify_date, is_active
※ is_active=true 필터 필수 (상장폐지 제외)

dart_financials

stock_code, corp_code, corp_name, bsns_year, reprt_code
revenue, operating_profit, net_income
total_assets, total_liabilities, total_equity, operating_cashflow
roe, operating_margin, net_margin, debt_ratio, revenue_growth, fcf_ratio
UNIQUE(stock_code, bsns_year, reprt_code)
※ F-Score는 전년 11011 사업보고서 필요 → years≥2 백필

stock_scores (주요 컬럼)

stock_code, score_date, total_score, recommendation
news_score, dart_score, technical_score, foreign_score, short_score, price_score
trend_score, intrinsic_value, margin_of_safety, earnings_quality
magic_score, f_score, roc_pct, earnings_yield_pct
altman_z, peg, momentum_pct, beneish_score
gpa_pct, g_score, amihud_illiq, market_beta  ← 학술 논문 기반 4개
signals(JSONB), buy_votes, sell_votes
position_size_pct, volatility_60d, market_regime_adj, sector
top_reasons, UNIQUE(stock_code, score_date)

weight_config

config_date(PK), weights(JSONB), period_days, sample_size
※ 최신 row가 calculate_daily_scores에서 자동 로드 → ensemble_bonus 가중

pricing_model_v2 (가격예측 모델 학습 결과 저장)

id, model_date, segment, model_type(linear/rf/xgb), target(return_7d/30d/alpha_30d)
feature_names(JSONB), feature_importance(JSONB), coef(JSONB), intercept
r2_oos, ic_spearman, hit_ratio, sample_size, period_days, model_blob(bytea), created_at
※ /learn-pricing 호출 시 모델별 row 갱신, /predict-price가 model_blob 역직렬화로 추론

news_raw (수집/분석 분리용 임시 저장소)

id, stock_code, title, url, url_hash(UNIQUE), source,
published_at_text, collected_at, processed(BOOL), processed_at
※ 크롤러는 raw만 빠르게 저장 → 야간 cron(process_raw)이 batch로 LLM 분석

  • v_recent_signals — 최근 24시간 호재/악재 (intensity DESC)
  • v_stock_news_count — 종목별 7일 뉴스 감성 카운트

환경변수 키 목록 (.env)

POSTGRES_HOST=postgres  POSTGRES_PORT=5432  POSTGRES_DB=trading_ai  POSTGRES_USER=kyu
REDIS_MAX_MEMORY=2gb  REDIS_MAXMEMORY_POLICY=allkeys-lru
OLLAMA_NUM_PARALLEL=4  (EXAONE→GPU0, bge-m3→GPU1 자동 분배)
QDRANT_COLLECTION=news_vectors  QDRANT_VECTOR_SIZE=1024
TELEGRAM_CHAT_ID=8690666445
KIS_IS_PAPER=true  (모의투자 모드)
ECOS_API_KEY=...   (한국은행 매크로 — ecos.bok.or.kr/api 무료)

자주 쓰는 명령어

# 전체 상태
docker compose ps

# 특정 서비스 로그 (실시간)
docker logs trading-news-collector --tail 50 -f
docker logs trading-score-engine --tail 50 -f
docker logs trading-n8n --tail 30

# 재빌드+재배포
docker compose build <service> && docker compose up -d <service>

# PostgreSQL 쿼리 (DB명: trading_ai, user: kyu)
docker exec trading-postgres psql -U kyu -d trading_ai -c "SELECT ..."

# Redis
source /home/kyu/trading/.env && docker exec trading-redis redis-cli -a $REDIS_PASSWORD

# n8n 마이그레이션 확인
docker exec trading-postgres psql -U kyu -d trading_ai -c "SELECT COUNT(*) FROM n8n.migrations;"

# 추천 종목 조회
docker exec trading-postgres psql -U kyu -d trading_ai -c "
  SELECT s.stock_code, d.corp_name, s.total_score, s.recommendation,
         s.magic_score, s.f_score, s.roc_pct, s.earnings_yield_pct
  FROM stock_scores s JOIN dart_corps d ON d.stock_code=s.stock_code
  WHERE d.is_active=true AND s.score_date=CURRENT_DATE
  ORDER BY s.total_score DESC LIMIT 10;"

# 다년치 사업보고서 백필 (F-Score / PEG용)
curl -X POST 'http://localhost:8888/collect/financials?count=3000&years=10&annual_only=true'

# 섹터 정보 채우기 (dart_corps.sector)
curl -X POST http://localhost:8888/collect/sectors

# 점수 수동 재계산 (전체 활성종목 대상)
curl -X POST http://localhost:8686/score/calculate

# 백테스트 기반 공식 가중치 학습
curl -X POST 'http://localhost:8686/learn-weights?days=90'

# 현재 가중치 조회
curl -s http://localhost:8686/learn-weights

# 종목별 6공식 신호 확인
docker exec trading-postgres psql -U kyu -d trading_ai -c "
  SELECT stock_code, stock_name, total_score, signals
  FROM stock_scores WHERE score_date=CURRENT_DATE
  ORDER BY total_score DESC LIMIT 10;"

주의사항

  • 상장폐지 필터: 모든 추천 쿼리에 JOIN dart_corps d ON d.stock_code=... WHERE d.is_active=true 필수
  • fstab: NAS 마운트는 반드시 한 줄로 작성, nfsvers=3 필수
  • GPU: Ollama 단일 컨테이너가 GPU0(EXAONE 추론)·GPU1(bge-m3 임베딩) 동시 사용. runtime: nvidia 필요
  • KIS: 현재 모의투자 모드 (KIS_IS_PAPER=true)
  • 바른API: KRX→Naver 폴백으로 ~3768 종목 로드. 형태소 실패 시 공백분리 폴백

현재 이슈 / TODO

  • fstab NAS 항목이 두 줄로 분리됨 — sudo로 직접 수정 필요
  • n8n 워크플로우 재구성 완료 (워크플로우 16개 / 활성 14개)
  • vLLM 제거 → Ollama 단일 운영으로 전환 (EXAONE 3.5 7.8B + bge-m3)
  • n8n DB 마이그레이션 오류 수정 완료 (51개 마이그레이션 등록)
  • SSL 인증서 자동 갱신 설정 완료 (certbot.timer + deploy hook → nginx reload) 도메인: al/cla/n8/pns/tr.kyleyang.co.kr, 훅: /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh

Behavioral Guidelines (LLM 공통 실수 감축)

Behavioral guidelines to reduce common LLM coding mistakes. Merge with project-specific instructions as needed.

Tradeoff: These guidelines bias toward caution over speed. For trivial tasks, use judgment.

1. Think Before Coding

Don't assume. Don't hide confusion. Surface tradeoffs.

Before implementing:

  • State your assumptions explicitly. If uncertain, ask.
  • If multiple interpretations exist, present them - don't pick silently.
  • If a simpler approach exists, say so. Push back when warranted.
  • If something is unclear, stop. Name what's confusing. Ask.

2. Simplicity First

Minimum code that solves the problem. Nothing speculative.

  • No features beyond what was asked.
  • No abstractions for single-use code.
  • No "flexibility" or "configurability" that wasn't requested.
  • No error handling for impossible scenarios.
  • If you write 200 lines and it could be 50, rewrite it.

Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify.

3. Surgical Changes

Touch only what you must. Clean up only your own mess.

When editing existing code:

  • Don't "improve" adjacent code, comments, or formatting.
  • Don't refactor things that aren't broken.
  • Match existing style, even if you'd do it differently.
  • If you notice unrelated dead code, mention it - don't delete it.

When your changes create orphans:

  • Remove imports/variables/functions that YOUR changes made unused.
  • Don't remove pre-existing dead code unless asked.

The test: Every changed line should trace directly to the user's request.

4. Goal-Driven Execution

Define success criteria. Loop until verified.

Transform tasks into verifiable goals:

  • "Add validation" → "Write tests for invalid inputs, then make them pass"
  • "Fix the bug" → "Write a test that reproduces it, then make it pass"
  • "Refactor X" → "Ensure tests pass before and after"

For multi-step tasks, state a brief plan:

1. [Step] → verify: [check]
2. [Step] → verify: [check]
3. [Step] → verify: [check]

Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification.

These guidelines are working if: fewer unnecessary changes in diffs, fewer rewrites due to overcomplication, and clarifying questions come before implementation rather than after mistakes.