Signed-off-by: Dinger <quantdinger@gmail.com>
This commit is contained in:
Dinger
2026-04-06 01:39:25 +08:00
parent 15c901364b
commit 3ca291a346
214 changed files with 2771 additions and 8535 deletions
@@ -19,13 +19,14 @@ from app.services.live_trading.symbols import to_binance_futures_symbol
class BinanceFuturesClient(BaseRestClient):
def __init__(self, *, api_key: str, secret_key: str, base_url: str = None, enable_demo_trading: bool = False, timeout_sec: float = 15.0):
def __init__(self, *, api_key: str, secret_key: str, base_url: str = None, enable_demo_trading: bool = False, timeout_sec: float = 15.0, broker_id: str = ""):
if not base_url:
base_url = "https://demo-fapi.binance.com" if enable_demo_trading else "https://fapi.binance.com"
super().__init__(base_url=base_url, timeout_sec=timeout_sec)
self.api_key = (api_key or "").strip()
self.secret_key = (secret_key or "").strip()
self.broker_id = (broker_id or "").strip()
if not self.api_key or not self.secret_key:
raise LiveTradingError("Missing Binance api_key/secret_key")
@@ -162,6 +163,21 @@ class BinanceFuturesClient(BaseRestClient):
def _signed_headers(self) -> Dict[str, str]:
return {"X-MBX-APIKEY": self.api_key}
def _format_client_order_id(self, client_order_id: Optional[str]) -> str:
raw = str(client_order_id or "").strip()
broker_id = str(self.broker_id or "").strip()
if not raw:
return ""
if not broker_id:
return raw[:36]
prefix = f"x-{broker_id}"
if raw.startswith(prefix):
return raw[:36]
suffix_budget = max(0, 36 - len(prefix))
if suffix_budget <= 0:
return prefix[:36]
return f"{prefix}{raw[:suffix_budget]}"
def _signed_request(self, method: str, path: str, *, params: Dict[str, Any]) -> Dict[str, Any]:
p = dict(params or {})
# Use server-accepted timestamp in ms.
@@ -649,8 +665,9 @@ class BinanceFuturesClient(BaseRestClient):
}
if reduce_only:
params["reduceOnly"] = "true"
if client_order_id:
params["newClientOrderId"] = str(client_order_id)
client_order_id_norm = self._format_client_order_id(client_order_id)
if client_order_id_norm:
params["newClientOrderId"] = client_order_id_norm
# Hedge mode requires explicit positionSide (LONG/SHORT). One-way mode should not use LONG/SHORT.
dual_side = self.get_dual_side_position()
@@ -787,8 +804,9 @@ class BinanceFuturesClient(BaseRestClient):
}
if reduce_only:
params["reduceOnly"] = "true"
if client_order_id:
params["newClientOrderId"] = str(client_order_id)
client_order_id_norm = self._format_client_order_id(client_order_id)
if client_order_id_norm:
params["newClientOrderId"] = client_order_id_norm
dual_side = self.get_dual_side_position()
pos_norm = self._normalize_position_side(position_side)