first commit

This commit is contained in:
soohyunmoon 2025-05-06 21:23:04 +09:00
parent 517f564386
commit 401c762683
48 changed files with 15080 additions and 0 deletions

57
.gitignore vendored Normal file
View File

@ -0,0 +1,57 @@
# ========================================
# Python 관련 무시 파일
# ========================================
__pycache__/
*.py[cod]
*.pyo
*.pyd
*.so
# 가상환경 (venv)
.venv/
venv/
ENV/
# 테스트, 로그, 데이터
*.log
*.tmp
*.db
*.sqlite3
*.bak
*.swp
# 환경 설정 / API 키 / 민감 정보
.env
.env.*
*.secret
secrets.json
config.json
api_keys.txt
# 파이썬 배포 파일
dist/
build/
*.egg-info/
# Jupyter Notebook 체크포인트
.ipynb_checkpoints/
# ========================================
# 에디터/IDE 관련
# ========================================
.vscode/
.idea/
*.code-workspace
# ========================================
# 시스템 파일
# ========================================
.DS_Store
Thumbs.db
desktop.ini
# ========================================
# Git 자체 관련 (안전)
# ========================================
*.orig
*.rej

View File

@ -0,0 +1,35 @@
from data_analysis_engine.dataset_builder import add_technical_indicators
from data_analysis_engine.models.xgboost_model import XGBoostModel
import pandas as pd
import os
import glob
def analyze_stocks_pipeline(cds_dir, model_path, top_n=10, output_path="prediction_result.csv"):
model = XGBoostModel()
model.load_model(model_path)
results = []
csv_files = glob.glob(os.path.join(cds_dir, "*_ohlcv.csv"))
for file in csv_files:
symbol = os.path.basename(file).replace("_ohlcv.csv", "")
df = pd.read_csv(file)
df = add_technical_indicators(df)
feature_cols = [
'open', 'high', 'low', 'close', 'volume',
'sma_5', 'sma_10', 'rsi_14', 'macd',
'boll_upper', 'boll_lower'
]
X = df[feature_cols].dropna()
if X.empty:
continue
prob = model.predict_proba(X.tail(1)) # 이미 float 값임
results.append({"symbol": symbol, "predicted_score": prob})
result_df = pd.DataFrame(results)
result_df.sort_values(by="predicted_score", ascending=False, inplace=True)
result_df.head(top_n).to_csv(output_path, index=False)
print("✅ 예측 결과 저장 완료:", output_path)

View File

@ -0,0 +1,66 @@
'''
📁 data_analysis_engine/dataset_builder.py
Complete Data Set(CDS) 학습용 피처(X) 타깍(y)으로 변환
기술 지표 포함
'''
import pandas as pd
import numpy as np
# 기술 지표 계산 함수
def add_technical_indicators(df: pd.DataFrame) -> pd.DataFrame:
df = df.copy()
# 이동 평균선
df['sma_5'] = df['close'].rolling(window=5).mean()
df['sma_10'] = df['close'].rolling(window=10).mean()
# RSI (상대 강도 지수)
delta = df['close'].diff()
gain = delta.where(delta > 0, 0)
loss = -delta.where(delta < 0, 0)
avg_gain = gain.rolling(window=14).mean()
avg_loss = loss.rolling(window=14).mean()
rs = avg_gain / (avg_loss + 1e-6)
df['rsi_14'] = 100 - (100 / (1 + rs))
# MACD
ema12 = df['close'].ewm(span=12, adjust=False).mean()
ema26 = df['close'].ewm(span=26, adjust=False).mean()
df['macd'] = ema12 - ema26
# Bollinger Bands
ma20 = df['close'].rolling(window=20).mean()
std20 = df['close'].rolling(window=20).std()
df['boll_upper'] = ma20 + (std20 * 2)
df['boll_lower'] = ma20 - (std20 * 2)
return df
def build_dataset(df: pd.DataFrame):
"""
CDS를 기반으로 피처(X) 타깍(y) 생성
기술 지표 포함
"""
df = df.copy()
df = add_technical_indicators(df)
df['target'] = (df['close'].shift(-1) > df['close']).astype(int)
df.dropna(inplace=True)
feature_cols = [
'open', 'high', 'low', 'close', 'volume',
'sma_5', 'sma_10', 'rsi_14', 'macd',
'boll_upper', 'boll_lower'
]
X = df[feature_cols]
y = df['target']
return X, y
def build_dataset_with_indicators(df: pd.DataFrame):
"""
build_dataset() 같은 기능을 행하지만, 필요없을 경우를 위해 다른 이름으로 제공
"""
return build_dataset(df)

View File

@ -0,0 +1,34 @@
'''
📁 data_analysis_engine/models/xgboost_model.py
XGBoost 모델 클래스: 학습, 예측, 저장, 로드, 전처리 지원
'''
import os
import xgboost as xgb
import pandas as pd
from data_analysis_engine.dataset_builder import build_dataset
class XGBoostModel:
def __init__(self):
self.model = xgb.XGBClassifier(use_label_encoder=False, eval_metric='logloss')
def fit(self, X: pd.DataFrame, y: pd.Series):
self.model.fit(X, y)
def predict_proba(self, X: pd.DataFrame) -> float:
return float(self.model.predict_proba(X)[-1][1])
def save_model(self, path: str):
os.makedirs(os.path.dirname(path), exist_ok=True)
self.model.save_model(path)
def load_model(self, path: str):
self.model.load_model(path)
def preprocess(self, df: pd.DataFrame) -> pd.DataFrame:
"""
예측 사용할 피처만 추출하는 전처리 함수
"""
X, _ = build_dataset(df)
return X

View File

@ -0,0 +1,48 @@
'''
data_analysis_engine/predict.py
분석 엔진 전체 흐름을 실행하는 진입점 모듈입니다.
- CLI 또는 스크립트 기반 실행 가능
- 입력: CDS CSV 파일들이 저장된 폴더 경로, 모델 파일 경로, 상위 추출
- 처리: analyzer.analyze_stocks() 호출
- 출력: 예측 결과를 콘솔에 출력하고 CSV로 저장
'''
import os
import glob
import argparse
import pandas as pd
from data_analysis_engine.analyzer import analyze_stocks
def main():
parser = argparse.ArgumentParser(description="SightRay 분석 엔진 실행")
parser.add_argument('--cds_dir', type=str, required=False, default=None, help='CDS CSV 파일들이 있는 디렉토리 경로')
parser.add_argument('--model_path', type=str, required=False, default=None, help='저장된 XGBoost 모델 파일 경로')
parser.add_argument('--top_n', type=int, default=5, help='상위 예측 종목 수 (기본 5개)')
parser.add_argument('--output_path', type=str, default='prediction_result.csv', help='결과 저장 파일명')
args = parser.parse_args()
cds_dir = args.cds_dir or input("CDS 디렉토리 경로를 입력하세요 (예: data/CS/2024-12-31): ").strip()
model_path = args.model_path or input("모델 파일 경로를 입력하세요 (예: data_analysis_engine/models/model_2024-04-17.json): ").strip()
# CDS 경로 리스트 생성 (*.csv)
cds_files = glob.glob(os.path.join(cds_dir, '*.csv'))
if not cds_files:
print("[오류] CDS 파일이 존재하지 않습니다.")
return
# 분석 실행
result_df = analyze_stocks(cds_files, model_path, args.top_n)
# 결과 출력 및 저장
print("\n[예측 결과 요약]")
print(result_df)
result_df.rename(columns={'probability': 'predicted_score'}, inplace=True)
result_df.to_csv(args.output_path, index=False)
print(f"\n결과가 다음 위치에 저장되었습니다: {args.output_path}")
if __name__ == '__main__':
main()

View File

@ -0,0 +1,113 @@
"""
📁 data_analysis_engine/train_model.py
Complete Data Set(CDS) 기반으로 XGBoost 모델을 학습 저장하는 스크립트
하이퍼파라미터 튜닝 (GridSearchCV) 포함 + 학습 로그 자동 저장 + logloss Precision@TopN 출력
"""
import os
import pandas as pd
from datetime import datetime
from sklearn.metrics import accuracy_score, roc_auc_score, f1_score, log_loss
from sklearn.model_selection import GridSearchCV
from xgboost import XGBClassifier
from data_analysis_engine.dataset_builder import build_dataset_with_indicators
def precision_at_top_n(y_true, y_score, top_n=50):
top_indices = pd.Series(y_score).nlargest(top_n).index
top_preds = pd.Series(y_true).iloc[top_indices]
return top_preds.sum() / top_n
def train_model(cds_dir: str, output_model_path: str = None):
"""
CDS 디렉토리에서 데이터를 읽고 모델 학습 + 최적 파라미터 탐색 저장
"""
X_total, y_total = [], []
for file in os.listdir(cds_dir):
if not file.endswith("_ohlcv.csv"):
continue
df = pd.read_csv(os.path.join(cds_dir, file))
if df.empty:
continue
X, y = build_dataset_with_indicators(df)
X_total.append(X)
y_total.append(y)
if not X_total:
raise ValueError("CDS 파일에서 학습 가능한 데이터가 없습니다.")
X_all = pd.concat(X_total, ignore_index=True)
y_all = pd.concat(y_total, ignore_index=True)
# ✅ 피처 이름 보존 확인
X_all.columns = X_all.columns.astype(str)
print("📎 학습 피처:", list(X_all.columns))
# 클래스 비율 확인
class_counts = y_all.value_counts().to_dict()
print(f"🎯 타깃 분포: {class_counts}")
weight = class_counts.get(0, 1) / class_counts.get(1, 1)
# 기본 모델 + 튜닝 대상 설정
base_model = XGBClassifier(
use_label_encoder=False,
eval_metric='logloss',
scale_pos_weight=weight,
verbosity=0
)
param_grid = {
'max_depth': [3, 5],
'learning_rate': [0.1, 0.01],
'n_estimators': [100, 300]
}
grid_search = GridSearchCV(base_model, param_grid, cv=3, scoring='roc_auc', n_jobs=-1, verbose=1)
grid_search.fit(X_all, y_all)
best_model = grid_search.best_estimator_
preds = best_model.predict(X_all)
probas = best_model.predict_proba(X_all)[:, 1]
acc = accuracy_score(y_all, preds)
auc = roc_auc_score(y_all, probas)
f1 = f1_score(y_all, preds)
logloss_val = log_loss(y_all, probas)
p_at_50 = precision_at_top_n(y_all, probas, top_n=50)
print(f"📊 정확도: {acc:.2%} | AUC: {auc:.3f} | F1: {f1:.3f} | LogLoss: {logloss_val:.4f} | P@50: {p_at_50:.3f} | 샘플 수: {len(X_all):,}")
print(f"🏆 최적 하이퍼파라미터: {grid_search.best_params_}")
# 로그 저장
date_tag = datetime.now().strftime("%Y-%m-%d")
log_path = "data_analysis_engine/train_log.csv"
log_exists = os.path.exists(log_path)
log_df = pd.DataFrame([{
"date": date_tag,
"accuracy": round(acc, 4),
"auc": round(auc, 4),
"f1_score": round(f1, 4),
"logloss": round(logloss_val, 4),
"precision@50": round(p_at_50, 4),
"samples": len(X_all),
"best_params": str(grid_search.best_params_),
"cds_dir": cds_dir
}])
log_df.to_csv(log_path, mode='a', index=False, header=not log_exists)
# 모델 저장
from xgboost import Booster
model_dir = "data_analysis_engine/models"
os.makedirs(model_dir, exist_ok=True)
versioned_path = os.path.join(model_dir, f"model_{date_tag}.json")
best_model.save_model(versioned_path)
print(f"✅ 모델 저장 완료: {versioned_path}")
print(f"📝 학습 로그 저장 완료: {log_path}")
if __name__ == "__main__":
cds_dir = input("CDS 데이터 디렉토리 [기본: data]: ").strip() or "data"
train_model(cds_dir)

View File

@ -0,0 +1,71 @@
## 📄 train_model.py - Concept 설명 문서
### ✅ 목적
CDS(Complete Data Set)를 기반으로 한 학습용 데이터셋을 생성하고, XGBoost 모델을 학습시켜 상위 분석 파이프라인에서 활용할 수 있도록 모델을 저장하는 스크립트입니다.
---
### 📂 입력 데이터
- `cds_dir`: `_ohlcv.csv` 형식의 종목별 CDS가 저장된 디렉토리
- 예: `AAPL_ohlcv.csv`, `MSFT_ohlcv.csv`
- 파일 구조는 OHLCV(Time Series) 형태
---
### ⚙️ 주요 기능
1. **데이터 적재 및 통합**
- 종목별 CDS 파일을 모두 읽어 피처(X), 타깃(y)으로 변환
- `build_dataset()` 호출 → 기술 지표 피처 등 포함 가능
2. **클래스 분포 확인 및 불균형 보정**
- `y_total`의 클래스 비율(상승/하락) 출력
- `scale_pos_weight` 자동 조정 → 불균형에 강한 학습 구조 지원
3. **XGBoost 모델 학습 + 하이퍼파라미터 튜닝**
- `GridSearchCV`로 최적 파라미터 탐색
- 튜닝 대상: `max_depth`, `learning_rate`, `n_estimators`
4. **모델 평가 지표 출력**
- 정확도 (`accuracy_score`)
- AUC (`roc_auc_score`)
- F1 점수 (`f1_score`)
- LogLoss (`log_loss`)
- Precision@TopN (`precision@TopN`, 예: P@50)
5. **모델 저장 (버전 관리 포함)**
- 저장 경로: `data_analysis_engine/models/model_YYYY-MM-DD.json`
- 날짜 기반 버전 관리 자동 수행
6. **학습 로그 자동 기록**
- `train_log.csv`에 날짜, 성능 지표, 파라미터, 샘플 수 기록
---
### 🧪 사용 방법
```bash
python -m data_analysis_engine.train_model
```
또는 내부에서 import 후 `train_model("data")` 호출
---
### 🧠 향후 확장 가능성
- Optuna 기반 자동 하이퍼파라미터 탐색
- K-fold 교차 검증 평가 구조 도입
- 예측 기반 ROI 피처 학습 (Target 다양화)
- 외부 평가 세트 적용 및 모델 비교 리포트 생성
---
### ⚠️ 주의사항
- 모든 CDS 파일은 비어 있지 않아야 하며, `_ohlcv.csv` 확장자를 따라야 함
- 피처 수가 변하면 모델 구조도 반드시 재학습 필요
---
### 📌 관련 파일
- `dataset_builder.py`: X, y 전처리 생성 및 기술 지표 포함
- `xgboost_model.py`: 모델 클래스 정의 및 저장/불러오기
- `X_total.csv`, `y_total.csv`: 통합 학습 데이터
- `model_YYYY-MM-DD.json`: 학습된 XGBoost 모델
- `train_log.csv`: 학습 결과 누적 로그

View File

