repo hygiene: track the PINK launcher import closure
67 production .py modules that the running PINK service imports but which were never committed: prod/bingx/ (HTTP client, market/user streams, journal, config), prod/clean_arch/ adapters/persistence/runtime/dita/dita_v2 production modules and their co-located tests. Rule going forward: every module imported by launch_dolphin_pink.py / pink_direct.py must appear in git ls-files. Excludes _backup dirs, __pycache__, and non-code files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
80
prod/bingx/schemas.py
Normal file
80
prod/bingx/schemas.py
Normal file
@@ -0,0 +1,80 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from decimal import Decimal
|
||||
|
||||
|
||||
def _as_decimal(value: object, default: str = "0") -> Decimal:
|
||||
if value is None:
|
||||
return Decimal(default)
|
||||
return Decimal(str(value))
|
||||
|
||||
|
||||
def unwrap_order_payload(payload: dict[str, object]) -> dict[str, object]:
|
||||
row = payload.get("order") if isinstance(payload, dict) else None
|
||||
return row if isinstance(row, dict) else payload
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class BingxContract:
|
||||
symbol: str
|
||||
venue_symbol: str
|
||||
quote_asset: str
|
||||
base_asset: str
|
||||
price_precision: int
|
||||
quantity_precision: int
|
||||
min_quantity: Decimal
|
||||
min_notional: Decimal
|
||||
tick_size: Decimal
|
||||
step_size: Decimal
|
||||
maker_fee: Decimal
|
||||
taker_fee: Decimal
|
||||
max_leverage: int
|
||||
|
||||
@classmethod
|
||||
def from_http(cls, payload: dict[str, object]) -> "BingxContract":
|
||||
venue_symbol = str(payload.get("symbol") or payload.get("ticker") or "")
|
||||
normalized = venue_symbol.replace("-", "")
|
||||
price_precision = int(payload.get("pricePrecision") or payload.get("price_scale") or 2)
|
||||
quantity_precision = int(
|
||||
payload.get("quantityPrecision") or payload.get("quantity_scale") or 3,
|
||||
)
|
||||
tick_size = _as_decimal(
|
||||
payload.get("tickSize") or payload.get("priceStep") or f"1e-{price_precision}",
|
||||
)
|
||||
step_size = _as_decimal(
|
||||
payload.get("stepSize") or payload.get("quantityStep") or f"1e-{quantity_precision}",
|
||||
)
|
||||
return cls(
|
||||
symbol=normalized,
|
||||
venue_symbol=venue_symbol,
|
||||
quote_asset=str(payload.get("currency") or payload.get("quoteAsset") or "USDT"),
|
||||
base_asset=str(payload.get("asset") or payload.get("baseAsset") or normalized[:-4]),
|
||||
price_precision=price_precision,
|
||||
quantity_precision=quantity_precision,
|
||||
min_quantity=_as_decimal(payload.get("minQty") or payload.get("minQuantity") or step_size),
|
||||
min_notional=_as_decimal(payload.get("minNotional") or payload.get("minQuoteAmount") or "2"),
|
||||
tick_size=tick_size,
|
||||
step_size=step_size,
|
||||
maker_fee=_as_decimal(payload.get("makerFeeRate") or payload.get("makerFee") or "0.0002"),
|
||||
taker_fee=_as_decimal(payload.get("takerFeeRate") or payload.get("takerFee") or "0.0005"),
|
||||
max_leverage=int(payload.get("maxLongLeverage") or payload.get("maxLeverage") or 1),
|
||||
)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class BingxOrderAck:
|
||||
order_id: str
|
||||
client_order_id: str
|
||||
symbol: str
|
||||
status: str | None
|
||||
|
||||
@classmethod
|
||||
def from_http(cls, payload: dict[str, object]) -> "BingxOrderAck":
|
||||
row = unwrap_order_payload(payload)
|
||||
return cls(
|
||||
order_id=str(row.get("orderId") or row.get("id") or ""),
|
||||
client_order_id=str(row.get("clientOrderID") or row.get("clientOrderId") or ""),
|
||||
symbol=str(row.get("symbol") or ""),
|
||||
status=str(row.get("status")) if row.get("status") is not None else None,
|
||||
)
|
||||
Reference in New Issue
Block a user