168 lines
7.7 KiB
Python
168 lines
7.7 KiB
Python
from datetime import datetime
|
|
from uuid import uuid4
|
|
|
|
from sqlalchemy import DateTime, Enum, Float, ForeignKey, Integer, String, Text
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
from tradingagents.database.base import Base
|
|
|
|
|
|
class BacktestRun(Base):
|
|
__tablename__ = "backtest_runs"
|
|
|
|
id: Mapped[str] = mapped_column(
|
|
String(36), primary_key=True, default=lambda: str(uuid4())
|
|
)
|
|
name: Mapped[str] = mapped_column(String(200), nullable=False)
|
|
description: Mapped[str | None] = mapped_column(Text, nullable=True)
|
|
tickers: Mapped[str] = mapped_column(Text, nullable=False)
|
|
start_date: Mapped[str] = mapped_column(String(10), nullable=False)
|
|
end_date: Mapped[str] = mapped_column(String(10), nullable=False)
|
|
interval: Mapped[str] = mapped_column(String(10), default="1d", nullable=False)
|
|
initial_cash: Mapped[float] = mapped_column(Float, nullable=False)
|
|
benchmark_ticker: Mapped[str | None] = mapped_column(String(20), nullable=True)
|
|
risk_free_rate: Mapped[float] = mapped_column(Float, default=0.05, nullable=False)
|
|
use_agent_pipeline: Mapped[bool] = mapped_column(default=True, nullable=False)
|
|
agent_config: Mapped[str | None] = mapped_column(Text, nullable=True)
|
|
status: Mapped[str] = mapped_column(
|
|
Enum("pending", "running", "completed", "failed", name="backtest_status"),
|
|
default="pending",
|
|
nullable=False,
|
|
)
|
|
error_message: Mapped[str | None] = mapped_column(Text, nullable=True)
|
|
started_at: Mapped[datetime] = mapped_column(
|
|
DateTime, default=datetime.utcnow, nullable=False
|
|
)
|
|
completed_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
|
|
|
metrics: Mapped["BacktestMetricsRecord | None"] = relationship(
|
|
"BacktestMetricsRecord",
|
|
back_populates="backtest_run",
|
|
uselist=False,
|
|
cascade="all, delete-orphan",
|
|
)
|
|
trades: Mapped[list["BacktestTrade"]] = relationship(
|
|
"BacktestTrade", back_populates="backtest_run", cascade="all, delete-orphan"
|
|
)
|
|
equity_curve: Mapped[list["EquityCurveRecord"]] = relationship(
|
|
"EquityCurveRecord", back_populates="backtest_run", cascade="all, delete-orphan"
|
|
)
|
|
|
|
|
|
class BacktestMetricsRecord(Base):
|
|
__tablename__ = "backtest_metrics"
|
|
|
|
id: Mapped[str] = mapped_column(
|
|
String(36), primary_key=True, default=lambda: str(uuid4())
|
|
)
|
|
backtest_run_id: Mapped[str] = mapped_column(
|
|
String(36),
|
|
ForeignKey("backtest_runs.id"),
|
|
nullable=False,
|
|
unique=True,
|
|
index=True,
|
|
)
|
|
total_return: Mapped[float] = mapped_column(Float, default=0.0, nullable=False)
|
|
total_return_percent: Mapped[float] = mapped_column(
|
|
Float, default=0.0, nullable=False
|
|
)
|
|
annualized_return: Mapped[float] = mapped_column(Float, default=0.0, nullable=False)
|
|
benchmark_return: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
benchmark_return_percent: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
alpha: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
beta: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
volatility: Mapped[float] = mapped_column(Float, default=0.0, nullable=False)
|
|
annualized_volatility: Mapped[float] = mapped_column(
|
|
Float, default=0.0, nullable=False
|
|
)
|
|
downside_volatility: Mapped[float] = mapped_column(
|
|
Float, default=0.0, nullable=False
|
|
)
|
|
sharpe_ratio: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
sortino_ratio: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
calmar_ratio: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
information_ratio: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
max_drawdown: Mapped[float] = mapped_column(Float, default=0.0, nullable=False)
|
|
max_drawdown_percent: Mapped[float] = mapped_column(
|
|
Float, default=0.0, nullable=False
|
|
)
|
|
max_drawdown_duration: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
|
avg_drawdown: Mapped[float] = mapped_column(Float, default=0.0, nullable=False)
|
|
total_trades: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
|
|
win_rate: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
profit_factor: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
avg_trade_pnl: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
avg_win: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
avg_loss: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
largest_win: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
largest_loss: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
avg_holding_period_days: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
trading_days: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
|
|
start_equity: Mapped[float] = mapped_column(Float, nullable=False)
|
|
end_equity: Mapped[float] = mapped_column(Float, nullable=False)
|
|
created_at: Mapped[datetime] = mapped_column(
|
|
DateTime, default=datetime.utcnow, nullable=False
|
|
)
|
|
|
|
backtest_run: Mapped["BacktestRun"] = relationship(
|
|
"BacktestRun", back_populates="metrics"
|
|
)
|
|
|
|
|
|
class BacktestTrade(Base):
|
|
__tablename__ = "backtest_trades"
|
|
|
|
id: Mapped[str] = mapped_column(
|
|
String(36), primary_key=True, default=lambda: str(uuid4())
|
|
)
|
|
backtest_run_id: Mapped[str] = mapped_column(
|
|
String(36), ForeignKey("backtest_runs.id"), nullable=False, index=True
|
|
)
|
|
ticker: Mapped[str] = mapped_column(String(20), nullable=False, index=True)
|
|
side: Mapped[str] = mapped_column(
|
|
Enum("buy", "sell", name="trade_side"), nullable=False
|
|
)
|
|
quantity: Mapped[float] = mapped_column(Float, nullable=False)
|
|
entry_price: Mapped[float] = mapped_column(Float, nullable=False)
|
|
exit_price: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
entry_date: Mapped[datetime] = mapped_column(DateTime, nullable=False)
|
|
exit_date: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
|
pnl: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
pnl_percent: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
is_closed: Mapped[bool] = mapped_column(default=False, nullable=False)
|
|
holding_period_days: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
|
commission: Mapped[float] = mapped_column(Float, default=0.0, nullable=False)
|
|
slippage: Mapped[float] = mapped_column(Float, default=0.0, nullable=False)
|
|
created_at: Mapped[datetime] = mapped_column(
|
|
DateTime, default=datetime.utcnow, nullable=False
|
|
)
|
|
|
|
backtest_run: Mapped["BacktestRun"] = relationship(
|
|
"BacktestRun", back_populates="trades"
|
|
)
|
|
|
|
|
|
class EquityCurveRecord(Base):
|
|
__tablename__ = "equity_curve_records"
|
|
|
|
id: Mapped[str] = mapped_column(
|
|
String(36), primary_key=True, default=lambda: str(uuid4())
|
|
)
|
|
backtest_run_id: Mapped[str] = mapped_column(
|
|
String(36), ForeignKey("backtest_runs.id"), nullable=False, index=True
|
|
)
|
|
timestamp: Mapped[datetime] = mapped_column(DateTime, nullable=False)
|
|
equity: Mapped[float] = mapped_column(Float, nullable=False)
|
|
cash: Mapped[float] = mapped_column(Float, nullable=False)
|
|
positions_value: Mapped[float] = mapped_column(Float, nullable=False)
|
|
benchmark_value: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
drawdown: Mapped[float] = mapped_column(Float, default=0.0, nullable=False)
|
|
drawdown_percent: Mapped[float] = mapped_column(Float, default=0.0, nullable=False)
|
|
created_at: Mapped[datetime] = mapped_column(
|
|
DateTime, default=datetime.utcnow, nullable=False
|
|
)
|
|
|
|
backtest_run: Mapped["BacktestRun"] = relationship(
|
|
"BacktestRun", back_populates="equity_curve"
|
|
)
|