Default to proposed stake

This commit is contained in:
Matthias 2021-07-11 14:10:41 +02:00
parent 0e4466ca1e
commit 7ea0a74c53
5 changed files with 37 additions and 5 deletions

View File

@ -523,7 +523,7 @@ class AwesomeStrategy(IStrategy):
### Stake size management ### Stake size management
It is possible to manage your risk by reducing or increasing or reducing stake amount when placing a new trade. It is possible to manage your risk by reducing or increasing stake amount when placing a new trade.
```python ```python
class AwesomeStrategy(IStrategy): class AwesomeStrategy(IStrategy):
@ -546,8 +546,10 @@ class AwesomeStrategy(IStrategy):
return proposed_stake return proposed_stake
``` ```
Freqtrade will fall back to the `proposed_stake` value should your code raise an exception. The exception itself will be logged.
!!! Tip !!! Tip
You do not _have_ to ensure that `min_stake <= returned_value <= max_stake`. Trades will succeed, as returned value will be clamped to supported range and this acton will be logged. You do not _have_ to ensure that `min_stake <= returned_value <= max_stake`. Trades will succeed as the returned value will be clamped to supported range and this acton will be logged.
!!! Tip !!! Tip
Returning `0` or `None` will prevent trades from being placed. Returning `0` or `None` will prevent trades from being placed.

View File

@ -486,7 +486,7 @@ class FreqtradeBot(LoggingMixin):
if not self.edge: if not self.edge:
max_stake_amount = self.wallets.get_available_stake_amount() max_stake_amount = self.wallets.get_available_stake_amount()
stake_amount = strategy_safe_wrapper(self.strategy.custom_stake_amount, stake_amount = strategy_safe_wrapper(self.strategy.custom_stake_amount,
default_retval=None)( default_retval=stake_amount)(
pair=pair, current_time=datetime.now(timezone.utc), pair=pair, current_time=datetime.now(timezone.utc),
current_rate=buy_limit_requested, proposed_stake=stake_amount, current_rate=buy_limit_requested, proposed_stake=stake_amount,
min_stake=min_stake_amount, max_stake=max_stake_amount) min_stake=min_stake_amount, max_stake=max_stake_amount)

View File

@ -319,7 +319,7 @@ class Backtesting:
max_stake_amount = self.wallets.get_available_stake_amount() max_stake_amount = self.wallets.get_available_stake_amount()
stake_amount = strategy_safe_wrapper(self.strategy.custom_stake_amount, stake_amount = strategy_safe_wrapper(self.strategy.custom_stake_amount,
default_retval=None)( default_retval=stake_amount)(
pair=pair, current_time=row[DATE_IDX].to_pydatetime(), current_rate=row[OPEN_IDX], pair=pair, current_time=row[DATE_IDX].to_pydatetime(), current_rate=row[OPEN_IDX],
proposed_stake=stake_amount, min_stake=min_stake_amount, max_stake=max_stake_amount) proposed_stake=stake_amount, min_stake=min_stake_amount, max_stake=max_stake_amount)
stake_amount = self.wallets._validate_stake_amount(pair, stake_amount, min_stake_amount) stake_amount = self.wallets._validate_stake_amount(pair, stake_amount, min_stake_amount)

View File

@ -496,6 +496,17 @@ def test_backtest__enter_trade(default_conf, fee, mocker) -> None:
trade = backtesting._enter_trade(pair, row=row) trade = backtesting._enter_trade(pair, row=row)
assert trade is not None assert trade is not None
backtesting.strategy.custom_stake_amount = lambda **kwargs: 123.5
trade = backtesting._enter_trade(pair, row=row)
assert trade
assert trade.stake_amount == 123.5
# In case of error - use proposed stake
backtesting.strategy.custom_stake_amount = lambda **kwargs: 20 / 0
trade = backtesting._enter_trade(pair, row=row)
assert trade
assert trade.stake_amount == 495
# Stake-amount too high! # Stake-amount too high!
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=600.0) mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=600.0)

View File

@ -397,7 +397,7 @@ def test_create_trade_minimal_amount(default_conf, ticker, limit_buy_order_open,
def test_create_trade_too_small_stake_amount(default_conf, ticker, limit_buy_order_open, def test_create_trade_too_small_stake_amount(default_conf, ticker, limit_buy_order_open,
fee, mocker) -> None: fee, mocker, caplog) -> None:
patch_RPCManager(mocker) patch_RPCManager(mocker)
patch_exchange(mocker) patch_exchange(mocker)
buy_mock = MagicMock(return_value=limit_buy_order_open) buy_mock = MagicMock(return_value=limit_buy_order_open)
@ -414,6 +414,7 @@ def test_create_trade_too_small_stake_amount(default_conf, ticker, limit_buy_ord
patch_get_signal(freqtrade) patch_get_signal(freqtrade)
assert freqtrade.create_trade('ETH/BTC') assert freqtrade.create_trade('ETH/BTC')
assert log_has_re(r"Stake amount for pair .* is too small.*", caplog)
def test_create_trade_zero_stake_amount(default_conf, ticker, limit_buy_order_open, def test_create_trade_zero_stake_amount(default_conf, ticker, limit_buy_order_open,
@ -862,6 +863,24 @@ def test_execute_buy(mocker, default_conf, fee, limit_buy_order, limit_buy_order
assert trade.open_rate == 0.5 assert trade.open_rate == 0.5
assert trade.stake_amount == 40.495905365 assert trade.stake_amount == 40.495905365
# Test with custom stake
limit_buy_order['status'] = 'open'
limit_buy_order['id'] = '556'
freqtrade.strategy.custom_stake_amount = lambda **kwargs: 150.0
assert freqtrade.execute_buy(pair, stake_amount)
trade = Trade.query.all()[4]
assert trade
assert trade.stake_amount == 150
# Exception case
limit_buy_order['id'] = '557'
freqtrade.strategy.custom_stake_amount = lambda **kwargs: 20 / 0
assert freqtrade.execute_buy(pair, stake_amount)
trade = Trade.query.all()[5]
assert trade
assert trade.stake_amount == 2.0
# In case of the order is rejected and not filled at all # In case of the order is rejected and not filled at all
limit_buy_order['status'] = 'rejected' limit_buy_order['status'] = 'rejected'
limit_buy_order['amount'] = 90.99181073 limit_buy_order['amount'] = 90.99181073