from datetime import datetime from typing import Optional, List from sqlalchemy import Column, Integer, String, Numeric, Boolean, DateTime, Text, ARRAY from sqlalchemy.dialects.postgresql import JSONB from app.core.database import Base class TradingRule(Base): __tablename__ = "trading_rules" id = Column(Integer, primary_key=True, index=True) name = Column(String(255), nullable=False) description = Column(Text) rule_type = Column(String(50), nullable=False) conditions = Column(JSONB, nullable=False) actions = Column(JSONB, nullable=False) is_active = Column(Boolean, default=True) priority = Column(Integer, default=0) created_at = Column(DateTime, default=datetime.utcnow) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) class TradeHistory(Base): __tablename__ = "trade_history" id = Column(Integer, primary_key=True, index=True) rule_id = Column(Integer) stock_code = Column(String(20), nullable=False, index=True) stock_name = Column(String(100)) order_type = Column(String(20), nullable=False) order_price = Column(Numeric(15, 2)) order_quantity = Column(Integer, nullable=False) executed_price = Column(Numeric(15, 2)) executed_quantity = Column(Integer) status = Column(String(50), nullable=False) order_id = Column(String(100)) message = Column(Text) created_at = Column(DateTime, default=datetime.utcnow, index=True) executed_at = Column(DateTime) class Portfolio(Base): __tablename__ = "portfolio" id = Column(Integer, primary_key=True, index=True) stock_code = Column(String(20), nullable=False, unique=True) stock_name = Column(String(100)) quantity = Column(Integer, nullable=False, default=0) average_price = Column(Numeric(15, 2)) current_price = Column(Numeric(15, 2)) profit_loss = Column(Numeric(15, 2)) profit_loss_rate = Column(Numeric(10, 4)) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) class MarketData(Base): __tablename__ = "market_data" id = Column(Integer, primary_key=True, index=True) stock_code = Column(String(20), nullable=False, index=True) price = Column(Numeric(15, 2), nullable=False) change_rate = Column(Numeric(10, 4)) volume = Column(Integer) high_price = Column(Numeric(15, 2)) low_price = Column(Numeric(15, 2)) open_price = Column(Numeric(15, 2)) timestamp = Column(DateTime, default=datetime.utcnow, index=True) class News(Base): __tablename__ = "news" id = Column(Integer, primary_key=True, index=True) title = Column(String(500), nullable=False) content = Column(Text) source = Column(String(100)) url = Column(Text) stock_codes = Column(ARRAY(String)) sentiment = Column(String(20)) published_at = Column(DateTime, index=True) created_at = Column(DateTime, default=datetime.utcnow) class ClaudeAnalysisLog(Base): __tablename__ = "claude_analysis_log" id = Column(Integer, primary_key=True, index=True) rule_id = Column(Integer) stock_code = Column(String(20)) analysis_type = Column(String(50)) input_data = Column(JSONB) analysis_result = Column(JSONB) decision = Column(String(50)) confidence = Column(Numeric(5, 4)) created_at = Column(DateTime, default=datetime.utcnow, index=True) class MCPToolCall(Base): __tablename__ = "mcp_tool_calls" id = Column(Integer, primary_key=True, index=True) tool_name = Column(String(100), nullable=False) parameters = Column(JSONB) result = Column(JSONB) status = Column(String(50)) execution_time_ms = Column(Integer) created_at = Column(DateTime, default=datetime.utcnow, index=True) class StockAnalysis(Base): """매일 배치로 저장되는 종목 분석 데이터""" __tablename__ = "stock_analysis" id = Column(Integer, primary_key=True, index=True) stock_code = Column(String(20), nullable=False, index=True) stock_name = Column(String(100), nullable=False) analysis_date = Column(DateTime, nullable=False, index=True) # 가격 정보 current_price = Column(Integer, nullable=False) change_rate = Column(Numeric(10, 4)) volume = Column(Integer) # 기술적 지표 rsi = Column(Numeric(10, 4)) ma5 = Column(Numeric(15, 2)) ma20 = Column(Numeric(15, 2)) ma60 = Column(Numeric(15, 2)) stochastic_k = Column(Numeric(10, 4)) stochastic_d = Column(Numeric(10, 4)) bollinger_upper = Column(Numeric(15, 2)) bollinger_lower = Column(Numeric(15, 2)) bollinger_middle = Column(Numeric(15, 2)) # 분석 결과 signals = Column(JSONB) # ["RSI 과매도", "골든크로스" 등] score = Column(Integer, default=0) # 메타데이터 created_at = Column(DateTime, default=datetime.utcnow) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)