diff --git a/freqtrade/constants.py b/freqtrade/constants.py index 434734ef0..7d3f9e2c1 100644 --- a/freqtrade/constants.py +++ b/freqtrade/constants.py @@ -155,7 +155,7 @@ CONF_SCHEMA = { 'ignore_roi_if_buy_signal': {'type': 'boolean'}, 'ignore_buying_expired_candle_after': {'type': 'number'}, 'trading_mode': {'type': 'string', 'enum': TRADING_MODES}, - 'collateral': {'type': 'string', 'enum': COLLATERAL_TYPES}, + 'margin_mode': {'type': 'string', 'enum': COLLATERAL_TYPES}, 'backtest_breakdown': { 'type': 'array', 'items': {'type': 'string', 'enum': BACKTEST_BREAKDOWNS} diff --git a/freqtrade/enums/__init__.py b/freqtrade/enums/__init__.py index 4eb0ce307..49f2f1a60 100644 --- a/freqtrade/enums/__init__.py +++ b/freqtrade/enums/__init__.py @@ -1,7 +1,7 @@ # flake8: noqa: F401 from freqtrade.enums.backteststate import BacktestState from freqtrade.enums.candletype import CandleType -from freqtrade.enums.collateral import Collateral +from freqtrade.enums.marginmode import MarginMode from freqtrade.enums.ordertypevalue import OrderTypeValues from freqtrade.enums.rpcmessagetype import RPCMessageType from freqtrade.enums.runmode import NON_UTIL_MODES, OPTIMIZE_MODES, TRADING_MODES, RunMode diff --git a/freqtrade/enums/collateral.py b/freqtrade/enums/marginmode.py similarity index 52% rename from freqtrade/enums/collateral.py rename to freqtrade/enums/marginmode.py index 979496f7b..999051ca4 100644 --- a/freqtrade/enums/collateral.py +++ b/freqtrade/enums/marginmode.py @@ -1,11 +1,11 @@ from enum import Enum -class Collateral(Enum): +class MarginMode(Enum): """ Enum to distinguish between - cross margin/futures collateral and - isolated margin/futures collateral + cross margin/futures margin_mode and + isolated margin/futures margin_mode """ CROSS = "cross" ISOLATED = "isolated" diff --git a/freqtrade/exchange/binance.py b/freqtrade/exchange/binance.py index 826087aac..7d50e2c57 100644 --- a/freqtrade/exchange/binance.py +++ b/freqtrade/exchange/binance.py @@ -8,7 +8,7 @@ from typing import Dict, List, Optional, Tuple import arrow import ccxt -from freqtrade.enums import CandleType, Collateral, TradingMode +from freqtrade.enums import CandleType, MarginMode, TradingMode from freqtrade.exceptions import (DDosProtection, InsufficientFundsError, InvalidOrderException, OperationalException, TemporaryError) from freqtrade.exchange import Exchange @@ -31,11 +31,11 @@ class Binance(Exchange): "ccxt_futures_name": "future" } - _supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [ + _supported_trading_mode_margin_pairs: List[Tuple[TradingMode, MarginMode]] = [ # TradingMode.SPOT always supported and not required in this list - # (TradingMode.MARGIN, Collateral.CROSS), - # (TradingMode.FUTURES, Collateral.CROSS), - (TradingMode.FUTURES, Collateral.ISOLATED) + # (TradingMode.MARGIN, MarginMode.CROSS), + # (TradingMode.FUTURES, MarginMode.CROSS), + (TradingMode.FUTURES, MarginMode.ISOLATED) ] def stoploss_adjust(self, stop_loss: float, order: Dict, side: str) -> bool: @@ -177,7 +177,7 @@ class Binance(Exchange): """ Returns the maximum leverage that a pair can be traded at :param pair: The base/quote currency pair being traded - :stake_amount: The total value of the traders collateral in quote currency + :stake_amount: The total value of the traders margin_mode in quote currency """ if stake_amount is None: raise OperationalException('binance.get_max_leverage requires argument stake_amount') @@ -324,7 +324,7 @@ class Binance(Exchange): side_1 = -1 if is_short else 1 position = abs(position) - cross_vars = upnl_ex_1 - mm_ex_1 if self.collateral == Collateral.CROSS else 0.0 + cross_vars = upnl_ex_1 - mm_ex_1 if self.margin_mode == MarginMode.CROSS else 0.0 # mm_ratio: Binance's formula specifies maintenance margin rate which is mm_ratio * 100% # maintenance_amt: (CUM) Maintenance Amount of position diff --git a/freqtrade/exchange/bybit.py b/freqtrade/exchange/bybit.py index 32bb0e284..484b8b9d3 100644 --- a/freqtrade/exchange/bybit.py +++ b/freqtrade/exchange/bybit.py @@ -2,7 +2,7 @@ import logging from typing import Dict, List, Tuple -from freqtrade.enums import Collateral, TradingMode +from freqtrade.enums import MarginMode, TradingMode from freqtrade.exchange import Exchange @@ -24,8 +24,8 @@ class Bybit(Exchange): "ccxt_futures_name": "linear" } - _supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [ + _supported_trading_mode_margin_pairs: List[Tuple[TradingMode, MarginMode]] = [ # TradingMode.SPOT always supported and not required in this list - # (TradingMode.FUTURES, Collateral.CROSS), - # (TradingMode.FUTURES, Collateral.ISOLATED) + # (TradingMode.FUTURES, MarginMode.CROSS), + # (TradingMode.FUTURES, MarginMode.ISOLATED) ] diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 8ca92df51..4c5cf0226 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -22,7 +22,7 @@ from pandas import DataFrame from freqtrade.constants import (DEFAULT_AMOUNT_RESERVE_PERCENT, NON_OPEN_EXCHANGE_STATES, ListPairsWithTimeframes, PairWithTimeframe) from freqtrade.data.converter import ohlcv_to_dataframe, trades_dict_to_list -from freqtrade.enums import CandleType, Collateral, TradingMode +from freqtrade.enums import CandleType, MarginMode, TradingMode from freqtrade.exceptions import (DDosProtection, ExchangeError, InsufficientFundsError, InvalidOrderException, OperationalException, PricingError, RetryableOrderError, TemporaryError) @@ -77,7 +77,7 @@ class Exchange: } _ft_has: Dict = {} - _supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [ + _supported_trading_mode_margin_pairs: List[Tuple[TradingMode, MarginMode]] = [ # TradingMode.SPOT always supported and not required in this list ] @@ -137,9 +137,9 @@ class Exchange: self.trading_mode = TradingMode(config.get('trading_mode', 'spot')) - self.collateral: Optional[Collateral] = ( - Collateral(config.get('collateral')) - if config.get('collateral') + self.margin_mode: Optional[MarginMode] = ( + MarginMode(config.get('margin_mode')) + if config.get('margin_mode') else None ) @@ -175,7 +175,7 @@ class Exchange: self.validate_order_time_in_force(config.get('order_time_in_force', {})) self.required_candle_call_count = self.validate_required_startup_candles( config.get('startup_candle_count', 0), config.get('timeframe', '')) - self.validate_trading_mode_and_collateral(self.trading_mode, self.collateral) + self.validate_trading_mode_and_margin_mode(self.trading_mode, self.margin_mode) # Converts the interval provided in minutes in config to seconds self.markets_refresh_interval: int = exchange_config.get( @@ -599,23 +599,23 @@ class Exchange: f"if you really need {startup_candles} candles for your strategy") return required_candle_call_count - def validate_trading_mode_and_collateral( + def validate_trading_mode_and_margin_mode( self, trading_mode: TradingMode, - collateral: Optional[Collateral] # Only None when trading_mode = TradingMode.SPOT + margin_mode: Optional[MarginMode] # Only None when trading_mode = TradingMode.SPOT ): """ Checks if freqtrade can perform trades using the configured - trading mode(Margin, Futures) and Collateral(Cross, Isolated) + trading mode(Margin, Futures) and MarginMode(Cross, Isolated) Throws OperationalException: - If the trading_mode/collateral type are not supported by freqtrade on this exchange + If the trading_mode/margin_mode type are not supported by freqtrade on this exchange """ if trading_mode != TradingMode.SPOT and ( - (trading_mode, collateral) not in self._supported_trading_mode_collateral_pairs + (trading_mode, margin_mode) not in self._supported_trading_mode_margin_pairs ): - collateral_value = collateral and collateral.value + mm_value = margin_mode and margin_mode.value raise OperationalException( - f"Freqtrade does not support {collateral_value} {trading_mode.value} on {self.name}" + f"Freqtrade does not support {mm_value} {trading_mode.value} on {self.name}" ) def exchange_has(self, endpoint: str) -> bool: @@ -879,7 +879,7 @@ class Exchange: def _lev_prep(self, pair: str, leverage: float): if self.trading_mode != TradingMode.SPOT: - self.set_margin_mode(pair, self.collateral) + self.set_margin_mode(pair, self.margin_mode) self._set_leverage(leverage, pair) def _get_params(self, ordertype: str, leverage: float, time_in_force: str = 'gtc') -> Dict: @@ -1810,7 +1810,7 @@ class Exchange: """ Returns the maximum leverage that a pair can be traded at :param pair: The base/quote currency pair being traded - :param nominal_value: The total value of the trade in quote currency (collateral + debt) + :param nominal_value: The total value of the trade in quote currency (margin_mode + debt) """ market = self.markets[pair] if market['limits']['leverage']['max'] is not None: @@ -1830,7 +1830,7 @@ class Exchange: have the same leverage on every trade """ if self._config['dry_run'] or not self.exchange_has("setLeverage"): - # Some exchanges only support one collateral type + # Some exchanges only support one margin_mode type return try: @@ -1851,17 +1851,17 @@ class Exchange: return open_date.minute > 0 or open_date.second > 0 @retrier - def set_margin_mode(self, pair: str, collateral: Collateral, params: dict = {}): + def set_margin_mode(self, pair: str, margin_mode: MarginMode, params: dict = {}): """ Set's the margin mode on the exchange to cross or isolated for a specific pair :param pair: base/quote currency pair (e.g. "ADA/USDT") """ if self._config['dry_run'] or not self.exchange_has("setMarginMode"): - # Some exchanges only support one collateral type + # Some exchanges only support one margin_mode type return try: - self._api.set_margin_mode(pair, collateral.value, params) + self._api.set_margin_mode(pair, margin_mode.value, params) except ccxt.DDoSProtection as e: raise DDosProtection(e) from e except (ccxt.NetworkError, ccxt.ExchangeError) as e: @@ -2000,11 +2000,11 @@ class Exchange: """ if self.trading_mode == TradingMode.SPOT: return None - elif (self.collateral is None): - raise OperationalException(f'{self.name}.collateral must be set for liquidation_price') - elif (self.trading_mode != TradingMode.FUTURES and self.collateral != Collateral.ISOLATED): + elif (self.margin_mode is None): + raise OperationalException(f'{self.name}.margin_mode must be set for liquidation_price') + elif (self.trading_mode != TradingMode.FUTURES and self.margin_mode != MarginMode.ISOLATED): raise OperationalException( - f"{self.name} does not support {self.collateral.value} {self.trading_mode.value}") + f"{self.name} does not support {self.margin_mode.value} {self.trading_mode.value}") if self._config['dry_run'] or not self.exchange_has("fetchPositions"): @@ -2064,8 +2064,8 @@ class Exchange: :param is_short: True if the trade is a short, false otherwise :param position: Absolute value of position size incl. leverage (in base currency) :param trading_mode: SPOT, MARGIN, FUTURES, etc. - :param collateral: Either ISOLATED or CROSS - :param wallet_balance: Amount of collateral in the wallet being used to trade + :param margin_mode: Either ISOLATED or CROSS + :param wallet_balance: Amount of margin_mode in the wallet being used to trade Cross-Margin Mode: crossWalletBalance Isolated-Margin Mode: isolatedWalletBalance @@ -2078,7 +2078,7 @@ class Exchange: taker_fee_rate = market['taker'] mm_ratio, _ = self.get_maintenance_ratio_and_amt(pair, position) - if self.trading_mode == TradingMode.FUTURES and self.collateral == Collateral.ISOLATED: + if self.trading_mode == TradingMode.FUTURES and self.margin_mode == MarginMode.ISOLATED: if market['inverse']: raise OperationalException( diff --git a/freqtrade/exchange/ftx.py b/freqtrade/exchange/ftx.py index e28c6bc45..88e906a56 100644 --- a/freqtrade/exchange/ftx.py +++ b/freqtrade/exchange/ftx.py @@ -4,7 +4,7 @@ from typing import Any, Dict, List, Tuple import ccxt -from freqtrade.enums import Collateral, TradingMode +from freqtrade.enums import MarginMode, TradingMode from freqtrade.exceptions import (DDosProtection, InsufficientFundsError, InvalidOrderException, OperationalException, TemporaryError) from freqtrade.exchange import Exchange @@ -25,10 +25,10 @@ class Ftx(Exchange): "mark_ohlcv_timeframe": "1h", } - _supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [ + _supported_trading_mode_margin_pairs: List[Tuple[TradingMode, MarginMode]] = [ # TradingMode.SPOT always supported and not required in this list - # (TradingMode.MARGIN, Collateral.CROSS), - # (TradingMode.FUTURES, Collateral.CROSS) + # (TradingMode.MARGIN, MarginMode.CROSS), + # (TradingMode.FUTURES, MarginMode.CROSS) ] def stoploss_adjust(self, stop_loss: float, order: Dict, side: str) -> bool: diff --git a/freqtrade/exchange/gateio.py b/freqtrade/exchange/gateio.py index c62b6222d..bcb4cce33 100644 --- a/freqtrade/exchange/gateio.py +++ b/freqtrade/exchange/gateio.py @@ -2,7 +2,7 @@ import logging from typing import Dict, List, Optional, Tuple -from freqtrade.enums import Collateral, TradingMode +from freqtrade.enums import MarginMode, TradingMode from freqtrade.exceptions import OperationalException from freqtrade.exchange import Exchange @@ -27,11 +27,11 @@ class Gateio(Exchange): _headers = {'X-Gate-Channel-Id': 'freqtrade'} - _supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [ + _supported_trading_mode_margin_pairs: List[Tuple[TradingMode, MarginMode]] = [ # TradingMode.SPOT always supported and not required in this list - # (TradingMode.MARGIN, Collateral.CROSS), - # (TradingMode.FUTURES, Collateral.CROSS), - (TradingMode.FUTURES, Collateral.ISOLATED) + # (TradingMode.MARGIN, MarginMode.CROSS), + # (TradingMode.FUTURES, MarginMode.CROSS), + (TradingMode.FUTURES, MarginMode.ISOLATED) ] def validate_ordertypes(self, order_types: Dict) -> None: diff --git a/freqtrade/exchange/kraken.py b/freqtrade/exchange/kraken.py index d96f171e1..308a6feab 100644 --- a/freqtrade/exchange/kraken.py +++ b/freqtrade/exchange/kraken.py @@ -6,7 +6,7 @@ from typing import Any, Dict, List, Optional, Tuple import ccxt from pandas import DataFrame -from freqtrade.enums import Collateral, TradingMode +from freqtrade.enums import MarginMode, TradingMode from freqtrade.exceptions import (DDosProtection, InsufficientFundsError, InvalidOrderException, OperationalException, TemporaryError) from freqtrade.exchange import Exchange @@ -27,10 +27,10 @@ class Kraken(Exchange): "mark_ohlcv_timeframe": "4h", } - _supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [ + _supported_trading_mode_margin_pairs: List[Tuple[TradingMode, MarginMode]] = [ # TradingMode.SPOT always supported and not required in this list - # (TradingMode.MARGIN, Collateral.CROSS), - # (TradingMode.FUTURES, Collateral.CROSS) + # (TradingMode.MARGIN, MarginMode.CROSS), + # (TradingMode.FUTURES, MarginMode.CROSS) ] def market_is_tradable(self, market: Dict[str, Any]) -> bool: diff --git a/freqtrade/exchange/okex.py b/freqtrade/exchange/okex.py index 7e9348f0c..b6252ed1e 100644 --- a/freqtrade/exchange/okex.py +++ b/freqtrade/exchange/okex.py @@ -1,7 +1,7 @@ import logging from typing import Dict, List, Tuple -from freqtrade.enums import Collateral, TradingMode +from freqtrade.enums import MarginMode, TradingMode from freqtrade.exchange import Exchange @@ -20,9 +20,9 @@ class Okex(Exchange): "funding_fee_timeframe": "8h", } - _supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [ + _supported_trading_mode_margin_pairs: List[Tuple[TradingMode, MarginMode]] = [ # TradingMode.SPOT always supported and not required in this list - # (TradingMode.MARGIN, Collateral.CROSS), - # (TradingMode.FUTURES, Collateral.CROSS), - # (TradingMode.FUTURES, Collateral.ISOLATED) + # (TradingMode.MARGIN, MarginMode.CROSS), + # (TradingMode.FUTURES, MarginMode.CROSS), + # (TradingMode.FUTURES, MarginMode.ISOLATED) ] diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index ad5bc0fb6..38d80ab7a 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -16,7 +16,7 @@ from freqtrade.configuration import validate_config_consistency from freqtrade.data.converter import order_book_to_dataframe from freqtrade.data.dataprovider import DataProvider from freqtrade.edge import Edge -from freqtrade.enums import (Collateral, RPCMessageType, RunMode, SellType, SignalDirection, State, +from freqtrade.enums import (MarginMode, RPCMessageType, RunMode, SellType, SignalDirection, State, TradingMode) from freqtrade.exceptions import (DependencyException, ExchangeError, InsufficientFundsError, InvalidOrderException, OperationalException, PricingError) @@ -105,9 +105,9 @@ class FreqtradeBot(LoggingMixin): self.trading_mode = TradingMode(self.config.get('trading_mode', 'spot')) - self.collateral_type: Optional[Collateral] = None - if 'collateral' in self.config: - self.collateral_type = Collateral(self.config['collateral']) + self.margin_mode_type: Optional[MarginMode] = None + if 'margin_mode' in self.config: + self.margin_mode = MarginMode(self.config['margin_mode']) self._schedule = Scheduler() @@ -615,7 +615,7 @@ class FreqtradeBot(LoggingMixin): if self.trading_mode == TradingMode.SPOT: return (0.0, None) elif ( - self.collateral_type == Collateral.ISOLATED and + self.margin_mode == MarginMode.ISOLATED and self.trading_mode == TradingMode.FUTURES ): wallet_balance = (amount * open_rate)/leverage diff --git a/tests/conftest.py b/tests/conftest.py index de1f44e89..15705e987 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -17,7 +17,7 @@ from freqtrade import constants from freqtrade.commands import Arguments from freqtrade.data.converter import ohlcv_to_dataframe from freqtrade.edge import PairInfo -from freqtrade.enums import CandleType, Collateral, RunMode, SignalDirection, TradingMode +from freqtrade.enums import CandleType, MarginMode, RunMode, SignalDirection, TradingMode from freqtrade.exchange import Exchange from freqtrade.freqtradebot import FreqtradeBot from freqtrade.persistence import LocalTrade, Trade, init_db @@ -115,12 +115,12 @@ def patch_exchange( if mock_supported_modes: mocker.patch( - f'freqtrade.exchange.{id.capitalize()}._supported_trading_mode_collateral_pairs', + f'freqtrade.exchange.{id.capitalize()}._supported_trading_mode_margin_pairs', PropertyMock(return_value=[ - (TradingMode.MARGIN, Collateral.CROSS), - (TradingMode.MARGIN, Collateral.ISOLATED), - (TradingMode.FUTURES, Collateral.CROSS), - (TradingMode.FUTURES, Collateral.ISOLATED) + (TradingMode.MARGIN, MarginMode.CROSS), + (TradingMode.MARGIN, MarginMode.ISOLATED), + (TradingMode.FUTURES, MarginMode.CROSS), + (TradingMode.FUTURES, MarginMode.ISOLATED) ]) ) diff --git a/tests/exchange/test_binance.py b/tests/exchange/test_binance.py index 00a2369bb..5bd383d6e 100644 --- a/tests/exchange/test_binance.py +++ b/tests/exchange/test_binance.py @@ -5,7 +5,7 @@ from unittest.mock import MagicMock, PropertyMock import ccxt import pytest -from freqtrade.enums import Collateral, TradingMode +from freqtrade.enums import MarginMode, TradingMode from freqtrade.exceptions import DependencyException, InvalidOrderException, OperationalException from tests.conftest import get_mock_coro, get_patched_exchange, log_has_re from tests.exchange.test_exchange import ccxt_exceptionhandlers @@ -236,7 +236,7 @@ def test_fill_leverage_brackets_binance(default_conf, mocker): }) default_conf['dry_run'] = False default_conf['trading_mode'] = TradingMode.FUTURES - default_conf['collateral'] = Collateral.ISOLATED + default_conf['margin_mode'] = MarginMode.ISOLATED exchange = get_patched_exchange(mocker, default_conf, api_mock, id="binance") exchange.fill_leverage_brackets() @@ -282,7 +282,7 @@ def test_fill_leverage_brackets_binance(default_conf, mocker): def test_fill_leverage_brackets_binance_dryrun(default_conf, mocker): api_mock = MagicMock() default_conf['trading_mode'] = TradingMode.FUTURES - default_conf['collateral'] = Collateral.ISOLATED + default_conf['margin_mode'] = MarginMode.ISOLATED exchange = get_patched_exchange(mocker, default_conf, api_mock, id="binance") exchange.fill_leverage_brackets() @@ -385,14 +385,14 @@ async def test__async_get_historic_ohlcv_binance(default_conf, mocker, caplog, c assert log_has_re(r"Candle-data for ETH/BTC available starting with .*", caplog) -@pytest.mark.parametrize("trading_mode,collateral,config", [ +@pytest.mark.parametrize("trading_mode,margin_mode,config", [ ("spot", "", {}), ("margin", "cross", {"options": {"defaultType": "margin"}}), ("futures", "isolated", {"options": {"defaultType": "future"}}), ]) -def test__ccxt_config(default_conf, mocker, trading_mode, collateral, config): +def test__ccxt_config(default_conf, mocker, trading_mode, margin_mode, config): default_conf['trading_mode'] = trading_mode - default_conf['collateral'] = collateral + default_conf['margin_mode'] = margin_mode exchange = get_patched_exchange(mocker, default_conf, id="binance") assert exchange._ccxt_config == config diff --git a/tests/exchange/test_ccxt_compat.py b/tests/exchange/test_ccxt_compat.py index a799bc302..e9b78af44 100644 --- a/tests/exchange/test_ccxt_compat.py +++ b/tests/exchange/test_ccxt_compat.py @@ -104,12 +104,12 @@ def exchange_futures(request, exchange_conf, class_mocker): exchange_conf = deepcopy(exchange_conf) exchange_conf['exchange']['name'] = request.param exchange_conf['trading_mode'] = 'futures' - exchange_conf['collateral'] = 'cross' + exchange_conf['margin_mode'] = 'cross' exchange_conf['stake_currency'] = EXCHANGES[request.param]['stake_currency'] # TODO-lev: This mock should no longer be necessary once futures are enabled. class_mocker.patch( - 'freqtrade.exchange.exchange.Exchange.validate_trading_mode_and_collateral') + 'freqtrade.exchange.exchange.Exchange.validate_trading_mode_and_margin_mode') class_mocker.patch( 'freqtrade.exchange.binance.Binance.fill_leverage_brackets') diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index a6d319687..ae94ae102 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -11,7 +11,7 @@ import ccxt import pytest from pandas import DataFrame -from freqtrade.enums import CandleType, Collateral, TradingMode +from freqtrade.enums import CandleType, MarginMode, TradingMode from freqtrade.exceptions import (DDosProtection, DependencyException, InvalidOrderException, OperationalException, PricingError, TemporaryError) from freqtrade.exchange import Binance, Bittrex, Exchange, Kraken @@ -263,7 +263,7 @@ def test_amount_to_precision( }) default_conf['trading_mode'] = trading_mode - default_conf['collateral'] = 'isolated' + default_conf['margin_mode'] = 'isolated' exchange = get_patched_exchange(mocker, default_conf, id="binance") # digits counting mode @@ -473,7 +473,7 @@ def test_get_min_pair_stake_amount(mocker, default_conf) -> None: markets["ETH/BTC"]["contractSize"] = '0.01' default_conf['trading_mode'] = 'futures' - default_conf['collateral'] = 'isolated' + default_conf['margin_mode'] = 'isolated' exchange = get_patched_exchange(mocker, default_conf, id="binance") mocker.patch( 'freqtrade.exchange.Exchange.markets', @@ -1165,7 +1165,7 @@ def test_create_order(default_conf, mocker, side, ordertype, rate, marketprice, 'amount': 1 }) default_conf['dry_run'] = False - default_conf['collateral'] = 'isolated' + default_conf['margin_mode'] = 'isolated' mocker.patch('freqtrade.exchange.Exchange.amount_to_precision', lambda s, x, y: y) mocker.patch('freqtrade.exchange.Exchange.price_to_precision', lambda s, x, y: y) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) @@ -2334,7 +2334,7 @@ async def test__async_fetch_trades(default_conf, mocker, caplog, exchange_name, async def test__async_fetch_trades_contract_size(default_conf, mocker, caplog, exchange_name, fetch_trades_result): caplog.set_level(logging.DEBUG) - default_conf['collateral'] = 'isolated' + default_conf['margin_mode'] = 'isolated' default_conf['trading_mode'] = 'futures' exchange = get_patched_exchange(mocker, default_conf, id=exchange_name) # Monkey-patch async function @@ -2796,7 +2796,7 @@ def test_get_trades_for_order(default_conf, mocker, exchange_name, trading_mode, since = datetime(2018, 5, 5, 0, 0, 0) default_conf["dry_run"] = False default_conf["trading_mode"] = trading_mode - default_conf["collateral"] = 'isolated' + default_conf["margin_mode"] = 'isolated' mocker.patch('freqtrade.exchange.Exchange.exchange_has', return_value=True) api_mock = MagicMock() @@ -3170,7 +3170,7 @@ def test_market_is_tradable( quote, spot, margin, futures, trademode, add_dict, exchange, expected_result ) -> None: default_conf['trading_mode'] = trademode - mocker.patch('freqtrade.exchange.exchange.Exchange.validate_trading_mode_and_collateral') + mocker.patch('freqtrade.exchange.exchange.Exchange.validate_trading_mode_and_margin_mode') ex = get_patched_exchange(mocker, default_conf, id=exchange) market = { 'symbol': market_symbol, @@ -3400,11 +3400,11 @@ def test__set_leverage(mocker, default_conf, exchange_name, trading_mode): ) -@pytest.mark.parametrize("collateral", [ - (Collateral.CROSS), - (Collateral.ISOLATED) +@pytest.mark.parametrize("margin_mode", [ + (MarginMode.CROSS), + (MarginMode.ISOLATED) ]) -def test_set_margin_mode(mocker, default_conf, collateral): +def test_set_margin_mode(mocker, default_conf, margin_mode): api_mock = MagicMock() api_mock.set_margin_mode = MagicMock() @@ -3419,70 +3419,70 @@ def test_set_margin_mode(mocker, default_conf, collateral): "set_margin_mode", "set_margin_mode", pair="XRP/USDT", - collateral=collateral + margin_mode=margin_mode ) -@pytest.mark.parametrize("exchange_name, trading_mode, collateral, exception_thrown", [ +@pytest.mark.parametrize("exchange_name, trading_mode, margin_mode, exception_thrown", [ ("binance", TradingMode.SPOT, None, False), - ("binance", TradingMode.MARGIN, Collateral.ISOLATED, True), + ("binance", TradingMode.MARGIN, MarginMode.ISOLATED, True), ("kraken", TradingMode.SPOT, None, False), - ("kraken", TradingMode.MARGIN, Collateral.ISOLATED, True), - ("kraken", TradingMode.FUTURES, Collateral.ISOLATED, True), + ("kraken", TradingMode.MARGIN, MarginMode.ISOLATED, True), + ("kraken", TradingMode.FUTURES, MarginMode.ISOLATED, True), ("ftx", TradingMode.SPOT, None, False), - ("ftx", TradingMode.MARGIN, Collateral.ISOLATED, True), - ("ftx", TradingMode.FUTURES, Collateral.ISOLATED, True), + ("ftx", TradingMode.MARGIN, MarginMode.ISOLATED, True), + ("ftx", TradingMode.FUTURES, MarginMode.ISOLATED, True), ("bittrex", TradingMode.SPOT, None, False), - ("bittrex", TradingMode.MARGIN, Collateral.CROSS, True), - ("bittrex", TradingMode.MARGIN, Collateral.ISOLATED, True), - ("bittrex", TradingMode.FUTURES, Collateral.CROSS, True), - ("bittrex", TradingMode.FUTURES, Collateral.ISOLATED, True), - ("gateio", TradingMode.MARGIN, Collateral.ISOLATED, True), + ("bittrex", TradingMode.MARGIN, MarginMode.CROSS, True), + ("bittrex", TradingMode.MARGIN, MarginMode.ISOLATED, True), + ("bittrex", TradingMode.FUTURES, MarginMode.CROSS, True), + ("bittrex", TradingMode.FUTURES, MarginMode.ISOLATED, True), + ("gateio", TradingMode.MARGIN, MarginMode.ISOLATED, True), ("okex", TradingMode.SPOT, None, False), - ("okex", TradingMode.MARGIN, Collateral.CROSS, True), - ("okex", TradingMode.MARGIN, Collateral.ISOLATED, True), - ("okex", TradingMode.FUTURES, Collateral.CROSS, True), + ("okex", TradingMode.MARGIN, MarginMode.CROSS, True), + ("okex", TradingMode.MARGIN, MarginMode.ISOLATED, True), + ("okex", TradingMode.FUTURES, MarginMode.CROSS, True), - ("binance", TradingMode.FUTURES, Collateral.ISOLATED, False), - ("gateio", TradingMode.FUTURES, Collateral.ISOLATED, False), + ("binance", TradingMode.FUTURES, MarginMode.ISOLATED, False), + ("gateio", TradingMode.FUTURES, MarginMode.ISOLATED, False), # * Remove once implemented - ("okex", TradingMode.FUTURES, Collateral.ISOLATED, True), - ("binance", TradingMode.MARGIN, Collateral.CROSS, True), - ("binance", TradingMode.FUTURES, Collateral.CROSS, True), - ("kraken", TradingMode.MARGIN, Collateral.CROSS, True), - ("kraken", TradingMode.FUTURES, Collateral.CROSS, True), - ("ftx", TradingMode.MARGIN, Collateral.CROSS, True), - ("ftx", TradingMode.FUTURES, Collateral.CROSS, True), - ("gateio", TradingMode.MARGIN, Collateral.CROSS, True), - ("gateio", TradingMode.FUTURES, Collateral.CROSS, True), + ("okex", TradingMode.FUTURES, MarginMode.ISOLATED, True), + ("binance", TradingMode.MARGIN, MarginMode.CROSS, True), + ("binance", TradingMode.FUTURES, MarginMode.CROSS, True), + ("kraken", TradingMode.MARGIN, MarginMode.CROSS, True), + ("kraken", TradingMode.FUTURES, MarginMode.CROSS, True), + ("ftx", TradingMode.MARGIN, MarginMode.CROSS, True), + ("ftx", TradingMode.FUTURES, MarginMode.CROSS, True), + ("gateio", TradingMode.MARGIN, MarginMode.CROSS, True), + ("gateio", TradingMode.FUTURES, MarginMode.CROSS, True), # * Uncomment once implemented - # ("okex", TradingMode.FUTURES, Collateral.ISOLATED, False), - # ("binance", TradingMode.MARGIN, Collateral.CROSS, False), - # ("binance", TradingMode.FUTURES, Collateral.CROSS, False), - # ("kraken", TradingMode.MARGIN, Collateral.CROSS, False), - # ("kraken", TradingMode.FUTURES, Collateral.CROSS, False), - # ("ftx", TradingMode.MARGIN, Collateral.CROSS, False), - # ("ftx", TradingMode.FUTURES, Collateral.CROSS, False), - # ("gateio", TradingMode.MARGIN, Collateral.CROSS, False), - # ("gateio", TradingMode.FUTURES, Collateral.CROSS, False), + # ("okex", TradingMode.FUTURES, MarginMode.ISOLATED, False), + # ("binance", TradingMode.MARGIN, MarginMode.CROSS, False), + # ("binance", TradingMode.FUTURES, MarginMode.CROSS, False), + # ("kraken", TradingMode.MARGIN, MarginMode.CROSS, False), + # ("kraken", TradingMode.FUTURES, MarginMode.CROSS, False), + # ("ftx", TradingMode.MARGIN, MarginMode.CROSS, False), + # ("ftx", TradingMode.FUTURES, MarginMode.CROSS, False), + # ("gateio", TradingMode.MARGIN, MarginMode.CROSS, False), + # ("gateio", TradingMode.FUTURES, MarginMode.CROSS, False), ]) -def test_validate_trading_mode_and_collateral( +def test_validate_trading_mode_and_margin_mode( default_conf, mocker, exchange_name, trading_mode, - collateral, + margin_mode, exception_thrown ): exchange = get_patched_exchange( mocker, default_conf, id=exchange_name, mock_supported_modes=False) if (exception_thrown): with pytest.raises(OperationalException): - exchange.validate_trading_mode_and_collateral(trading_mode, collateral) + exchange.validate_trading_mode_and_margin_mode(trading_mode, margin_mode) else: - exchange.validate_trading_mode_and_collateral(trading_mode, collateral) + exchange.validate_trading_mode_and_margin_mode(trading_mode, margin_mode) @pytest.mark.parametrize("exchange_name,trading_mode,ccxt_config", [ @@ -3508,7 +3508,7 @@ def test__ccxt_config( ccxt_config ): default_conf['trading_mode'] = trading_mode - default_conf['collateral'] = 'isolated' + default_conf['margin_mode'] = 'isolated' exchange = get_patched_exchange(mocker, default_conf, id=exchange_name) assert exchange._ccxt_config == ccxt_config @@ -3609,7 +3609,7 @@ def test_get_liquidation_price(mocker, default_conf): 'marginRatio': None, 'liquidationPrice': 17.47, 'markPrice': 18.89, - 'collateral': 1.52549075, + 'margin_mode': 1.52549075, 'marginType': 'isolated', 'side': 'buy', 'percentage': 0.003177292946409658 @@ -3622,7 +3622,7 @@ def test_get_liquidation_price(mocker, default_conf): ) default_conf['dry_run'] = False default_conf['trading_mode'] = 'futures' - default_conf['collateral'] = 'isolated' + default_conf['margin_mode'] = 'isolated' exchange = get_patched_exchange(mocker, default_conf, api_mock) liq_price = exchange.get_liquidation_price( @@ -3786,7 +3786,7 @@ def test__fetch_and_calculate_funding_fees_datetime_called( def test__get_contract_size(mocker, default_conf, pair, expected_size, trading_mode): api_mock = MagicMock() default_conf['trading_mode'] = trading_mode - default_conf['collateral'] = 'isolated' + default_conf['margin_mode'] = 'isolated' mocker.patch('freqtrade.exchange.Exchange.markets', { 'LTC/USD': { 'symbol': 'LTC/USD', @@ -3826,7 +3826,7 @@ def test__order_contracts_to_amount( ): api_mock = MagicMock() default_conf['trading_mode'] = trading_mode - default_conf['collateral'] = 'isolated' + default_conf['margin_mode'] = 'isolated' mocker.patch('freqtrade.exchange.Exchange.markets', markets) exchange = get_patched_exchange(mocker, default_conf, api_mock) @@ -3910,7 +3910,7 @@ def test__trades_contracts_to_amount( ): api_mock = MagicMock() default_conf['trading_mode'] = trading_mode - default_conf['collateral'] = 'isolated' + default_conf['margin_mode'] = 'isolated' mocker.patch('freqtrade.exchange.Exchange.markets', markets) exchange = get_patched_exchange(mocker, default_conf, api_mock) @@ -3946,7 +3946,7 @@ def test__amount_to_contracts( ): api_mock = MagicMock() default_conf['trading_mode'] = 'spot' - default_conf['collateral'] = 'isolated' + default_conf['margin_mode'] = 'isolated' mocker.patch('freqtrade.exchange.Exchange.markets', { 'LTC/USD': { 'symbol': 'LTC/USD', @@ -3978,7 +3978,7 @@ def test__amount_to_contracts( assert result_amount == param_amount -@pytest.mark.parametrize('exchange_name,open_rate,is_short,trading_mode,collateral', [ +@pytest.mark.parametrize('exchange_name,open_rate,is_short,trading_mode,margin_mode', [ # Bittrex ('bittrex', 2.0, False, 'spot', None), ('bittrex', 2.0, False, 'spot', 'cross'), @@ -3995,10 +3995,10 @@ def test_liquidation_price_is_none( open_rate, is_short, trading_mode, - collateral + margin_mode ): default_conf['trading_mode'] = trading_mode - default_conf['collateral'] = collateral + default_conf['margin_mode'] = margin_mode exchange = get_patched_exchange(mocker, default_conf, id=exchange_name) assert exchange.get_liquidation_price( pair='DOGE/USDT', @@ -4012,7 +4012,7 @@ def test_liquidation_price_is_none( @pytest.mark.parametrize( - 'exchange_name, is_short, trading_mode, collateral, wallet_balance, ' + 'exchange_name, is_short, trading_mode, margin_mode, wallet_balance, ' 'mm_ex_1, upnl_ex_1, maintenance_amt, position, open_rate, ' 'mm_ratio, expected', [ @@ -4027,10 +4027,10 @@ def test_liquidation_price_is_none( ]) def test_liquidation_price( mocker, default_conf, exchange_name, open_rate, is_short, trading_mode, - collateral, wallet_balance, mm_ex_1, upnl_ex_1, maintenance_amt, position, mm_ratio, expected + margin_mode, wallet_balance, mm_ex_1, upnl_ex_1, maintenance_amt, position, mm_ratio, expected ): default_conf['trading_mode'] = trading_mode - default_conf['collateral'] = collateral + default_conf['margin_mode'] = margin_mode exchange = get_patched_exchange(mocker, default_conf, id=exchange_name) exchange.get_maintenance_ratio_and_amt = MagicMock(return_value=(mm_ratio, maintenance_amt)) assert isclose(round(exchange.get_liquidation_price( diff --git a/tests/optimize/test_backtesting.py b/tests/optimize/test_backtesting.py index 30cb3932d..ce58cf72a 100644 --- a/tests/optimize/test_backtesting.py +++ b/tests/optimize/test_backtesting.py @@ -1177,7 +1177,7 @@ def test_backtest_start_nomock_futures(default_conf_usdt, mocker, # Tests detail-data loading default_conf_usdt.update({ "trading_mode": "futures", - "collateral": "isolated", + "margin_mode": "isolated", "use_sell_signal": True, "sell_profit_only": False, "sell_profit_offset": 0.0, @@ -1495,7 +1495,7 @@ def test_get_strategy_run_id(default_conf_usdt): default_conf_usdt.update({ 'strategy': 'StrategyTestV2', 'max_open_trades': float('inf') - }) + }) strategy = StrategyResolver.load_strategy(default_conf_usdt) x = get_strategy_run_id(strategy) assert isinstance(x, str) diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index a2a3bebed..32b7d543b 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -749,7 +749,7 @@ def test_execute_entry(mocker, default_conf_usdt, fee, limit_order, leverage = 1.0 if trading_mode == 'spot' else 5.0 default_conf_usdt['exchange']['name'] = exchange_name if margin_mode: - default_conf_usdt['collateral'] = margin_mode + default_conf_usdt['margin_mode'] = margin_mode mocker.patch('freqtrade.exchange.Gateio.validate_ordertypes') patch_RPCManager(mocker) patch_exchange(mocker, id=exchange_name) @@ -4809,7 +4809,7 @@ def test_update_funding_fees_schedule(mocker, default_conf, trading_mode, calls, patch_exchange(mocker) mocker.patch('freqtrade.freqtradebot.FreqtradeBot.update_funding_fees', return_value=True) default_conf['trading_mode'] = trading_mode - default_conf['collateral'] = 'isolated' + default_conf['margin_mode'] = 'isolated' freqtrade = get_patched_freqtradebot(mocker, default_conf) time_machine.move_to(f"{t2} +00:00") @@ -4859,7 +4859,7 @@ def test_update_funding_fees( patch_RPCManager(mocker) patch_exchange(mocker) default_conf['trading_mode'] = 'futures' - default_conf['collateral'] = 'isolated' + default_conf['margin_mode'] = 'isolated' date_midnight = arrow.get('2021-09-01 00:00:00') date_eight = arrow.get('2021-09-01 08:00:00')