From fc2d3649a197919b915c2904c46ea78dc3e74758 Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Sat, 12 Feb 2022 16:10:21 -0600 Subject: [PATCH 1/8] edited todos --- freqtrade/commands/data_commands.py | 3 +-- freqtrade/enums/candletype.py | 4 +++- freqtrade/exchange/exchange.py | 2 +- freqtrade/freqtradebot.py | 4 ++-- freqtrade/optimize/backtesting.py | 4 +--- freqtrade/templates/sample_short_strategy.py | 2 +- tests/optimize/test_backtest_detail.py | 4 ++-- tests/strategy/strats/strategy_test_v3.py | 2 +- 8 files changed, 12 insertions(+), 13 deletions(-) diff --git a/freqtrade/commands/data_commands.py b/freqtrade/commands/data_commands.py index 0c6f48088..220dfce22 100644 --- a/freqtrade/commands/data_commands.py +++ b/freqtrade/commands/data_commands.py @@ -85,7 +85,7 @@ def start_download_data(args: Dict[str, Any]) -> None: new_pairs_days=config['new_pairs_days'], erase=bool(config.get('erase')), data_format=config['dataformat_ohlcv'], trading_mode=config.get('trading_mode', 'spot'), - ) + ) except KeyboardInterrupt: sys.exit("SIGINT received, aborting ...") @@ -160,7 +160,6 @@ def start_list_data(args: Dict[str, Any]) -> None: from freqtrade.data.history.idatahandler import get_datahandler dhc = get_datahandler(config['datadir'], config['dataformat_ohlcv']) - # TODO-lev: trading-mode should be parsed at config level, and available as Enum in the config. paircombs = dhc.ohlcv_get_available_data(config['datadir'], config.get('trading_mode', 'spot')) if args['pairs']: diff --git a/freqtrade/enums/candletype.py b/freqtrade/enums/candletype.py index 0188650f6..6df735616 100644 --- a/freqtrade/enums/candletype.py +++ b/freqtrade/enums/candletype.py @@ -8,8 +8,10 @@ class CandleType(str, Enum): MARK = "mark" INDEX = "index" PREMIUMINDEX = "premiumIndex" - # TODO-lev: not sure this belongs here, as the datatype is really different + + # TODO: Could take up less memory if these weren't a CandleType FUNDING_RATE = "funding_rate" + BORROW_RATE = "borrow_rate" # * unimplemented @staticmethod def from_string(value: str) -> 'CandleType': diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 90b63b57b..9074ed3cb 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -1528,7 +1528,7 @@ class Exchange: :return: Dict of [{(pair, timeframe): Dataframe}] """ logger.debug("Refreshing candle (OHLCV) data for %d pairs", len(pair_list)) - # TODO-lev: maybe depend this on candle type? + # TODO: maybe depend this on candle type? drop_incomplete = self._ohlcv_partial_candle if drop_incomplete is None else drop_incomplete input_coroutines = [] cached_pairs = [] diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 0906276f9..6d87dc6bc 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -1049,7 +1049,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 always on exchange, even without stoploss_on_exchange + # TODO: liquidation price always on exchange, even without stoploss_on_exchange """ logger.debug('Handling stoploss on exchange %s ...', trade) @@ -1736,7 +1736,7 @@ class FreqtradeBot(LoggingMixin): trade.update_fee(fee_cost, fee_currency, fee_rate, order.get('side', '')) if not isclose(amount, order_amount, abs_tol=constants.MATH_CLOSE_PREC): - # TODO-lev: leverage? + # * Leverage could be a cause for this warning, leverage hasn't been thoroughly tested logger.warning(f"Amount {amount} does not match amount {trade.amount}") raise DependencyException("Half bought? Amounts don't match") diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 719aea8aa..8d604f9eb 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -127,8 +127,6 @@ class Backtesting: self.config['startup_candle_count'] = self.required_startup self.exchange.validate_required_startup_candles(self.required_startup, self.timeframe) - # TODO-lev: This should come from the configuration setting or better a - # TODO-lev: combination of config/strategy "use_shorts"(?) and "can_short" from the exchange self.trading_mode = TradingMode(config.get('trading_mode', 'spot')) self._can_short = self.trading_mode != TradingMode.SPOT @@ -538,7 +536,7 @@ class Backtesting: sell_candle_time: datetime = sell_row[DATE_IDX].to_pydatetime() if self.trading_mode == TradingMode.FUTURES: - # TODO-lev: liquidation price? + # TODO: liquidation price? trade.funding_fees = self.exchange.calculate_funding_fees( self.futures_data[trade.pair], amount=trade.amount, diff --git a/freqtrade/templates/sample_short_strategy.py b/freqtrade/templates/sample_short_strategy.py index e9deba6af..bcb6c921e 100644 --- a/freqtrade/templates/sample_short_strategy.py +++ b/freqtrade/templates/sample_short_strategy.py @@ -15,7 +15,7 @@ import talib.abstract as ta import freqtrade.vendor.qtpylib.indicators as qtpylib -# TODO-lev: Create a meaningfull short strategy (not just revresed signs). +# TODO: Create a meaningfull short strategy (not just revresed signs). # This class is a sample. Feel free to customize it. class SampleShortStrategy(IStrategy): """ diff --git a/tests/optimize/test_backtest_detail.py b/tests/optimize/test_backtest_detail.py index ee13715f6..e0154160b 100644 --- a/tests/optimize/test_backtest_detail.py +++ b/tests/optimize/test_backtest_detail.py @@ -558,7 +558,7 @@ tc35 = BTContainer(data=[ stop_loss=-0.01, roi={"0": 0.10}, profit_perc=-0.01, custom_entry_price=7200, trades=[ BTrade(sell_reason=SellType.STOP_LOSS, open_tick=1, close_tick=1) - ] +] ) # Test 36: Custom-entry-price around candle low @@ -697,7 +697,7 @@ def test_backtest_results(default_conf, fee, mocker, caplog, data) -> None: backtesting._set_strategy(backtesting.strategylist[0]) backtesting.required_startup = 0 if data.leverage > 1.0: - # TODO-lev: Should we initialize this properly?? + # TODO: Should we initialize this properly?? backtesting._can_short = True backtesting.strategy.advise_entry = lambda a, m: frame backtesting.strategy.advise_exit = lambda a, m: frame diff --git a/tests/strategy/strats/strategy_test_v3.py b/tests/strategy/strats/strategy_test_v3.py index 5d689e0a1..a056b316c 100644 --- a/tests/strategy/strats/strategy_test_v3.py +++ b/tests/strategy/strats/strategy_test_v3.py @@ -71,7 +71,7 @@ class StrategyTestV3(IStrategy): protection_enabled = BooleanParameter(default=True) protection_cooldown_lookback = IntParameter([0, 50], default=30) - # TODO-lev: Can this work with protection tests? (replace HyperoptableStrategy implicitly ... ) + # TODO: Can this work with protection tests? (replace HyperoptableStrategy implicitly ... ) # @property # def protections(self): # prot = [] From 2523c12c710f6f7f5865877fe78c6127c56ebd92 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 13 Feb 2022 14:33:37 +0100 Subject: [PATCH 2/8] Small enhancements and notes --- freqtrade/exchange/exchange.py | 2 +- freqtrade/freqtradebot.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 90b63b57b..6213ecbff 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -499,7 +499,7 @@ class Exchange: # Note: ccxt has BaseCurrency/QuoteCurrency format for pairs if self.markets and pair not in self.markets: raise OperationalException( - f'Pair {pair} is not available on {self.name}. ' + f'Pair {pair} is not available on {self.name} {self.trading_mode.value}. ' f'Please remove {pair} from your whitelist.') # From ccxt Documentation: diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 0906276f9..39b404fd4 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -740,6 +740,9 @@ class FreqtradeBot(LoggingMixin): # in case of FOK the order may be filled immediately and fully elif order_status == 'closed': + # TODO-lev: Evaluate this. Why is setting stake_amount here necessary? + # it should never change in theory - and in case of leveraged orders, + # may be the leveraged amount. stake_amount = order['cost'] amount = safe_value_fallback(order, 'filled', 'amount') enter_limit_filled_price = safe_value_fallback(order, 'average', 'price') @@ -1288,6 +1291,7 @@ class FreqtradeBot(LoggingMixin): # * Check edge cases, we don't want to make leverage > 1.0 if we don't have to # * (for leverage modes which aren't isolated futures) + # TODO-lev: The below calculation needs to include leverage ... trade.stake_amount = trade.amount * trade.open_rate self.update_trade_state(trade, trade.open_order_id, corder) From 5b65448e5677e2ecf226a0e5684a76d9d56232d0 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 13 Feb 2022 16:17:41 +0100 Subject: [PATCH 3/8] Fix some todo-lev's in tests --- tests/test_freqtradebot.py | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index 1442186ea..a64c105f1 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -522,13 +522,11 @@ def test_create_trades_preopen(default_conf_usdt, ticker_usdt, fee, mocker, assert len(trades) == 4 -@pytest.mark.parametrize('is_short, open_rate', [ - (False, 2.0), - (True, 2.02) -]) +@pytest.mark.parametrize('is_short', [False, True]) def test_process_trade_creation(default_conf_usdt, ticker_usdt, limit_order, limit_order_open, - is_short, open_rate, fee, mocker, caplog + is_short, fee, mocker, caplog ) -> None: + ticker_side = 'ask' if is_short else 'bid' patch_RPCManager(mocker) patch_exchange(mocker) mocker.patch.multiple( @@ -554,8 +552,8 @@ def test_process_trade_creation(default_conf_usdt, ticker_usdt, limit_order, lim assert trade.is_open assert trade.open_date is not None assert trade.exchange == 'binance' - assert trade.open_rate == open_rate # TODO-lev: I think? That's what the ticker ask price is - assert isclose(trade.amount, 60 / open_rate) + assert trade.open_rate == ticker_usdt.return_value[ticker_side] + assert isclose(trade.amount, 60 / ticker_usdt.return_value[ticker_side]) assert log_has( f'{"Short" if is_short else "Long"} signal found: about create a new trade for ETH/USDT ' @@ -3342,13 +3340,12 @@ def test_may_execute_trade_exit_after_stoploss_on_exchange_hit(default_conf_usdt @pytest.mark.parametrize( - "is_short,amount,open_rate,current_rate,limit,profit_amount,profit_ratio,profit_or_loss", [ - (False, 30, 2.0, 2.3, 2.2, 5.685, 0.09451372, 'profit'), - # TODO-lev: Should the current rate be 2.2 for shorts? - (True, 29.70297029, 2.02, 2.2, 2.3, -8.63762376, -0.1443212, 'loss'), + "is_short,amount,current_rate,limit,profit_amount,profit_ratio,profit_or_loss", [ + (False, 30, 2.3, 2.2, 5.685, 0.09451372, 'profit'), + (True, 29.70297029, 2.2, 2.3, -8.63762376, -0.1443212, 'loss'), ]) def test_execute_trade_exit_market_order( - default_conf_usdt, ticker_usdt, fee, is_short, current_rate, amount, open_rate, + default_conf_usdt, ticker_usdt, fee, is_short, current_rate, amount, limit, profit_amount, profit_ratio, profit_or_loss, ticker_usdt_sell_up, mocker ) -> None: """ @@ -3368,6 +3365,7 @@ def test_execute_trade_exit_market_order( long: (65.835/60.15) - 1 = 0.0945137157107232 short: 1 - (68.48762376237624/59.85) = -0.1443211990371971 """ + open_rate = ticker_usdt.return_value['ask' if is_short else 'bid'] rpc_mock = patch_RPCManager(mocker) patch_exchange(mocker) mocker.patch.multiple( @@ -4234,14 +4232,13 @@ def test_apply_fee_conditional(default_conf_usdt, fee, mocker, (0.1, False), (100, True), ]) -@pytest.mark.parametrize('is_short, open_rate', [ - (False, 2.0), - (True, 2.02), -]) +@pytest.mark.parametrize('is_short', [False, True]) def test_order_book_depth_of_market( - default_conf_usdt, ticker_usdt, limit_order, limit_order_open, - fee, mocker, order_book_l2, delta, is_high_delta, is_short, open_rate + default_conf_usdt, ticker_usdt, limit_order_open, + fee, mocker, order_book_l2, delta, is_high_delta, is_short ): + ticker_side = 'ask' if is_short else 'bid' + default_conf_usdt['bid_strategy']['check_depth_of_market']['enabled'] = True default_conf_usdt['bid_strategy']['check_depth_of_market']['bids_to_ask_delta'] = delta patch_RPCManager(mocker) @@ -4276,7 +4273,7 @@ def test_order_book_depth_of_market( # Simulate fulfilled LIMIT_BUY order for trade trade.update(limit_order_open[enter_side(is_short)]) - assert trade.open_rate == open_rate # TODO-lev: double check + assert trade.open_rate == ticker_usdt.return_value[ticker_side] assert whitelist == default_conf_usdt['exchange']['pair_whitelist'] From 09cc43b5338bfa82554cf420d910ed163e5775e8 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 13 Feb 2022 16:23:01 +0100 Subject: [PATCH 4/8] Test short trade exiting --- freqtrade/enums/rpcmessagetype.py | 15 +++++++++------ tests/test_freqtradebot.py | 22 ++++++++++++++-------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/freqtrade/enums/rpcmessagetype.py b/freqtrade/enums/rpcmessagetype.py index 663b37b83..661f9ce5c 100644 --- a/freqtrade/enums/rpcmessagetype.py +++ b/freqtrade/enums/rpcmessagetype.py @@ -10,16 +10,19 @@ class RPCMessageType(Enum): BUY_FILL = 'buy_fill' BUY_CANCEL = 'buy_cancel' - SELL = 'sell' - SELL_FILL = 'sell_fill' - SELL_CANCEL = 'sell_cancel' - PROTECTION_TRIGGER = 'protection_trigger' - PROTECTION_TRIGGER_GLOBAL = 'protection_trigger_global' - SHORT = 'short' SHORT_FILL = 'short_fill' SHORT_CANCEL = 'short_cancel' + # TODO: The below messagetypes should be renamed to "exit"! + # Careful - has an impact on webhooks, therefore needs proper communication + SELL = 'sell' + SELL_FILL = 'sell_fill' + SELL_CANCEL = 'sell_cancel' + + PROTECTION_TRIGGER = 'protection_trigger' + PROTECTION_TRIGGER_GLOBAL = 'protection_trigger_global' + def __repr__(self): return self.value diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index a64c105f1..61c7d9dfa 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -3266,9 +3266,9 @@ def test_execute_trade_exit_with_stoploss_on_exchange( assert rpc_mock.call_count == 3 -# TODO-lev: add short, RPC short, short fill -def test_may_execute_trade_exit_after_stoploss_on_exchange_hit(default_conf_usdt, ticker_usdt, fee, - mocker) -> None: +@pytest.mark.parametrize("is_short", [False, True]) +def test_may_execute_trade_exit_after_stoploss_on_exchange_hit( + default_conf_usdt, ticker_usdt, fee, mocker, is_short) -> None: default_conf_usdt['exchange']['name'] = 'binance' rpc_mock = patch_RPCManager(mocker) patch_exchange(mocker) @@ -3292,7 +3292,7 @@ def test_may_execute_trade_exit_after_stoploss_on_exchange_hit(default_conf_usdt freqtrade = FreqtradeBot(default_conf_usdt) freqtrade.strategy.order_types['stoploss_on_exchange'] = True - patch_get_signal(freqtrade) + patch_get_signal(freqtrade, enter_long=not is_short, enter_short=is_short) # Create some test data freqtrade.enter_positions() @@ -3306,7 +3306,7 @@ def test_may_execute_trade_exit_after_stoploss_on_exchange_hit(default_conf_usdt assert trade.stoploss_order_id == '123' assert trade.open_order_id is None - # Assuming stoploss on exchnage is hit + # Assuming stoploss on exchange is hit # stoploss_order_id should become None # and trade should be sold at the price of stoploss stoploss_executed = MagicMock(return_value={ @@ -3334,9 +3334,15 @@ def test_may_execute_trade_exit_after_stoploss_on_exchange_hit(default_conf_usdt assert trade.is_open is False assert trade.sell_reason == SellType.STOPLOSS_ON_EXCHANGE.value assert rpc_mock.call_count == 3 - assert rpc_mock.call_args_list[0][0][0]['type'] == RPCMessageType.BUY - assert rpc_mock.call_args_list[1][0][0]['type'] == RPCMessageType.BUY_FILL - assert rpc_mock.call_args_list[2][0][0]['type'] == RPCMessageType.SELL + if is_short: + assert rpc_mock.call_args_list[0][0][0]['type'] == RPCMessageType.SHORT + assert rpc_mock.call_args_list[1][0][0]['type'] == RPCMessageType.SHORT_FILL + assert rpc_mock.call_args_list[2][0][0]['type'] == RPCMessageType.SELL + + else: + assert rpc_mock.call_args_list[0][0][0]['type'] == RPCMessageType.BUY + assert rpc_mock.call_args_list[1][0][0]['type'] == RPCMessageType.BUY_FILL + assert rpc_mock.call_args_list[2][0][0]['type'] == RPCMessageType.SELL @pytest.mark.parametrize( From 19783e0d3977ef0b86698103f8bd1c241d00b529 Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Mon, 14 Feb 2022 09:01:08 -0600 Subject: [PATCH 5/8] edited todos --- freqtrade/commands/data_commands.py | 1 + freqtrade/exchange/exchange.py | 1 - freqtrade/freqtradebot.py | 2 +- freqtrade/optimize/backtesting.py | 1 - 4 files changed, 2 insertions(+), 3 deletions(-) diff --git a/freqtrade/commands/data_commands.py b/freqtrade/commands/data_commands.py index 220dfce22..95ad67a65 100644 --- a/freqtrade/commands/data_commands.py +++ b/freqtrade/commands/data_commands.py @@ -160,6 +160,7 @@ def start_list_data(args: Dict[str, Any]) -> None: from freqtrade.data.history.idatahandler import get_datahandler dhc = get_datahandler(config['datadir'], config['dataformat_ohlcv']) + # TODO-lev: trading-mode should be parsed at config level, and available as Enum in the config. paircombs = dhc.ohlcv_get_available_data(config['datadir'], config.get('trading_mode', 'spot')) if args['pairs']: diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 9074ed3cb..9c7c774a9 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -1528,7 +1528,6 @@ class Exchange: :return: Dict of [{(pair, timeframe): Dataframe}] """ logger.debug("Refreshing candle (OHLCV) data for %d pairs", len(pair_list)) - # TODO: maybe depend this on candle type? drop_incomplete = self._ohlcv_partial_candle if drop_incomplete is None else drop_incomplete input_coroutines = [] cached_pairs = [] diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 6d87dc6bc..55887529b 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -1049,7 +1049,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: liquidation price always on exchange, even without stoploss_on_exchange + # TODO-lev: liquidation price always on exchange, even without stoploss_on_exchange """ logger.debug('Handling stoploss on exchange %s ...', trade) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 8d604f9eb..c24f6e5db 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -536,7 +536,6 @@ class Backtesting: sell_candle_time: datetime = sell_row[DATE_IDX].to_pydatetime() if self.trading_mode == TradingMode.FUTURES: - # TODO: liquidation price? trade.funding_fees = self.exchange.calculate_funding_fees( self.futures_data[trade.pair], amount=trade.amount, From a2b84561fee77d5a9784bb1610f8c15be3e4bacb Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Mon, 14 Feb 2022 10:00:03 -0600 Subject: [PATCH 6/8] removed a todo --- freqtrade/freqtradebot.py | 1 - 1 file changed, 1 deletion(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 55887529b..c7e9ff19c 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -1358,7 +1358,6 @@ class FreqtradeBot(LoggingMixin): trade_base_currency = self.exchange.get_pair_base_currency(pair) wallet_amount = self.wallets.get_free(trade_base_currency) logger.debug(f"{pair} - Wallet: {wallet_amount} - Trade-amount: {amount}") - # TODO-lev: Get wallet amount + value of positions if wallet_amount >= amount or self.trading_mode == TradingMode.FUTURES: # A safe exit amount isn't needed for futures, you can just exit/close the position return amount From 5f42ebfa4c6f824a521498eb16b0f7c931df6079 Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Mon, 14 Feb 2022 23:53:10 -0600 Subject: [PATCH 7/8] Update candletype.py --- freqtrade/enums/candletype.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/enums/candletype.py b/freqtrade/enums/candletype.py index 6df735616..9d05ff6d7 100644 --- a/freqtrade/enums/candletype.py +++ b/freqtrade/enums/candletype.py @@ -11,7 +11,7 @@ class CandleType(str, Enum): # TODO: Could take up less memory if these weren't a CandleType FUNDING_RATE = "funding_rate" - BORROW_RATE = "borrow_rate" # * unimplemented + # BORROW_RATE = "borrow_rate" # * unimplemented @staticmethod def from_string(value: str) -> 'CandleType': From a9eb8ce1bf8bd807e6aebf7c98cd210fcf9acfa7 Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Wed, 16 Feb 2022 05:47:41 -0600 Subject: [PATCH 8/8] added todos back in --- freqtrade/freqtradebot.py | 1 + freqtrade/optimize/backtesting.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index c7e9ff19c..55887529b 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -1358,6 +1358,7 @@ class FreqtradeBot(LoggingMixin): trade_base_currency = self.exchange.get_pair_base_currency(pair) wallet_amount = self.wallets.get_free(trade_base_currency) logger.debug(f"{pair} - Wallet: {wallet_amount} - Trade-amount: {amount}") + # TODO-lev: Get wallet amount + value of positions if wallet_amount >= amount or self.trading_mode == TradingMode.FUTURES: # A safe exit amount isn't needed for futures, you can just exit/close the position return amount diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index c24f6e5db..c1dad72d5 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -127,6 +127,8 @@ class Backtesting: self.config['startup_candle_count'] = self.required_startup self.exchange.validate_required_startup_candles(self.required_startup, self.timeframe) + # TODO-lev: This should come from the configuration setting or better a + # TODO-lev: combination of config/strategy "use_shorts"(?) and "can_short" from the exchange self.trading_mode = TradingMode(config.get('trading_mode', 'spot')) self._can_short = self.trading_mode != TradingMode.SPOT