Build 060.1: add canonical Trade model
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
# app/src/market_data/acquisition/models/trade.py
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
from enum import Enum
|
||||
|
||||
|
||||
# Сторона агрессора, инициировавшего исполнение биржевой сделки.
|
||||
class TradeAggressorSide(Enum):
|
||||
BUY = "buy"
|
||||
SELL = "sell"
|
||||
|
||||
|
||||
# Каноническая неизменяемая модель одной исполненной биржевой сделки.
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class Trade:
|
||||
symbol: str
|
||||
|
||||
trade_id: int
|
||||
|
||||
price: Decimal
|
||||
quantity: Decimal
|
||||
|
||||
executed_at: datetime
|
||||
|
||||
aggressor_side: TradeAggressorSide
|
||||
|
||||
source: str
|
||||
|
||||
62
app/tests/unit/market_data/acquisition/models/test_trade.py
Normal file
62
app/tests/unit/market_data/acquisition/models/test_trade.py
Normal file
@@ -0,0 +1,62 @@
|
||||
# app/tests/unit/market_data/acquisition/models/test_trade.py
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import FrozenInstanceError
|
||||
from datetime import datetime, timezone
|
||||
from decimal import Decimal
|
||||
|
||||
import pytest
|
||||
|
||||
from src.market_data.acquisition.models.trade import Trade, TradeAggressorSide
|
||||
|
||||
|
||||
def _trade(
|
||||
*,
|
||||
aggressor_side: TradeAggressorSide = TradeAggressorSide.BUY,
|
||||
) -> Trade:
|
||||
return Trade(
|
||||
symbol="BTC/USD_LEVERAGE",
|
||||
trade_id=2134857062,
|
||||
price=Decimal("64497.25"),
|
||||
quantity=Decimal("0.005"),
|
||||
executed_at=datetime(2026, 7, 16, 11, 27, 46, 823000, tzinfo=timezone.utc),
|
||||
aggressor_side=aggressor_side,
|
||||
source="dzengi",
|
||||
)
|
||||
|
||||
|
||||
def test_trade_stores_canonical_values() -> None:
|
||||
trade = _trade()
|
||||
|
||||
assert trade.symbol == "BTC/USD_LEVERAGE"
|
||||
assert trade.trade_id == 2134857062
|
||||
assert trade.price == Decimal("64497.25")
|
||||
assert trade.quantity == Decimal("0.005")
|
||||
assert trade.executed_at.tzinfo is timezone.utc
|
||||
assert trade.aggressor_side is TradeAggressorSide.BUY
|
||||
assert trade.source == "dzengi"
|
||||
|
||||
|
||||
def test_trade_supports_sell_aggressor_side() -> None:
|
||||
trade = _trade(aggressor_side=TradeAggressorSide.SELL)
|
||||
|
||||
assert trade.aggressor_side is TradeAggressorSide.SELL
|
||||
|
||||
|
||||
def test_trade_aggressor_side_has_stable_values() -> None:
|
||||
assert TradeAggressorSide.BUY.value == "buy"
|
||||
assert TradeAggressorSide.SELL.value == "sell"
|
||||
|
||||
|
||||
def test_trade_is_frozen() -> None:
|
||||
trade = _trade()
|
||||
|
||||
with pytest.raises(FrozenInstanceError):
|
||||
setattr(trade, "price", Decimal("1"))
|
||||
|
||||
|
||||
def test_trade_uses_slots() -> None:
|
||||
trade = _trade()
|
||||
|
||||
assert not hasattr(trade, "__dict__")
|
||||
Reference in New Issue
Block a user