@ -0,0 +1,123 @@
'''
📁 data_collection_engine/collect_all_cds.py
S&P500 여러 종목에 대해 CDS 데이터를 일괄 수집하고,
XGBoost 학습을 위한 통합 데이터셋도 자동 생성하는 스크립트
'''
import os
import time
import pandas as pd
from data_collection_engine.engine import DataCollectionEngine
from data_analysis_engine.dataset_builder import build_dataset
def collect_all_cds(ticker_list_path: str, start: str, end: str, save_dir: str = "data", delay_sec: int = 13):
"""
여러 종목의 CDS 데이터를 일괄 수집하여 저장하고, 학습용 통합 데이터셋도 생성
Parameters:
ticker_list_path (str): 수집할 종목 코드가 들어 있는 CSV 파일 경로
start (str): 시작일 (YYYY-MM-DD)
end (str): 종료일 (YYYY-MM-DD)
save_dir (str): 저장 디렉토리
delay_sec (int): API 호출 간격 (기본 13)
"""
df = pd.read_csv(ticker_list_path)
# 사용자에게 타입 선택 옵션 제공
print("\n🔍 선택 가능한 종목 유형:")
type_mapping = {
"CS": "Common Stock - 일반 주식 (가장 보편적인 기업 지분)",
"ETF": "Exchange Traded Fund - 지수 추종형 상장지수펀드",
"ETN": "Exchange Traded Note - 채권 기반의 상장지수증권",
"ADR": "American Depository Receipt - 해외 주식의 미국 상장 버전",
"PREF": "Preferred Stock - 배당 우선주",
"UNIT": "Unit - ETF 구성 단위 또는 묶음",
"RIGHT": "Rights - 신주인수권, 일정 기간 내 주식 매입 권리",
"FUND": "Mutual Fund - 공모펀드 또는 투자신탁",
"SP": "Structured Product - 파생결합증권",
"WARRANT": "Warrant - 일정 가격에 주식 구매 권한을 부여하는 증서",
"INDEX": "Market Index - 종합 주가지수 등",
"BOND": "Bond - 회사채 또는 정부채 등 고정수익 상품"
}
for k, v in type_mapping.items():
print(f"{k:<7}: {v}")
type_input = input("\n✅ 수집할 종목 유형을 입력하세요 (예: CS): ").strip().upper()
if "type" not in df.columns:
print("'type' 컬럼이 존재하지 않습니다. 전체 데이터 사용.")
filtered_df = df.copy()
else:
filtered_df = df[df["type"] == type_input].copy()
total_available = len(filtered_df)
print(f"\n{total_available}개의 종목이 선택된 유형({type_input})에 해당합니다.")
estimated_time = total_available * delay_sec / 60
print(f"⏳ 예상 소요 시간: 약 {estimated_time:.1f}분 (요금제 기준 {delay_sec}초 간격)")
count_limit = input(f"몇 개를 수집하시겠습니까? [기본: {total_available}]: ").strip()
count = int(count_limit) if count_limit else total_available
tickers = filtered_df.head(count)
symbol_col = "symbol" if "symbol" in tickers.columns else "ticker"
ticker_list = tickers[symbol_col].dropna().unique()
# 종료 날짜 기준으로 저장 디렉토리 세분화 (예: data/CS/2024-12-31)
dated_dir = os.path.join(save_dir, type_input, end)
engine = DataCollectionEngine(data_dir=dated_dir)
os.makedirs(dated_dir, exist_ok=True)
failed = []
X_all, y_all = [], []
error_429_count = 0
for i, symbol in enumerate(ticker_list):
try:
print(f"[{i+1}/{len(ticker_list)}] {symbol} 수집 중...")
df = engine.collect(symbol.strip().upper(), start, end)
X, y = build_dataset(df)
X_all.append(X)
y_all.append(y)
error_429_count = 0
time.sleep(delay_sec)
except Exception as e:
print(f"{symbol} 수집 실패: {e}")
failed.append(symbol)
if "429" in str(e):
error_429_count += 1
if error_429_count >= 2:
print("⏸️ 연속된 429 오류 감지 → 60초 대기 중...")
time.sleep(60)
if failed:
print("\n⚠️ 일부 종목 수집 실패:", failed)
failed_df = pd.DataFrame(failed, columns=["ticker"])
failed_df.to_csv(os.path.join(dated_dir, "failed_tickers.csv"), index=False)
print("📄 실패 종목 목록 저장 완료: failed_tickers.csv")
else:
print("\n✅ 전체 종목 수집 완료!")
if X_all:
X_total = pd.concat(X_all, ignore_index=True)
y_total = pd.concat(y_all, ignore_index=True)
X_total.to_csv(os.path.join(dated_dir, "X_total.csv"), index=False)
y_total.to_csv(os.path.join(dated_dir, "y_total.csv"), index=False)
print("✅ 통합 학습용 데이터 저장 완료: X_total.csv, y_total.csv")
else:
print("❗ 유효한 CDS 데이터가 없어 학습용 데이터셋을 생성하지 못했습니다.")
if __name__ == "__main__":
print("CDS 일괄 수집을 시작합니다. 아래 정보를 입력해 주세요:")
ticker_list_path = input("티커 리스트 CSV 경로 [기본: sp500_tickers.csv]: ").strip() or "sp500_tickers.csv"
start = input("시작일 (YYYY-MM-DD) [기본: 2023-01-01]: ").strip() or "2023-01-01"
end = input("종료일 (YYYY-MM-DD) [기본: 2024-12-31]: ").strip() or "2024-12-31"
save_dir = input("저장 디렉토리 이름 [기본: data]: ").strip() or "data"
delay = input("API 호출 간격 (초) [기본: 13]: ").strip()
delay_sec = int(delay) if delay else 13
collect_all_cds(
ticker_list_path=ticker_list_path,
start=start,
end=end,
save_dir=save_dir,
delay_sec=delay_sec
)

View File

@ -0,0 +1,48 @@
# os 모듈은 폴더 생성, 파일 경로 등 운영체제와 관련된 기능을 다룹니다
try:
from data_collection_engine.modules.fetchers.polygon import fetch_ohlcv
from data_collection_engine.modules.preprocessors import clean_ohlcv
except ModuleNotFoundError:
from modules.fetchers.polygon import fetch_ohlcv
from modules.preprocessors import clean_ohlcv
import os
# Polygon API를 통해 주가 데이터를 가져오는 함수 (fetcher 모듈에 정의됨)
# 가져온 데이터를 정제(clean)하는 함수 (preprocessor 모듈에 정의됨)
# 데이터 수집을 담당하는 클래스
class DataCollectionEngine:
# 생성자 함수: 객체가 만들어질 때 실행됨
def __init__(self, data_dir="data"):
self.data_dir = data_dir # 수집한 데이터를 저장할 디렉토리 경로
# 데이터 저장 폴더가 없으면 새로 생성함
os.makedirs(data_dir, exist_ok=True)
# 실제 데이터를 수집하고 저장하는 메인 함수
def collect(self, symbol: str, start_date: str, end_date: str):
# 사용자에게 현재 어떤 종목의 데이터를 수집 중인지 출력
print(f"{symbol} 데이터를 수집 중입니다...")
# fetch_ohlcv 함수를 사용하여 API로부터 주가 원본 데이터(raw data)를 수집
raw_data = fetch_ohlcv(symbol, start_date, end_date)
# 수집한 데이터를 정제(cleaning)하여 DataFrame으로 변환
df = clean_ohlcv(raw_data)
# 저장할 파일 경로를 지정함 (예: data/AAPL_ohlcv.csv)
save_path = os.path.join(self.data_dir, f"{symbol}_ohlcv.csv")
# DataFrame을 CSV 파일로 저장
df.to_csv(save_path, index=False)
# 사용자에게 저장 완료 메시지를 출력
print(f"{symbol} 데이터 저장 완료: {save_path}")
# 수집한 데이터프레임을 반환 (다른 곳에서 쓸 수 있도록)
return df

View File

@ -0,0 +1,25 @@
# 데이터 수집 엔진을 불러옵니다 (engine.py에 있는 DataCollectionEngine 클래스 사용)
from engine import DataCollectionEngine
# 프로그램의 시작 지점을 정의하는 함수
def main():
# 사용자에게 종목 코드를 입력받습니다 (예: AAPL, TSLA 등)
# 입력값에서 양쪽 공백을 제거하고 대문자로 변환합니다
symbol = input("조회할 주식 종목 코드를 입력하세요 (예: AAPL, TSLA): ").strip().upper()
# 사용자에게 수집할 시작 날짜를 입력받습니다 (형식: 2024-01-01)
start = input("시작 날짜를 입력하세요 (YYYY-MM-DD): ").strip()
# 사용자에게 수집할 종료 날짜를 입력받습니다 (형식: 2024-12-31)
end = input("종료 날짜를 입력하세요 (YYYY-MM-DD): ").strip()
# 데이터 수집 엔진 객체를 생성합니다
engine = DataCollectionEngine()
# 입력받은 종목, 날짜에 따라 데이터를 수집하고 저장합니다
engine.collect(symbol, start, end)
# 이 파일이 직접 실행되었을 때만 main() 함수를 실행합니다
# (다른 파일에서 이 파일을 import 하면 실행되지 않도록 하기 위함)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,40 @@
# 운영체제 관련 기능 (예: 환경변수 읽기, 경로 등)을 위한 모듈
import os
# HTTP 요청을 보내기 위한 외부 라이브러리 (API 호출용)
import requests
# .env 파일에 저장된 환경변수를 불러오기 위한 도구
from dotenv import load_dotenv
# .env 파일에서 환경변수들을 로드합니다 (예: API 키)
load_dotenv()
# 환경변수에서 Polygon API 키를 읽어옵니다
API_KEY = os.getenv("POLYGON_API_KEY")
# 주어진 종목(symbol)에 대해 Polygon API를 사용하여 OHLCV 데이터를 수집하는 함수
# 예: fetch_ohlcv("AAPL", "2024-01-01", "2024-03-01")
def fetch_ohlcv(symbol: str, start_date: str, end_date: str, interval: str = "day") -> list:
# Polygon API의 엔드포인트 URL 구성
url = f"https://api.polygon.io/v2/aggs/ticker/{symbol}/range/1/{interval}/{start_date}/{end_date}"
# API 호출에 필요한 파라미터 정의
params = {
"adjusted": "true", # 분할, 배당 등을 반영한 데이터 사용 여부
"sort": "asc", # 날짜 기준 오름차순 정렬
"limit": 50000, # 한 번에 최대 수집 가능한 데이터 수
"apiKey": API_KEY # 인증을 위한 API 키
}
# GET 방식으로 API 호출을 수행
res = requests.get(url, params=params)
# 응답 상태 코드가 200이 아니면 예외를 발생시킴 (에러 메시지도 함께 출력)
if res.status_code != 200:
raise Exception(f"Polygon API error: {res.status_code} - {res.text}")
# JSON 응답 중 'results' 키에 들어있는 실제 데이터를 추출하여 반환
data = res.json()
return data.get("results", [])

View File

@ -0,0 +1,35 @@
# pandas는 데이터를 표 형태(DataFrame)로 다루기 위한 라이브러리입니다
import pandas as pd
# 이 함수는 Polygon API에서 받아온 주식 데이터를 CDS(Complete Data Set)로 정리합니다
def clean_ohlcv(raw_data: list) -> pd.DataFrame:
# 입력된 raw_data (딕셔너리 리스트)를 pandas의 DataFrame으로 변환
df = pd.DataFrame(raw_data)
# 't' 컬럼은 timestamp인데 밀리초 단위이므로 datetime 형식으로 변환
df['t'] = pd.to_datetime(df['t'], unit='ms')
# 컬럼 이름을 사람이 이해하기 쉬운 형태로 바꿉니다
df.rename(columns={
't': 'timestamp', # 날짜 및 시간
'o': 'open', # 시가
'h': 'high', # 고가
'l': 'low', # 저가
'c': 'close', # 종가
'v': 'volume' # 거래량
}, inplace=True)
# 중복된 행이 있다면 제거
df.drop_duplicates(inplace=True)
# 결측값(NaN)이 포함된 행이 있다면 제거
df.dropna(inplace=True)
# 날짜(timestamp)를 기준으로 오름차순 정렬
df.sort_values(by='timestamp', inplace=True)
# 인덱스를 다시 0부터 순서대로 지정
df.reset_index(drop=True, inplace=True)
# 최종적으로 정제된 CDS(DataFrame)를 반환
return df

View File

@ -0,0 +1,45 @@
## 📘 거래량 가중 평균가 (VWAP: Volume Weighted Average Price) 개념 정리
### ✅ VWAP란?
VWAP는 특정 시간 구간 내에서 **거래량을 고려한 평균 가격**을 의미합니다. 단순 평균가보다 실제 체결 강도와 시장 중심가를 더 잘 반영하므로, 기관 투자자와 알고리즘 트레이딩 시스템에서 핵심적으로 활용됩니다.
---
### 🧮 계산식
VWAP는 다음 수식으로 계산됩니다:
\[
\text{VWAP} = \frac{\sum (\text{가격} \times \text{거래량})}{\sum \text{거래량}}
\]
※ Polygon.io API에서는 이 값을 미리 계산해 `vw` 컬럼으로 제공합니다.
---
### 📊 SightRay에서의 활용
- CDS 생성 시 API로부터 받은 `vw` 값을 그대로 포함
- 분석 엔진이나 모델 학습 단계에서 **독립 피처로 활용 가능**
- 특정 시점의 종가(close)와 VWAP 간 차이로 **시장 심리나 평균 체결 강도** 해석 가능
---
### 🧠 예측 모델에서의 장점
| 항목 | 효과 |
|------|------|
| 평균보다 실제 중심가 반영 | 단기 가격 왜곡을 필터링 가능 |
| 종가 대비 VWAP 분석 | 매수/매도 강도 판단에 활용 가능 |
| 거래량 포함 | 수급 기반 전략 반영에 유리 |
---
### 💡 활용 아이디어
- `close > VWAP` 여부를 바이너리 피처로 추가
- `close - VWAP` 값을 연속형 피처로 사용
- VWAP 상하 이격률을 통해 **기관 중심 매매 강도** 파악
- VWAP을 기준선으로 한 기술적 전략 (ex: VWAP Breakout)
---
### 📌 정리
VWAP는 단순 가격 평균보다 정보량이 풍부하고, 실제 거래 강도를 반영하는 핵심적인 기술적 데이터입니다. SightRay에서는 CDS 수집 시 이를 포함하고, 모델 학습 피처로도 적극 활용 가능하도록 설계되어 있습니다.

View File

