From f4a57b71e78f91dbbc0f880ffbb0eb314475dc75 Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Mon, 14 Feb 2022 16:53:29 -0600 Subject: [PATCH] Filled in test_load_leverage_tiers_okx --- freqtrade/exchange/exchange.py | 5 +- freqtrade/exchange/okx.py | 3 +- tests/conftest.py | 106 ++++++++++- tests/exchange/test_okx.py | 324 ++++++++++++++++++++------------- 4 files changed, 304 insertions(+), 134 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 8af81ad47..55c75ca0a 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -347,7 +347,10 @@ class Exchange: return self.markets.get(pair, {}).get('base', '') def market_is_future(self, market: Dict[str, Any]) -> bool: - return market.get(self._ft_has["ccxt_futures_name"], False) is True + return ( + market.get(self._ft_has["ccxt_futures_name"], False) is True and + market.get('linear', False) is True + ) def market_is_spot(self, market: Dict[str, Any]) -> bool: return market.get('spot', False) is True diff --git a/freqtrade/exchange/okx.py b/freqtrade/exchange/okx.py index bd2913932..09bb48aa6 100644 --- a/freqtrade/exchange/okx.py +++ b/freqtrade/exchange/okx.py @@ -77,7 +77,8 @@ class Okx(Exchange): tiers = {} for symbol in symbols: res = self._api.fetchLeverageTiers(symbol) - tiers[symbol] = res[symbol] + res_symbol = res[symbol] + tiers[symbol] = self.parse_leverage_tier(res[symbol]) return tiers else: diff --git a/tests/conftest.py b/tests/conftest.py index b22e45526..04c4fd70d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -891,7 +891,8 @@ def get_markets(): 'future': True, 'swap': True, 'margin': True, - 'linear': True, + 'linear': False, + 'inverse': True, 'type': 'spot', 'contractSize': None, 'taker': 0.0006, @@ -1286,7 +1287,108 @@ def get_markets(): 'strike': None, 'optionType': None, 'info': {} - } + }, + 'SOL/BUSD:BUSD': { + 'limits': { + 'leverage': {'min': None, 'max': None}, + 'amount': {'min': 1, 'max': 1000000}, + 'price': {'min': 0.04, 'max': 100000}, + 'cost': {'min': 5, 'max': None}, + 'market': {'min': 1, 'max': 1500} + }, + 'precision': {'amount': 0, 'price': 2, 'base': 8, 'quote': 8}, + 'tierBased': False, + 'percentage': True, + 'taker': 0.0004, + 'maker': 0.0002, + 'feeSide': 'get', + 'id': 'SOLBUSD', + 'lowercaseId': 'solbusd', + 'symbol': 'SOL/BUSD', + 'base': 'SOL', + 'quote': 'BUSD', + 'settle': 'BUSD', + 'baseId': 'SOL', + 'quoteId': 'BUSD', + 'settleId': 'BUSD', + 'type': 'future', + 'spot': False, + 'margin': False, + 'future': True, + 'delivery': False, + 'option': False, + 'active': True, + 'contract': True, + 'linear': True, + 'inverse': False, + 'contractSize': 1, + 'expiry': None, + 'expiryDatetime': None, + 'strike': None, + 'optionType': None, + 'info': { + 'symbol': 'SOLBUSD', + 'pair': 'SOLBUSD', + 'contractType': 'PERPETUAL', + 'deliveryDate': '4133404800000', + 'onboardDate': '1630566000000', + 'status': 'TRADING', + 'maintMarginPercent': '2.5000', + 'requiredMarginPercent': '5.0000', + 'baseAsset': 'SOL', + 'quoteAsset': 'BUSD', + 'marginAsset': 'BUSD', + 'pricePrecision': '4', + 'quantityPrecision': '0', + 'baseAssetPrecision': '8', + 'quotePrecision': '8', + 'underlyingType': 'COIN', + 'underlyingSubType': [], + 'settlePlan': '0', + 'triggerProtect': '0.0500', + 'liquidationFee': '0.005000', + 'marketTakeBound': '0.05', + 'filters': [ + { + 'minPrice': '0.0400', + 'maxPrice': '100000', + 'filterType': 'PRICE_FILTER', + 'tickSize': '0.0100' + }, + { + 'stepSize': '1', + 'filterType': 'LOT_SIZE', + 'maxQty': '1000000', + 'minQty': '1' + }, + { + 'stepSize': '1', + 'filterType': 'MARKET_LOT_SIZE', + 'maxQty': '1500', + 'minQty': '1' + }, + {'limit': '200', 'filterType': 'MAX_NUM_ORDERS'}, + {'limit': '10', 'filterType': 'MAX_NUM_ALGO_ORDERS'}, + {'notional': '5', 'filterType': 'MIN_NOTIONAL'}, + { + 'multiplierDown': '0.9500', + 'multiplierUp': '1.0500', + 'multiplierDecimal': '4', + 'filterType': 'PERCENT_PRICE' + } + ], + 'orderTypes': [ + 'LIMIT', + 'MARKET', + 'STOP', + 'STOP_MARKET', + 'TAKE_PROFIT', + 'TAKE_PROFIT_MARKET', + 'TRAILING_STOP_MARKET' + ], + 'timeInForce': ['GTC', 'IOC', 'FOK', 'GTX'] + } + }, } diff --git a/tests/exchange/test_okx.py b/tests/exchange/test_okx.py index f9a93c569..388d8b510 100644 --- a/tests/exchange/test_okx.py +++ b/tests/exchange/test_okx.py @@ -1,6 +1,7 @@ from unittest.mock import MagicMock # , PropertyMock from tests.conftest import get_patched_exchange +from freqtrade.enums import TradingMode, MarginMode def test_get_maintenance_ratio_and_amt_okx( @@ -169,133 +170,196 @@ def test_get_max_pair_stake_amount_okx(default_conf, mocker, leverage_tiers): assert exchange.get_max_pair_stake_amount('TTT/USDT', 1.0) == float('inf') # Not in tiers -# def test_load_leverage_tiers_okx(default_conf, mocker): -# mocker.patch.multiple( -# 'freqtrade.exchange.okx', -# load_leverage_tiers=MagicMock(return_value={ -# 'ETH/USDT:USDT': [ -# { -# 'tier': 1, -# 'notionalFloor': 0, -# 'notionalCap': 2000, -# 'maintenanceMarginRatio': 0.01, -# 'maxLeverage': 75, -# 'info': { -# 'baseMaxLoan': '', -# 'imr': '0.013', -# 'instId': '', -# 'maxLever': '75', -# 'maxSz': '2000', -# 'minSz': '0', -# 'mmr': '0.01', -# 'optMgnFactor': '0', -# 'quoteMaxLoan': '', -# 'tier': '1', -# 'uly': 'ETH-USDT' -# } -# }, -# { -# 'tier': 2, -# 'notionalFloor': 2001, -# 'notionalCap': 4000, -# 'maintenanceMarginRatio': 0.015, -# 'maxLeverage': 50, -# 'info': { -# 'baseMaxLoan': '', -# 'imr': '0.02', -# 'instId': '', -# 'maxLever': '50', -# 'maxSz': '4000', -# 'minSz': '2001', -# 'mmr': '0.015', -# 'optMgnFactor': '0', -# 'quoteMaxLoan': '', -# 'tier': '2', -# 'uly': 'ETH-USDT' -# } -# }, -# { -# 'tier': 3, -# 'notionalFloor': 4001, -# 'notionalCap': 8000, -# 'maintenanceMarginRatio': 0.02, -# 'maxLeverage': 20, -# 'info': { -# 'baseMaxLoan': '', -# 'imr': '0.05', -# 'instId': '', -# 'maxLever': '20', -# 'maxSz': '8000', -# 'minSz': '4001', -# 'mmr': '0.02', -# 'optMgnFactor': '0', -# 'quoteMaxLoan': '', -# 'tier': '3', -# 'uly': 'ETH-USDT' -# } -# }, -# ], -# 'ADA/USDT:USDT': [ -# { -# 'tier': 1, -# 'notionalFloor': 0, -# 'notionalCap': 500, -# 'maintenanceMarginRatio': 0.02, -# 'maxLeverage': 75, -# 'info': { -# 'baseMaxLoan': '', -# 'imr': '0.013', -# 'instId': '', -# 'maxLever': '75', -# 'maxSz': '500', -# 'minSz': '0', -# 'mmr': '0.01', -# 'optMgnFactor': '0', -# 'quoteMaxLoan': '', -# 'tier': '1', -# 'uly': 'ADA-USDT' -# } -# }, -# { -# 'tier': 2, -# 'notionalFloor': 501, -# 'notionalCap': 1000, -# 'maintenanceMarginRatio': 0.025, -# 'maxLeverage': 50, -# 'info': { -# 'baseMaxLoan': '', -# 'imr': '0.02', -# 'instId': '', -# 'maxLever': '50', -# 'maxSz': '1000', -# 'minSz': '501', -# 'mmr': '0.015', -# 'optMgnFactor': '0', -# 'quoteMaxLoan': '', -# 'tier': '2', -# 'uly': 'ADA-USDT' -# } -# }, -# { -# 'tier': 3, -# 'notionalFloor': 1001, -# 'notionalCap': 2000, -# 'maintenanceMarginRatio': 0.03, -# 'maxLeverage': 20, -# 'info': { -# 'baseMaxLoan': '', -# 'imr': '0.05', -# 'instId': '', -# 'maxLever': '20', -# 'maxSz': '2000', -# 'minSz': '1001', -# 'mmr': '0.02', -# 'optMgnFactor': '0', -# 'quoteMaxLoan': '', -# 'tier': '3', -# 'uly': 'ADA-USDT' -# } -# }, -# ] -# }) -# ) +def test_load_leverage_tiers_okx(default_conf, mocker, markets): + api_mock = MagicMock() + api_mock.fetch_leverage_tiers = MagicMock(side_effect=[ + { + 'ADA/USDT:USDT': [ + { + 'tier': 1, + 'notionalFloor': 0, + 'notionalCap': 500, + 'maintenanceMarginRatio': 0.02, + 'maxLeverage': 75, + 'info': { + 'baseMaxLoan': '', + 'imr': '0.013', + 'instId': '', + 'maxLever': '75', + 'maxSz': '500', + 'minSz': '0', + 'mmr': '0.01', + 'optMgnFactor': '0', + 'quoteMaxLoan': '', + 'tier': '1', + 'uly': 'ADA-USDT' + } + }, + { + 'tier': 2, + 'notionalFloor': 501, + 'notionalCap': 1000, + 'maintenanceMarginRatio': 0.025, + 'maxLeverage': 50, + 'info': { + 'baseMaxLoan': '', + 'imr': '0.02', + 'instId': '', + 'maxLever': '50', + 'maxSz': '1000', + 'minSz': '501', + 'mmr': '0.015', + 'optMgnFactor': '0', + 'quoteMaxLoan': '', + 'tier': '2', + 'uly': 'ADA-USDT' + } + }, + { + 'tier': 3, + 'notionalFloor': 1001, + 'notionalCap': 2000, + 'maintenanceMarginRatio': 0.03, + 'maxLeverage': 20, + 'info': { + 'baseMaxLoan': '', + 'imr': '0.05', + 'instId': '', + 'maxLever': '20', + 'maxSz': '2000', + 'minSz': '1001', + 'mmr': '0.02', + 'optMgnFactor': '0', + 'quoteMaxLoan': '', + 'tier': '3', + 'uly': 'ADA-USDT' + } + }, + ] + }, + { + 'ETH/USDT:USDT': [ + { + 'tier': 1, + 'notionalFloor': 0, + 'notionalCap': 2000, + 'maintenanceMarginRatio': 0.01, + 'maxLeverage': 75, + 'info': { + 'baseMaxLoan': '', + 'imr': '0.013', + 'instId': '', + 'maxLever': '75', + 'maxSz': '2000', + 'minSz': '0', + 'mmr': '0.01', + 'optMgnFactor': '0', + 'quoteMaxLoan': '', + 'tier': '1', + 'uly': 'ETH-USDT' + } + }, + { + 'tier': 2, + 'notionalFloor': 2001, + 'notionalCap': 4000, + 'maintenanceMarginRatio': 0.015, + 'maxLeverage': 50, + 'info': { + 'baseMaxLoan': '', + 'imr': '0.02', + 'instId': '', + 'maxLever': '50', + 'maxSz': '4000', + 'minSz': '2001', + 'mmr': '0.015', + 'optMgnFactor': '0', + 'quoteMaxLoan': '', + 'tier': '2', + 'uly': 'ETH-USDT' + } + }, + { + 'tier': 3, + 'notionalFloor': 4001, + 'notionalCap': 8000, + 'maintenanceMarginRatio': 0.02, + 'maxLeverage': 20, + 'info': { + 'baseMaxLoan': '', + 'imr': '0.05', + 'instId': '', + 'maxLever': '20', + 'maxSz': '8000', + 'minSz': '4001', + 'mmr': '0.02', + 'optMgnFactor': '0', + 'quoteMaxLoan': '', + 'tier': '3', + 'uly': 'ETH-USDT' + } + }, + ] + }, + ]) + default_conf['trading_mode'] = 'futures' + default_conf['margin_mode'] = 'isolated' + default_conf['stake_currency'] = 'USDT' + exchange = get_patched_exchange(mocker, default_conf, api_mock, id="okx") + exchange.trading_mode = TradingMode.FUTURES + exchange.margin_mode = MarginMode.ISOLATED + exchange.markets = markets + assert exchange.load_leverage_tiers() == { + 'ADA/USDT:USDT': [ + { + 'tier': 1, + 'min': 0, + 'max': 500, + 'mmr': 0.02, + 'lev': 75, + 'maintAmt': None + }, + { + 'tier': 2, + 'min': 501, + 'max': 1000, + 'mmr': 0.025, + 'lev': 50, + 'maintAmt': None + }, + { + 'tier': 3, + 'min': 1001, + 'max': 2000, + 'mmr': 0.03, + 'lev': 20, + 'maintAmt': None + }, + ], + 'ETH/USDT:USDT': [ + { + 'tier': 1, + 'min': 0, + 'max': 2000, + 'mmr': 0.01, + 'lev': 75, + 'maintAmt': None + }, + { + 'tier': 2, + 'min': 2001, + 'max': 4000, + 'mmr': 0.015, + 'lev': 50, + 'maintAmt': None + }, + { + 'tier': 3, + 'min': 4001, + 'max': 8000, + 'mmr': 0.02, + 'lev': 20, + 'maintAmt': None + }, + ], + }