mirror of
https://github.com/freqtrade/freqtrade.git
synced 2025-11-29 08:33:07 +00:00
fix: hyperliquid doesn't provide "average" in fetch_order
therefore this needs to be filled from trades to have a good price for market orders
This commit is contained in:
@@ -7,7 +7,8 @@ from freqtrade.constants import BuySell
|
|||||||
from freqtrade.enums import MarginMode, TradingMode
|
from freqtrade.enums import MarginMode, TradingMode
|
||||||
from freqtrade.exceptions import ExchangeError, OperationalException
|
from freqtrade.exceptions import ExchangeError, OperationalException
|
||||||
from freqtrade.exchange import Exchange
|
from freqtrade.exchange import Exchange
|
||||||
from freqtrade.exchange.exchange_types import FtHas
|
from freqtrade.exchange.exchange_types import CcxtOrder, FtHas
|
||||||
|
from freqtrade.util.datetime_helpers import dt_from_ts
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -155,3 +156,26 @@ class Hyperliquid(Exchange):
|
|||||||
except ExchangeError:
|
except ExchangeError:
|
||||||
logger.warning(f"Could not update funding fees for {pair}.")
|
logger.warning(f"Could not update funding fees for {pair}.")
|
||||||
return 0.0
|
return 0.0
|
||||||
|
|
||||||
|
def fetch_order(self, order_id: str, pair: str, params: dict | None = None) -> CcxtOrder:
|
||||||
|
order = super().fetch_order(order_id, pair, params)
|
||||||
|
|
||||||
|
if (
|
||||||
|
order["average"] is None
|
||||||
|
and order["status"] in ("canceled", "closed")
|
||||||
|
and order["filled"] > 0
|
||||||
|
):
|
||||||
|
# Hyperliquid does not fill the average price in the order response
|
||||||
|
# Fetch trades to calculate the average price to have the actual price
|
||||||
|
# the order was executed at
|
||||||
|
trades = self.get_trades_for_order(order_id, pair, since=dt_from_ts(order["timestamp"]))
|
||||||
|
|
||||||
|
if trades:
|
||||||
|
total_amount = sum(t["amount"] for t in trades)
|
||||||
|
order["average"] = (
|
||||||
|
sum(t["price"] * t["amount"] for t in trades) / total_amount
|
||||||
|
if total_amount
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
|
||||||
|
return order
|
||||||
|
|||||||
@@ -372,3 +372,46 @@ def test_hyperliquid__lev_prep(default_conf, mocker):
|
|||||||
|
|
||||||
assert api_mock.set_margin_mode.call_count == 1
|
assert api_mock.set_margin_mode.call_count == 1
|
||||||
api_mock.set_margin_mode.assert_called_with("isolated", "BTC/USDC:USDC", {"leverage": 19})
|
api_mock.set_margin_mode.assert_called_with("isolated", "BTC/USDC:USDC", {"leverage": 19})
|
||||||
|
|
||||||
|
|
||||||
|
def test_hyperliquid_fetch_order(default_conf_usdt, mocker):
|
||||||
|
default_conf_usdt["dry_run"] = False
|
||||||
|
|
||||||
|
api_mock = MagicMock()
|
||||||
|
api_mock.fetch_order = MagicMock(
|
||||||
|
return_value={
|
||||||
|
"id": "12345",
|
||||||
|
"symbol": "ETH/USDC:USDC",
|
||||||
|
"status": "closed",
|
||||||
|
"filled": 0.1,
|
||||||
|
"average": None,
|
||||||
|
"timestamp": 1630000000,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
mocker.patch(f"{EXMS}.exchange_has", return_value=True)
|
||||||
|
gtfo_mock = mocker.patch(
|
||||||
|
f"{EXMS}.get_trades_for_order",
|
||||||
|
return_value=[
|
||||||
|
{
|
||||||
|
"order_id": "12345",
|
||||||
|
"price": 1000,
|
||||||
|
"amount": 3,
|
||||||
|
"filled": 3,
|
||||||
|
"remaining": 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"order_id": "12345",
|
||||||
|
"price": 3000,
|
||||||
|
"amount": 1,
|
||||||
|
"filled": 1,
|
||||||
|
"remaining": 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
exchange = get_patched_exchange(mocker, default_conf_usdt, api_mock, exchange="hyperliquid")
|
||||||
|
o = exchange.fetch_order("12345", "ETH/USDC:USDC")
|
||||||
|
# Uses weighted average
|
||||||
|
assert o["average"] == 1500
|
||||||
|
|
||||||
|
assert gtfo_mock.call_count == 1
|
||||||
|
|||||||
Reference in New Issue
Block a user