chore: first step to improved ccxtOrder Typing

This commit is contained in:
Matthias
2024-11-04 07:23:25 +01:00
parent 31bcee1a13
commit ecf5e1ce6b
5 changed files with 38 additions and 25 deletions
+5 -3
View File
@@ -11,7 +11,7 @@ from freqtrade.enums import CandleType, MarginMode, PriceType, TradingMode
from freqtrade.exceptions import DDosProtection, ExchangeError, OperationalException, TemporaryError from freqtrade.exceptions import DDosProtection, ExchangeError, OperationalException, TemporaryError
from freqtrade.exchange import Exchange from freqtrade.exchange import Exchange
from freqtrade.exchange.common import retrier from freqtrade.exchange.common import retrier
from freqtrade.exchange.exchange_types import FtHas from freqtrade.exchange.exchange_types import CcxtOrder, FtHas
from freqtrade.util.datetime_helpers import dt_now, dt_ts from freqtrade.util.datetime_helpers import dt_now, dt_ts
@@ -229,7 +229,9 @@ class Bybit(Exchange):
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_orders(self, pair: str, since: datetime, params: Optional[dict] = None) -> list[dict]: def fetch_orders(
self, pair: str, since: datetime, params: Optional[dict] = None
) -> list[CcxtOrder]:
""" """
Fetch all orders for a pair "since" Fetch all orders for a pair "since"
:param pair: Pair for the query :param pair: Pair for the query
@@ -246,7 +248,7 @@ class Bybit(Exchange):
return orders return orders
def fetch_order(self, order_id: str, pair: str, params: Optional[dict] = None) -> dict: def fetch_order(self, order_id: str, pair: str, params: Optional[dict] = None) -> CcxtOrder:
if self.exchange_has("fetchOrder"): if self.exchange_has("fetchOrder"):
# Set acknowledged to True to avoid ccxt exception # Set acknowledged to True to avoid ccxt exception
params = {"acknowledged": True} params = {"acknowledged": True}
+19 -14
View File
@@ -70,6 +70,7 @@ from freqtrade.exchange.common import (
) )
from freqtrade.exchange.exchange_types import ( from freqtrade.exchange.exchange_types import (
CcxtBalances, CcxtBalances,
CcxtOrder,
CcxtPosition, CcxtPosition,
FtHas, FtHas,
OHLCVResponse, OHLCVResponse,
@@ -1003,14 +1004,14 @@ class Exchange:
leverage: float, leverage: float,
params: Optional[dict] = None, params: Optional[dict] = None,
stop_loss: bool = False, stop_loss: bool = False,
) -> dict[str, Any]: ) -> CcxtOrder:
now = dt_now() now = dt_now()
order_id = f"dry_run_{side}_{pair}_{now.timestamp()}" order_id = f"dry_run_{side}_{pair}_{now.timestamp()}"
# Rounding here must respect to contract sizes # Rounding here must respect to contract sizes
_amount = self._contracts_to_amount( _amount = self._contracts_to_amount(
pair, self.amount_to_precision(pair, self._amount_to_contracts(pair, amount)) pair, self.amount_to_precision(pair, self._amount_to_contracts(pair, amount))
) )
dry_order: dict[str, Any] = { dry_order: CcxtOrder = {
"id": order_id, "id": order_id,
"symbol": pair, "symbol": pair,
"price": rate, "price": rate,
@@ -1072,9 +1073,9 @@ class Exchange:
def add_dry_order_fee( def add_dry_order_fee(
self, self,
pair: str, pair: str,
dry_order: dict[str, Any], dry_order: CcxtOrder,
taker_or_maker: MakerTaker, taker_or_maker: MakerTaker,
) -> dict[str, Any]: ) -> CcxtOrder:
fee = self.get_fee(pair, taker_or_maker=taker_or_maker) fee = self.get_fee(pair, taker_or_maker=taker_or_maker)
dry_order.update( dry_order.update(
{ {
@@ -1158,8 +1159,8 @@ class Exchange:
return False return False
def check_dry_limit_order_filled( def check_dry_limit_order_filled(
self, order: dict[str, Any], immediate: bool = False, orderbook: Optional[OrderBook] = None self, order: CcxtOrder, immediate: bool = False, orderbook: Optional[OrderBook] = None
) -> dict[str, Any]: ) -> CcxtOrder:
""" """
Check dry-run limit order fill and update fee (if it filled). Check dry-run limit order fill and update fee (if it filled).
""" """
@@ -1186,7 +1187,7 @@ class Exchange:
return order return order
def fetch_dry_run_order(self, order_id) -> dict[str, Any]: def fetch_dry_run_order(self, order_id) -> CcxtOrder:
""" """
Return dry-run order Return dry-run order
Only call if running in dry-run mode. Only call if running in dry-run mode.
@@ -1460,7 +1461,7 @@ class Exchange:
except ccxt.BaseError as e: except ccxt.BaseError as e:
raise OperationalException(e) from e raise OperationalException(e) from e
def fetch_order_emulated(self, order_id: str, pair: str, params: dict) -> dict: def fetch_order_emulated(self, order_id: str, pair: str, params: dict) -> CcxtOrder:
""" """
Emulated fetch_order if the exchange doesn't support fetch_order, but requires separate Emulated fetch_order if the exchange doesn't support fetch_order, but requires separate
calls for open and closed orders. calls for open and closed orders.
@@ -1494,7 +1495,7 @@ class Exchange:
raise OperationalException(e) from e raise OperationalException(e) from e
@retrier(retries=API_FETCH_ORDER_RETRY_COUNT) @retrier(retries=API_FETCH_ORDER_RETRY_COUNT)
def fetch_order(self, order_id: str, pair: str, params: Optional[dict] = None) -> dict: def fetch_order(self, order_id: str, pair: str, params: Optional[dict] = None) -> CcxtOrder:
if self._config["dry_run"]: if self._config["dry_run"]:
return self.fetch_dry_run_order(order_id) return self.fetch_dry_run_order(order_id)
if params is None: if params is None:
@@ -1523,12 +1524,14 @@ class Exchange:
except ccxt.BaseError as e: except ccxt.BaseError as e:
raise OperationalException(e) from e raise OperationalException(e) from e
def fetch_stoploss_order(self, order_id: str, pair: str, params: Optional[dict] = None) -> dict: def fetch_stoploss_order(
self, order_id: str, pair: str, params: Optional[dict] = None
) -> CcxtOrder:
return self.fetch_order(order_id, pair, params) return self.fetch_order(order_id, pair, params)
def fetch_order_or_stoploss_order( def fetch_order_or_stoploss_order(
self, order_id: str, pair: str, stoploss_order: bool = False self, order_id: str, pair: str, stoploss_order: bool = False
) -> dict: ) -> CcxtOrder:
""" """
Simple wrapper calling either fetch_order or fetch_stoploss_order depending on Simple wrapper calling either fetch_order or fetch_stoploss_order depending on
the stoploss_order parameter the stoploss_order parameter
@@ -1589,7 +1592,7 @@ class Exchange:
required = ("fee", "status", "amount") required = ("fee", "status", "amount")
return all(corder.get(k, None) is not None for k in required) return all(corder.get(k, None) is not None for k in required)
def cancel_order_with_result(self, order_id: str, pair: str, amount: float) -> dict: def cancel_order_with_result(self, order_id: str, pair: str, amount: float) -> CcxtOrder:
""" """
Cancel order returning a result. Cancel order returning a result.
Creates a fake result if cancel order returns a non-usable result Creates a fake result if cancel order returns a non-usable result
@@ -1686,7 +1689,7 @@ class Exchange:
except ccxt.BaseError as e: except ccxt.BaseError as e:
raise OperationalException(e) from e raise OperationalException(e) from e
def _fetch_orders_emulate(self, pair: str, since_ms: int) -> list[dict]: def _fetch_orders_emulate(self, pair: str, since_ms: int) -> list[CcxtOrder]:
orders = [] orders = []
if self.exchange_has("fetchClosedOrders"): if self.exchange_has("fetchClosedOrders"):
orders = self._api.fetch_closed_orders(pair, since=since_ms) orders = self._api.fetch_closed_orders(pair, since=since_ms)
@@ -1696,7 +1699,9 @@ class Exchange:
return orders return orders
@retrier(retries=0) @retrier(retries=0)
def fetch_orders(self, pair: str, since: datetime, params: Optional[dict] = None) -> list[dict]: def fetch_orders(
self, pair: str, since: datetime, params: Optional[dict] = None
) -> list[CcxtOrder]:
""" """
Fetch all orders for a pair "since" Fetch all orders for a pair "since"
:param pair: Pair for the query :param pair: Pair for the query
+3 -1
View File
@@ -1,4 +1,4 @@
from typing import Optional, TypedDict from typing import Any, Optional, TypedDict
from freqtrade.enums import CandleType from freqtrade.enums import CandleType
@@ -94,5 +94,7 @@ class CcxtPosition(TypedDict):
liquidationPrice: Optional[float] liquidationPrice: Optional[float]
CcxtOrder = dict[str, Any]
# pair, timeframe, candleType, OHLCV, drop last?, # pair, timeframe, candleType, OHLCV, drop last?,
OHLCVResponse = tuple[str, str, CandleType, list, bool] OHLCVResponse = tuple[str, str, CandleType, list, bool]
+4 -2
View File
@@ -7,7 +7,7 @@ from typing import Any, Optional
from freqtrade.constants import BuySell from freqtrade.constants import BuySell
from freqtrade.enums import MarginMode, PriceType, TradingMode from freqtrade.enums import MarginMode, PriceType, TradingMode
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.misc import safe_value_fallback2 from freqtrade.misc import safe_value_fallback2
@@ -102,7 +102,9 @@ class Gate(Exchange):
def get_order_id_conditional(self, order: dict[str, Any]) -> str: def get_order_id_conditional(self, order: dict[str, Any]) -> str:
return safe_value_fallback2(order, order, "id_stop", "id") return safe_value_fallback2(order, order, "id_stop", "id")
def fetch_stoploss_order(self, order_id: str, pair: str, params: Optional[dict] = None) -> dict: def fetch_stoploss_order(
self, order_id: str, pair: str, params: Optional[dict] = None
) -> CcxtOrder:
order = self.fetch_order(order_id=order_id, pair=pair, params={"stop": True}) order = self.fetch_order(order_id=order_id, pair=pair, params={"stop": True})
if order.get("status", "open") == "closed": if order.get("status", "open") == "closed":
# Places a real order - which we need to fetch explicitly. # Places a real order - which we need to fetch explicitly.
+7 -5
View File
@@ -14,7 +14,7 @@ from freqtrade.exceptions import (
) )
from freqtrade.exchange import Exchange, date_minus_candles from freqtrade.exchange import Exchange, date_minus_candles
from freqtrade.exchange.common import API_RETRY_COUNT, retrier from freqtrade.exchange.common import API_RETRY_COUNT, retrier
from freqtrade.exchange.exchange_types import FtHas from freqtrade.exchange.exchange_types import CcxtOrder, FtHas
from freqtrade.misc import safe_value_fallback2 from freqtrade.misc import safe_value_fallback2
from freqtrade.util import dt_now, dt_ts from freqtrade.util import dt_now, dt_ts
@@ -209,7 +209,9 @@ class Okx(Exchange):
return order return order
@retrier(retries=API_RETRY_COUNT) @retrier(retries=API_RETRY_COUNT)
def fetch_stoploss_order(self, order_id: str, pair: str, params: Optional[dict] = None) -> dict: def fetch_stoploss_order(
self, order_id: str, pair: str, params: Optional[dict] = None
) -> CcxtOrder:
if self._config["dry_run"]: if self._config["dry_run"]:
return self.fetch_dry_run_order(order_id) return self.fetch_dry_run_order(order_id)
@@ -231,7 +233,7 @@ class Okx(Exchange):
return self._fetch_stop_order_fallback(order_id, pair) return self._fetch_stop_order_fallback(order_id, pair)
def _fetch_stop_order_fallback(self, order_id: str, pair: str) -> dict: def _fetch_stop_order_fallback(self, order_id: str, pair: str) -> CcxtOrder:
params2 = {"stop": True, "ordType": "conditional"} params2 = {"stop": True, "ordType": "conditional"}
for method in ( for method in (
self._api.fetch_open_orders, self._api.fetch_open_orders,
@@ -263,7 +265,7 @@ class Okx(Exchange):
def cancel_stoploss_order( def cancel_stoploss_order(
self, order_id: str, pair: str, params: Optional[dict] = None self, order_id: str, pair: str, params: Optional[dict] = None
) -> dict: ) -> CcxtOrder:
params1 = {"stop": True} params1 = {"stop": True}
# 'ordType': 'conditional' # 'ordType': 'conditional'
# #
@@ -273,7 +275,7 @@ class Okx(Exchange):
params=params1, params=params1,
) )
def _fetch_orders_emulate(self, pair: str, since_ms: int) -> list[dict]: def _fetch_orders_emulate(self, pair: str, since_ms: int) -> list[CcxtOrder]:
orders = [] orders = []
orders = self._api.fetch_closed_orders(pair, since=since_ms) orders = self._api.fetch_closed_orders(pair, since=since_ms)