Skip to content
Merged

Futures #1384

Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 10 additions & 18 deletions Trading/Exchange/binance/binance_exchange.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,17 @@ def get_adapter_class(self):
return BinanceCCXTAdapter

async def get_account_id(self, **kwargs: dict) -> str:
raw_balance = await self.connector.client.fetch_balance()
try:
return raw_balance[ccxt_constants.CCXT_INFO]["uid"]
except KeyError:
if self.exchange_manager.is_future:
raise NotImplementedError("get_account_id is not implemented on binance futures account")
# should not happen in spot
raw_binance_balance = await self.connector.client.fapiPrivateV3GetBalance()
# accountAlias = unique account code
# from https://binance-docs.github.io/apidocs/futures/en/#futures-account-balance-v3-user_data
return raw_binance_balance[0]["accountAlias"]
else:
raw_balance = await self.connector.client.fetch_balance()
return raw_balance[ccxt_constants.CCXT_INFO]["uid"]
except (KeyError, IndexError):
# should not happen
raise

def _infer_account_types(self, exchange_manager):
Expand Down Expand Up @@ -275,19 +279,7 @@ def fix_trades(self, raw, **kwargs):

def parse_position(self, fixed, force_empty=False, **kwargs):
try:
parsed = super().parse_position(fixed, force_empty=force_empty, **kwargs)
parsed[trading_enums.ExchangeConstantsPositionColumns.MARGIN_TYPE.value] = \
trading_enums.MarginType(
fixed.get(ccxt_enums.ExchangePositionCCXTColumns.MARGIN_MODE.value)
)
# use one way by default.
if parsed[trading_enums.ExchangeConstantsPositionColumns.POSITION_MODE.value] is None:
parsed[trading_enums.ExchangeConstantsPositionColumns.POSITION_MODE.value] = (
trading_enums.PositionMode.HEDGE if fixed.get(ccxt_enums.ExchangePositionCCXTColumns.HEDGED.value,
True)
else trading_enums.PositionMode.ONE_WAY
)
return parsed
Comment on lines -279 to -290
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not necessary anymore right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return super().parse_position(fixed, force_empty=force_empty, **kwargs)
except decimal.InvalidOperation:
# on binance, positions might be invalid (ex: LUNAUSD_PERP as None contact size)
return None
Expand Down
35 changes: 27 additions & 8 deletions Trading/Exchange/kucoin/kucoin_exchange.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ class Kucoin(exchanges.RestExchange):
("order does not exist",),
]

DEFAULT_BALANCE_CURRENCIES_TO_FETCH = ["USDT"]

@classmethod
def get_name(cls):
return 'kucoin'
Expand Down Expand Up @@ -288,9 +290,16 @@ async def get_balance(self, **kwargs: dict):
if self.exchange_manager.is_future:
# on futures, balance has to be fetched per currency
# use gather to fetch everything at once (and not allow other requests to get in between)
currencies = self.exchange_manager.exchange_config.get_all_traded_currencies()
if not currencies:
currencies = self.DEFAULT_BALANCE_CURRENCIES_TO_FETCH
self.logger.warning(
f"Can't fetch balance on {self.exchange_manager.exchange_name} futures when no traded currencies "
f"are set, fetching {currencies[0]} balance instead"
)
await asyncio.gather(*(
self._update_balance(balance, currency, **kwargs)
for currency in self.exchange_manager.exchange_config.get_all_traded_currencies()
for currency in currencies
))
return balance
return await super().get_balance(**kwargs)
Expand Down Expand Up @@ -333,8 +342,21 @@ async def create_order(self, order_type: trading_enums.TraderOrderType, symbol:
side: trading_enums.TradeOrderSide = None, current_price: decimal.Decimal = None,
reduce_only: bool = False, params: dict = None) -> typing.Optional[dict]:
if self.exchange_manager.is_future:
params = params or {}
# on futures exchange expects, quantity in contracts: convert quantity into contracts
quantity = quantity / self.get_contract_size(symbol)
try:
# "marginMode": "ISOLATED" // Added field for margin mode: ISOLATED, CROSS, default: ISOLATED
# from https://www.kucoin.com/docs/rest/futures-trading/orders/place-order
if (
KucoinCCXTAdapter.KUCOIN_MARGIN_MODE not in params and
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

self.exchange_manager.exchange_personal_data.positions_manager.get_symbol_position_margin_type(
symbol
) is trading_enums.MarginType.CROSS
):
params[KucoinCCXTAdapter.KUCOIN_MARGIN_MODE] = "CROSS"
except ValueError as err:
self.logger.error(f"Impossible to add {KucoinCCXTAdapter.KUCOIN_MARGIN_MODE} to order: {err}")
return await super().create_order(order_type, symbol, quantity,
price=price, stop_price=stop_price,
side=side, current_price=current_price,
Expand Down Expand Up @@ -448,6 +470,7 @@ class KucoinCCXTAdapter(exchanges.CCXTAdapter):

# ORDER
KUCOIN_LEVERAGE = "leverage"
KUCOIN_MARGIN_MODE = "marginMode"

def fix_order(self, raw, symbol=None, **kwargs):
raw_order_info = raw[ccxt_enums.ExchangePositionCCXTColumns.INFO.value]
Expand Down Expand Up @@ -515,13 +538,9 @@ def parse_funding_rate(self, fixed, from_ticker=False, **kwargs):
def parse_position(self, fixed, **kwargs):
raw_position_info = fixed[ccxt_enums.ExchangePositionCCXTColumns.INFO.value]
parsed = super().parse_position(fixed, **kwargs)
parsed[trading_enums.ExchangeConstantsPositionColumns.MARGIN_TYPE.value] = \
trading_enums.MarginType(
fixed.get(ccxt_enums.ExchangePositionCCXTColumns.MARGIN_MODE.value)
)
parsed[trading_enums.ExchangeConstantsPositionColumns.POSITION_MODE.value] = \
trading_enums.PositionMode.HEDGE if raw_position_info[self.KUCOIN_AUTO_DEPOSIT] \
else trading_enums.PositionMode.ONE_WAY
parsed[trading_enums.ExchangeConstantsPositionColumns.AUTO_DEPOSIT_MARGIN.value] = (
raw_position_info.get(self.KUCOIN_AUTO_DEPOSIT, False) # unset for cross positions
)
parsed_leverage = self.safe_decimal(
parsed, trading_enums.ExchangeConstantsPositionColumns.LEVERAGE.value, constants.ZERO
)
Expand Down