@ -0,0 +1,96 @@
# 🧠 SightRay 데이터 분석 엔진 기능 요약 및 MVP 충족도 평가
---
## ✅ 엔진 개요
**SightRay 데이터 분석 엔진**은 CDS(Complete Data Set)를 입력으로 받아
주가의 상승 여부 또는 ROI(수익률)를 예측하고, 상승 가능성이 높은 종목을 선별하는 핵심 예측 시스템입니다.
- **입력:** OHLCV 기반의 CDS 파일 (CSV)
- **출력:** 예측 결과 + 상승 확률 + 상위 종목 리스트 (CSV 저장)
- **연계 대상:** 리스크 관리 엔진
---
## 🧩 디렉토리 구조 및 구성 파일
```plaintext
sightray/
├── data_analysis_engine/
│ ├── dataset_builder.py # CDS → 학습용 피처/타깃 변환
│ ├── models/
│ │ └── xgboost_model.py # XGBoost 모델 정의 및 예측 기능
│ ├── analyzer.py # 다중 종목 예측 + 상위 추출
│ └── predict.py # CLI 실행 진입점 (결과 저장)
```
| 파일명 | 역할 | 계층 |
|--------|------|------|
| `dataset_builder.py` | CDS → 학습용 데이터셋 변환 | Module Layer |
| `xgboost_model.py` | 모델 정의, 학습, 예측 | Module Layer |
| `analyzer.py` | 종목 순회, 예측, 정렬 | Engine Layer |
| `predict.py` | 분석 흐름 실행 CLI | Application Layer |
---
## 🔁 데이터 흐름
```plaintext
[CDS CSV 파일]
dataset_builder.py → 학습용 피처 + 타깃 생성
xgboost_model.py → 모델 로드 + 예측 수행
analyzer.py → 종목별 예측 결과 정리
predict.py → 결과 출력 및 prediction_result.csv 저장
```
---
## ✅ 구현된 기능 목록
| 기능 항목 | 구현 여부 | 설명 |
|-----------|-----------|--------|
| CDS 입력 처리 | ✅ | CDS → 학습용 데이터로 변환 |
| 단일 모델 예측 (XGBoost) | ✅ | 분류 모델로 상승 확률 예측 |
| 다중 종목 분석 | ✅ | CDS 파일 목록을 순회하며 예측 수행 |
| 상위 종목 추출 | ✅ | 상승 확률 기준 top-N 종목 정렬 |
| CLI 실행 및 결과 저장 | ✅ | `predict.py`에서 CSV로 저장 가능 |
| 결과 포맷 | ✅ | `symbol, prediction, probability` 포함한 DataFrame |
| 계층화된 구조 | ✅ | 분석 모듈 구조 분리 및 재사용성 확보 |
| 문서화 가능성 | ✅ | 각 모듈별 역할 및 흐름 주석 포함 완료 |
| 평가 지표, ROC 등 | ❌ | (추후 확장 예정) |
| LSTM 또는 앙상블 | ❌ | (MVP 이후 단계에서 추가 예정) |
---
## 📈 예측 결과 예시
| symbol | prediction | probability |
|--------|------------|-------------|
| AAPL | 1 | 0.84 |
| TSLA | 0 | 0.48 |
| NVDA | 1 | 0.76 |
---
## 🎯 MVP 충족도 평가
| 항목 | 달성률 | 설명 |
|-------|---------|------------------------|
| 핵심 기능 구현 | **85%+** | CDS 분석 → 상위 종목 추출까지 구현 완료 |
| 예측 정확도 개선 | 🚧 | LSTM, 앙상블은 추후 도입 예정 |
| 평가/리포트 기능 | 🚧 | 성능 평가 지표 및 시각화는 향후 추가 예정 |
| 연계 준비도 | ✅ | 리스크 엔진에 결과 연동 가능 상태 |
---
## ✅ 결론
SightRay의 데이터 분석 엔진은 현재 단계에서 **MVP 수준의 주요 기능을 모두 구현 완료**하였으며,
이제 리스크 관리 엔진과의 연계 또는 예측 성능 향상(모델 고도화)으로 나아갈 수 있는 준비가 완료된 상태입니다.
> 🚀 다음 단계로는 LSTM 또는 앙상블 모델 추가, 성능 평가 지표 도입, 실거래 적용 테스트가 가능합니다.

View File

@ -0,0 +1,105 @@
# 📦 SightRay 데이터 수집 엔진 기능 요약 및 MVP 충족도 평가
---
## ✅ 엔진 개요
**SightRay 데이터 수집 엔진**은 외부 주가 API(Polygon 등)를 통해 종목별 OHLCV 데이터를 수집하고,
분석 엔진이 바로 사용할 수 있도록 정제된 CDS(Complete Data Set)를 생성하는 핵심 모듈입니다.
- **입력:** 종목 코드, 날짜 범위
- **출력:** 정제된 CDS 파일 (CSV 형식)
- **사용자 입력 기반 동작 (CLI)**
- **기술 지표 생성은 포함하지 않음 → 분석 엔진에서 처리**
---
## 🧩 디렉토리 구조 및 구성 파일
```plaintext
sightray/
└── data_collection_engine/
├── engine.py # 수집 실행을 담당하는 통합 엔진 클래스
└── modules/
├── fetchers/
│ └── polygon.py # Polygon API를 통한 주가 수집 기능
└── preprocessors.py # 결측/중복 제거, timestamp 정제 등 전처리
```
| 파일명 | 역할 | 계층 |
|--------|------|------|
| `engine.py` | 사용자 입력 → 수집 → 전처리 → 저장 흐름 실행 | Engine Layer |
| `fetchers/polygon.py` | Polygon API로 OHLCV 데이터 수집 | Module Layer |
| `preprocessors.py` | 데이터 클렌징 및 CDS 구조 정제 | Module Layer |
---
## 🔁 데이터 흐름
```plaintext
[사용자 입력: 종목, 날짜 범위]
fetchers/polygon.py → Polygon API 호출
preprocessors.py → DataFrame 정제 및 컬럼 리네이밍
engine.py → 전체 흐름 제어 및 CSV 저장 (data/SYMBOL_ohlcv.csv)
```
---
## ✅ 구현된 기능 목록
| 기능 항목 | 구현 여부 | 설명 |
|-----------|-----------|--------|
| 사용자 입력 처리 | ✅ | 종목코드, 날짜 범위 입력 가능 (CLI 기반) |
| 외부 API 연동 | ✅ | Polygon API 연동 및 에러 핸들링 포함 |
| 결측치/중복 제거 | ✅ | DataFrame 전처리 수행 |
| 컬럼 정제 및 타입 변환 | ✅ | 컬럼 이름 변경, datetime 변환 포함 |
| 정렬 및 저장 | ✅ | timestamp 기준 정렬 후 CSV 저장 |
| 디렉토리 구조화 | ✅ | fetcher / preprocessor 모듈 분리 구조 적용 |
| 환경변수 관리 | ✅ | `.env` 파일로 API 키 분리 |
| CDS 정의 준수 | ✅ | 분석 엔진이 바로 사용할 수 있는 포맷 제공 |
---
## 📄 생성되는 CDS 예시
| timestamp | open | high | low | close | volume | vw | n |
|-----------|------|------|-----|-------|--------|----|---|
| 2024-01-02 | 187.15 | 188.44 | 183.88 | 185.64 | 81964874 | 185.9465 | 1008871 |
- timestamp는 정렬 및 datetime 형식 변환 완료
- 분석용 OHLCV 컬럼 포함
- 거래량(volume), 체결 수(n), 거래량 가중 평균가(vw) 포함
### 🔍 `vw` 컬럼 (거래량 가중 평균가, VWAP)
- 해당 기간 동안 체결된 가격과 거래량을 기반으로 산출된 **실질적인 평균 매수/매도 가격**
- 계산식 예시:
\[
VWAP = \\frac{\\sum (\\text{가격} \\times \\text{거래량})}{\\sum \\text{거래량}}
\]
- **기술 지표로도 활용됨** (지지선/저항선 판단 근거로 자주 사용)
- `Polygon.io`의 응답에 포함된 기본 컬럼으로, SightRay는 그대로 CDS에 반영
---
## 🎯 MVP 충족도 평가
| 항목 | 달성률 | 설명 |
|-------|---------|------------------------|
| CDS 수집 및 저장 | ✅ 100% | 분석에 활용 가능한 형식으로 저장 완료 |
| CLI 실행 및 구조화 | ✅ | 사용자 친화적 구조로 엔진 실행 가능 |
| 지표 생성 미포함 | ⛔ | 지표는 분석 엔진에서 처리 예정 |
| API 오류 대응 | ✅ | 응답 코드 체크 및 예외 처리 구현 |
| 확장 가능성 (다중 종목, 자동화) | 🔜 | 향후 배치 처리 및 스케줄링 가능성 고려됨 |
---
## ✅ 결론
SightRay의 데이터 수집 엔진은 MVP 기준에서 요구되는 **CDS 생성 기능을 완전히 충족**하고 있으며,
다음 단계인 분석 엔진, 리스크 엔진으로 원활하게 데이터를 공급할 수 있는 상태입니다.
> 🚀 이후 확장 과제로는 다중 종목 수집, 자동화 실행 스케줄링, DB 저장 연계 기능이 고려될 수 있습니다.

View File

@ -0,0 +1,140 @@
### SightRay 핵심 디렉토리 구조 설명 (MVP 기준)
---
## 프로젝트 루트 구조 예시
```
sightray/
├── data_collection_engine/ # 데이터 수집 및 CDS 생성 담당
│ ├── engine.py # 수집 + 정제 + 저장 실행 흐름
│ └── modules/
│ ├── fetchers/
│ │ └── polygon.py # Polygon API 연동
│ └── preprocessors.py # CDS 정제 및 전처리
└── data_analysis_engine/ # CDS를 기반으로 주가 예측 담당
│ ├── dataset_builder.py # CDS → 학습용 데이터로 변환
│ ├── models/
│ │ └── xgboost_model.py # XGBoost 모델 정의, 학습, 예측
│ ├── analyzer.py # 여러 종목 예측, 상위 선정
│ ├── predict.py # 전체 분석 흐름 실행 CLI
├── risk_manage_engine/ # 예측된 종목의 리스크를 정량적으로 평가
│ ├── calculators/ # 리스크 지표 계산 모듈 집합
│ │ ├── var.py # Value at Risk 계산
│ │ ├── svar.py # Stressed Value at Risk 계산
│ │ ├── monte_carlo.py # Monte Carlo 시뮬레이션
│ │ └── atr.py # ATR 지표 계산
│ ├── risk_calculator.py # 모든 지표를 불러와 계산하는 통합 인터페이스
│ ├── risk_scorer.py # risk_score 산출 (0~100)
│ ├── filter.py # 투자 적격 종목 필터링
│ └── evaluate.py # 전체 리스크 평가 흐름 실행
├── strategy_engine/ # 리스크 필터링된 종목을 기반으로 실제 투자 전략 수립
│ ├── templates/ # 다양한 전략 유형 정의 (기본, 리스크 기반 등)
│ │ ├── basic_strategy.py # TP/SL 기준의 기본 전략
│ │ ├── risk_adjusted_strategy.py # 리스크 점수 기반 투자 강도 조절 전략
│ ├── selector.py # tradable 종목 중 전략 조건 부합 종목만 선택
│ ├── position_manager.py # 진입/청산 시점 판단, 자금 배분 전략 실행
│ └── run_strategy.py # 전략 엔진 실행 진입점
```
---
## 데이터 수집 엔진 (data_collection_engine)
### engine.py
- CDS 생성을 위한 메인 클래스 (`DataCollectionEngine`) 구현
- fetcher와 preprocessor를 조합하여 데이터 수집 → 정제 → CSV 저장
### modules/fetchers/polygon.py
- Polygon API에서 주식의 OHLCV 데이터를 요청하고 받아오는 로직 구현
- API 키는 `.env` 파일을 통해 안전하게 불러옴
### modules/preprocessors.py
- API로 받은 원본 데이터를 CDS 형식으로 정제
- 결측치 제거, 중복 제거, 컬럼명 정리, 정렬, 인덱스 리셋 등 포함
---
## 데이터 분석 엔진 (data_analysis_engine)
### dataset_builder.py
"""
파일 설명:
CDS (OHLCV) 데이터를 머신러닝 학습용 구조로 변환
- 입력: CDS CSV 파일 (DataFrame)
- 출력: XGBoost 학습용 피처 + 타깃 컬럼 포함 DataFrame
- 타깃: 다음날 종가가 오르면 1, 내리면 0
"""
### models/xgboost_model.py
"""
파일 설명:
XGBoost 모델 학습, 저장, 예측을 포함한 클래스 정의
- fit(): 학습
- predict(): 예측 결과 및 상위 종목 정렬 반환
- save_model(), load_model(): 모델 파일 저장 및 로드
"""
### analyzer.py
"""
파일 설명:
각 종목의 CDS를 불러와 XGBoost 예측 실행
- ROI, 상승 확률 등을 기반으로 상위 종목 필터링
"""
### predict.py
"""
파일 설명:
전체 분석 흐름을 실행하는 엔트리 포인트
- CLI 또는 스크립트로 사용
- analyzer.py를 통해 결과 생성 후 저장
"""
---
## 리스크 관리 엔진 (risk_manage_engine)
### calculators/
- var.py: Value at Risk 계산 로직
- svar.py: Stressed Value at Risk 계산 로직
- monte_carlo.py: Monte Carlo Simulation을 통한 리스크 추정
- atr.py: Average True Range 계산을 통한 변동성 측정
### risk_calculator.py
- 위의 리스크 지표 계산 모듈들을 통합 호출
- 분석 결과와 CDS를 입력받아 리스크 요소 계산
### risk_scorer.py
- 여러 리스크 지표를 통합하여 종합 risk_score(0~100)를 산출
- 사용자 정의 가중치를 적용한 리스크 평가 기준 가능
### filter.py
- risk_score 기반으로 투자 적격 종목을 필터링
- 기준치 이하 종목은 제외
### evaluate.py
- 분석 엔진에서 넘어온 종목에 대해 전체 리스크 평가 파이프라인 실행
- 결과를 CSV로 저장하거나 전략 엔진에 전달
---
## 전략 엔진 (strategy_engine)
### templates/
- basic_strategy.py: TP/SL 기준의 기본 전략 로직 정의
- risk_adjusted_strategy.py: 리스크 점수 기반으로 자금 배분 전략 설정
### selector.py
- tradable 종목 중 전략 조건에 부합하는 종목만 선별
### position_manager.py
- 각 종목에 대해 실제 매수 시점, 목표 수익률(TP), 손절 기준(SL) 설정
- 자산 배분 로직 포함
### run_strategy.py
- 전략 템플릿을 실행하고 결과를 저장하는 전략 엔진 실행 진입점

View File

@ -0,0 +1,98 @@
# ⚠️ SightRay 리스크 관리 엔진 요약 (`risk_manage_engine`)
---
## ✅ 엔진 목적
리스크 관리 엔진은 데이터 분석 엔진에서 예측된 종목들에 대해,
**실제로 투자 가능한 종목인지 판단하기 위한 정량적 위험 평가**를 수행합니다.
> 🎯 핵심 목표: `리스크 점수 산출 + 종목 필터링`
---
## 📦 주요 기능
| 기능 | 설명 |
|------|------|
| **리스크 지표 계산** | VaR, SVaR, Monte Carlo, ATR 등 계산하여 종목별 리스크 정량화 |
| **risk_score 산출** | 여러 지표를 종합하여 0~100점의 리스크 점수 계산 |
| **종목 필터링** | 기준치 이상의 종목만 `tradable = True` 로 설정 |
| **전략 엔진 연결** | `risk_filtered_result.csv`로 전략 엔진에 전달 |
---
## 📁 디렉토리 구조
```plaintext
risk_manage_engine/
├── calculators/
│ ├── var.py # Value at Risk 계산
│ ├── svar.py # Stressed VaR 계산
│ ├── monte_carlo.py # Monte Carlo Simulation 계산
│ └── atr.py # ATR (Average True Range) 계산
├── risk_calculator.py # 네 가지 지표를 통합 호출하는 계산기
├── risk_scorer.py # risk_score(0~100) 산출
├── filter.py # 기준치 미만 종목 제외
└── evaluate.py # 전체 파이프라인 실행 (분석 결과 + CDS 평가)
```
---
## 🔁 실행 흐름
```plaintext
[prediction_result.csv + CDS 파일들]
risk_calculator.py → 종목별 risk 요소 계산
risk_scorer.py → 종합 점수화
filter.py → tradable 종목만 필터링
[evaluate.py 실행] → risk_filtered_result.csv 저장
```
---
## 📊 출력 예시
| symbol | prediction | probability | risk_score | tradable |
|--------|------------|-------------|------------|----------|
| AAPL | 1 | 0.83 | 78 | ✅ |
| TSLA | 1 | 0.79 | 64 | ❌ |
---
## 📌 구성 파일 역할 요약
| 파일 | 설명 |
|------|------|
| `var.py` | 히스토리컬 수익률 기반 Value at Risk 계산 |
| `svar.py` | 최근 급락 구간만 추출해 VaR을 재계산 |
| `monte_carlo.py` | 정규분포 기반 무작위 시뮬레이션으로 미래 손실 예측 |
| `atr.py` | 고가/저가/종가 기반 변동성 계산 |
| `risk_calculator.py` | 위 4개 계산기 통합 호출하여 dict 반환 |
| `risk_scorer.py` | 역수 + 가중치 방식으로 0~100 점수화 |
| `filter.py` | 점수 기준치 이상인 종목만 `tradable = True` 설정 |
| `evaluate.py` | 전체 실행 파이프라인 연결 진입점 |
---
## ⚠️ 정적 vs 동적 모델
현재 리스크 엔진은 **정적 통계 기반 모델**로 구성되어 있으며:
- 학습 없이 과거 데이터를 기반으로 즉시 계산
- 빠르고 해석 가능함
향후 확장 계획은 `risk_engine_future_plan.txt`에 명시되어 있음:
- ML 기반 예측 리스크 모델 (LSTM, XGBoost 등)
- risk_score 예측 기반 강화 전략 연계 가능
---
## ✅ 요약 정리
SightRay의 리스크 관리 엔진은 종목의 상승 가능성만이 아닌,
**투자 안정성과 리스크 수용 범위**를 정량적으로 판단하여,
실제로 **투자 가능한 종목(tradable)** 만 전략 엔진으로 넘겨주는 핵심 필터 역할을 수행합니다.

