from pydantic import BaseModel, Field from typing import Optional, List from datetime import datetime from enum import Enum class TradeAction(str, Enum): BUY = "BUY" SELL = "SELL" class Recommendation(str, Enum): BUY = "BUY" SELL = "SELL" HOLD = "HOLD" class RiskLevel(str, Enum): LOW = "LOW" MEDIUM = "MEDIUM" HIGH = "HIGH" class PriceData(BaseModel): time: int open: float high: float low: float close: float volume: Optional[float] = None class TradeCreate(BaseModel): action: TradeAction quantity: float price: float class TradeResponse(BaseModel): id: int simulation_id: int action: TradeAction quantity: float price: float total: float pnl: Optional[float] = None timestamp: datetime class Config: from_attributes = True class PositionResponse(BaseModel): symbol: str quantity: float avg_price: float current_price: float unrealized_pnl: float unrealized_pnl_percent: float class Config: from_attributes = True class PortfolioResponse(BaseModel): cash: float initial_capital: float total_value: float total_pnl: float total_pnl_percent: float position: Optional[PositionResponse] = None trades: List[TradeResponse] = [] class MarketDataResponse(BaseModel): symbol: str = "XAU/USD" price: float change: float change_percent: float high_24h: float low_24h: float volume: float class SupportResistance(BaseModel): support: List[float] = [] resistance: List[float] = [] class AIAnalysisRequest(BaseModel): price_data: List[PriceData] indicators: List[dict] current_price: float class AIAnalysisResponse(BaseModel): recommendation: Recommendation confidence: float = Field(..., ge=0, le=100) reasoning: str support_resistance: SupportResistance risk_level: RiskLevel class IndicatorData(BaseModel): time: int value: float # News and Sentiment Schemas class Sentiment(str, Enum): POSITIVE = "POSITIVE" NEGATIVE = "NEGATIVE" NEUTRAL = "NEUTRAL" class NewsArticle(BaseModel): id: str source: str title: str description: Optional[str] = None url: str published_at: datetime sentiment: Sentiment sentiment_score: float = Field(..., ge=-1, le=1) impact_on_gold: str # HIGH, MEDIUM, LOW relevance_score: float = Field(..., ge=0, le=1) category: str # MONETARY_POLICY, GEOPOLITICS, ECONOMIC_DATA, etc. class NewsFeedResponse(BaseModel): articles: List[NewsArticle] total_count: int bullish_count: int bearish_count: int neutral_count: int overall_sentiment: Sentiment avg_sentiment_score: float class EconomicEvent(BaseModel): id: str title: str country: str currency: str event_date: datetime importance: str # HIGH, MEDIUM, LOW forecast: Optional[str] = None previous: Optional[str] = None actual: Optional[str] = None impact_on_gold: str class EconomicCalendarResponse(BaseModel): events: List[EconomicEvent] upcoming_high_impact: int # Alert Schemas class AlertType(str, Enum): PRICE_SPIKE = "PRICE_SPIKE" PRICE_DROP = "PRICE_DROP" NEWS_BREAKING = "NEWS_BREAKING" SUPPORT_BREACH = "SUPPORT_BREACH" RESISTANCE_BREACH = "RESISTANCE_BREACH" HIGH_VOLATILITY = "HIGH_VOLATILITY" ECONOMIC_EVENT = "ECONOMIC_EVENT" class AlertSeverity(str, Enum): CRITICAL = "CRITICAL" HIGH = "HIGH" MEDIUM = "MEDIUM" LOW = "LOW" class Alert(BaseModel): id: str type: AlertType severity: AlertSeverity title: str message: str price: Optional[float] = None change_percent: Optional[float] = None timestamp: datetime related_news: Optional[List[str]] = [] # URLs to related news action_required: bool = False class AlertsResponse(BaseModel): alerts: List[Alert] critical_count: int unread_count: int # News-Price Correlation class NewsPriceCorrelation(BaseModel): news_id: str news_title: str news_time: datetime price_before: float price_after: float price_change: float price_change_percent: float time_delta_minutes: int correlation_strength: str # STRONG, MODERATE, WEAK class CorrelationAnalysisResponse(BaseModel): correlations: List[NewsPriceCorrelation] significant_events: int avg_price_impact: float # Phase 1: Daily Helper Schemas class UserProfileCreate(BaseModel): email: Optional[str] = None username: Optional[str] = None timezone: str = "UTC" preferred_trading_start: str = "09:00" preferred_trading_end: str = "17:00" risk_tolerance: str = "moderate" trading_style: str = "day_trader" daily_target: Optional[float] = None max_loss: Optional[float] = None class UserProfileUpdate(BaseModel): timezone: Optional[str] = None preferred_trading_start: Optional[str] = None preferred_trading_end: Optional[str] = None risk_tolerance: Optional[str] = None trading_style: Optional[str] = None daily_target: Optional[float] = None max_loss: Optional[float] = None notifications_enabled: Optional[bool] = None email_reports: Optional[bool] = None sms_enabled: Optional[bool] = None push_notifications: Optional[bool] = None phone_number: Optional[str] = None class UserProfileResponse(BaseModel): id: int email: Optional[str] username: Optional[str] timezone: str preferred_trading_start: str preferred_trading_end: str risk_tolerance: str trading_style: str daily_target: Optional[float] max_loss: Optional[float] notifications_enabled: bool email_reports: bool sms_enabled: bool push_notifications: bool created_at: datetime updated_at: datetime class Config: from_attributes = True class DailyRoutineCreate(BaseModel): routine_type: str # morning, active_trading, evening scheduled_time: str # HH:MM tasks: List[str] = [] enabled: bool = True class DailyRoutineUpdate(BaseModel): scheduled_time: Optional[str] = None tasks: Optional[List[str]] = None enabled: Optional[bool] = None class DailyRoutineResponse(BaseModel): id: int routine_type: str scheduled_time: str tasks: List[str] enabled: bool created_at: datetime updated_at: datetime class Config: from_attributes = True class RoutineExecutionResponse(BaseModel): id: int routine_id: int executed_at: datetime completion_status: str tasks_completed: List[str] execution_notes: Optional[str] class Config: from_attributes = True class NotificationCreate(BaseModel): notification_type: str title: str message: str priority: str = "normal" delivery_method: str = "push" data: Optional[dict] = None class NotificationResponse(BaseModel): id: int notification_type: str title: str message: str priority: str delivery_method: str read: bool created_at: datetime read_at: Optional[datetime] class Config: from_attributes = True class NotificationListResponse(BaseModel): notifications: List[NotificationResponse] unread_count: int total_count: int class ChecklistItem(BaseModel): id: str title: str completed: bool = False completed_at: Optional[datetime] = None class DailyChecklistCreate(BaseModel): checklist_type: str # morning, active_trading, evening, all items: Optional[List[ChecklistItem]] = None notes: Optional[str] = None class DailyChecklistUpdate(BaseModel): items: Optional[List[ChecklistItem]] = None notes: Optional[str] = None class DailyChecklistResponse(BaseModel): id: int checklist_date: str # ISO date string checklist_type: str items: List[ChecklistItem] completion_percentage: float notes: Optional[str] created_at: datetime updated_at: datetime class Config: from_attributes = True class HabitTrackerCreate(BaseModel): habit_name: str frequency: str = "daily" # daily, weekly class HabitTrackerResponse(BaseModel): id: int habit_name: str frequency: str current_streak: int longest_streak: int total_completions: int created_at: datetime updated_at: datetime class Config: from_attributes = True class HabitCompletionRequest(BaseModel): habit_id: int completion_date: Optional[str] = None # ISO date string, defaults to today # Phase 3: Advanced Analytics Schemas class PerformanceSnapshotCreate(BaseModel): snapshot_date: Optional[str] = None # ISO date, defaults to today daily_pnl: float daily_pnl_percent: float total_trades: int winning_trades: int losing_trades: int win_rate: float best_trade: Optional[float] = None worst_trade: Optional[float] = None avg_win: Optional[float] = None avg_loss: Optional[float] = None sharpe_ratio: Optional[float] = None profit_factor: Optional[float] = None max_drawdown: Optional[float] = None cumulative_pnl: float portfolio_value: Optional[float] = None class PerformanceSnapshotResponse(BaseModel): id: int snapshot_date: str daily_pnl: float daily_pnl_percent: float total_trades: int winning_trades: int losing_trades: int win_rate: float best_trade: Optional[float] worst_trade: Optional[float] avg_win: Optional[float] avg_loss: Optional[float] sharpe_ratio: Optional[float] profit_factor: Optional[float] max_drawdown: Optional[float] cumulative_pnl: float portfolio_value: Optional[float] created_at: datetime class Config: from_attributes = True class TradePatternCreate(BaseModel): pattern_name: str description: Optional[str] = None win_rate: float avg_win: float avg_loss: float sample_count: int best_timeframe: Optional[str] = None best_time_of_day: Optional[str] = None confidence_score: float indicators_used: List[str] = [] market_conditions: Optional[str] = None class TradePatternResponse(BaseModel): id: int pattern_name: str description: Optional[str] win_rate: float avg_win: float avg_loss: float sample_count: int best_timeframe: Optional[str] best_time_of_day: Optional[str] confidence_score: float indicators_used: List[str] market_conditions: Optional[str] total_profit: float created_at: datetime updated_at: datetime class Config: from_attributes = True class LessonLearnedCreate(BaseModel): category: str # entry, exit, risk, psychology, market lesson_text: str related_trades: List[int] = [] impact: str = "neutral" # positive, negative, neutral tags: List[str] = [] importance: str = "helpful" # critical, important, helpful class LessonLearnedResponse(BaseModel): id: int date_learned: datetime category: str lesson_text: str related_trades: List[int] impact: str tags: List[str] importance: str status: str created_at: datetime class Config: from_attributes = True class MonthlyReviewCreate(BaseModel): year: int month: int total_trades: int total_pnl: float total_pnl_percent: float best_day: Optional[str] = None # ISO date worst_day: Optional[str] = None best_trade: Optional[float] = None worst_trade: Optional[float] = None win_rate: float avg_daily_pnl: Optional[float] = None sharpe_ratio: Optional[float] = None max_drawdown: Optional[float] = None trading_days: int best_pattern: Optional[str] = None summary: Optional[str] = None improvements: List[str] = [] goals_met: List[str] = [] goals_missed: List[str] = [] class MonthlyReviewResponse(BaseModel): id: int year: int month: int total_trades: int total_pnl: float total_pnl_percent: float best_day: Optional[str] worst_day: Optional[str] best_trade: Optional[float] worst_trade: Optional[float] win_rate: float avg_daily_pnl: Optional[float] sharpe_ratio: Optional[float] max_drawdown: Optional[float] trading_days: int best_pattern: Optional[str] summary: Optional[str] improvements: List[str] goals_met: List[str] goals_missed: List[str] created_at: datetime class Config: from_attributes = True