krakenfutures: run order adjustments via _order_contracts_to_amount

This commit is contained in:
matstedt
2026-02-25 22:21:50 +01:00
committed by Matthias
parent 1e79c1961b
commit 35d812a271
+23 -22
View File
@@ -134,14 +134,29 @@ class Krakenfutures(Exchange):
return None
def _order_contracts_to_amount(self, order: CcxtOrder) -> CcxtOrder:
"""Normalize order and fix missing trigger price from CCXT parsing.
"""Normalize order and apply Kraken Futures-specific fixes.
CCXT's krakenfutures parse_order reads triggerPrice from the top level of
the order details, but the /orders/status endpoint nests it inside
priceTriggerOptions.triggerPrice. This extracts it so stopPrice/triggerPrice
are populated correctly for stoploss order handling.
This override applies all CCXT workarounds by calling _adjust_krakenfutures_order
after the base class normalization. This ensures all orders (including those
from create_order that fill immediately) get correct prices and fees.
"""
order = super()._order_contracts_to_amount(order)
return self._adjust_krakenfutures_order(order)
def _adjust_krakenfutures_order(self, order: CcxtOrder) -> CcxtOrder:
"""Apply Kraken Futures-specific order corrections.
Fixes CCXT parsing issues:
1. triggerPrice nested in info.order.priceTriggerOptions (not extracted)
2. average set to limitPrice instead of actual fill price
For filled terminal orders, we ALWAYS fetch trades and compute VWAP because
CCXT's average is unreliable. We also aggregate fees to avoid a
redundant get_trades_for_order call from fee_detection_from_trades.
See: https://github.com/ccxt/ccxt/issues/27979
"""
# Fix 1: Extract nested triggerPrice for stoploss orders
if order.get("triggerPrice") is None and order.get("stopPrice") is None:
trigger = safe_value_nested(order, "info.order.priceTriggerOptions.triggerPrice")
if trigger is not None:
@@ -149,23 +164,10 @@ class Krakenfutures(Exchange):
if trigger_float is not None:
order["triggerPrice"] = trigger_float
order["stopPrice"] = trigger_float
return order
def _adjust_krakenfutures_order(self, order: CcxtOrder) -> CcxtOrder:
"""Fix missing average price and aggregate fees for filled orders.
Kraken Futures' /orders/status endpoint does not include execution data,
so CCXT sets price/average to the limitPrice (the order's limit, not the
actual fill price). For closed/filled orders we ALWAYS fetch trades and
compute VWAP because CCXT's average field is unreliable.
We also aggregate fees here to avoid a redundant get_trades_for_order call
from fee_detection_from_trades.
See: https://github.com/ccxt/ccxt/issues/27979
"""
filled = self._safe_float(order.get("filled")) or 0.0
if order.get("status") in ("canceled", "closed") and filled > 0:
# Fix 2: Compute VWAP and aggregate fees for filled orders
trades = self.get_trades_for_order(
order["id"], order["symbol"], since=dt_from_ts(order["timestamp"])
)
@@ -229,8 +231,7 @@ class Krakenfutures(Exchange):
try:
order = self._api.fetch_order(order_id, pair, params=status_params)
self._log_exchange_response("fetch_order", order)
order = self._order_contracts_to_amount(order)
return self._adjust_krakenfutures_order(order)
return self._order_contracts_to_amount(order)
except ccxt.OrderNotFound:
# Expected for older Kraken Futures orders not visible in orders/status.
pass
@@ -247,7 +248,7 @@ class Krakenfutures(Exchange):
order = self._fetch_order_fallback(order_id, pair, params)
if order is not None:
return self._adjust_krakenfutures_order(order)
return order
# Order not in status, open, closed, or canceled endpoints - genuinely gone.
# Raise non-retrying InvalidOrderException (Kraken has limited history retention).