View File

@ -0,0 +1,99 @@
# 📈 SightRay 전략 엔진 요약 (`strategy_engine`)
---
## ✅ 엔진 목적
전략 엔진은 리스크 관리 엔진에서 통과된 `tradable 종목들`에 대해,
**실제 투자 전략을 구성하고, 자금 배분 및 매수 실행 조건을 설정하는 역할**을 수행합니다.
> 🎯 핵심 목표: "이 종목을 얼마에, 얼마나, 어떤 조건으로 살 것인가?"
---
## 📦 주요 기능
| 기능 | 설명 |
|------|------|
| **전략 템플릿 적용** | TP/SL 기준 전략(`basic`), risk_score 기반 전략(`adjusted`) 선택 적용 |
| **자금 배분 및 수량 계산** | total_capital을 종목 수 또는 전략 기준에 따라 분배 |
| **실행 결과 저장** | 포지션, 전략 조건 포함 최종 전략 테이블 생성 |
---
## 📁 디렉토리 구조
```plaintext
strategy_engine/
├── templates/
│ ├── basic_strategy.py # 고정 TP/SL 전략
│ └── risk_adjusted_strategy.py # 리스크 점수 기반 전략
├── selector.py # tradable 종목 중 전략 조건 필터링
├── position_manager.py # 자금 배분 및 포지션 수량 계산
└── run_strategy.py # 전체 전략 흐름 실행 (CLI 지원)
```
---
## 🧠 전략 템플릿 비교
| 전략 | 설명 | TP | SL | Action 기준 |
|--------|------|----|----|----------------|
| `basic` | 고정 비율 설정 | +5% | -3% | 모두 Buy |
| `adjusted` | risk_score 기준 조정 | +3~7% | -2~3% | score < 60 → 제외 |
---
## 🧪 실행 흐름
```plaintext
[risk_filtered_result.csv]
selector.py → 전략 조건 만족 종목 추출
templates/ 전략 템플릿 적용 (TP/SL 설정)
position_manager.py → 자금 배분, 포지션 수량 결정
run_strategy.py → 결과 저장: final_strategy_result.csv
```
---
## 📊 최종 출력 예시
| symbol | entry_price | target_price | stop_loss | position_size | capital_allocated | action |
|--------|-------------|--------------|-----------|----------------|--------------------|--------|
| AAPL | 186.5 | 199.55 | 180.9 | 1340 | 250000 | Buy |
| TSLA | 241.3 | — | — | 0 | 0 | None |
---
## ⚙️ 실행 예시 (CLI)
```bash
python run_strategy.py \
--input risk_filtered_result.csv \
--capital 1000000 \
--strategy adjusted \
--output final_strategy_result.csv
```
---
## 📌 구성 파일 요약
| 파일 | 역할 |
|------|------|
| `selector.py` | tradable 종목 중 전략 조건 만족 종목 필터링 |
| `basic_strategy.py` | 고정 비율 기반 TP/SL 설정 전략 |
| `risk_adjusted_strategy.py` | risk_score에 따라 전략을 조절하는 템플릿 |
| `position_manager.py` | 자본 분배 및 실제 매수 수량 결정 |
| `run_strategy.py` | 전체 전략 실행 컨트롤러 + CLI 지원 |
---
## ✅ 정리
SightRay 전략 엔진은 분석/리스크 단계를 통과한 종목에 대해 **실행 전략을 자동 구성**하며,
**전략 템플릿 기반 + 자금 배분 + 매수 조건 설정**의 완전한 실행 구조를 갖춘 엔진입니다.

11
prediction_result.csv Normal file
View File

@ -0,0 +1,11 @@
symbol,predicted_score
TSM,0.5220013856887817
TSLA,0.5193219780921936
GOOG,0.5187392234802246
PG,0.5162783265113831
AMZN,0.5112144947052002
MSFT,0.49892768263816833
MMM,0.49567362666130066
AAPL,0.4697483777999878
NVDA,0.4667884111404419
ADBE,0.3825182616710663
1 symbol predicted_score
2 TSM 0.5220013856887817
3 TSLA 0.5193219780921936
4 GOOG 0.5187392234802246
5 PG 0.5162783265113831
6 AMZN 0.5112144947052002
7 MSFT 0.49892768263816833
8 MMM 0.49567362666130066
9 AAPL 0.4697483777999878
10 NVDA 0.4667884111404419
11 ADBE 0.3825182616710663

4
requirements.txt Normal file
View File

@ -0,0 +1,4 @@
pandas
requests
python-dotenv
xgboost

11
risk_filtered_result.csv Normal file
View File

@ -0,0 +1,11 @@
symbol,predicted_score,risk_score,tradable
TSM,0.5220013856887817,-5326.75,False
TSLA,0.5193219780921936,-4104.57,False
GOOG,0.5187392234802246,-3846.49,False
PG,0.5162783265113831,-2485.12,False
AMZN,0.5112144947052002,-6766.41,False
MSFT,0.4989276826381683,-9061.16,False
MMM,0.4956736266613006,-3985.47,False
AAPL,0.4697483777999878,-7455.38,False
NVDA,0.4667884111404419,-4811.97,False
ADBE,0.3825182616710663,-8660.04,False
1 symbol predicted_score risk_score tradable
2 TSM 0.5220013856887817 -5326.75 False
3 TSLA 0.5193219780921936 -4104.57 False
4 GOOG 0.5187392234802246 -3846.49 False
5 PG 0.5162783265113831 -2485.12 False
6 AMZN 0.5112144947052002 -6766.41 False
7 MSFT 0.4989276826381683 -9061.16 False
8 MMM 0.4956736266613006 -3985.47 False
9 AAPL 0.4697483777999878 -7455.38 False
10 NVDA 0.4667884111404419 -4811.97 False
11 ADBE 0.3825182616710663 -8660.04 False

View File

@ -0,0 +1,37 @@
'''
risk_manage_engine/calculators/atr.py
ATR (Average True Range) 계산하는 함수 모듈입니다.
- 목적: 주가의 평균적인 일일 변동폭을 계산하여 **변동성 기반 리스크** 수치화함
- 특징: 종가 대비 고가/저가 차이, 전일 종가와의 차이 등을 종합적으로 고려한 지표
- 출력: 지정된 기간 동안의 평균 TR (변동폭)
'''
import pandas as pd
import numpy as np
def calculate_atr(df: pd.DataFrame, period: int = 14) -> float:
"""
Average True Range (ATR) 계산 함수
Parameters:
df (pd.DataFrame): CDS 데이터 (필수: 'high', 'low', 'close')
period (int): ATR 계산에 사용할 기간 (기본: 14)
Returns:
float: 평균 True Range (최근 period일 기준)
"""
df = df.copy()
df['prev_close'] = df['close'].shift(1)
# True Range 계산: 세 가지 중 가장 큰 값
df['tr1'] = df['high'] - df['low']
df['tr2'] = (df['high'] - df['prev_close']).abs()
df['tr3'] = (df['low'] - df['prev_close']).abs()
df['true_range'] = df[['tr1', 'tr2', 'tr3']].max(axis=1)
# ATR: True Range의 이동 평균
atr = df['true_range'].rolling(window=period).mean().iloc[-1]
return round(atr, 4) if not np.isnan(atr) else 0.0

View File

@ -0,0 +1,97 @@
# 📈 ATR (Average True Range) 개념 정리
---
## ✅ ATR이란?
**ATR(Average True Range)**는 자산의 **일일 평균 가격 변동폭**을 나타내는 기술적 지표입니다.
> "이 종목은 하루에 평균적으로 얼마나 출렁이는가?"
1978년 J. Welles Wilder가 고안했으며, 변동성 중심의 트레이딩 전략에 널리 사용됩니다.
---
## 📊 True Range(TR) 계산 방식
True Range는 단순히 고가 - 저가가 아니라 다음 세 가지 중 **가장 큰 값**을 사용합니다:
1. 고가 - 저가
2. |고가 - 전일 종가|
3. |저가 - 전일 종가|
> 이유: 갭 상승/하락까지 포함한 **진짜 변동폭**을 측정하기 위해
---
## 🔢 공식
- True Range(TR): `max(high - low, |high - prev_close|, |low - prev_close|)`
- Average True Range(ATR): `TR의 N일 이동평균`
```python
# ATR 계산 예시
tr1 = high - low
tr2 = abs(high - prev_close)
tr3 = abs(low - prev_close)
true_range = max(tr1, tr2, tr3)
atr = true_range.rolling(N).mean()
```
---
## 💡 사용 목적
| 목적 | 설명 |
|------|------|
| **변동성 측정** | 일일 가격의 출렁임 정도(리스크)를 수치화 |
| **손절/익절 기준** | 트레일링 스탑 설정 시 활용 가능 (예: 1.5 * ATR) |
| **시장 과열 판단** | 갑작스런 ATR 상승은 과도한 움직임의 신호로 해석 가능 |
---
## ⚙️ SightRay에서의 활용 방식
- CDS를 기반으로 최신 14일 기준 ATR을 계산
- ATR이 높을수록 리스크 점수 증가
- ROI 대비 ATR이 지나치게 크면 **변동성이 과도한 종목으로 간주**
```python
from atr import calculate_atr
atr = calculate_atr(cds_df, period=14)
```
---
## 📈 예시 그래프 개념
```
가격 차트 vs ATR 지표
▲ 가격 ▲ ATR
│ │
200 ──┐ ┌── 3.0 ──┐ ┌──
150 ──┘┌──┘ 상승장 2.0 ──┘┌──┘ 상승 추세
100 ───────────────▶ 1.0 ───────────▶
시간 시간
```
---
## 🚧 한계점
| 항목 | 설명 |
|------|------|
| **방향성 정보 없음** | ATR은 변동성만 측정하며 상승/하락 구분 불가 |
| **추세 없는 시장에 민감** | 박스권 장세에서 ATR이 낮아질 수 있음 |
| **종목 특성 반영 어려움** | 일부 종목은 원래부터 ATR이 높은 경향이 있음 |
---
## ✅ 정리
ATR은 가격의 **안정성 또는 출렁임을 정량적으로 측정**하는 지표이며,
SightRay에서는 ROI와 함께 고려하여 **리스크 점수화에 포함**되는 중요한 요소 중 하나입니다.
> 📘 기본 설정: 14일 기준 ATR 사용
> → 변동성이 과도한 종목은 자동 필터링 또는 감점 처리 가능

View File

@ -0,0 +1,88 @@
# 🎲 Monte Carlo Simulation (MCS) 개념 정리
---
## ✅ Monte Carlo Simulation이란?
Monte Carlo Simulation(MCS)은 **확률적인 요소를 가진 문제를 수많은 무작위 시뮬레이션을 통해 해결**하는 기법입니다.
금융에서는 **미래의 자산 가격 변동 경로를 예측**하는 데 자주 사용됩니다.
> "미래에 주가가 어떻게 움직일지 알 수 없다면, 수천 번 랜덤하게 시뮬레이션해서 확률적으로 평가해보자!"
---
## 📊 기본 아이디어
1. 과거 데이터를 통해 수익률의 평균(μ)과 표준편차(σ)를 구함
2. **정규분포 N(μ, σ)**를 가정하고 랜덤 수익률 생성
3. 해당 수익률로 미래 가격 시뮬레이션 (ex. 1일 후 가격)
4. 이걸 수천 번 반복하여 손실 분포 생성
5. 이 분포의 하위 (1-신뢰수준)% 값을 **VaR 유사 값**으로 사용
---
## 🔢 수식 요약
- 수익률 생성: \( r_i \sim N(\mu, \sigma) \)
- 시뮬레이션 가격: \( P_{i} = P_{0} \times (1 + r_i)^d \)
- 손실 계산: \( L_i = P_0 - P_i \)
- 손실 정렬 후 하위 α% 값을 VaR로 간주
---
## 💡 SightRay에서의 사용 방식
- 입력: CDS (OHLCV) 데이터
- 수익률: `df['close'].pct_change()`로 계산
- 시뮬레이션: `np.random.normal(mean, std, N)`
- 출력: 손실 비율 (예: 0.045 → 4.5% 손실 가능성)
```python
simulated_returns = np.random.normal(mu, sigma, size=1000)
simulated_prices = P0 * (1 + simulated_returns)
losses = P0 - simulated_prices
MonteCarlo_VaR = np.percentile(losses, 5) # 95% 신뢰수준
```
---
## 📈 시각적 예시
```
1000번 시뮬레이션 결과 (가격 경로)
P(t) ↑
250┤ . . .
200┤ . . . .
150┤ . . . .
100┤──────────────────────────────▶ 시간 t
↖ 손실 구간은 좌측 하단 영역
```
---
## ✅ 사용 목적 (SightRay 기준)
- 기존 VaR이 수익률 분포만 보는 것과 달리, **미래 가격 경로까지 시뮬레이션** 가능
- 급변동 상황을 반영하는 **더 현실적인 리스크 평가 가능**
- SVaR과 함께 **리스크 점수화에 기여하는 핵심 요소 중 하나**
---
## 🚧 한계점
| 항목 | 설명 |
|------|------|
| 정규분포 가정 | 실제 수익률은 비대칭적일 수 있음 (Fat tail 등) |
| 계산량 | 시뮬레이션 횟수가 많을수록 느림 (CPU 부담) |
| 파라미터 민감성 | 평균/표준편차 설정에 따라 결과가 크게 달라짐 |
---
## ✅ 정리
Monte Carlo Simulation은 **불확실한 미래 가격의 확률 분포를 직접 생성**하여,
보다 직관적이고 현실적인 리스크 추정이 가능한 고급 리스크 평가 기법입니다.
> 📘 SightRay에서는 1000회 이상 시뮬레이션을 통해 1일 후 가격 손실 가능성을 평가하고,
> 이를 리스크 점수 산출의 중요한 피처로 사용합니다.

View File

