From fab19ae3a7e0bf554f102ba292fc7199268aa847 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 10 Jan 2020 06:36:28 +0100 Subject: [PATCH] Implement last_stake_amount_min_ratio --- config_full.json.example | 1 + docs/configuration.md | 6 +++++- freqtrade/constants.py | 4 ++++ freqtrade/freqtradebot.py | 7 ++++++- tests/test_freqtradebot.py | 18 ++++++++++++------ 5 files changed, 28 insertions(+), 8 deletions(-) diff --git a/config_full.json.example b/config_full.json.example index f39abb00c..82d8bd04a 100644 --- a/config_full.json.example +++ b/config_full.json.example @@ -6,6 +6,7 @@ "fiat_display_currency": "USD", "amount_reserve_percent" : 0.05, "amend_last_stake_amount": false, + "last_stake_amount_min_ratio": 0.5, "dry_run": false, "ticker_interval": "5m", "trailing_stop": false, diff --git a/docs/configuration.md b/docs/configuration.md index a0e7610f6..e609f89d9 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -45,6 +45,7 @@ Mandatory parameters are marked as **Required**, which means that they are requi | `stake_amount` | **Required.** Amount of crypto-currency your bot will use for each trade. Set it to `"unlimited"` to allow the bot to use all available balance. [More information below](#configuring-amount-per-trade). [Strategy Override](#parameters-in-the-strategy).
***Datatype:*** *Positive float or `"unlimited"`.* | `tradable_balance_ratio` | Ratio of the total account balance the bot is allowed to trade. [More information below](#configuring-amount-per-trade).
*Defaults to `0.99` 99%).*
***Datatype:*** *Positive float between `0.1` and `1.0`.* | `amend_last_stake_amount` | **Required.** Use reduced last stake amount if necessary. [More information below](#configuring-amount-per-trade).
*Defaults to `false`.*
***Datatype:*** *Boolean* +| `last_stake_amount_min_ratio` | **Required.** Minimum amount that has to be left. Applies only to "last_stake_amount" if `amend_last_stake_amount=True` [More information below](#configuring-amount-per-trade).
*Defaults to `0.5`.*
***Datatype:*** *Float (as ratio)* | `amount_reserve_percent` | Reserve some amount in min pair stake amount. The bot will reserve `amount_reserve_percent` + stoploss value when calculating min pair stake amount in order to avoid possible trade refusals.
*Defaults to `0.05` (5%).*
***Datatype:*** *Positive Float as ratio.* | `ticker_interval` | The ticker interval to use (e.g `1m`, `5m`, `15m`, `30m`, `1h` ...). [Strategy Override](#parameters-in-the-strategy).
***Datatype:*** *String* | `fiat_display_currency` | Fiat currency used to show your profits. [More information below](#what-values-can-be-used-for-fiat_display_currency).
***Datatype:*** *String* @@ -149,7 +150,7 @@ For example, if you have 10 ETH available in your wallet on the exchange and `tr #### Amend last stake amount -Assuming we have the tradable balance of 1000 USDT, `stake_amount=400`, and `max_open_trades=3` (This example assumes `tradable_balance_ratio=1`). +Assuming we have the tradable balance of 1000 USDT, `stake_amount=400`, and `max_open_trades=3`. The bot would open 2 trades, and will be unable to fill the last trading slot, since the requested 400 USDT are no longer available, since 800 USDT are already tied in other trades. To overcome this, the option `amend_last_stake_amount` can be set to `True`, which will enable the bot to reduce stake_amount to the available balance in order to fill the last trade slot. @@ -163,6 +164,9 @@ In the example above this would mean: !!! Note This option only applies with [Static stake amount](#static-stake-amount) - since [Dynamic stake amount](#dynamic-stake-amount) divides the balances evenly. +!!! Note + The minimum last stake amount can be configured using `amend_last_stake_amount` - which defaults to 0.5 (50%). This means that the minimum stake-amount that's ever used is `stake_amount * 0.5`. This avoids very low stake-amounts, close to the minimum tradable amount. + #### Static stake amount The `stake_amount` configuration statically configures the amount of stake-currency your bot will use for each trade. diff --git a/freqtrade/constants.py b/freqtrade/constants.py index a1bd70183..e9c103db9 100644 --- a/freqtrade/constants.py +++ b/freqtrade/constants.py @@ -80,6 +80,9 @@ CONF_SCHEMA = { 'default': 0.99 }, 'amend_last_stake_amount': {'type': 'boolean', 'default': False}, + 'last_stake_amount_min_ratio': { + 'type': 'number', 'minimum': 0.0, 'maximum': 1.0, 'default': 0.5 + }, 'fiat_display_currency': {'type': 'string', 'enum': SUPPORTED_FIAT}, 'dry_run': {'type': 'boolean'}, 'dry_run_wallet': {'type': 'number', 'default': DRY_RUN_WALLET}, @@ -284,6 +287,7 @@ SCHEMA_TRADE_REQUIRED = [ 'stake_currency', 'stake_amount', 'tradable_balance_ratio', + 'last_stake_amount_min_ratio', 'dry_run', 'dry_run_wallet', 'bid_strategy', diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 06f435421..e3f2616a2 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -312,7 +312,12 @@ class FreqtradeBot: available_amount = self._get_available_stake_amount() if self.config['amend_last_stake_amount']: - stake_amount = min(stake_amount, available_amount) + # Remaining amount needs to be at least stake_amount * last_stake_amount_min_ratio + # Otherwise the remaining amount is too low to trade. + if available_amount > (stake_amount * self.config['last_stake_amount_min_ratio']): + stake_amount = min(stake_amount, available_amount) + else: + stake_amount = 0 if available_amount < stake_amount: raise DependencyException( diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index 6d794fc05..58f88198a 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -140,14 +140,18 @@ def test_get_trade_stake_amount(default_conf, ticker, mocker) -> None: assert result == default_conf['stake_amount'] -@pytest.mark.parametrize("amend_last,wallet,max_open,expected", [ - (False, 0.002, 2, [0.001, None]), - (True, 0.002, 2, [0.001, 0.00098]), - (False, 0.003, 3, [0.001, 0.001, None]), - (True, 0.003, 3, [0.001, 0.001, 0.00097]), +@pytest.mark.parametrize("amend_last,wallet,max_open,lsamr,expected", [ + (False, 0.002, 2, 0.5, [0.001, None]), + (True, 0.002, 2, 0.5, [0.001, 0.00098]), + (False, 0.003, 3, 0.5, [0.001, 0.001, None]), + (True, 0.003, 3, 0.5, [0.001, 0.001, 0.00097]), + (False, 0.0022, 3, 0.5, [0.001, 0.001, None]), + (True, 0.0022, 3, 0.5, [0.001, 0.001, 0.0]), + (True, 0.0027, 3, 0.5, [0.001, 0.001, 0.000673]), + (True, 0.0022, 3, 1, [0.001, 0.001, 0.0]), ]) def test_check_available_stake_amount(default_conf, ticker, mocker, fee, limit_buy_order, - amend_last, wallet, max_open, expected) -> None: + amend_last, wallet, max_open, lsamr, expected) -> None: patch_RPCManager(mocker) patch_exchange(mocker) mocker.patch.multiple( @@ -160,6 +164,8 @@ def test_check_available_stake_amount(default_conf, ticker, mocker, fee, limit_b default_conf['dry_run_wallet'] = wallet default_conf['amend_last_stake_amount'] = amend_last + default_conf['last_stake_amount_min_ratio'] = lsamr + freqtrade = FreqtradeBot(default_conf) for i in range(0, max_open):