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