@ -0,0 +1,80 @@
# 📉 SVaR (Stressed Value at Risk) 개념 정리
---
## ✅ SVaR이란?
**Stressed Value at Risk (SVaR)**는 일반적인 VaR보다 더 **극단적인 시장 상황(= 스트레스 시나리오)**을 가정하여
리스크를 측정하는 방식입니다.
> "만약 시장이 최근과 같은 스트레스 상황에 빠진다면, 우리는 어느 정도 손실을 감당해야 하는가?"
---
## 🧠 SVaR과 VaR의 차이점
| 항목 | VaR | SVaR |
|------|-----|------|
| 기준 수익률 | 전체 수익률 분포 | **특정 스트레스 기간** 수익률만 사용 |
| 위험 수준 | 일반적인 리스크 측정 | **비정상적이고 급격한 시장 상황에 초점** |
| 보수성 | 보통 수준 | **보다 보수적인 손실 예측** |
---
## 📌 예시 (실제 의미)
- VaR 95% = -2.8% → “95% 확률로 -2.8% 이상 손해는 안 본다.”
- SVaR 95% = -4.7% → “급락장이 온다면, 최대 -4.7%까지 손실을 볼 수 있다.”
---
## 🔢 SightRay에서의 계산 방식 (MVP)
- 최근 N일(기본: 30일)을 **스트레스 구간**으로 간주
- 이 구간의 수익률 분포만으로 VaR을 다시 계산
- 계산 방식은 히스토리컬 방식과 동일
```python
# 스트레스 수익률 기준 SVaR
stress_returns = df['return'].iloc[-30:]
sorted_returns = np.sort(stress_returns)
svar = abs(sorted_returns[int((1 - 0.95) * len(sorted_returns))])
```
---
## 📈 시각적 차이 (개념)
```
전체 수익률 분포 스트레스 기간 수익률 분포
─────────────── ───────────────
▁▁▂▃▅▆██▇▅▃▂ ▁▂▃▅▇██▇▅▃▁
↑ VaR ↑ SVaR
```
---
## ⚙️ 사용 목적 (SightRay 기준)
- 데이터 분석 엔진의 결과 종목 중 **최근 급락에 취약한 종목 필터링**
- 일반 VaR보다 더 **보수적인 리스크 기준** 적용
- 리스크 점수 산출 시 가중치를 크게 부여 가능
---
## 🚧 한계점
| 항목 | 설명 |
|------|------|
| 스트레스 정의 주관성 | 어느 기간을 스트레스로 볼 것인가는 분석가 판단에 따라 달라질 수 있음 |
| 시장 구조 변화 반영 부족 | 과거 스트레스가 미래 스트레스로 반복될 것이라는 보장은 없음 |
| 기간 설정 영향 큼 | window 값을 20, 30, 60일 등으로 설정할 때 결과가 많이 달라짐 |
---
## ✅ 정리
**SVaR은 극단적인 시장 환경을 가정한 리스크 관리 수단이며**, SightRay에서는 **최근 급변 구간 수익률**만을 이용해 VaR을 다시 계산하는 방식으로 적용됩니다.
> 📘 기본 설정: 30일 스트레스 구간, 95% 신뢰 수준
> → 향후: 위기 기간 자동 탐지 기능 등으로 확장 가능

View File

@ -0,0 +1,87 @@
# 📉 VaR (Value at Risk) 개념 정리
---
## ✅ VaR이란?
**Value at Risk (VaR)**는 일정 기간 동안 특정 신뢰 수준(confidence level)에서
금융 자산이나 포트폴리오가 감수할 수 있는 **최대 손실 금액**을 추정하는 지표입니다.
> 쉽게 말해:
> "95% 확률로, 내일 이 자산의 손실이 **3%를 넘지 않을 것이다."
---
## 📌 공식 정의
> **VaR(신뢰수준 α)** = 수익률 분포에서 **하위 (1-α)% 지점의 손실 크기**
예를 들어:
- 95% 신뢰 수준 → 하위 5% 수익률 지점의 절대값
- 99% 신뢰 수준 → 하위 1% 수익률 지점의 절대값
---
## 💡 사용 목적
| 목적 | 설명 |
|------|------|
| **위험 평가** | 특정 포지션 또는 포트폴리오의 손실 한계치를 수치화 |
| **투자 판단 기준** | 리스크 관리 기준으로 활용 (리스크가 과도한 종목 배제 등) |
| **자본 관리** | 기관의 자기자본 대비 리스크 노출 통제 수단 |
---
## 🔢 계산 방식
1. 과거 수익률(%)을 계산
2. 수익률들을 정렬 (오름차순)
3. 하위 (1 - confidence level)% 위치의 값 추출
4. 절대값을 취해 **손실 크기**로 사용
예시 (Python 기준):
```python
import numpy as np
sorted_returns = np.sort(df['return'].values)
var_index = int((1 - 0.95) * len(sorted_returns))
VaR = abs(sorted_returns[var_index])
```
---
## 📊 시각적 이해
```
수익률 분포 (히스토그램)
│ ▁▆█▇▆▅▄▃▂
│ ▂▃▅▆█▇▇▅▃▂
VaR → ▁▂▃ ← 손실 구간 (좌측 꼬리)
──────────┼────────────────────▶ 수익률
│ ↑
신뢰 수준 (예: 95%)
```
---
## 🚧 한계점
| 항목 | 설명 |
|------|------|
| **정규분포 가정 문제** | 실무에서는 수익률 분포가 비대칭/두꺼운 꼬리(heavy-tail)인 경우가 많음 |
| **극단 리스크 무시** | 신뢰 수준 바깥(1% 이하)의 극단적인 손실은 반영하지 않음 |
| **과거 기반** | 과거 수익률만을 기반으로 미래 위험을 추정함 |
---
## ✅ SightRay에서의 사용 목적
- 분석 엔진에서 선별한 종목들에 대해 **예측 ROI에 비해 감수할 리스크가 과도한지 판단**
- `risk_score`에 반영되어 **전략 엔진으로 전달 여부 결정**
- 향후 SVaR, Monte Carlo와 함께 **리스크 통합 점수화 기준 중 하나**
---
> 📘 참고: SightRay는 VaR을 히스토리컬 방식으로 계산하며, 신뢰 수준은 기본 95%로 설정되어 있습니다.

View File

@ -0,0 +1,45 @@
'''
risk_manage_engine/calculators/monte_carlo.py
Monte Carlo Simulation을 기반으로 향후 주가 경로를 시뮬레이션하고,
미래 손실 가능성을 추정하는 함수 모듈입니다.
- 목적: 수익률 분포를 정규분포로 가정하여 미래 경로를 확률적으로 생성
- 출력: 특정 신뢰수준 하에서의 최대 손실 (VaR 유사)
'''
import numpy as np
import pandas as pd
def monte_carlo_var(df: pd.DataFrame, simulations: int = 1000, days: int = 1, confidence_level: float = 0.95) -> float:
"""
Monte Carlo Simulation 기반 VaR 추정
Parameters:
df (pd.DataFrame): CDS 데이터 (필수: 'close' 컬럼)
simulations (int): 시뮬레이션 횟수 (기본 1000)
days (int): 후까지 예측할지 (기본 1)
confidence_level (float): 신뢰 수준 (기본 95%)
Returns:
float: 시뮬레이션 기반 손실 추정치 (VaR 유사)
"""
df = df.copy()
df['return'] = df['close'].pct_change()
df.dropna(inplace=True)
mu = df['return'].mean()
sigma = df['return'].std()
# 시뮬레이션된 수익률 (정규분포 기반)
simulated_returns = np.random.normal(loc=mu, scale=sigma, size=simulations)
# 누적 수익률로 변환 (1일 예측 기준)
simulated_prices = df['close'].iloc[-1] * (1 + simulated_returns) ** days
losses = df['close'].iloc[-1] - simulated_prices
losses = np.sort(losses)
var_index = int((1 - confidence_level) * simulations)
var_value = losses[var_index]
return round(abs(var_value / df['close'].iloc[-1]), 4)

View File

@ -0,0 +1,36 @@
'''
risk_manage_engine/calculators/svar.py
Stressed Value at Risk (SVaR) 계산하는 함수 모듈입니다.
- SVaR은 일반적인 VaR보다 극단적인 시장 상황(스트레스 조건) 고려한 리스크 측정 방식입니다.
- MVP 기준에서는 "특정 구간(예: 최근 급락 구간)의 수익률만을 기준으로 VaR을 재계산"하는 방식으로 간단하게 구현합니다.
'''
import numpy as np
import pandas as pd
def calculate_svar(df: pd.DataFrame, confidence_level: float = 0.95, window: int = 30) -> float:
"""
Stressed Value at Risk (SVaR) 계산하는 함수
Parameters:
df (pd.DataFrame): CDS 데이터 (필수: 'close' 컬럼)
confidence_level (float): 신뢰 수준 (기본 95%)
window (int): 최근 며칠간의 스트레스 구간만 사용할지 (기본: 30)
Returns:
float: SVaR (양수, 손실 한계치)
"""
df = df.copy()
df['return'] = df['close'].pct_change()
df.dropna(inplace=True)
# 최근 window일간의 스트레스 구간 수익률만 사용
stress_returns = df['return'].iloc[-window:]
sorted_returns = np.sort(stress_returns.values)
svar_index = int((1 - confidence_level) * len(sorted_returns))
svar_value = abs(sorted_returns[svar_index])
return round(svar_value, 4)

View File

@ -0,0 +1,38 @@
'''
risk_manage_engine/calculators/var.py
Value at Risk (VaR) 계산하는 함수 모듈입니다.
- 목적: 일정 기간 손실이 특정 확률(신뢰수준) 이상 발생하지 않을 것이라는 수준을 계산
- 방법: 수익률 분포 기반, 정규분포 가정 또는 히스토리 기반 가능
MVP 단계에서는 히스토리컬 방식 사용
'''
import numpy as np
import pandas as pd
def calculate_var(df: pd.DataFrame, confidence_level: float = 0.95) -> float:
"""
Value at Risk (VaR) 계산하는 함수
Parameters:
df (pd.DataFrame): CDS 데이터 (필수: 'close' 컬럼)
confidence_level (float): 신뢰 수준 (기본 95%)
Returns:
float: VaR (양수, 손실 한계치)
"""
# 수익률 계산: 오늘 대비 내일 수익률
df = df.copy()
df['return'] = df['close'].pct_change()
df.dropna(inplace=True)
# 수익률들을 오름차순 정렬
sorted_returns = np.sort(df['return'].values)
# VaR은 하위 (1 - 신뢰수준)% 위치에 해당하는 손실
var_index = int((1 - confidence_level) * len(sorted_returns))
var_value = abs(sorted_returns[var_index])
return round(var_value, 4)

View File

@ -0,0 +1,52 @@
import os
import argparse
import pandas as pd
from risk_manage_engine.risk_calculator import calculate_all_risks
from risk_manage_engine.risk_scorer import compute_risk_score
from risk_manage_engine.filter import filter_by_risk
def evaluate_predictions(prediction_file, cds_dir, output_path="risk_filtered_result.csv"):
df = pd.read_csv(prediction_file)
results = []
for _, row in df.iterrows():
symbol = row["symbol"]
score = row["predicted_score"]
cds_path = os.path.join(cds_dir, f"{symbol}_ohlcv.csv")
if not os.path.exists(cds_path):
continue
try:
df_cds = pd.read_csv(cds_path)
risk_factors = calculate_all_risks(df_cds)
risk_score = compute_risk_score(risk_factors)
results.append({
"symbol": symbol,
"predicted_score": score,
"risk_score": risk_score,
"tradable": risk_score >= 60 # 기준점은 조정 가능
})
except Exception as e:
print(f"{symbol} 리스크 평가 중 오류 발생: {e}")
continue
result_df = pd.DataFrame(results)
print("\n[리스크 평가 요약]")
print(result_df)
result_df.to_csv(output_path, index=False)
print(f"\n결과가 다음 위치에 저장되었습니다: {output_path}")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="SightRay 리스크 평가 실행")
parser.add_argument('--cds_dir', type=str, required=True, help='CDS 디렉토리 경로')
parser.add_argument('--prediction_file', type=str, required=True, help='예측 결과 CSV 파일 경로')
parser.add_argument('--output_file', type=str, default='risk_filtered_result.csv', help='리스크 평가 결과 저장 경로')
args = parser.parse_args()
evaluate_predictions(
prediction_file=args.prediction_file,
cds_dir=args.cds_dir,
output_path=args.output_file
)

View File

@ -0,0 +1,41 @@
"""
risk_manage_engine/filter.py
리스크 점수(risk_score) 기반으로 투자 적격 종목만 필터링하는 모듈입니다.
- 기준치 이상의 종목만 `tradable = True` 표시
- 분석 결과와 리스크 평가 결과를 결합해 출력
"""
import pandas as pd
def apply_risk_filter(predictions: pd.DataFrame, risk_scores: dict, threshold: int = 70) -> pd.DataFrame:
"""
예측 결과와 리스크 점수를 결합하여 필터링 결과 반환
Parameters:
predictions (pd.DataFrame): symbol, prediction, probability 등의 예측 결과
risk_scores (dict): {symbol: score} 형태의 리스크 점수
threshold (int): 투자 적격 기준치 (기본 70)
Returns:
pd.DataFrame: 종목 + 예측 결과 + risk_score + tradable 여부 포함
"""
predictions = predictions.copy()
predictions['risk_score'] = predictions['symbol'].map(risk_scores)
predictions['tradable'] = predictions['risk_score'] >= threshold
return predictions
def filter_by_risk(df: pd.DataFrame, threshold: int = 60) -> pd.DataFrame:
"""
risk_score 컬럼을 기반으로 필터링
Parameters:
df (pd.DataFrame): risk_score 컬럼이 포함된 데이터프레임
threshold (int): 필터링 기준점 (기본 60)
Returns:
pd.DataFrame: risk_score >= threshold 종목만 반환
"""
return df[df["risk_score"] >= threshold].reset_index(drop=True)

View File

@ -0,0 +1,33 @@
'''
risk_manage_engine/risk_calculator.py
리스크 관리 엔진의 통합 계산기 모듈입니다.
- 개별 리스크 지표 모듈들을 불러와 번에 계산
- 분석 엔진에서 전달된 종목 CDS에 대해 VaR, SVaR, MCS, ATR 계산 수행
- 결과는 하나의 딕셔너리로 반환
'''
import pandas as pd
from risk_manage_engine.calculators.var import calculate_var
from risk_manage_engine.calculators.svar import calculate_svar
from risk_manage_engine.calculators.monte_carlo import monte_carlo_var
from risk_manage_engine.calculators.atr import calculate_atr
def calculate_all_risks(df: pd.DataFrame, confidence_level: float = 0.95) -> dict:
"""
CDS에 대해 모든 리스크 지표 계산
Parameters:
df (pd.DataFrame): 단일 종목의 CDS
confidence_level (float): 신뢰 수준 (기본 95%)
Returns:
dict: {'var': ..., 'svar': ..., 'mcs': ..., 'atr': ...}
"""
return {
'var': calculate_var(df, confidence_level),
'svar': calculate_svar(df, confidence_level),
'mcs': monte_carlo_var(df, confidence_level=confidence_level),
'atr': calculate_atr(df)
}

View File

