Files
crypto_trading/backend/app/models.py
T
matitos 03dfa369e5
CI/CD / backend (pull_request) Successful in 6m18s
CI/CD / frontend (pull_request) Successful in 4m55s
CI/CD / build (pull_request) Skipped
CI/CD / deploy (pull_request) Skipped
CI/CD / cleanup (pull_request) Skipped
Risk controls, alerts, API token, more exchanges, presets
- RiskManager halts + flattens on max daily loss / drawdown, caps position
  size and trades per day; adds a manual kill switch (POST /api/bot/kill).
- Telegram and webhook notifications on trades, errors and halts.
- Optional API bearer token on /api, injected server-side by the frontend
  nginx so the browser never sees it.
- Kraken and Coinbase market data (public); Coinbase live broker. Live on an
  unsupported exchange now errors instead of silently falling back to paper.
- Strategy presets backed by the StrategyConfig table (CRUD API + UI).
- Idempotent additive-column migration so existing SQLite databases upgrade in
  place (fixes the new strategy_configs.name column).
2026-09-18 19:26:29 +00:00

123 lines
4.0 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)
name: Mapped[str] = mapped_column(String(80), default="")
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
)