From 3d86b184929bc6d9d6f2ca75548775a87c35367d Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Sat, 13 Nov 2021 05:00:47 -0600 Subject: [PATCH 1/9] Added property _ft_has_default.ccxt_futures_name and removed subclass ccxt_config properties --- freqtrade/exchange/binance.py | 19 +------------------ freqtrade/exchange/bybit.py | 1 + freqtrade/exchange/exchange.py | 16 +++++++++++++++- freqtrade/exchange/gateio.py | 18 ------------------ freqtrade/exchange/okex.py | 18 ------------------ tests/exchange/test_exchange.py | 7 ------- 6 files changed, 17 insertions(+), 62 deletions(-) diff --git a/freqtrade/exchange/binance.py b/freqtrade/exchange/binance.py index c16566fde..9a707072d 100644 --- a/freqtrade/exchange/binance.py +++ b/freqtrade/exchange/binance.py @@ -27,6 +27,7 @@ class Binance(Exchange): "trades_pagination": "id", "trades_pagination_arg": "fromId", "l2_limit_range": [5, 10, 20, 50, 100, 500, 1000], + "ccxt_futures_name": "future" } funding_fee_times: List[int] = [0, 8, 16] # hours of the day # but the schedule won't check within this timeframe @@ -38,24 +39,6 @@ class Binance(Exchange): # (TradingMode.FUTURES, Collateral.ISOLATED) # TODO-lev: Uncomment once supported ] - @property - def _ccxt_config(self) -> Dict: - # Parameters to add directly to ccxt sync/async initialization. - if self.trading_mode == TradingMode.MARGIN: - return { - "options": { - "defaultType": "margin" - } - } - elif self.trading_mode == TradingMode.FUTURES: - return { - "options": { - "defaultType": "future" - } - } - else: - return {} - def stoploss_adjust(self, stop_loss: float, order: Dict, side: str) -> bool: """ Verify stop_loss against stoploss-order value (limit or price) diff --git a/freqtrade/exchange/bybit.py b/freqtrade/exchange/bybit.py index df19a671b..27deb79d7 100644 --- a/freqtrade/exchange/bybit.py +++ b/freqtrade/exchange/bybit.py @@ -21,6 +21,7 @@ class Bybit(Exchange): _ft_has: Dict = { "ohlcv_candle_limit": 200, + "ccxt_futures_name": "linear" } funding_fee_times: List[int] = [0, 8, 16] # hours of the day diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index cf7772600..5025d2396 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -69,6 +69,7 @@ class Exchange: "trades_pagination_arg": "since", "l2_limit_range": None, "l2_limit_range_required": True, # Allow Empty L2 limit (kucoin) + "ccxt_futures_name": "swap" } _ft_has: Dict = {} @@ -234,7 +235,20 @@ class Exchange: @property def _ccxt_config(self) -> Dict: # Parameters to add directly to ccxt sync/async initialization. - return {} + if self.trading_mode == TradingMode.MARGIN: + return { + "options": { + "defaultType": "margin" + } + } + elif self.trading_mode == TradingMode.FUTURES: + return { + "options": { + "defaultType": self._ft_has["ccxt_futures_name"] + } + } + else: + return {} @property def name(self) -> str: diff --git a/freqtrade/exchange/gateio.py b/freqtrade/exchange/gateio.py index 83abd1266..d7edb843c 100644 --- a/freqtrade/exchange/gateio.py +++ b/freqtrade/exchange/gateio.py @@ -35,24 +35,6 @@ class Gateio(Exchange): # (TradingMode.FUTURES, Collateral.ISOLATED) # TODO-lev: Uncomment once supported ] - @property - def _ccxt_config(self) -> Dict: - # Parameters to add directly to ccxt sync/async initialization. - if self.trading_mode == TradingMode.MARGIN: - return { - "options": { - "defaultType": "margin" - } - } - elif self.trading_mode == TradingMode.FUTURES: - return { - "options": { - "defaultType": "swap" - } - } - else: - return {} - def validate_ordertypes(self, order_types: Dict) -> None: super().validate_ordertypes(order_types) diff --git a/freqtrade/exchange/okex.py b/freqtrade/exchange/okex.py index 100bf3adf..a435ef819 100644 --- a/freqtrade/exchange/okex.py +++ b/freqtrade/exchange/okex.py @@ -25,21 +25,3 @@ class Okex(Exchange): # (TradingMode.FUTURES, Collateral.CROSS), # TODO-lev: Uncomment once supported # (TradingMode.FUTURES, Collateral.ISOLATED) # TODO-lev: Uncomment once supported ] - - @property - def _ccxt_config(self) -> Dict: - # Parameters to add directly to ccxt sync/async initialization. - if self.trading_mode == TradingMode.MARGIN: - return { - "options": { - "defaultType": "margin" - } - } - elif self.trading_mode == TradingMode.FUTURES: - return { - "options": { - "defaultType": "swap" - } - } - else: - return {} diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index 8e3fdfe74..6b6900752 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -3253,13 +3253,6 @@ def test_validate_trading_mode_and_collateral( ("binance", "spot", {}), ("binance", "margin", {"options": {"defaultType": "margin"}}), ("binance", "futures", {"options": {"defaultType": "future"}}), - ("kraken", "spot", {}), - ("kraken", "margin", {}), - ("kraken", "futures", {}), - ("ftx", "spot", {}), - ("ftx", "margin", {}), - ("ftx", "futures", {}), - ("bittrex", "spot", {}), ("gateio", "spot", {}), ("gateio", "margin", {"options": {"defaultType": "margin"}}), ("gateio", "futures", {"options": {"defaultType": "swap"}}), From 099bf7691e2a932ae0e980f81326a4df4d306e6a Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Sat, 13 Nov 2021 16:22:36 -0600 Subject: [PATCH 2/9] Updated bibox to combine parent _ccxt_config and minimized _ccxt_config tests --- freqtrade/exchange/bibox.py | 4 +++- tests/exchange/test_exchange.py | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/freqtrade/exchange/bibox.py b/freqtrade/exchange/bibox.py index e0741e34a..5574c401a 100644 --- a/freqtrade/exchange/bibox.py +++ b/freqtrade/exchange/bibox.py @@ -23,6 +23,8 @@ class Bibox(Exchange): @property def _ccxt_config(self) -> Dict: # Parameters to add directly to ccxt sync/async initialization. - return {"has": {"fetchCurrencies": False}} + config = {"has": {"fetchCurrencies": False}} + config.update(super()._ccxt_config) + return config funding_fee_times: List[int] = [0, 8, 16] # hours of the day diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index 6b6900752..b92299fdd 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -3253,9 +3253,10 @@ def test_validate_trading_mode_and_collateral( ("binance", "spot", {}), ("binance", "margin", {"options": {"defaultType": "margin"}}), ("binance", "futures", {"options": {"defaultType": "future"}}), - ("gateio", "spot", {}), - ("gateio", "margin", {"options": {"defaultType": "margin"}}), ("gateio", "futures", {"options": {"defaultType": "swap"}}), + ("bibox", "spot", {"has": {"fetchCurrencies": False}}), + ("bibox", "margin", {"has": {"fetchCurrencies": False}, "options": {"defaultType": "margin"}}), + ("bibox", "futures", {"has": {"fetchCurrencies": False}, "options": {"defaultType": "swap"}}), ]) def test__ccxt_config( default_conf, From 3ce64dd4e9ac6236400d48af88b35e7a57866a2d Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Sat, 13 Nov 2021 16:32:43 -0600 Subject: [PATCH 3/9] Added test__ccxt_config for all exchanges with subclass files on freqtrade --- tests/exchange/test_exchange.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index b92299fdd..1846b3721 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -3253,10 +3253,16 @@ def test_validate_trading_mode_and_collateral( ("binance", "spot", {}), ("binance", "margin", {"options": {"defaultType": "margin"}}), ("binance", "futures", {"options": {"defaultType": "future"}}), - ("gateio", "futures", {"options": {"defaultType": "swap"}}), ("bibox", "spot", {"has": {"fetchCurrencies": False}}), ("bibox", "margin", {"has": {"fetchCurrencies": False}, "options": {"defaultType": "margin"}}), ("bibox", "futures", {"has": {"fetchCurrencies": False}, "options": {"defaultType": "swap"}}), + ("bybit", "futures", {"options": {"defaultType": "linear"}}), + ("ftx", "futures", {"options": {"defaultType": "swap"}}), + ("gateio", "futures", {"options": {"defaultType": "swap"}}), + ("hitbtc", "futures", {"options": {"defaultType": "swap"}}), + ("kraken", "futures", {"options": {"defaultType": "swap"}}), + ("kucoin", "futures", {"options": {"defaultType": "swap"}}), + ("okex", "futures", {"options": {"defaultType": "swap"}}), ]) def test__ccxt_config( default_conf, From 01ad65de68f30d9516ae5ce4da9417a4bcaae49c Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Sat, 13 Nov 2021 19:22:43 -0600 Subject: [PATCH 4/9] test_rpc_apiserver.py --- .../plugins/protections/stoploss_guard.py | 2 +- tests/rpc/test_rpc_apiserver.py | 22 +++++++++---------- tests/rpc/test_rpc_telegram.py | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/freqtrade/plugins/protections/stoploss_guard.py b/freqtrade/plugins/protections/stoploss_guard.py index 888dc0316..79b311f2b 100644 --- a/freqtrade/plugins/protections/stoploss_guard.py +++ b/freqtrade/plugins/protections/stoploss_guard.py @@ -32,7 +32,7 @@ class StoplossGuard(IProtection): def _reason(self) -> str: """ LockReason to use - #TODO-lev: check if min is the right word for shorts + # TODO-lev: check if min is the right word for shorts """ return (f'{self._trade_limit} stoplosses in {self._lookback_period} min, ' f'locking for {self._stop_duration} min.') diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index a3788872f..e0e73f6f1 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -586,10 +586,10 @@ def test_api_trades(botclient, mocker, fee, markets, is_short): assert rc.json()['total_trades'] == 2 -# TODO-lev: @pytest.mark.parametrize('is_short', [True, False]) -def test_api_trade_single(botclient, mocker, fee, ticker, markets): +@pytest.mark.parametrize('is_short', [True, False]) +def test_api_trade_single(botclient, mocker, fee, ticker, markets, is_short): ftbot, client = botclient - patch_get_signal(ftbot) + patch_get_signal(ftbot, enter_long=not is_short, enter_short=is_short) mocker.patch.multiple( 'freqtrade.exchange.Exchange', markets=PropertyMock(return_value=markets), @@ -599,7 +599,7 @@ def test_api_trade_single(botclient, mocker, fee, ticker, markets): assert_response(rc, 404) assert rc.json()['detail'] == 'Trade not found.' - create_mock_trades(fee, False) + create_mock_trades(fee, is_short=is_short) Trade.query.session.flush() rc = client_get(client, f"{BASE_URI}/trade/3") @@ -607,10 +607,10 @@ def test_api_trade_single(botclient, mocker, fee, ticker, markets): assert rc.json()['trade_id'] == 3 -# TODO-lev: @pytest.mark.parametrize('is_short', [True, False]) -def test_api_delete_trade(botclient, mocker, fee, markets): +@pytest.mark.parametrize('is_short', [True, False]) +def test_api_delete_trade(botclient, mocker, fee, markets, is_short): ftbot, client = botclient - patch_get_signal(ftbot) + patch_get_signal(ftbot, enter_long=not is_short, enter_short=is_short) stoploss_mock = MagicMock() cancel_mock = MagicMock() mocker.patch.multiple( @@ -749,10 +749,10 @@ def test_api_profit(botclient, mocker, ticker, fee, markets): } -# TODO-lev: @pytest.mark.parametrize('is_short', [True, False]) -def test_api_stats(botclient, mocker, ticker, fee, markets,): +@pytest.mark.parametrize('is_short', [True, False]) +def test_api_stats(botclient, mocker, ticker, fee, markets, is_short): ftbot, client = botclient - patch_get_signal(ftbot) + patch_get_signal(ftbot, enter_long=not is_short, enter_short=is_short) mocker.patch.multiple( 'freqtrade.exchange.Exchange', get_balances=MagicMock(return_value=ticker), @@ -766,7 +766,7 @@ def test_api_stats(botclient, mocker, ticker, fee, markets,): assert 'durations' in rc.json() assert 'sell_reasons' in rc.json() - create_mock_trades(fee, False) + create_mock_trades(fee, is_short=is_short) rc = client_get(client, f"{BASE_URI}/stats") assert_response(rc, 200) diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index d88c7b24e..522883a36 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -1261,8 +1261,8 @@ def test_edge_enabled(edge_conf, update, mocker) -> None: assert 'Winrate' not in msg_mock.call_args_list[0][0][0] -# TODO-lev: @pytest.mark.parametrize('is_short', [True, False]) -def test_telegram_trades(mocker, update, default_conf, fee): +@pytest.mark.parametrize('is_short', [True, False]) +def test_telegram_trades(mocker, update, default_conf, fee, is_short): telegram, _, msg_mock = get_telegram_testobject(mocker, default_conf) From ca9805112db78cfa7b2d87e7dd1bca8b8cb95314 Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Sat, 13 Nov 2021 19:26:30 -0600 Subject: [PATCH 5/9] test_get_trades_proxy and test_select_order for shorts passes --- tests/test_persistence.py | 40 +++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/tests/test_persistence.py b/tests/test_persistence.py index 9dd5b175b..2d4a7406f 100644 --- a/tests/test_persistence.py +++ b/tests/test_persistence.py @@ -1907,12 +1907,12 @@ def test_get_total_closed_profit(fee, use_db): @pytest.mark.usefixtures("init_persistence") -# TODO-lev: @pytest.mark.parametrize('is_short', [True, False]) +@pytest.mark.parametrize('is_short', [True, False]) @pytest.mark.parametrize('use_db', [True, False]) -def test_get_trades_proxy(fee, use_db): +def test_get_trades_proxy(fee, use_db, is_short): Trade.use_db = use_db Trade.reset_trades() - create_mock_trades(fee, False, use_db) + create_mock_trades(fee, is_short, use_db) trades = Trade.get_trades_proxy() assert len(trades) == 6 @@ -2042,48 +2042,48 @@ def test_update_order_from_ccxt(caplog): @pytest.mark.usefixtures("init_persistence") -# TODO-lev: @pytest.mark.parametrize('is_short', [True, False]) -def test_select_order(fee): - create_mock_trades(fee, False) +@pytest.mark.parametrize('is_short', [True, False]) +def test_select_order(fee, is_short): + create_mock_trades(fee, is_short) trades = Trade.get_trades().all() # Open buy order, no sell order - order = trades[0].select_order('buy', True) + order = trades[0].select_order(trades[0].enter_side, True) assert order is None - order = trades[0].select_order('buy', False) + order = trades[0].select_order(trades[0].enter_side, False) assert order is not None - order = trades[0].select_order('sell', None) + order = trades[0].select_order(trades[0].exit_side, None) assert order is None # closed buy order, and open sell order - order = trades[1].select_order('buy', True) + order = trades[1].select_order(trades[1].enter_side, True) assert order is None - order = trades[1].select_order('buy', False) + order = trades[1].select_order(trades[1].enter_side, False) assert order is not None - order = trades[1].select_order('buy', None) + order = trades[1].select_order(trades[1].enter_side, None) assert order is not None - order = trades[1].select_order('sell', True) + order = trades[1].select_order(trades[1].exit_side, True) assert order is None - order = trades[1].select_order('sell', False) + order = trades[1].select_order(trades[1].exit_side, False) assert order is not None # Has open buy order - order = trades[3].select_order('buy', True) + order = trades[3].select_order(trades[3].enter_side, True) assert order is not None - order = trades[3].select_order('buy', False) + order = trades[3].select_order(trades[3].enter_side, False) assert order is None # Open sell order - order = trades[4].select_order('buy', True) + order = trades[4].select_order(trades[4].enter_side, True) assert order is None - order = trades[4].select_order('buy', False) + order = trades[4].select_order(trades[4].enter_side, False) assert order is not None - order = trades[4].select_order('sell', True) + order = trades[4].select_order(trades[4].exit_side, True) assert order is not None assert order.ft_order_side == 'stoploss' - order = trades[4].select_order('sell', False) + order = trades[4].select_order(trades[4].exit_side, False) assert order is None From 77f8f8658cd6e820bd0551757e2fd8a7d66ac2df Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Sat, 13 Nov 2021 19:36:49 -0600 Subject: [PATCH 6/9] test_rpc_telegram short test --- tests/rpc/test_rpc_telegram.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index 522883a36..323eddd4d 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -1261,8 +1261,8 @@ def test_edge_enabled(edge_conf, update, mocker) -> None: assert 'Winrate' not in msg_mock.call_args_list[0][0][0] -@pytest.mark.parametrize('is_short', [True, False]) -def test_telegram_trades(mocker, update, default_conf, fee, is_short): +# TODO-lev: @pytest.mark.parametrize('is_short', [True, False]) +def test_telegram_trades(mocker, update, default_conf, fee): telegram, _, msg_mock = get_telegram_testobject(mocker, default_conf) @@ -1294,8 +1294,8 @@ def test_telegram_trades(mocker, update, default_conf, fee, is_short): msg_mock.call_args_list[0][0][0])) -# TODO-lev: @pytest.mark.parametrize('is_short', [True, False]) -def test_telegram_delete_trade(mocker, update, default_conf, fee): +@pytest.mark.parametrize('is_short', [True, False]) +def test_telegram_delete_trade(mocker, update, default_conf, fee, is_short): telegram, _, msg_mock = get_telegram_testobject(mocker, default_conf) context = MagicMock() @@ -1305,7 +1305,7 @@ def test_telegram_delete_trade(mocker, update, default_conf, fee): assert "Trade-id not set." in msg_mock.call_args_list[0][0][0] msg_mock.reset_mock() - create_mock_trades(fee, False) + create_mock_trades(fee, is_short) context = MagicMock() context.args = [1] From 430aa0903f6e698e39739c7de1b318ea78d55c4d Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Sat, 13 Nov 2021 19:45:41 -0600 Subject: [PATCH 7/9] Removed redundent TODO-levs --- freqtrade/exchange/binance.py | 7 ++++--- freqtrade/exchange/bybit.py | 5 +++-- freqtrade/exchange/ftx.py | 5 +++-- freqtrade/exchange/gateio.py | 7 ++++--- freqtrade/exchange/kraken.py | 5 +++-- freqtrade/exchange/okex.py | 7 ++++--- freqtrade/freqtradebot.py | 5 ++--- freqtrade/persistence/models.py | 4 ++-- tests/conftest_trades.py | 2 +- 9 files changed, 26 insertions(+), 21 deletions(-) diff --git a/freqtrade/exchange/binance.py b/freqtrade/exchange/binance.py index c16566fde..ba3528949 100644 --- a/freqtrade/exchange/binance.py +++ b/freqtrade/exchange/binance.py @@ -33,9 +33,10 @@ class Binance(Exchange): _supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [ # TradingMode.SPOT always supported and not required in this list - # (TradingMode.MARGIN, Collateral.CROSS), # TODO-lev: Uncomment once supported - # (TradingMode.FUTURES, Collateral.CROSS), # TODO-lev: Uncomment once supported - # (TradingMode.FUTURES, Collateral.ISOLATED) # TODO-lev: Uncomment once supported + # TODO-lev: Uncomment once supported + # (TradingMode.MARGIN, Collateral.CROSS), + # (TradingMode.FUTURES, Collateral.CROSS), + # (TradingMode.FUTURES, Collateral.ISOLATED) ] @property diff --git a/freqtrade/exchange/bybit.py b/freqtrade/exchange/bybit.py index df19a671b..31152d6c1 100644 --- a/freqtrade/exchange/bybit.py +++ b/freqtrade/exchange/bybit.py @@ -27,6 +27,7 @@ class Bybit(Exchange): _supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [ # TradingMode.SPOT always supported and not required in this list - # (TradingMode.FUTURES, Collateral.CROSS), # TODO-lev: Uncomment once supported - # (TradingMode.FUTURES, Collateral.ISOLATED) # TODO-lev: Uncomment once supported + # TODO-lev: Uncomment once supported + # (TradingMode.FUTURES, Collateral.CROSS), + # (TradingMode.FUTURES, Collateral.ISOLATED) ] diff --git a/freqtrade/exchange/ftx.py b/freqtrade/exchange/ftx.py index 2acf32ba3..d8df8bc97 100644 --- a/freqtrade/exchange/ftx.py +++ b/freqtrade/exchange/ftx.py @@ -25,8 +25,9 @@ class Ftx(Exchange): _supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [ # TradingMode.SPOT always supported and not required in this list - # (TradingMode.MARGIN, Collateral.CROSS), # TODO-lev: Uncomment once supported - # (TradingMode.FUTURES, Collateral.CROSS) # TODO-lev: Uncomment once supported + # TODO-lev: Uncomment once supported + # (TradingMode.MARGIN, Collateral.CROSS), + # (TradingMode.FUTURES, Collateral.CROSS) ] def market_is_tradable(self, market: Dict[str, Any]) -> bool: diff --git a/freqtrade/exchange/gateio.py b/freqtrade/exchange/gateio.py index 83abd1266..eb5d244aa 100644 --- a/freqtrade/exchange/gateio.py +++ b/freqtrade/exchange/gateio.py @@ -30,9 +30,10 @@ class Gateio(Exchange): _supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [ # TradingMode.SPOT always supported and not required in this list - # (TradingMode.MARGIN, Collateral.CROSS), # TODO-lev: Uncomment once supported - # (TradingMode.FUTURES, Collateral.CROSS), # TODO-lev: Uncomment once supported - # (TradingMode.FUTURES, Collateral.ISOLATED) # TODO-lev: Uncomment once supported + # TODO-lev: Uncomment once supported + # (TradingMode.MARGIN, Collateral.CROSS), + # (TradingMode.FUTURES, Collateral.CROSS), + # (TradingMode.FUTURES, Collateral.ISOLATED) ] @property diff --git a/freqtrade/exchange/kraken.py b/freqtrade/exchange/kraken.py index 8bd5d2fb3..6d0294e1c 100644 --- a/freqtrade/exchange/kraken.py +++ b/freqtrade/exchange/kraken.py @@ -27,8 +27,9 @@ class Kraken(Exchange): _supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [ # TradingMode.SPOT always supported and not required in this list - # (TradingMode.MARGIN, Collateral.CROSS), # TODO-lev: Uncomment once supported - # (TradingMode.FUTURES, Collateral.CROSS) # TODO-lev: No CCXT support + # TODO-lev: Uncomment once supported + # (TradingMode.MARGIN, Collateral.CROSS), + # (TradingMode.FUTURES, Collateral.CROSS) ] def market_is_tradable(self, market: Dict[str, Any]) -> bool: diff --git a/freqtrade/exchange/okex.py b/freqtrade/exchange/okex.py index 100bf3adf..cade318a5 100644 --- a/freqtrade/exchange/okex.py +++ b/freqtrade/exchange/okex.py @@ -21,9 +21,10 @@ class Okex(Exchange): _supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [ # TradingMode.SPOT always supported and not required in this list - # (TradingMode.MARGIN, Collateral.CROSS), # TODO-lev: Uncomment once supported - # (TradingMode.FUTURES, Collateral.CROSS), # TODO-lev: Uncomment once supported - # (TradingMode.FUTURES, Collateral.ISOLATED) # TODO-lev: Uncomment once supported + # TODO-lev: Uncomment once supported + # (TradingMode.MARGIN, Collateral.CROSS), + # (TradingMode.FUTURES, Collateral.CROSS), + # (TradingMode.FUTURES, Collateral.ISOLATED) ] @property diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 8369a8579..092d658c2 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -922,8 +922,7 @@ class FreqtradeBot(LoggingMixin): Check if trade is fulfilled in which case the stoploss on exchange should be added immediately if stoploss on exchange is enabled. - # TODO-lev: liquidation price will always be on exchange, even though - # TODO-lev: stoploss_on_exchange might not be enabled + # TODO-lev: liquidation price always on exchange, even without stoploss_on_exchange """ logger.debug('Handling stoploss on exchange %s ...', trade) @@ -1517,7 +1516,7 @@ class FreqtradeBot(LoggingMixin): self.wallets.update() if fee_abs != 0 and self.wallets.get_free(trade_base_currency) >= amount: # Eat into dust if we own more than base currency - # TODO-lev: won't be in base currency for shorts + # TODO-lev: settle currency for futures logger.info(f"Fee amount for {trade} was in base currency - " f"Eating Fee {fee_abs} into dust.") elif fee_abs != 0: diff --git a/freqtrade/persistence/models.py b/freqtrade/persistence/models.py index 4835a1772..9ba88057c 100644 --- a/freqtrade/persistence/models.py +++ b/freqtrade/persistence/models.py @@ -916,8 +916,8 @@ class Trade(_DECL_BASE, LocalTrade): max_rate = Column(Float, nullable=True, default=0.0) # Lowest price reached min_rate = Column(Float, nullable=True) - sell_reason = Column(String(100), nullable=True) # TODO-lev: Change to close_reason - sell_order_status = Column(String(100), nullable=True) # TODO-lev: Change to close_order_status + sell_reason = Column(String(100), nullable=True) + sell_order_status = Column(String(100), nullable=True) strategy = Column(String(100), nullable=True) buy_tag = Column(String(100), nullable=True) timeframe = Column(Integer, nullable=True) diff --git a/tests/conftest_trades.py b/tests/conftest_trades.py index c13b482dc..dcd5e70df 100644 --- a/tests/conftest_trades.py +++ b/tests/conftest_trades.py @@ -488,7 +488,7 @@ def leverage_trade(fee): open_order_id='dry_run_leverage_buy_12368', strategy='DefaultStrategy', timeframe=5, - sell_reason='sell_signal', # TODO-lev: Update to exit/close reason + sell_reason='sell_signal', open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=300), close_date=datetime.now(tz=timezone.utc), interest_rate=0.0005 From 86e5b480a84ed9ac50a36c5b9b03cf420d3493cc Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Sat, 13 Nov 2021 19:50:53 -0600 Subject: [PATCH 8/9] test_strategy_test_v2 for shorts --- tests/strategy/test_default_strategy.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/tests/strategy/test_default_strategy.py b/tests/strategy/test_default_strategy.py index a995491f2..19f645d90 100644 --- a/tests/strategy/test_default_strategy.py +++ b/tests/strategy/test_default_strategy.py @@ -1,5 +1,6 @@ from datetime import datetime +import pytest from pandas import DataFrame from freqtrade.persistence.models import Trade @@ -16,7 +17,11 @@ def test_strategy_test_v2_structure(): assert hasattr(StrategyTestV3, 'populate_sell_trend') -def test_strategy_test_v2(result, fee): +@pytest.mark.parametrize('is_short,side', [ + (True, 'short'), + (False, 'long'), +]) +def test_strategy_test_v2(result, fee, is_short, side): strategy = StrategyTestV3({}) metadata = {'pair': 'ETH/BTC'} @@ -32,16 +37,18 @@ def test_strategy_test_v2(result, fee): open_rate=19_000, amount=0.1, pair='ETH/BTC', - fee_open=fee.return_value + fee_open=fee.return_value, + is_short=is_short ) assert strategy.confirm_trade_entry(pair='ETH/BTC', order_type='limit', amount=0.1, rate=20000, time_in_force='gtc', - current_time=datetime.utcnow(), side='long') is True + current_time=datetime.utcnow(), + side=side) is True assert strategy.confirm_trade_exit(pair='ETH/BTC', trade=trade, order_type='limit', amount=0.1, rate=20000, time_in_force='gtc', sell_reason='roi', - current_time=datetime.utcnow()) is True + current_time=datetime.utcnow(), + side=side) is True - # TODO-lev: Test for shorts? assert strategy.custom_stoploss(pair='ETH/BTC', trade=trade, current_time=datetime.now(), current_rate=20_000, current_profit=0.05) == strategy.stoploss From 38362e0ec52c0e8f28adf25610dc0e4d9f160125 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 14 Nov 2021 09:02:25 +0100 Subject: [PATCH 9/9] Update test names --- tests/strategy/test_default_strategy.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/strategy/test_default_strategy.py b/tests/strategy/test_default_strategy.py index 19f645d90..ff2ce10a7 100644 --- a/tests/strategy/test_default_strategy.py +++ b/tests/strategy/test_default_strategy.py @@ -8,7 +8,7 @@ from freqtrade.persistence.models import Trade from .strats.strategy_test_v3 import StrategyTestV3 -def test_strategy_test_v2_structure(): +def test_strategy_test_v3_structure(): assert hasattr(StrategyTestV3, 'minimal_roi') assert hasattr(StrategyTestV3, 'stoploss') assert hasattr(StrategyTestV3, 'timeframe') @@ -21,7 +21,7 @@ def test_strategy_test_v2_structure(): (True, 'short'), (False, 'long'), ]) -def test_strategy_test_v2(result, fee, is_short, side): +def test_strategy_test_v3(result, fee, is_short, side): strategy = StrategyTestV3({}) metadata = {'pair': 'ETH/BTC'}