@ -0,0 +1,95 @@
# 🧮 리스크 통합 계산기 (`risk_calculator.py`) 개념 정리
---
## ✅ 목적
`risk_calculator.py`는 SightRay의 리스크 관리 엔진 내에서
**VaR, SVaR, Monte Carlo, ATR 등 여러 리스크 지표를 하나의 함수로 통합 계산**하는 모듈입니다.
> 📌 각 지표는 별도의 모듈로 계산되며, 이 파일은 해당 지표들을 조합해서 일괄 계산하는 "통합 계산기" 역할을 수행합니다.
---
## 📦 포함 지표 목록
| 지표 | 설명 | 파일명 |
|------|------|--------|
| **VaR** | Value at Risk 통계 기반 손실 한계 추정 | `var.py` |
| **SVaR** | Stressed VaR 스트레스 구간 기반 VaR | `svar.py` |
| **MCS** | Monte Carlo Simulation 시뮬레이션 기반 손실 예측 | `monte_carlo.py` |
| **ATR** | Average True Range 기술적 변동성 지표 | `atr.py` |
---
## 🧠 내부 구조
```python
from var import calculate_var
from svar import calculate_svar
from monte_carlo import monte_carlo_var
from atr import calculate_atr
def calculate_all_risks(df):
return {
'var': calculate_var(df),
'svar': calculate_svar(df),
'mcs': monte_carlo_var(df),
'atr': calculate_atr(df)
}
```
---
## 🔁 작동 흐름
```plaintext
[단일 종목의 CDS 입력 (DataFrame)]
calculate_var(df)
calculate_svar(df)
monte_carlo_var(df)
calculate_atr(df)
통합된 dict 형태로 반환
```
---
## 📊 출력 예시
```python
{
'var': 0.0312,
'svar': 0.0443,
'mcs': 0.0375,
'atr': 2.91
}
```
- **각 값은 비율 또는 포인트 단위의 손실 위험을 의미**하며,
- 이후 `risk_score` 산출 모듈에서 가중치 등을 통해 통합 점수로 변환됩니다.
---
## ✅ SightRay에서의 역할
| 기능 | 설명 |
|------|------|
| 지표 통합 | 분석된 종목 하나에 대해 리스크 지표를 일괄 계산 |
| 스코어 입력 | `risk_scorer.py`에서 사용할 기초 입력 값 제공 |
| 확장성 확보 | 새로운 지표를 추가해도 이 모듈에서 간단히 조정 가능 |
---
## 🚀 다음 단계와 연계
- 다음 파일인 `risk_scorer.py`에서 `calculate_all_risks()` 결과를 받아
종합 리스크 점수(`risk_score`)를 계산하게 됩니다.
---
## ✅ 요약
- `risk_calculator.py`는 **지표 계산을 하나의 인터페이스로 통합**해주는 모듈
- 향후 리스크 엔진 전체의 모듈화와 유지보수 효율성을 높이는 **핵심 연결 지점**입니다

View File

@ -0,0 +1,83 @@
# 🔮 SightRay 리스크 관리 엔진 정적 모델 기반 → 동적 모델 확장 계획
---
## ✅ 현재 구조 요약: 정적 모델 기반 리스크 엔진
| 구성 요소 | 방식 | 설명 |
|------------|-------|------|
| VaR | 히스토리컬 방식 | 수익률 정렬 기반 손실 한계치 계산 |
| SVaR | 최근 급락 구간 기반 VaR | 보수적 리스크 추정 |
| MCS | 정규분포 기반 시뮬레이션 | 확률적 미래 손실 분포 예측 |
| ATR | 기술적 지표 (변동성) | 평균 변동폭 기반 위험도 평가 |
| Risk Score | 역수 + 가중 평균 | 정규화된 0~100 점수 산출 |
> ☑️ 장점: 구현이 쉽고 해석 가능, 규제 친화적, MVP에 적합
> ⚠️ 한계: 시장 변화에 적응 불가, 예외 상황 예측 한계
---
## 🚀 향후 확장 목표: 동적 학습 기반 리스크 엔진
### 🔄 목적
- 고정된 수치가 아니라, **시장 환경/데이터 흐름에 따라 리스크 예측이 변화하도록 설계**
### 🧠 핵심 방향
| 목표 기능 | 설명 |
|-----------|------|
| **리스크 예측 모델** | 미래 손실 확률 자체를 ML 모델로 학습 및 예측 (Regression) |
| **상호작용 학습** | ATR, ROI, VaR 등의 관계를 모델이 자동으로 파악 |
| **시나리오 기반 강화 학습** | 다양한 시장 조건에서 최적의 리스크 대응 전략 학습 |
---
## 🧩 구조적 확장 계획
```plaintext
risk_manage_engine/
├── predictors/ ← 새로운 하위 디렉토리
│ ├── risk_lstm.py # 시계열 기반 리스크 예측 모델
│ └── risk_xgboost.py # 지도학습 기반 예측 모델 (회귀 or 분류)
├── risk_dataset_builder.py # CDS + 리스크 지표 → 학습용 피처 구성
├── risk_evaluator.py # 실제 예측 vs 계산 비교 평가
```
---
## 🔬 사용할 모델 후보
| 모델 | 목적 | 특성 |
|------|------|------|
| LSTM | 시계열 리스크 추정 | 과거 변화 추세를 고려한 예측 |
| XGBoost | 리스크 점수 회귀 | 고정 피처 기반 예측, 빠른 학습 |
| Autoencoder | 이상 감지 | 갑작스러운 위험 신호 탐지 |
---
## 📊 출력 구조 (예시)
| symbol | pred_risk_score | actual_risk_score | diff | alert |
|--------|------------------|-------------------|------|--------|
| AAPL | 75 | 68 | -7 | ⚠️ |
| TSLA | 62 | 64 | +2 | |
---
## ✅ 적용 순서 제안
1. **CDS + 기존 risk_score → 학습용 데이터 구성** (`risk_dataset_builder.py`)
2. **단일 모델(XGBoost 등)로 `risk_score` 예측 회귀 모델 구축**
3. **실제 risk_score와 비교하여 예측 정확도 평가** (`risk_evaluator.py`)
4. **LSTM 기반 시계열 예측 추가**
5. **전략 엔진과 연계하여 실시간 대응 체계 구축**
---
## ✅ 요약
- 현재: **정적 모델 기반**으로 안정성과 해석성을 확보
- 미래: **동적·학습 기반**으로 예외 상황 적응성과 예측 정밀도 확보
- SightRay는 이 둘을 유기적으로 결합하여 진화 가능한 구조를 갖추고 있음
> 📘 정적 리스크 모델은 기본 평가 수단으로 유지하되,
> 예측력 향상과 고도화를 위해 동적 모델을 확장 적용해 나갈 계획

View File

@ -0,0 +1,50 @@
'''
📁 risk_manage_engine/risk_scorer.py
여러 리스크 지표를 종합하여 종합 리스크 점수를 계산하는 모듈
정규화 안정성 고려한 계산 방식 적용
'''
import numpy as np
# 안정성 유지를 위한 정규화 함수
def normalize(value, min_val, max_val):
if max_val == min_val:
return 0.0 # 모든 값이 동일한 경우 → 중립값
return (value - min_val) / (max_val - min_val)
def compute_risk_score(risk_values: dict) -> float:
"""
입력된 리스크 지표들을 기반으로 종합 리스크 점수를 계산합니다.
Parameters:
risk_values (dict): 리스크 지표들의 원시
: {'var': 0.02, 'svar': 0.03, 'atr': 0.015, 'monte_carlo': 0.05}
Returns:
score (float): 0 ~ 100 사이의 리스크 점수 (높을수록 안정적)
"""
# 기준 범위 지정 (샘플 기준)
expected_ranges = {
'var': (0.01, 0.10),
'svar': (0.01, 0.12),
'atr': (0.005, 0.05),
'monte_carlo': (0.01, 0.20)
}
weights = {
'var': 0.25,
'svar': 0.25,
'atr': 0.25,
'monte_carlo': 0.25
}
score = 0
for key, value in risk_values.items():
min_v, max_v = expected_ranges.get(key, (0, 1))
norm = normalize(value, min_v, max_v)
inverted = 1 - norm # 위험이 낮을수록 점수는 높아야 함
weighted = inverted * weights.get(key, 0.25)
score += weighted
return round(score * 100, 2) # 점수를 0~100 범위로 환산

View File

@ -0,0 +1,87 @@
# 🧮 종합 리스크 점수 산출기 (`risk_scorer.py`) 개념 정리
---
## ✅ 목적
`risk_scorer.py`는 리스크 관리 엔진에서 계산된 다양한 리스크 지표(VaR, SVaR, MCS, ATR)를 기반으로,
**0 ~ 100 사이의 단일 리스크 점수(`risk_score`)**를 산출하는 모듈입니다.
> 📌 이 점수는 종목의 전반적인 투자 안정성을 나타내며, 전략 엔진에서 매매 대상 필터링 기준으로 사용됩니다.
---
## 🔢 점수 계산 방식
1. 각 지표 값(`var`, `svar`, `mcs`, `atr`)을 입력으로 받음
2. 위험이 클수록 점수는 낮아야 하므로 **역수 방식**으로 가공
3. 각 지표에 대해 **가중치(weight)** 적용
4. 모든 점수 합산 후 0~100 범위로 **정규화 (스케일링)**
---
## ⚙️ 내부 구조 요약
```python
def calculate_risk_score(risks: dict, weights: dict = None) -> int:
# 기본 가중치 설정
weights = {
'var': 0.25,
'svar': 0.30,
'mcs': 0.25,
'atr': 0.20
}
# 점수 계산 (역수 방식)
score = sum(weights[key] * (1 / risks[key]) for key in risks)
# 정규화: 0~100 범위
return int(round(min(max(score * 10, 0), 100)))
```
---
## ⚖️ 기본 가중치 설정
| 지표 | 가중치 | 이유 |
|------|--------|------|
| VaR | 0.25 | 기본적인 손실 한계 예측 |
| SVaR | 0.30 | 극단 리스크 고려 (더 보수적으로 반영) |
| MCS | 0.25 | 확률적 시나리오 기반 손실 예측 |
| ATR | 0.20 | 기술적 변동성 고려 (짧은 구간 민감도) |
> ⚠️ 향후 사용자 또는 운영자가 이 가중치를 조절할 수 있도록 설계되어 있음
---
## 📊 출력 예시
```python
input: {'var': 0.032, 'svar': 0.045, 'mcs': 0.037, 'atr': 2.8}
output: risk_score = 74
```
---
## ✅ SightRay에서의 역할
| 기능 | 설명 |
|------|------|
| 리스크 정량화 | 다양한 위험 요소를 하나의 숫자로 요약 |
| 전략 엔진 연계 | 기준치 이상일 때만 매수 대상 종목으로 전송 |
| 기준치 예: `risk_score >= 70` | 이하는 자동 제외 |
---
## 🚀 이후 확장 가능성
- **비선형 스코어링 함수 적용** (예: log scale, 비율 변화율 기반 등)
- **산업군별 위험 기준 조정**
- **리스크 대 ROI 비율 기반 스코어링**
---
## ✅ 요약
`risk_scorer.py`는 리스크 엔진의 **지표 계산 → 투자 결정** 사이를 연결하는 핵심 모듈로,
여러 지표를 통합한 종합 점수 기반으로 **투자 적격 여부 판단**을 가능하게 만듭니다.

142
sightray.py Normal file
View File

@ -0,0 +1,142 @@
"""
📁 sightray/sightray.py
SightRay 전체 통합 실행 스크립트
- 사용자가 종목 코드, 날짜, 자본금만 입력하면 전체 파이프라인 자동 실행
- 수집 학습 분석 리스크 평가 전략 실행까지 번에 완료
- 실행 필요한 라이브러리 설치 여부 확인
"""
import os
import importlib.util
import subprocess
import sys
import glob
from dotenv import load_dotenv, set_key
# 필요한 패키지 목록 (import명: 설치명)
REQUIRED_PACKAGES = {
"pandas": "pandas",
"requests": "requests",
"xgboost": "xgboost",
"dotenv": "python-dotenv"
}
def check_and_install_packages():
missing = []
for import_name, pip_name in REQUIRED_PACKAGES.items():
if importlib.util.find_spec(import_name) is None:
missing.append(pip_name)
if not missing:
return
print(f"❗ 필수 라이브러리 누락: {', '.join(missing)}")
confirm = input("자동으로 설치할까요? (y/n): ").strip().lower()
if confirm == 'y':
subprocess.check_call([sys.executable, "-m", "pip", "install"] + missing)
print("✅ 설치 완료. 다시 실행해 주세요.")
sys.exit()
else:
print("❌ 설치되지 않았습니다. 수동으로 설치 후 다시 실행하세요.")
sys.exit()
# 라이브러리 설치 여부 확인
check_and_install_packages()
# API 키 확인 및 설정
# 🌐 .env 파일 체크 및 API 키 확인/생성
if not os.path.exists(".env"):
with open(".env", "w") as f:
f.write("# SightRay 환경설정 파일\n")
load_dotenv()
api_key = os.getenv("POLYGON_API_KEY")
if not api_key or '--reset-api' in sys.argv:
print("🔐 Polygon API 키가 설정되어 있지 않거나 초기화 요청이 감지되었습니다.")
new_key = input("Polygon API 키를 입력하세요: ").strip()
if new_key:
set_key(".env", "POLYGON_API_KEY", new_key)
print("✅ API 키가 .env 파일에 저장되었습니다.")
else:
raise ValueError("API 키가 입력되지 않았습니다.")
print("🔑 Polygon API 키가 설정되어 있지 않거나 초기화 요청이 감지되었습니다.")
new_key = input("Polygon API 키를 입력하세요: ").strip()
if new_key:
print("✅ API 키가 .env 파일에 저장되었습니다.")
# 엔진 import
from data_collection_engine.engine import DataCollectionEngine
from data_analysis_engine.analyzer import analyze_stocks_pipeline
from data_analysis_engine.train_model import train_model
from data_analysis_engine.dataset_builder import build_dataset
from risk_manage_engine.evaluate import evaluate_predictions
from strategy_engine.run_strategy import run_strategy
# (사용되지 않지만 보관된 build_dataset 예시)
def build_dataset(df):
df = df.copy()
df['target'] = (df['close'].shift(-1) > df['close']).astype(int)
df.dropna(inplace=True)
X = df[['open', 'high', 'low', 'close', 'volume']]
y = df['target']
return X, y
def run_sightray(symbol: str, start: str, end: str, capital: float, strategy: str = "adjusted"):
# 파일 경로 설정
data_dir = "data"
ohlcv_path = os.path.join(data_dir, f"{symbol}_ohlcv.csv")
prediction_path = "prediction_result.csv"
risk_path = "risk_filtered_result.csv"
output_path = "final_strategy_result.csv"
# 최신 모델 자동 탐색
model_dir = "data_analysis_engine/models"
model_list = sorted(glob.glob(f"{model_dir}/model_*.json"), reverse=True)
if not model_list:
raise FileNotFoundError("모델 파일이 존재하지 않습니다.")
model_path = model_list[0]
# 1⃣ 데이터 수집
print("[1단계] 데이터 수집 중...")
engine = DataCollectionEngine(data_dir=data_dir)
engine.collect(symbol, start, end)
# 2⃣ 모델 학습
print("[2단계] 분석 모델 학습 중...")
train_model(data_dir, output_model_path=model_path)
# 3⃣ 분석 예측
print("[3단계] 예측 실행 중...")
analyze_stocks_pipeline(
cds_dir=data_dir,
model_path=model_path,
top_n=10,
output_path=prediction_path
)
# 4⃣ 리스크 평가
print("[4단계] 리스크 평가 실행 중...")
evaluate_predictions(prediction_path, data_dir, output_path=risk_path)
# 5⃣ 전략 실행
print("[5단계] 전략 생성 및 포지션 설정 중...")
run_strategy(
risk_filtered_path=risk_path,
total_capital=capital,
strategy=strategy,
output_path=output_path
)
print("\n✅ SightRay 전체 파이프라인 실행 완료!")
print(f"→ 최종 전략 결과: {output_path}")
if __name__ == "__main__":
print("SightRay 실행을 시작합니다. 다음 정보를 입력해 주세요:")
symbol = input("종목 코드 (예: AAPL, TSLA): ").strip().upper()
start = input("시작일 (YYYY-MM-DD): ").strip()
end = input("종료일 (YYYY-MM-DD): ").strip()
capital = float(input("총 투자 자본 (예: 1000000): ").strip())
strategy = input("전략 템플릿 (adjusted / basic) [기본: adjusted]: ").strip().lower()
if strategy not in ["basic", "adjusted"]:
strategy = "adjusted"
run_sightray(symbol, start, end, capital, strategy)

