Files
crypto_trading/backend/app/models.py
T
matitos 9c3bee87ac
CI/CD / backend (push) Successful in 5m18s
CI/CD / frontend (push) Successful in 5m2s
CI/CD / build (push) Successful in 34s
CI/CD / cleanup (push) Successful in 6s
CI/CD / deploy (push) Successful in 22s
Crypto trading bot: engine, brokers, backtester, dashboard, deploy
FastAPI backend with a single-strategy async engine, paper and Binance
brokers, pure-python indicators, a backtester that shares the engine's
portfolio math, and a Vue dashboard with a live WebSocket feed. Adds the
Gitea Actions CI/CD workflow that deploys to Traefik via docker_default.
2026-09-18 17:02:33 +00:00

122 lines
3.9 KiB
Python

from __future__ import annotations
from datetime import UTC, datetime
from enum import StrEnum
from typing import Any
from sqlalchemy import (
JSON,
DateTime,
Float,
ForeignKey,
Integer,
String,
)
from sqlalchemy import (
Enum as SAEnum,
)
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship
def utcnow() -> datetime:
return datetime.now(UTC)
class Base(DeclarativeBase):
pass
class PositionSide(StrEnum):
LONG = "long"
SHORT = "short"
class PositionStatus(StrEnum):
OPEN = "open"
CLOSED = "closed"
class OrderSide(StrEnum):
BUY = "buy"
SELL = "sell"
class StrategyConfig(Base):
__tablename__ = "strategy_configs"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
strategy_key: Mapped[str] = mapped_column(String(64), index=True)
symbol: Mapped[str] = mapped_column(String(32))
timeframe: Mapped[str] = mapped_column(String(16))
params: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict)
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utcnow)
class Position(Base):
__tablename__ = "positions"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
strategy_key: Mapped[str] = mapped_column(String(64), index=True)
symbol: Mapped[str] = mapped_column(String(32), index=True)
side: Mapped[PositionSide] = mapped_column(SAEnum(PositionSide))
qty: Mapped[float] = mapped_column(Float)
entry_price: Mapped[float] = mapped_column(Float)
status: Mapped[PositionStatus] = mapped_column(
SAEnum(PositionStatus), default=PositionStatus.OPEN, index=True
)
stop_loss: Mapped[float | None] = mapped_column(Float, nullable=True)
take_profit: Mapped[float | None] = mapped_column(Float, nullable=True)
entry_fee: Mapped[float] = mapped_column(Float, default=0.0)
exit_price: Mapped[float | None] = mapped_column(Float, nullable=True)
exit_fee: Mapped[float] = mapped_column(Float, default=0.0)
realized_pnl: Mapped[float | None] = mapped_column(Float, nullable=True)
opened_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utcnow)
closed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
orders: Mapped[list[Order]] = relationship(back_populates="position")
class Order(Base):
__tablename__ = "orders"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
position_id: Mapped[int | None] = mapped_column(
ForeignKey("positions.id"), nullable=True, index=True
)
strategy_key: Mapped[str] = mapped_column(String(64), index=True)
symbol: Mapped[str] = mapped_column(String(32))
side: Mapped[OrderSide] = mapped_column(SAEnum(OrderSide))
qty: Mapped[float] = mapped_column(Float)
price: Mapped[float] = mapped_column(Float)
fee: Mapped[float] = mapped_column(Float, default=0.0)
reason: Mapped[str] = mapped_column(String(255), default="")
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=utcnow, index=True
)
position: Mapped[Position | None] = relationship(back_populates="orders")
class EquitySnapshot(Base):
__tablename__ = "equity_snapshots"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
equity: Mapped[float] = mapped_column(Float)
cash: Mapped[float] = mapped_column(Float)
price: Mapped[float] = mapped_column(Float)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=utcnow, index=True
)
class Event(Base):
__tablename__ = "events"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
level: Mapped[str] = mapped_column(String(16), default="info")
message: Mapped[str] = mapped_column(String(512))
strategy_key: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=utcnow, index=True
)