Stage 05.6 - order draft logic improvements
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
# app/src/integrations/exchange/models.py
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
@@ -36,6 +38,9 @@ class ExchangeSymbol:
|
||||
market_modes: list[str]
|
||||
market_type: str
|
||||
tick_size: float | None
|
||||
step_size: float | None
|
||||
min_qty: float | None
|
||||
min_notional: float | None
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
@@ -50,4 +55,4 @@ class SymbolValidationResult:
|
||||
@dataclass(slots=True)
|
||||
class PrivateAuthHealth:
|
||||
ok: bool
|
||||
message: str
|
||||
message: str
|
||||
@@ -1,3 +1,5 @@
|
||||
# app/src/integrations/exchange/service.py
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
@@ -227,28 +229,85 @@ class ExchangeService:
|
||||
if isinstance(inner, dict) and isinstance(inner.get("symbols"), list):
|
||||
symbols_raw = inner["symbols"]
|
||||
else:
|
||||
raise ExchangeError(
|
||||
"Field 'symbols' is missing in exchangeInfo response."
|
||||
)
|
||||
raise ExchangeError("Field 'symbols' is missing in exchangeInfo response.")
|
||||
|
||||
def _safe_str(value: object, default: str = "") -> str:
|
||||
if value is None:
|
||||
return default
|
||||
return str(value).strip()
|
||||
|
||||
def _safe_float(value: object) -> float | None:
|
||||
if value in (None, ""):
|
||||
return None
|
||||
try:
|
||||
return float(str(value).strip())
|
||||
except (TypeError, ValueError):
|
||||
return None
|
||||
|
||||
def _extract_filter_value(
|
||||
filters: object,
|
||||
filter_names: list[str],
|
||||
keys: list[str],
|
||||
) -> float | None:
|
||||
if not isinstance(filters, list):
|
||||
return None
|
||||
|
||||
normalized_filter_names = {name.upper() for name in filter_names}
|
||||
|
||||
for entry in filters:
|
||||
if not isinstance(entry, dict):
|
||||
continue
|
||||
|
||||
filter_type = str(entry.get("filterType", "")).strip().upper()
|
||||
if filter_type not in normalized_filter_names:
|
||||
continue
|
||||
|
||||
for key in keys:
|
||||
value = _safe_float(entry.get(key))
|
||||
if value is not None:
|
||||
return value
|
||||
|
||||
return None
|
||||
|
||||
items: list[ExchangeSymbol] = []
|
||||
|
||||
for item in symbols_raw:
|
||||
if not isinstance(item, dict):
|
||||
continue
|
||||
|
||||
tick_size_raw = item.get("tickSize")
|
||||
tick_size = None
|
||||
if tick_size_raw not in (None, ""):
|
||||
try:
|
||||
tick_size = float(str(tick_size_raw))
|
||||
except (TypeError, ValueError):
|
||||
tick_size = None
|
||||
filters = item.get("filters")
|
||||
|
||||
tick_size = _safe_float(item.get("tickSize"))
|
||||
if tick_size is None:
|
||||
tick_size = _extract_filter_value(
|
||||
filters,
|
||||
filter_names=["PRICE_FILTER"],
|
||||
keys=["tickSize"],
|
||||
)
|
||||
|
||||
step_size = _safe_float(item.get("stepSize"))
|
||||
if step_size is None:
|
||||
step_size = _extract_filter_value(
|
||||
filters,
|
||||
filter_names=["LOT_SIZE", "MARKET_LOT_SIZE"],
|
||||
keys=["stepSize"],
|
||||
)
|
||||
|
||||
min_qty = _safe_float(item.get("minQty"))
|
||||
if min_qty is None:
|
||||
min_qty = _extract_filter_value(
|
||||
filters,
|
||||
filter_names=["LOT_SIZE", "MARKET_LOT_SIZE"],
|
||||
keys=["minQty"],
|
||||
)
|
||||
|
||||
min_notional = _safe_float(item.get("minNotional"))
|
||||
if min_notional is None:
|
||||
min_notional = _extract_filter_value(
|
||||
filters,
|
||||
filter_names=["MIN_NOTIONAL", "NOTIONAL"],
|
||||
keys=["minNotional", "notional"],
|
||||
)
|
||||
|
||||
market_modes_raw = item.get("marketModes")
|
||||
if isinstance(market_modes_raw, list):
|
||||
@@ -259,7 +318,11 @@ class ExchangeService:
|
||||
market_modes = []
|
||||
|
||||
market_type_raw = item.get("marketType")
|
||||
market_type = str(market_type_raw).strip() if market_type_raw is not None else "unknown"
|
||||
market_type = (
|
||||
str(market_type_raw).strip()
|
||||
if market_type_raw is not None
|
||||
else "unknown"
|
||||
)
|
||||
|
||||
items.append(
|
||||
ExchangeSymbol(
|
||||
@@ -271,6 +334,9 @@ class ExchangeService:
|
||||
market_modes=market_modes,
|
||||
market_type=market_type,
|
||||
tick_size=tick_size,
|
||||
step_size=step_size,
|
||||
min_qty=min_qty,
|
||||
min_notional=min_notional,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user