103
sightray_concept.txt Normal file
View File

@ -0,0 +1,103 @@
# 🧠 SightRay 통합 실행 엔트리포인트 개념 정리 (`sightray.py`)
---
## ✅ 목적
`sightray.py`는 SightRay의 모든 엔진을 **하나의 흐름으로 통합 실행**하는 CLI 기반 진입점입니다.
사용자가 종목 코드와 날짜, 자본만 입력하면:
> 수집 → 분석 → 리스크 평가 → 전략 실행 → 결과 저장 까지 전부 자동화됩니다.
---
## 🔁 실행 흐름 요약
```plaintext
[사용자 입력: symbol, start, end, capital]
DataCollectionEngine.collect() → CDS 수집 및 저장
train_model.py → 학습 및 모델 저장
predict.py → 예측 결과 (prediction_result.csv)
evaluate.py → 리스크 평가 + tradable 종목 선정
run_strategy.py → 전략 적용 + 포지션 설정
[최종 결과: final_strategy_result.csv 저장]
```
---
## ⚙️ 실행 인자
```bash
python sightray.py \
--symbol AAPL \
--start 2024-01-01 \
--end 2024-04-01 \
--capital 1000000 \
--strategy adjusted
```
| 인자 | 설명 |
|------|------|
| `--symbol` | 분석할 종목 코드 (예: AAPL, TSLA) |
| `--start` | 시작일 (`YYYY-MM-DD`) |
| `--end` | 종료일 (`YYYY-MM-DD`) |
| `--capital` | 총 투자 자본 (정수 단위) |
| `--strategy` | 전략 템플릿 (`basic` 또는 `adjusted`, 기본: `adjusted`) |
---
## 📁 내부 구성 연계
| 모듈 | 역할 |
|------|------|
| `engine.py` | 데이터 수집 및 저장 (`data/`) |
| `train_model.py` | XGBoost 모델 학습 및 저장 |
| `predict.py` | 분석 예측 수행 (상위 종목 선정) |
| `evaluate.py` | 리스크 점수 산출 및 필터링 |
| `run_strategy.py` | 전략 실행 및 결과 저장 |
---
## 🔐 API 키 설정 기능
| 기능 | 설명 |
|------|------|
| `.env` 자동 로딩 | POLYGON_API_KEY 로딩 시도 |
| 키 미입력 시 | 사용자에게 직접 입력받아 `.env`에 저장 |
| `--reset-api` | 강제로 API 키 재설정 가능 |
---
## 📊 출력 파일 예시
| 파일명 | 내용 |
|--------|------|
| `data/AAPL_ohlcv.csv` | 수집된 OHLCV 데이터 (CDS) |
| `prediction_result.csv` | 예측된 상위 종목 및 확률 |
| `risk_filtered_result.csv` | tradable 종목 리스트 + risk_score |
| `final_strategy_result.csv` | TP/SL 및 포지션 포함된 전략 결과 ✅ |
---
## ✅ SightRay에서의 역할
| 기능 | 설명 |
|------|------|
| 자동화 허브 | 모든 엔진을 순차 실행하여 결과까지 자동 도출 |
| CLI 통제 포인트 | 사용자 입력 기반 실행 환경 구성 |
| 확장 인터페이스 | 추후 Web, API, GUI에서 호출할 핵심 함수로도 전환 가능 |
---
## ✅ 요약
`sightray.py`는 SightRay의 **완전 자동화 파이프라인**을 실행하기 위한 단일 진입점입니다.
사용자는 단 한 줄의 명령으로 전체 분석과 전략 실행을 완료할 수 있으며,
이 파일은 운영자, 자동화 시스템, 외부 API 호출 등에서 **실전 통합 인터페이스**로 사용됩니다.

504
sp500_tickers.csv Normal file
View File

@ -0,0 +1,504 @@
symbol
MMM
AOS
ABT
ABBV
ACN
ADBE
AMD
AES
AFL
A
APD
ABNB
AKAM
ALB
ARE
ALGN
ALLE
LNT
ALL
GOOGL
GOOG
MO
AMZN
AMCR
AEE
AEP
AXP
AIG
AMT
AWK
AMP
AME
AMGN
APH
ADI
ANSS
AON
APA
APO
AAPL
AMAT
APTV
ACGL
ADM
ANET
AJG
AIZ
T
ATO
ADSK
ADP
AZO
AVB
AVY
AXON
BKR
BALL
BAC
BAX
BDX
BRK.B
BBY
TECH
BIIB
BLK
BX
BK
BA
BKNG
BSX
BMY
AVGO
BR
BRO
BF.B
BLDR
BG
BXP
CHRW
CDNS
CZR
CPT
CPB
COF
CAH
KMX
CCL
CARR
CAT
CBOE
CBRE
CDW
COR
CNC
CNP
CF
CRL
SCHW
CHTR
CVX
CMG
CB
CHD
CI
CINF
CTAS
CSCO
C
CFG
CLX
CME
CMS
KO
CTSH
CL
CMCSA
CAG
COP
ED
STZ
CEG
COO
CPRT
GLW
CPAY
CTVA
CSGP
COST
CTRA
CRWD
CCI
CSX
CMI
CVS
DHR
DRI
DVA
DAY
DECK
DE
DELL
DAL
DVN
DXCM
FANG
DLR
DFS
DG
DLTR
D
DPZ
DASH
DOV
DOW
DHI
DTE
DUK
DD
EMN
ETN
EBAY
ECL
EIX
EW
EA
ELV
EMR
ENPH
ETR
EOG
EPAM
EQT
EFX
EQIX
EQR
ERIE
ESS
EL
EG
EVRG
ES
EXC
EXE
EXPE
EXPD
EXR
XOM
FFIV
FDS
FICO
FAST
FRT
FDX
FIS
FITB
FSLR
FE
FI
F
FTNT
FTV
FOXA
FOX
BEN
FCX
GRMN
IT
GE
GEHC
GEV
GEN
GNRC
GD
GIS
GM
GPC
GILD
GPN
GL
GDDY
GS
HAL
HIG
HAS
HCA
DOC
HSIC
HSY
HES
HPE
HLT
HOLX
HD
HON
HRL
HST
HWM
HPQ
HUBB
HUM
HBAN
HII
IBM
IEX
IDXX
ITW
INCY
IR
PODD
INTC
ICE
IFF
IP
IPG
INTU
ISRG
IVZ
INVH
IQV
IRM
JBHT
JBL
JKHY
J
JNJ
JCI
JPM
JNPR
K
KVUE
KDP
KEY
KEYS
KMB
KIM
KMI
KKR
KLAC
KHC
KR
LHX
LH
LRCX
LW
LVS
LDOS
LEN
LII
LLY
LIN
LYV
LKQ
LMT
L
LOW
LULU
LYB
MTB
MPC
MKTX
MAR
MMC
MLM
MAS
MA
MTCH
MKC
MCD
MCK
MDT
MRK
META
MET
MTD
MGM
MCHP
MU
MSFT
MAA
MRNA
MHK
MOH
TAP
MDLZ
MPWR
MNST
MCO
MS
MOS
MSI
MSCI
NDAQ
NTAP
NFLX
NEM
NWSA
NWS
NEE
NKE
NI
NDSN
NSC
NTRS
NOC
NCLH
NRG
NUE
NVDA
NVR
NXPI
ORLY
OXY
ODFL
OMC
ON
OKE
ORCL
OTIS
PCAR
PKG
PLTR
PANW
PARA
PH
PAYX
PAYC
PYPL
PNR
PEP
PFE
PCG
PM
PSX
PNW
PNC
POOL
PPG
PPL
PFG
PG
PGR
PLD
PRU
PEG
PTC
PSA
PHM
PWR
QCOM
DGX
RL
RJF
RTX
O
REG
REGN
RF
RSG
RMD
RVTY
ROK
ROL
ROP
ROST
RCL
SPGI
CRM
SBAC
SLB
STX
SRE
NOW
SHW
SPG
SWKS
SJM
SW
SNA
SOLV
SO
LUV
SWK
SBUX
STT
STLD
STE
SYK
SMCI
SYF
SNPS
SYY
TMUS
TROW
TTWO
TPR
TRGP
TGT
TEL
TDY
TER
TSLA
TXN
TPL
TXT
TMO
TJX
TKO
TSCO
TT
TDG
TRV
TRMB
TFC
TYL
TSN
USB
UBER
UDR
ULTA
UNP
UAL
UPS
URI
UNH
UHS
VLO
VTR
VLTO
VRSN
VRSK
VZ
VRTX
VTRS
VICI
V
VST
VMC
WRB
GWW
WAB
WBA
WMT
DIS
WBD
WM
WAT
WEC
WFC
WELL
WST
WDC
WY
WSM
WMB
WTW
WDAY
WYNN
XEL
XYL
YUM
ZBRA
ZBH
ZTS
1 symbol
2 MMM
3 AOS
4 ABT
5 ABBV
6 ACN
7 ADBE
8 AMD
9 AES
10 AFL
11 A
12 APD
13 ABNB
14 AKAM
15 ALB
16 ARE
17 ALGN
18 ALLE
19 LNT
20 ALL
21 GOOGL
22 GOOG
23 MO
24 AMZN
25 AMCR
26 AEE
27 AEP
28 AXP
29 AIG
30 AMT
31 AWK
32 AMP
33 AME
34 AMGN
35 APH
36 ADI
37 ANSS
38 AON
39 APA
40 APO
41 AAPL
42 AMAT
43 APTV
44 ACGL
45 ADM
46 ANET
47 AJG
48 AIZ
49 T
50 ATO
51 ADSK
52 ADP
53 AZO
54 AVB
55 AVY
56 AXON
57 BKR
58 BALL
59 BAC
60 BAX
61 BDX
62 BRK.B
63 BBY
64 TECH
65 BIIB
66 BLK
67 BX
68 BK
69 BA
70 BKNG
71 BSX
72 BMY
73 AVGO
74 BR
75 BRO
76 BF.B
77 BLDR
78 BG
79 BXP
80 CHRW
81 CDNS
82 CZR
83 CPT
84 CPB
85 COF
86 CAH
87 KMX
88 CCL
89 CARR
90 CAT
91 CBOE
92 CBRE
93 CDW
94 COR
95 CNC
96 CNP
97 CF
98 CRL
99 SCHW
100 CHTR
101 CVX
102 CMG
103 CB
104 CHD
105 CI
106 CINF
107 CTAS
108 CSCO
109 C
110 CFG
111 CLX
112 CME
113 CMS
114 KO
115 CTSH
116 CL
117 CMCSA
118 CAG
119 COP
120 ED
121 STZ
122 CEG
123 COO
124 CPRT
125 GLW
126 CPAY
127 CTVA
128 CSGP
129 COST
130 CTRA
131 CRWD
132 CCI
133 CSX
134 CMI
135 CVS
136 DHR
137 DRI
138 DVA
139 DAY
140 DECK
141 DE
142 DELL
143 DAL
144 DVN
145 DXCM
146 FANG
147 DLR
148 DFS
149 DG
150 DLTR
151 D
152 DPZ
153 DASH
154 DOV
155 DOW
156 DHI
157 DTE
158 DUK
159 DD
160 EMN
161 ETN
162 EBAY
163 ECL
164 EIX
165 EW
166 EA
167 ELV
168 EMR
169 ENPH
170 ETR
171 EOG
172 EPAM
173 EQT
174 EFX
175 EQIX
176 EQR
177 ERIE
178 ESS
179 EL
180 EG
181 EVRG
182 ES
183 EXC
184 EXE
185 EXPE
186 EXPD
187 EXR
188 XOM
189 FFIV
190 FDS
191 FICO
192 FAST
193 FRT
194 FDX
195 FIS
196 FITB
197 FSLR
198 FE
199 FI
200 F
201 FTNT
202 FTV
203 FOXA
204 FOX
205 BEN
206 FCX
207 GRMN
208 IT
209 GE
210 GEHC
211 GEV
212 GEN
213 GNRC
214 GD
215 GIS
216 GM
217 GPC
218 GILD
219 GPN
220 GL
221 GDDY
222 GS
223 HAL
224 HIG
225 HAS
226 HCA
227 DOC
228 HSIC
229 HSY
230 HES
231 HPE
232 HLT
233 HOLX
234 HD
235 HON
236 HRL
237 HST
238 HWM
239 HPQ
240 HUBB
241 HUM
242 HBAN
243 HII
244 IBM
245 IEX
246 IDXX
247 ITW
248 INCY
249 IR
250 PODD
251 INTC
252 ICE
253 IFF
254 IP
255 IPG
256 INTU
257 ISRG
258 IVZ
259 INVH
260 IQV
261 IRM
262 JBHT
263 JBL
264 JKHY
265 J
266 JNJ
267 JCI
268 JPM
269 JNPR
270 K
271 KVUE
272 KDP
273 KEY
274 KEYS
275 KMB
276 KIM
277 KMI
278 KKR
279 KLAC
280 KHC
281 KR
282 LHX
283 LH
284 LRCX
285 LW
286 LVS
287 LDOS
288 LEN
289 LII
290 LLY
291 LIN
292 LYV
293 LKQ
294 LMT
295 L
296 LOW
297 LULU
298 LYB
299 MTB
300 MPC
301 MKTX
302 MAR
303 MMC
304 MLM
305 MAS
306 MA
307 MTCH
308 MKC
309 MCD
310 MCK
311 MDT
312 MRK
313 META
314 MET
315 MTD
316 MGM
317 MCHP
318 MU
319 MSFT
320 MAA
321 MRNA
322 MHK
323 MOH
324 TAP
325 MDLZ
326 MPWR
327 MNST
328 MCO
329 MS
330 MOS
331 MSI
332 MSCI
333 NDAQ
334 NTAP
335 NFLX
336 NEM
337 NWSA
338 NWS
339 NEE
340 NKE
341 NI
342 NDSN
343 NSC
344 NTRS
345 NOC
346 NCLH
347 NRG
348 NUE
349 NVDA
350 NVR
351 NXPI
352 ORLY
353 OXY
354 ODFL
355 OMC
356 ON
357 OKE
358 ORCL
359 OTIS
360 PCAR
361 PKG
362 PLTR
363 PANW
364 PARA
365 PH
366 PAYX
367 PAYC
368 PYPL
369 PNR
370 PEP
371 PFE
372 PCG
373 PM
374 PSX
375 PNW
376 PNC
377 POOL
378 PPG
379 PPL
380 PFG
381 PG
382 PGR
383 PLD
384 PRU
385 PEG
386 PTC
387 PSA
388 PHM
389 PWR
390 QCOM
391 DGX
392 RL
393 RJF
394 RTX
395 O
396 REG
397 REGN
398 RF
399 RSG
400 RMD
401 RVTY
402 ROK
403 ROL
404 ROP
405 ROST
406 RCL
407 SPGI
408 CRM
409 SBAC
410 SLB
411 STX
412 SRE
413 NOW
414 SHW
415 SPG
416 SWKS
417 SJM
418 SW
419 SNA
420 SOLV
421 SO
422 LUV
423 SWK
424 SBUX
425 STT
426 STLD
427 STE
428 SYK
429 SMCI
430 SYF
431 SNPS
432 SYY
433 TMUS
434 TROW
435 TTWO
436 TPR
437 TRGP
438 TGT
439 TEL
440 TDY
441 TER
442 TSLA
443 TXN
444 TPL
445 TXT
446 TMO
447 TJX
448 TKO
449 TSCO
450 TT
451 TDG
452 TRV
453 TRMB
454 TFC
455 TYL
456 TSN
457 USB
458 UBER
459 UDR
460 ULTA
461 UNP
462 UAL
463 UPS
464 URI
465 UNH
466 UHS
467 VLO
468 VTR
469 VLTO
470 VRSN
471 VRSK
472 VZ
473 VRTX
474 VTRS
475 VICI
476 V
477 VST
478 VMC
479 WRB
480 GWW
481 WAB
482 WBA
483 WMT
484 DIS
485 WBD
486 WM
487 WAT
488 WEC
489 WFC
490 WELL
491 WST
492 WDC
493 WY
494 WSM
495 WMB
496 WTW
497 WDAY
498 WYNN
499 XEL
500 XYL
501 YUM
502 ZBRA
503 ZBH
504 ZTS

