feat: add grid trading calculations
This commit is contained in:
146
src/grid_trading/domain/models.py
Normal file
146
src/grid_trading/domain/models.py
Normal file
@@ -0,0 +1,146 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import date
|
||||
from decimal import Decimal
|
||||
from enum import StrEnum
|
||||
|
||||
|
||||
class TradeSide(StrEnum):
|
||||
BUY = "buy"
|
||||
SELL = "sell"
|
||||
|
||||
|
||||
class TradeGroup(StrEnum):
|
||||
BASE = "base"
|
||||
GRID = "grid"
|
||||
OTHER = "other"
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Account:
|
||||
id: int | None
|
||||
name: str
|
||||
initial_cash: Decimal
|
||||
notes: str = ""
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Instrument:
|
||||
id: int | None
|
||||
code: str
|
||||
name: str
|
||||
market: str = "A"
|
||||
lot_size: int = 100
|
||||
manual_price: Decimal | None = None
|
||||
allow_odd_lot: bool = False
|
||||
active: bool = True
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class StrategyTemplate:
|
||||
id: int | None
|
||||
name: str
|
||||
grid_spacing_pct: Decimal
|
||||
amount_per_grid: Decimal
|
||||
base_target_amount: Decimal
|
||||
max_position_amount: Decimal
|
||||
min_lot: int = 100
|
||||
is_default: bool = False
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class StrategyOverride:
|
||||
instrument_id: int
|
||||
template_id: int | None = None
|
||||
grid_spacing_pct: Decimal | None = None
|
||||
amount_per_grid: Decimal | None = None
|
||||
base_target_amount: Decimal | None = None
|
||||
max_position_amount: Decimal | None = None
|
||||
min_lot: int | None = None
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Trade:
|
||||
id: int | None
|
||||
account_id: int
|
||||
instrument_id: int
|
||||
trade_date: date
|
||||
side: TradeSide
|
||||
price: Decimal
|
||||
quantity: int
|
||||
commission: Decimal = Decimal("0")
|
||||
stamp_tax: Decimal = Decimal("0")
|
||||
transfer_fee: Decimal = Decimal("0")
|
||||
trade_group: TradeGroup = TradeGroup.GRID
|
||||
notes: str = ""
|
||||
|
||||
@property
|
||||
def gross_amount(self) -> Decimal:
|
||||
return self.price * Decimal(self.quantity)
|
||||
|
||||
@property
|
||||
def total_fee(self) -> Decimal:
|
||||
return self.commission + self.stamp_tax + self.transfer_fee
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class CashLedgerEntry:
|
||||
id: int | None
|
||||
account_id: int
|
||||
entry_date: date
|
||||
amount: Decimal
|
||||
category: str
|
||||
instrument_id: int | None = None
|
||||
notes: str = ""
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class FeeRules:
|
||||
commission_rate: Decimal
|
||||
min_commission: Decimal
|
||||
stamp_tax_rate: Decimal
|
||||
transfer_fee_rate: Decimal
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class FeeEstimate:
|
||||
commission: Decimal
|
||||
stamp_tax: Decimal
|
||||
transfer_fee: Decimal
|
||||
|
||||
@property
|
||||
def total(self) -> Decimal:
|
||||
return self.commission + self.stamp_tax + self.transfer_fee
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class PositionSummary:
|
||||
instrument_id: int
|
||||
code: str
|
||||
name: str
|
||||
market: str
|
||||
current_price: Decimal | None
|
||||
price_source: str
|
||||
total_quantity: int
|
||||
available_quantity: int
|
||||
base_quantity: int
|
||||
grid_quantity: int
|
||||
other_quantity: int
|
||||
remaining_cost: Decimal
|
||||
cost_price: Decimal | None
|
||||
position_breakeven_price: Decimal | None
|
||||
account_breakeven_price: Decimal | None
|
||||
realized_pnl: Decimal
|
||||
grid_profit: Decimal
|
||||
floating_pnl: Decimal | None
|
||||
market_value: Decimal | None
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class AccountSummary:
|
||||
total_assets: Decimal
|
||||
cash: Decimal
|
||||
market_value: Decimal
|
||||
floating_pnl: Decimal
|
||||
capital_usage_rate: Decimal
|
||||
Reference in New Issue
Block a user