Add trade setup outcome tracking and performance stats
Closes the feedback loop on R:R scanner signals: - Nightly outcome_evaluator job replays unresolved setups against daily OHLCV bars: target_hit / stop_hit / ambiguous (same-bar, counted as loss) / expired after OUTCOME_EVALUATION_MAX_BARS (default 30) - Migration 004: evaluated_at + outcome_date on trade_setups - GET /trades/performance: hit rate, expectancy (avg R), total R with breakdowns by direction, recommended action, and confidence bucket - New Performance page (stat cards, breakdown tables, Evaluate Now, methodology disclosure) wired into sidebar and mobile nav - 17 new unit tests for evaluation logic and stats aggregation Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
from datetime import datetime
|
||||
from datetime import date, datetime
|
||||
|
||||
import json
|
||||
|
||||
from sqlalchemy import DateTime, Float, ForeignKey, String, Text
|
||||
from sqlalchemy import Date, DateTime, Float, ForeignKey, String, Text
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
|
||||
from app.database import Base
|
||||
@@ -32,6 +32,10 @@ class TradeSetup(Base):
|
||||
reasoning: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
risk_level: Mapped[str | None] = mapped_column(String(10), nullable=True)
|
||||
actual_outcome: Mapped[str | None] = mapped_column(String(20), nullable=True)
|
||||
evaluated_at: Mapped[datetime | None] = mapped_column(
|
||||
DateTime(timezone=True), nullable=True
|
||||
)
|
||||
outcome_date: Mapped[date | None] = mapped_column(Date, nullable=True)
|
||||
|
||||
ticker = relationship("Ticker", back_populates="trade_setups")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user