View File

@ -0,0 +1,35 @@
'''
strategy_engine/position_manager.py
전략 조건이 부여된 종목에 대해 실제 포지션(자금 배분, 수량 ) 결정하는 모듈입니다.
- 고정 자산 총액을 기준으로 자산을 분산하여 종목에 배정
- 리스크 점수를 반영하여 투자 비중 조정 가능 (향후 확장)
'''
import pandas as pd
def assign_position(df: pd.DataFrame, total_capital: float = 0) -> pd.DataFrame:
"""
종목에 대해 자금 배분 포지션 수량 계산
Parameters:
df (pd.DataFrame): 전략 조건이 포함된 종목 테이블 (symbol, entry_price )
total_capital (float): 전체 투자 가능 자금 (기본: 0 반드시 사용자가 설정해야 )
Returns:
pd.DataFrame: position_size, capital_allocated 컬럼 추가된 최종 포지션 테이블
"""
if total_capital <= 0:
raise ValueError("[오류] total_capital 값이 0 이하입니다. 유효한 자금 규모를 입력하세요.")
df = df.copy()
num_assets = len(df)
if num_assets == 0:
return df
capital_per_asset = total_capital / num_assets
df['capital_allocated'] = capital_per_asset
df['position_size'] = (capital_per_asset / df['entry_price']).apply(lambda x: int(x)) # 정수 주식 수량
return df

View File

@ -0,0 +1,53 @@
'''
strategy_engine/run_strategy.py
전략 엔진 실행 진입점:
- tradable 종목 로딩 전략 템플릿 적용 포지션 계산 최종 결과 저장
- 사용자 입력: 투자 금액(total_capital), 전략 유형(strategy)
'''
import argparse
import pandas as pd
from strategy_engine.selector import select_candidates
from strategy_engine.templates.basic_strategy import apply_basic_strategy
from strategy_engine.templates.risk_adjusted_strategy import apply_risk_adjusted_strategy
from strategy_engine.position_manager import assign_position
def run_strategy(risk_filtered_path: str, total_capital: float, strategy: str = "adjusted", output_path: str = "final_strategy_result.csv"):
# 1단계: 전략 대상 종목 필터링
selected = select_candidates(risk_filtered_path)
if selected.empty:
print("[알림] 조건을 만족하는 종목이 없습니다.")
return None
# 2단계: 전략 템플릿 선택 적용
if strategy == "basic":
strategy_df = apply_basic_strategy(selected)
else:
strategy_df = apply_risk_adjusted_strategy(selected)
# 3단계: 포지션 할당 (자금 배분)
final_df = pd.merge(selected, strategy_df, on="symbol")
final_df = assign_position(final_df, total_capital=total_capital)
# 4단계: 결과 저장 및 반환
final_df.to_csv(output_path, index=False)
print(f"[완료] 전략 실행 결과 저장됨 → {output_path}")
return final_df
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="SightRay 전략 엔진 실행")
parser.add_argument("--input", type=str, required=True, help="risk_filtered_result.csv 경로")
parser.add_argument("--capital", type=float, required=True, help="총 투자 자본 (예: 1000000)")
parser.add_argument("--strategy", type=str, choices=["basic", "adjusted"], default="adjusted", help="사용할 전략 템플릿 (기본: adjusted)")
parser.add_argument("--output", type=str, default="final_strategy_result.csv", help="출력 파일명")
args = parser.parse_args()
run_strategy(
risk_filtered_path=args.input,
total_capital=args.capital,
strategy=args.strategy,
output_path=args.output
)

View File

@ -0,0 +1,83 @@
# 🚀 전략 실행 컨트롤러 개념 정리 (`run_strategy.py`)
---
## ✅ 목적
`run_strategy.py`는 SightRay 전략 엔진의 실행 진입점(entrypoint)으로,
**전략 실행의 전체 흐름을 자동화**하여 사용자가 단일 명령으로 전략 결과를 생성할 수 있게 합니다.
> 📌 이 스크립트는 `selector → strategy template → position manager`까지의 모든 과정을 통합합니다.
---
## 🔁 전체 실행 흐름 요약
```plaintext
[risk_filtered_result.csv]
selector.py
→ tradable 종목 + 전략 조건 만족 종목 추출
templates/basic_strategy.py
→ TP/SL 기준 설정, 매수 여부 결정
position_manager.py
→ 자금 배분 및 포지션 크기 계산
[final_strategy_result.csv] 저장
```
---
## 🧩 주요 역할별 연결 구조
| 순서 | 파일 | 역할 |
|------|------|------|
| 1 | `selector.py` | 전략 조건 만족 종목 선택 (확률, risk_score 기준) |
| 2 | `basic_strategy.py` | 전략 템플릿 적용: 진입가, 목표가, 손절가 설정 |
| 3 | `position_manager.py` | 자금 배분 및 포지션 수량 계산 |
| 4 | `run_strategy.py` | 전체 흐름 통합 및 실행 CLI 제공 |
---
## ⚙️ CLI 실행 인자
```bash
python run_strategy.py \
--input risk_filtered_result.csv \
--capital 1000000 \
--output final_strategy_result.csv
```
| 인자 | 설명 |
|------|------|
| `--input` | 필수: 분석 + 리스크 필터링 결과 파일 경로 |
| `--capital` | 필수: 총 투자 자본 (ex. 1,000,000) |
| `--output` | 선택: 결과 저장 경로 (기본값: `final_strategy_result.csv`) |
---
## ✅ 출력 예시
| symbol | entry_price | target_price | stop_loss | position_size | capital_allocated |
|--------|-------------|--------------|-----------|----------------|--------------------|
| AAPL | 186.5 | 195.8 | 180.0 | 1340 | 250000 |
| TSLA | 245.2 | 257.5 | 237.8 | 1020 | 250000 |
---
## 📌 특징
- 사용자 중심 구조: 자본 입력만으로 실행 가능
- 확장 가능: 향후 다른 전략 템플릿과의 교체 용이
- CLI 환경, 자동화 배치, 대시보드 API 연동까지 고려된 진입점 설계
---
## ✅ 정리
`run_strategy.py`는 SightRay 전략 엔진의 핵심 실행 도구로,
**분석-리스크 결과 → 실전 전략 실행**을 연결하는 완전 자동화 인터페이스입니다.
> 🎯 운영자가 이 파일 하나만 실행하면 전략이 전부 적용된 결과를 받을 수 있습니다.

View File

@ -0,0 +1,31 @@
'''
strategy_engine/selector.py
risk_filtered_result.csv에서 tradable 종목만 선택하고,
추가적인 전략 조건(: 상승 확률, 리스크 점수 기준) 따라 최종 전략 대상 종목을 선별합니다.
'''
import pandas as pd
def select_candidates(risk_filtered_path: str, min_probability: float = 0.7, min_risk_score: int = 70) -> pd.DataFrame:
"""
전략 실행 대상 종목을 선별하는 함수
Parameters:
risk_filtered_path (str): risk_filtered_result.csv 파일 경로
min_probability (float): 최소 상승 확률 기준 (기본 0.7)
min_risk_score (int): 최소 리스크 점수 기준 (기본 70)
Returns:
pd.DataFrame: 전략 조건을 만족하는 종목들
"""
df = pd.read_csv(risk_filtered_path)
# tradable 종목 중 전략 조건 만족하는 종목만 선별
filtered = df[
(df['tradable'] == True) &
(df['predicted_score'] >= min_probability) &
(df['risk_score'] >= min_risk_score)
].copy()
return filtered.reset_index(drop=True)

View File

@ -0,0 +1,31 @@
'''
strategy_engine/templates/basic_strategy.py
기본 전략 템플릿:
- 매수 신호가 있는 tradable 종목에 대해 TP(목표가), SL(손절가) 자동 계산
- 단순 비율 방식으로 설정 (: +5%, -3%)
- Buy 여부 결정 포함
'''
import pandas as pd
def apply_basic_strategy(df: pd.DataFrame, tp_ratio: float = 0.05, sl_ratio: float = 0.03) -> pd.DataFrame:
"""
전략 종목에 대해 TP/SL 조건 액션(Buy) 설정
Parameters:
df (pd.DataFrame): selector에서 필터링된 종목 DataFrame (최소: symbol, close 컬럼 포함)
tp_ratio (float): 목표 수익률 비율 (기본 5%)
sl_ratio (float): 손절 비율 (기본 3%)
Returns:
pd.DataFrame: 전략 조건이 부여된 종목 테이블
"""
df = df.copy()
df['entry_price'] = df['close'] # 현재 종가를 진입가로 가정
df['target_price'] = df['entry_price'] * (1 + tp_ratio)
df['stop_loss'] = df['entry_price'] * (1 - sl_ratio)
df['action'] = 'Buy' # 현재는 모두 매수 대상으로 판단
return df[['symbol', 'entry_price', 'target_price', 'stop_loss', 'action']]

View File

@ -0,0 +1,52 @@
'''
strategy_engine/templates/risk_adjusted_strategy.py
리스크 점수 기반 전략 템플릿:
- 종목별 risk_score에 따라 TP/SL 비율 action(Buy 여부) 다르게 설정
- 리스크가 낮을수록 공격적인 전략 적용, 높을수록 보수적으로 필터링
'''
import pandas as pd
def apply_risk_adjusted_strategy(df: pd.DataFrame) -> pd.DataFrame:
"""
risk_score에 따라 전략 조건(TP/SL/Buy 여부) 결정하는 함수
Parameters:
df (pd.DataFrame): selector에서 필터링된 종목 DataFrame (symbol, close, risk_score 포함)
Returns:
pd.DataFrame: entry_price, target_price, stop_loss, action 포함한 전략 테이블
"""
df = df.copy()
df['entry_price'] = df['close']
def compute_strategy(row):
score = row['risk_score']
price = row['entry_price']
if score >= 80:
tp = 0.07
sl = 0.03
action = 'Buy'
elif score >= 70:
tp = 0.05
sl = 0.03
action = 'Buy'
elif score >= 60:
tp = 0.03
sl = 0.02
action = 'Buy'
else:
tp = None
sl = None
action = 'None'
return pd.Series({
'target_price': price * (1 + tp) if tp is not None else None,
'stop_loss': price * (1 - sl) if sl is not None else None,
'action': action
})
strategy_info = df.apply(compute_strategy, axis=1)
return pd.concat([df[['symbol', 'entry_price']], strategy_info], axis=1)

View File

@ -0,0 +1,71 @@
# 📈 리스크 점수 기반 전략 템플릿 개념 정리 (`risk_adjusted_strategy.py`)
---
## ✅ 목적
`risk_adjusted_strategy.py`는 **리스크 점수(risk_score)**를 기준으로 종목별 전략 조건을 다르게 설정하는 템플릿입니다.
> 리스크가 낮은 종목은 **더 공격적으로**, 리스크가 높은 종목은 **보수적으로 또는 제외**하는 전략 구조입니다.
---
## 🧠 전략 설계 기준
| risk_score | TP 비율 | SL 비율 | 매수 여부 (action) |
|------------|---------|---------|---------------------|
| ≥ 80 | +7% | -3% | Buy |
| 70 ~ 79 | +5% | -3% | Buy |
| 60 ~ 69 | +3% | -2% | Buy |
| < 60 | — | — | None (매수 제외) |
- TP: Target Price (목표 수익률)
- SL: Stop Loss (손절 기준)
---
## 🔁 내부 동작 흐름
```python
df['entry_price'] = df['close']
if risk_score >= 80:
target = price * 1.07
stop = price * 0.97
action = 'Buy'
elif risk_score < 60:
action = 'None'
```
---
## 📊 출력 예시
| symbol | entry_price | target_price | stop_loss | action |
|--------|-------------|--------------|-----------|--------|
| AAPL | 185.6 | 198.6 | 180.0 | Buy |
| TSLA | 241.3 | — | — | None |
---
## ⚙️ 적용 위치
- `strategy_engine/templates/` 디렉토리에 위치
- `run_strategy.py` 또는 분석 시점에서 `basic_strategy`와 교체 사용 가능
---
## 🔧 향후 확장 방향
| 확장 항목 | 설명 |
|-----------|------|
| TP/SL 비율 튜닝 | ROI 또는 ATR 기반으로 동적 조정 |
| Buy/Sell 조건 추가 | 상승 확률, 모멘텀, 거래량 등 복합 조건 반영 |
| 전략 유형 구분 | 보수형/공격형 등 사용자 선택 가능 구조로 개선 |
---
## ✅ 정리
- 이 전략 템플릿은 **risk_score에 따라 전략을 유연하게 조정**하는 구조입니다.
- `basic_strategy.py`보다 **한 단계 정교한 판단 로직**을 제공하며,
- **리스크 점수를 전략적으로 활용**하는 대표적인 전략 템플릿입니다.

11667
utils/all_polygon_tickers.csv Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,55 @@
import requests
import os
import pandas as pd
from dotenv import load_dotenv
from datetime import datetime
import time
# .env 파일에서 API 키 로드
load_dotenv()
API_KEY = os.getenv("POLYGON_API_KEY")
def fetch_all_us_stock_tickers(save_path="all_polygon_tickers.csv", delay_sec=13):
"""
Polygon.io에서 모든 US 주식 티커를 가져와 CSV로 저장
사용자의 요금제에 따라 요청 대기 시간 조절 가능
"""
base_url = "https://api.polygon.io/v3/reference/tickers"
params = {
"market": "stocks",
"active": "true",
"limit": 1000,
"apiKey": API_KEY
}
all_tickers = []
next_url = base_url
page = 1
while next_url:
print(f"🔄 요청 중 ({page} 페이지): {next_url}")
response = requests.get(next_url, params=params if next_url == base_url else {})
if response.status_code != 200:
raise Exception(f"요청 실패: {response.status_code} - {response.text}")
data = response.json()
results = data.get("results", [])
all_tickers.extend(results)
next_url = data.get("next_url")
if next_url and "apiKey" not in next_url:
next_url += f"&apiKey={API_KEY}"
page += 1
time.sleep(delay_sec) # 요청 간 간격 조정
# DataFrame으로 정리 후 저장
df = pd.DataFrame(all_tickers)
df.to_csv(save_path, index=False)
print(f"✅ 총 {len(df)}개 종목 저장 완료 → {save_path}")
if __name__ == "__main__":
print("전체 US 주식 티커를 가져옵니다. 요금제에 따라 요청 간 대기 시간을 조정하세요.")
delay = input("요청 간 대기 시간 (초) [기본: 13]: ").strip()
delay_sec = int(delay) if delay else 13
fetch_all_us_stock_tickers(delay_sec=delay_sec)