diff --git a/config_examples/config_binance.example.json b/config_examples/config_binance.example.json index 151527d8e..05c872fbd 100644 --- a/config_examples/config_binance.example.json +++ b/config_examples/config_binance.example.json @@ -15,7 +15,7 @@ }, "entry_pricing": { "price_side": "same", - "ask_last_balance": 0.0, + "price_last_balance": 0.0, "use_order_book": true, "order_book_top": 1, "check_depth_of_market": { diff --git a/config_examples/config_bittrex.example.json b/config_examples/config_bittrex.example.json index 3c113ebe8..b694890d7 100644 --- a/config_examples/config_bittrex.example.json +++ b/config_examples/config_bittrex.example.json @@ -16,7 +16,7 @@ "entry_pricing": { "price_side": "same", "use_order_book": true, - "ask_last_balance": 0.0, + "price_last_balance": 0.0, "order_book_top": 1, "check_depth_of_market": { "enabled": false, diff --git a/config_examples/config_ftx.example.json b/config_examples/config_ftx.example.json index 5784f524b..afbce830f 100644 --- a/config_examples/config_ftx.example.json +++ b/config_examples/config_ftx.example.json @@ -15,7 +15,7 @@ }, "entry_pricing": { "price_side": "same", - "ask_last_balance": 0.0, + "price_last_balance": 0.0, "use_order_book": true, "order_book_top": 1, "check_depth_of_market": { diff --git a/config_examples/config_full.example.json b/config_examples/config_full.example.json index 63606953c..540e83af6 100644 --- a/config_examples/config_full.example.json +++ b/config_examples/config_full.example.json @@ -39,7 +39,7 @@ "price_side": "same", "use_order_book": true, "order_book_top": 1, - "ask_last_balance": 0.0, + "price_last_balance": 0.0, "check_depth_of_market": { "enabled": false, "bids_to_ask_delta": 1 @@ -48,7 +48,8 @@ "exit_pricing":{ "price_side": "same", "use_order_book": true, - "order_book_top": 1 + "order_book_top": 1, + "price_last_balance": 0.0 }, "order_types": { "entry": "limit", diff --git a/config_examples/config_kraken.example.json b/config_examples/config_kraken.example.json index 62fcf0c8a..912c1b912 100644 --- a/config_examples/config_kraken.example.json +++ b/config_examples/config_kraken.example.json @@ -16,7 +16,7 @@ "entry_pricing": { "price_side": "same", "use_order_book": true, - "ask_last_balance": 0.0, + "price_last_balance": 0.0, "order_book_top": 1, "check_depth_of_market": { "enabled": false, diff --git a/docs/configuration.md b/docs/configuration.md index cb0c2fdb8..8e38fa331 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -107,13 +107,13 @@ Mandatory parameters are marked as **Required**, which means that they are requi | `unfilledtimeout.unit` | Unit to use in unfilledtimeout setting. Note: If you set unfilledtimeout.unit to "seconds", "internals.process_throttle_secs" must be inferior or equal to timeout [Strategy Override](#parameters-in-the-strategy).
*Defaults to `minutes`.*
**Datatype:** String | `unfilledtimeout.exit_timeout_count` | How many times can exit orders time out. Once this number of timeouts is reached, an emergency sell is triggered. 0 to disable and allow unlimited order cancels. [Strategy Override](#parameters-in-the-strategy).
*Defaults to `0`.*
**Datatype:** Integer | `enter_pricing.price_side` | Select the side of the spread the bot should look at to get the entry rate. [More information below](#buy-price-side).
*Defaults to `same`.*
**Datatype:** String (either `ask`, `bid`, `same` or `other`). -| `enter_pricing.ask_last_balance` | **Required.** Interpolate the bidding price. More information [below](#buy-price-without-orderbook-enabled). +| `enter_pricing.price_last_balance` | **Required.** Interpolate the bidding price. More information [below](#buy-price-without-orderbook-enabled). | `enter_pricing.use_order_book` | Enable entering using the rates in [Order Book Bids](#buy-price-with-orderbook-enabled).
*Defaults to `True`.*
**Datatype:** Boolean | `enter_pricing.order_book_top` | Bot will use the top N rate in Order Book "price_side" to enter a trade. I.e. a value of 2 will allow the bot to pick the 2nd entry in [Order Book Bids](#buy-price-with-orderbook-enabled).
*Defaults to `1`.*
**Datatype:** Positive Integer | `enter_pricing. check_depth_of_market.enabled` | Do not enter if the difference of buy orders and sell orders is met in Order Book. [Check market depth](#check-depth-of-market).
*Defaults to `false`.*
**Datatype:** Boolean | `enter_pricing. check_depth_of_market.bids_to_ask_delta` | The difference ratio of buy orders and sell orders found in Order Book. A value below 1 means sell order size is greater, while value greater than 1 means buy order size is higher. [Check market depth](#check-depth-of-market)
*Defaults to `0`.*
**Datatype:** Float (as ratio) | `exit_pricing.price_side` | Select the side of the spread the bot should look at to get the exit rate. [More information below](#sell-price-side).
*Defaults to `same`.*
**Datatype:** String (either `ask`, `bid`, `same` or `other`). -| `exit_pricing.bid_last_balance` | Interpolate the exiting price. More information [below](#sell-price-without-orderbook-enabled). +| `exit_pricing.price_last_balance` | Interpolate the exiting price. More information [below](#sell-price-without-orderbook-enabled). | `exit_pricing.use_order_book` | Enable exiting of open trades using [Order Book Asks](#sell-price-with-orderbook-enabled).
*Defaults to `True`.*
**Datatype:** Boolean | `exit_pricing.order_book_top` | Bot will use the top N rate in Order Book "price_side" to sell. I.e. a value of 2 will allow the bot to pick the 2nd ask rate in [Order Book Asks](#sell-price-with-orderbook-enabled)
*Defaults to `1`.*
**Datatype:** Positive Integer | `use_sell_signal` | Use sell signals produced by the strategy in addition to the `minimal_roi`. [Strategy Override](#parameters-in-the-strategy).
*Defaults to `true`.*
**Datatype:** Boolean diff --git a/docs/includes/pricing.md b/docs/includes/pricing.md index 8a551d8a9..6e92564b9 100644 --- a/docs/includes/pricing.md +++ b/docs/includes/pricing.md @@ -53,9 +53,9 @@ When buying with the orderbook enabled (`bid_strategy.use_order_book=True`), Fre The following section uses `side` as the configured `bid_strategy.price_side` (defaults to `"bid"`). -When not using orderbook (`bid_strategy.use_order_book=False`), Freqtrade uses the best `side` price from the ticker if it's below the `last` traded price from the ticker. Otherwise (when the `side` price is above the `last` price), it calculates a rate between `side` and `last` price based on `bid_strategy.ask_last_balance`.. +When not using orderbook (`bid_strategy.use_order_book=False`), Freqtrade uses the best `side` price from the ticker if it's below the `last` traded price from the ticker. Otherwise (when the `side` price is above the `last` price), it calculates a rate between `side` and `last` price based on `bid_strategy.price_last_balance`.. -The `bid_strategy.ask_last_balance` configuration parameter controls this. A value of `0.0` will use `side` price, while `1.0` will use the `last` price and values between those interpolate between ask and last price. +The `bid_strategy.price_last_balance` configuration parameter controls this. A value of `0.0` will use `side` price, while `1.0` will use the `last` price and values between those interpolate between ask and last price. ### Sell price @@ -90,9 +90,9 @@ When selling with the orderbook enabled (`ask_strategy.use_order_book=True`), Fr The following section uses `side` as the configured `ask_strategy.price_side` (defaults to `"ask"`). -When not using orderbook (`ask_strategy.use_order_book=False`), Freqtrade uses the best `side` price from the ticker if it's above the `last` traded price from the ticker. Otherwise (when the `side` price is below the `last` price), it calculates a rate between `side` and `last` price based on `ask_strategy.bid_last_balance`. +When not using orderbook (`ask_strategy.use_order_book=False`), Freqtrade uses the best `side` price from the ticker if it's above the `last` traded price from the ticker. Otherwise (when the `side` price is below the `last` price), it calculates a rate between `side` and `last` price based on `ask_strategy.price_last_balance`. -The `ask_strategy.bid_last_balance` configuration parameter controls this. A value of `0.0` will use `side` price, while `1.0` will use the last price and values between those interpolate between `side` and last price. +The `ask_strategy.price_last_balance` configuration parameter controls this. A value of `0.0` will use `side` price, while `1.0` will use the last price and values between those interpolate between `side` and last price. ### Market order pricing diff --git a/docs/strategy_migration.md b/docs/strategy_migration.md index fbaba89cd..88bda90e4 100644 --- a/docs/strategy_migration.md +++ b/docs/strategy_migration.md @@ -337,10 +337,11 @@ unfilledtimeout = { #### `order pricing` Order pricing changed in 2 ways. `bid_strategy` was renamed to `entry_strategy` and `ask_strategy` was renamed to `exit_strategy`. +The attributes `ask_last_balance` -> `price_last_balance` and `bid_last_balance` -> `price_last_balance` were renamed as well. Also, price-side can now be defined as `ask`, `bid`, `same` or `other`. Please refer to the [pricing documentation](configuration.md) for more information. -``` json hl_lines="2-3 12-13" +``` json hl_lines="2-3 6 12-13 16" { "bid_strategy": { "price_side": "bid", @@ -355,20 +356,21 @@ Please refer to the [pricing documentation](configuration.md) for more informati "ask_strategy":{ "price_side": "ask", "use_order_book": true, - "order_book_top": 1 + "order_book_top": 1, + "bid_last_balance": 0.0 } } ``` after: -``` json hl_lines="2-3 12-13" +``` json hl_lines="2-3 6 12-13 16" { "entry_pricing": { "price_side": "same", "use_order_book": true, "order_book_top": 1, - "ask_last_balance": 0.0, + "price_last_balance": 0.0, "check_depth_of_market": { "enabled": false, "bids_to_ask_delta": 1 @@ -377,7 +379,8 @@ after: "exit_pricing":{ "price_side": "same", "use_order_book": true, - "order_book_top": 1 + "order_book_top": 1, + "price_last_balance": 0.0 } } ``` diff --git a/freqtrade/configuration/config_validation.py b/freqtrade/configuration/config_validation.py index 07da88a01..09e7b3335 100644 --- a/freqtrade/configuration/config_validation.py +++ b/freqtrade/configuration/config_validation.py @@ -297,9 +297,18 @@ def _validate_pricing_rules(conf: Dict[str, Any]) -> None: ) conf['entry_pricing'] = {} for obj in list(conf.get('bid_strategy', {}).keys()): - process_deprecated_setting(conf, 'bid_strategy', obj, 'entry_pricing', obj) + if obj == 'ask_last_balance': + process_deprecated_setting(conf, 'bid_strategy', obj, + 'entry_pricing', 'price_last_balance') + else: + process_deprecated_setting(conf, 'bid_strategy', obj, 'entry_pricing', obj) del conf['bid_strategy'] + conf['exit_pricing'] = {} for obj in list(conf.get('ask_strategy', {}).keys()): - process_deprecated_setting(conf, 'ask_strategy', obj, 'exit_pricing', obj) + if obj == 'bid_last_balance': + process_deprecated_setting(conf, 'ask_strategy', obj, + 'exit_pricing', 'price_last_balance') + else: + process_deprecated_setting(conf, 'ask_strategy', obj, 'exit_pricing', obj) del conf['ask_strategy'] diff --git a/freqtrade/constants.py b/freqtrade/constants.py index 19abadc5f..a06e2771f 100644 --- a/freqtrade/constants.py +++ b/freqtrade/constants.py @@ -174,7 +174,7 @@ CONF_SCHEMA = { 'entry_pricing': { 'type': 'object', 'properties': { - 'ask_last_balance': { + 'price_last_balance': { 'type': 'number', 'minimum': 0, 'maximum': 1, @@ -197,7 +197,7 @@ CONF_SCHEMA = { 'type': 'object', 'properties': { 'price_side': {'type': 'string', 'enum': PRICING_SIDES, 'default': 'same'}, - 'bid_last_balance': { + 'price_last_balance': { 'type': 'number', 'minimum': 0, 'maximum': 1, diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 1b0d556b7..fc8174e62 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -1503,10 +1503,10 @@ class Exchange: ticker_rate = ticker[price_side] if ticker['last'] and ticker_rate: if side == 'entry' and ticker_rate > ticker['last']: - balance = conf_strategy.get('ask_last_balance', 0.0) + balance = conf_strategy.get('price_last_balance', 0.0) ticker_rate = ticker_rate + balance * (ticker['last'] - ticker_rate) elif side == 'exit' and ticker_rate < ticker['last']: - balance = conf_strategy.get('bid_last_balance', 0.0) + balance = conf_strategy.get('price_last_balance', 0.0) ticker_rate = ticker_rate - balance * (ticker_rate - ticker['last']) rate = ticker_rate diff --git a/freqtrade/templates/base_config.json.j2 b/freqtrade/templates/base_config.json.j2 index dd6723642..49af62cb3 100644 --- a/freqtrade/templates/base_config.json.j2 +++ b/freqtrade/templates/base_config.json.j2 @@ -23,8 +23,8 @@ }, "entry_pricing": { "price_side": "same", - "ask_last_balance": 0.0, "use_order_book": true, + "price_last_balance": 0.0, "order_book_top": 1, "check_depth_of_market": { "enabled": false, diff --git a/tests/conftest.py b/tests/conftest.py index 489c8b5b3..b00feb14b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -420,7 +420,7 @@ def get_default_conf(testdatadir): "exit": 30 }, "entry_pricing": { - "ask_last_balance": 0.0, + "price_last_balance": 0.0, "use_order_book": False, "order_book_top": 1, "check_depth_of_market": { diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index 2faa27417..ac736f4ae 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -2283,7 +2283,7 @@ def test_fetch_l2_order_book_exception(default_conf, mocker, exchange_name): ('ask', 20, 19, 10, 0.3, 17), # Between ask and last ('ask', 5, 6, 10, 1.0, 5), # last bigger than ask ('ask', 5, 6, 10, 0.5, 5), # last bigger than ask - ('ask', 20, 19, 10, None, 20), # ask_last_balance missing + ('ask', 20, 19, 10, None, 20), # price_last_balance missing ('ask', 10, 20, None, 0.5, 10), # last not available - uses ask ('ask', 4, 5, None, 0.5, 4), # last not available - uses ask ('ask', 4, 5, None, 1, 4), # last not available - uses ask @@ -2294,7 +2294,7 @@ def test_fetch_l2_order_book_exception(default_conf, mocker, exchange_name): ('bid', 21, 20, 10, 0.7, 13), # Between bid and last ('bid', 21, 20, 10, 0.3, 17), # Between bid and last ('bid', 6, 5, 10, 1.0, 5), # last bigger than bid - ('bid', 21, 20, 10, None, 20), # ask_last_balance missing + ('bid', 21, 20, 10, None, 20), # price_last_balance missing ('bid', 6, 5, 10, 0.5, 5), # last bigger than bid ('bid', 21, 20, None, 0.5, 20), # last not available - uses bid ('bid', 6, 5, None, 0.5, 5), # last not available - uses bid @@ -2305,9 +2305,9 @@ def test_get_entry_rate(mocker, default_conf, caplog, side, ask, bid, last, last_ab, expected) -> None: caplog.set_level(logging.DEBUG) if last_ab is None: - del default_conf['entry_pricing']['ask_last_balance'] + del default_conf['entry_pricing']['price_last_balance'] else: - default_conf['entry_pricing']['ask_last_balance'] = last_ab + default_conf['entry_pricing']['price_last_balance'] = last_ab default_conf['entry_pricing']['price_side'] = side exchange = get_patched_exchange(mocker, default_conf) mocker.patch('freqtrade.exchange.Exchange.fetch_ticker', @@ -2351,7 +2351,7 @@ def test_get_exit_rate(default_conf, mocker, caplog, side, bid, ask, default_conf['exit_pricing']['price_side'] = side if last_ab is not None: - default_conf['exit_pricing']['bid_last_balance'] = last_ab + default_conf['exit_pricing']['price_last_balance'] = last_ab mocker.patch('freqtrade.exchange.Exchange.fetch_ticker', return_value={'ask': ask, 'bid': bid, 'last': last}) pair = "ETH/BTC" @@ -2381,10 +2381,10 @@ def test_get_exit_rate(default_conf, mocker, caplog, side, bid, ask, def test_get_ticker_rate_error(mocker, entry, default_conf, caplog, side, is_short, ask, bid, last, last_ab, expected) -> None: caplog.set_level(logging.DEBUG) - default_conf['entry_pricing']['ask_last_balance'] = last_ab + default_conf['entry_pricing']['price_last_balance'] = last_ab default_conf['entry_pricing']['price_side'] = side default_conf['exit_pricing']['price_side'] = side - default_conf['exit_pricing']['ask_last_balance'] = last_ab + default_conf['exit_pricing']['price_last_balance'] = last_ab exchange = get_patched_exchange(mocker, default_conf) mocker.patch('freqtrade.exchange.Exchange.fetch_ticker', return_value={'ask': ask, 'last': last, 'bid': bid}) diff --git a/tests/test_configuration.py b/tests/test_configuration.py index 1f5370d85..3783e30a1 100644 --- a/tests/test_configuration.py +++ b/tests/test_configuration.py @@ -1031,10 +1031,12 @@ def test__validate_pricing_rules(default_conf, caplog) -> None: def_conf['ask_strategy'] = { 'price_side': 'ask', 'use_order_book': True, + 'bid_last_balance': 0.5 } def_conf['bid_strategy'] = { 'price_side': 'bid', 'use_order_book': False, + 'ask_last_balance': 0.7 } conf = deepcopy(def_conf) @@ -1043,8 +1045,10 @@ def test__validate_pricing_rules(default_conf, caplog) -> None: r"DEPRECATED: Using 'ask_strategy' and 'bid_strategy' is.*", caplog) assert conf['exit_pricing']['price_side'] == 'ask' assert conf['exit_pricing']['use_order_book'] is True + assert conf['exit_pricing']['price_last_balance'] == 0.5 assert conf['entry_pricing']['price_side'] == 'bid' assert conf['entry_pricing']['use_order_book'] is False + assert conf['entry_pricing']['price_last_balance'] == 0.7 assert 'ask_strategy' not in conf assert 'bid_strategy' not in conf diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index 47ee29219..6e5b8a119 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -4491,7 +4491,7 @@ def test_order_book_entry_pricing1(mocker, default_conf_usdt, order_book_l2, exc default_conf_usdt['exchange']['name'] = 'binance' default_conf_usdt['entry_pricing']['use_order_book'] = True default_conf_usdt['entry_pricing']['order_book_top'] = order_book_top - default_conf_usdt['entry_pricing']['ask_last_balance'] = 0 + default_conf_usdt['entry_pricing']['price_last_balance'] = 0 default_conf_usdt['telegram']['enabled'] = False freqtrade = FreqtradeBot(default_conf_usdt)