From 0eff324ce04d6b19e41908edf6b00065b1fcd20b Mon Sep 17 00:00:00 2001 From: Gianluca Puglia Date: Wed, 20 Mar 2019 18:38:10 +0100 Subject: [PATCH 01/14] Use dedicated index for every pair --- freqtrade/optimize/backtesting.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 031b490c8..8d0768d43 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -10,7 +10,7 @@ from datetime import datetime, timedelta from pathlib import Path from typing import Any, Dict, List, NamedTuple, Optional -from pandas import DataFrame +from pandas import DataFrame, Timestamp from tabulate import tabulate from freqtrade import optimize @@ -325,19 +325,29 @@ class Backtesting(object): pairs.append(pair) lock_pair_until: Dict = {} + indexes: Dict = {} tmp = start_date + timedelta(minutes=self.ticker_interval_mins) - index = 0 + # Loop timerange and test per pair while tmp < end_date: # print(f"time: {tmp}") + for i, pair in enumerate(ticker): + if pair not in indexes: + indexes[pair] = 0 + try: - row = ticker[pair][index] + row = ticker[pair][indexes[pair]] except IndexError: # missing Data for one pair ... # Warnings for this are shown by `validate_backtest_data` continue + if row.date > Timestamp(tmp.datetime): + continue + + indexes[pair] += 1 + if row.buy == 0 or row.sell == 1: continue # skip rows where no buy signal or that would immediately sell off @@ -351,7 +361,7 @@ class Backtesting(object): trade_count_lock[row.date] = trade_count_lock.get(row.date, 0) + 1 - trade_entry = self._get_sell_trade_entry(pair, row, ticker[pair][index + 1:], + trade_entry = self._get_sell_trade_entry(pair, row, ticker[pair][indexes[pair]:], trade_count_lock, args) if trade_entry: @@ -359,11 +369,9 @@ class Backtesting(object): trades.append(trade_entry) else: # Set lock_pair_until to end of testing period if trade could not be closed - # This happens only if the buy-signal was with the last candle - lock_pair_until[pair] = end_date + lock_pair_until[pair] = Timestamp(end_date.datetime) tmp += timedelta(minutes=self.ticker_interval_mins) - index += 1 return DataFrame.from_records(trades, columns=BacktestResult._fields) def start(self) -> None: From 6b89e86a97de6fc81cd0212e82e3267a339fc9d0 Mon Sep 17 00:00:00 2001 From: Gianluca Puglia Date: Wed, 20 Mar 2019 19:44:59 +0100 Subject: [PATCH 02/14] Removed Timestamp cast --- freqtrade/optimize/backtesting.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 8d0768d43..f54560a0e 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -10,7 +10,7 @@ from datetime import datetime, timedelta from pathlib import Path from typing import Any, Dict, List, NamedTuple, Optional -from pandas import DataFrame, Timestamp +from pandas import DataFrame from tabulate import tabulate from freqtrade import optimize @@ -343,7 +343,7 @@ class Backtesting(object): # Warnings for this are shown by `validate_backtest_data` continue - if row.date > Timestamp(tmp.datetime): + if row.date > tmp.datetime: continue indexes[pair] += 1 @@ -369,7 +369,7 @@ class Backtesting(object): trades.append(trade_entry) else: # Set lock_pair_until to end of testing period if trade could not be closed - lock_pair_until[pair] = Timestamp(end_date.datetime) + lock_pair_until[pair] = end_date.datetime tmp += timedelta(minutes=self.ticker_interval_mins) return DataFrame.from_records(trades, columns=BacktestResult._fields) From 05466d318a2f3971bff4e234ecbc7aa00e57f419 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 23 Mar 2019 14:50:18 +0100 Subject: [PATCH 03/14] Modify test to check for this condition --- freqtrade/tests/optimize/test_backtesting.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/freqtrade/tests/optimize/test_backtesting.py b/freqtrade/tests/optimize/test_backtesting.py index 40754cfbc..531f73916 100644 --- a/freqtrade/tests/optimize/test_backtesting.py +++ b/freqtrade/tests/optimize/test_backtesting.py @@ -683,18 +683,20 @@ def test_backtest_alternate_buy_sell(default_conf, fee, mocker): assert len(results.loc[results.open_at_end]) == 0 -def test_backtest_multi_pair(default_conf, fee, mocker): +@pytest.mark.parametrize("pair", ['ADA/BTC', 'LTC/BTC']) +@pytest.mark.parametrize("tres", [0, 20, 30]) +def test_backtest_multi_pair(default_conf, fee, mocker, tres, pair): def _trend_alternate_hold(dataframe=None, metadata=None): """ - Buy every 8th candle - sell every other 8th -2 (hold on to pairs a bit) + Buy every xth candle - sell every other xth -2 (hold on to pairs a bit)flake """ - multi = 8 + if metadata['pair'] in('ETH/BTC', 'LTC/BTC'): + multi = 20 + else: + multi = 18 dataframe['buy'] = np.where(dataframe.index % multi == 0, 1, 0) dataframe['sell'] = np.where((dataframe.index + multi - 2) % multi == 0, 1, 0) - if metadata['pair'] in('ETH/BTC', 'LTC/BTC'): - dataframe['buy'] = dataframe['buy'].shift(-4) - dataframe['sell'] = dataframe['sell'].shift(-4) return dataframe mocker.patch('freqtrade.exchange.Exchange.get_fee', fee) @@ -702,6 +704,7 @@ def test_backtest_multi_pair(default_conf, fee, mocker): pairs = ['ADA/BTC', 'DASH/BTC', 'ETH/BTC', 'LTC/BTC', 'NXT/BTC'] data = history.load_data(datadir=None, ticker_interval='5m', pairs=pairs) data = trim_dictlist(data, -500) + data[pair] = data[pair][tres:] # We need to enable sell-signal - otherwise it sells on ROI!! default_conf['experimental'] = {"use_sell_signal": True} default_conf['ticker_interval'] = '5m' From 00e6749d8bf8e7fc9c8924d0525d855acc8a72ea Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 23 Mar 2019 15:00:07 +0100 Subject: [PATCH 04/14] Refactor backtest() to be a bit more concise --- freqtrade/optimize/backtesting.py | 47 ++++++++++++++++++------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index f54560a0e..f3661ab32 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -202,6 +202,32 @@ class Backtesting(object): logger.info('Dumping backtest results to %s', recordfilename) file_dump_json(recordfilename, records) + def _get_ticker_list(self, processed) -> Dict[str, DataFrame]: + """ + Helper function to convert a processed tickerlist into a list for performance reasons. + + Used by backtest() - so keep this optimized for performance. + """ + headers = ['date', 'buy', 'open', 'close', 'sell', 'low', 'high'] + ticker: Dict = {} + # Create ticker dict + for pair, pair_data in processed.items(): + pair_data['buy'], pair_data['sell'] = 0, 0 # cleanup from previous run + + ticker_data = self.advise_sell( + self.advise_buy(pair_data, {'pair': pair}), {'pair': pair})[headers].copy() + + # to avoid using data from future, we buy/sell with signal from previous candle + ticker_data.loc[:, 'buy'] = ticker_data['buy'].shift(1) + ticker_data.loc[:, 'sell'] = ticker_data['sell'].shift(1) + + ticker_data.drop(ticker_data.head(1).index, inplace=True) + + # Convert from Pandas to list for performance reasons + # (Looping Pandas is slow.) + ticker[pair] = [x for x in ticker_data.itertuples()] + return ticker + def _get_sell_trade_entry( self, pair: str, buy_row: DataFrame, partial_ticker: List, trade_count_lock: Dict, args: Dict) -> Optional[BacktestResult]: @@ -296,7 +322,6 @@ class Backtesting(object): position_stacking: do we allow position stacking? (default: False) :return: DataFrame """ - headers = ['date', 'buy', 'open', 'close', 'sell', 'low', 'high'] processed = args['processed'] max_open_trades = args.get('max_open_trades', 0) position_stacking = args.get('position_stacking', False) @@ -304,25 +329,7 @@ class Backtesting(object): end_date = args['end_date'] trades = [] trade_count_lock: Dict = {} - ticker: Dict = {} - pairs = [] - # Create ticker dict - for pair, pair_data in processed.items(): - pair_data['buy'], pair_data['sell'] = 0, 0 # cleanup from previous run - - ticker_data = self.advise_sell( - self.advise_buy(pair_data, {'pair': pair}), {'pair': pair})[headers].copy() - - # to avoid using data from future, we buy/sell with signal from previous candle - ticker_data.loc[:, 'buy'] = ticker_data['buy'].shift(1) - ticker_data.loc[:, 'sell'] = ticker_data['sell'].shift(1) - - ticker_data.drop(ticker_data.head(1).index, inplace=True) - - # Convert from Pandas to list for performance reasons - # (Looping Pandas is slow.) - ticker[pair] = [x for x in ticker_data.itertuples()] - pairs.append(pair) + ticker: Dict = self._get_ticker_list(processed) lock_pair_until: Dict = {} indexes: Dict = {} From 40899d08dd76aca924c52ce02be418747468ef25 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 23 Mar 2019 15:24:11 +0100 Subject: [PATCH 05/14] Fix failing test (all timezones are in UTC, so we should not convert to None) --- freqtrade/tests/edge/test_edge.py | 4 ++-- freqtrade/tests/optimize/__init__.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/freqtrade/tests/edge/test_edge.py b/freqtrade/tests/edge/test_edge.py index c1c1b49cd..af8674188 100644 --- a/freqtrade/tests/edge/test_edge.py +++ b/freqtrade/tests/edge/test_edge.py @@ -122,8 +122,8 @@ def test_edge_results(edge_conf, mocker, caplog, data) -> None: for c, trade in enumerate(data.trades): res = results.iloc[c] assert res.exit_type == trade.sell_reason - assert res.open_time == _get_frame_time_from_offset(trade.open_tick) - assert res.close_time == _get_frame_time_from_offset(trade.close_tick) + assert arrow.get(res.open_time) == _get_frame_time_from_offset(trade.open_tick) + assert arrow.get(res.close_time) == _get_frame_time_from_offset(trade.close_tick) def test_adjust(mocker, edge_conf): diff --git a/freqtrade/tests/optimize/__init__.py b/freqtrade/tests/optimize/__init__.py index 129a09f40..b1bf55f50 100644 --- a/freqtrade/tests/optimize/__init__.py +++ b/freqtrade/tests/optimize/__init__.py @@ -32,7 +32,7 @@ class BTContainer(NamedTuple): def _get_frame_time_from_offset(offset): return ticker_start_time.shift(minutes=(offset * TICKER_INTERVAL_MINUTES[tests_ticker_interval]) - ).datetime.replace(tzinfo=None) + ).datetime def _build_backtest_dataframe(ticker_with_signals): From b2c2b42408753c0d2a976fbeb91aac094fbeef0f Mon Sep 17 00:00:00 2001 From: Gianluca Puglia Date: Tue, 26 Mar 2019 18:53:16 +0100 Subject: [PATCH 06/14] Removed unwanted comment --- freqtrade/tests/optimize/test_backtesting.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/tests/optimize/test_backtesting.py b/freqtrade/tests/optimize/test_backtesting.py index 531f73916..64a33fae2 100644 --- a/freqtrade/tests/optimize/test_backtesting.py +++ b/freqtrade/tests/optimize/test_backtesting.py @@ -689,7 +689,7 @@ def test_backtest_multi_pair(default_conf, fee, mocker, tres, pair): def _trend_alternate_hold(dataframe=None, metadata=None): """ - Buy every xth candle - sell every other xth -2 (hold on to pairs a bit)flake + Buy every xth candle - sell every other xth -2 (hold on to pairs a bit) """ if metadata['pair'] in('ETH/BTC', 'LTC/BTC'): multi = 20 From 0307ba7883c55eb7b2a763feda5373df39f9210c Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 3 Apr 2019 20:04:04 +0200 Subject: [PATCH 07/14] Remove one branch - python does lazy evaluation --- freqtrade/optimize/backtesting.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index f3661ab32..0fcfd11f1 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -337,7 +337,6 @@ class Backtesting(object): # Loop timerange and test per pair while tmp < end_date: - # print(f"time: {tmp}") for i, pair in enumerate(ticker): if pair not in indexes: @@ -358,9 +357,9 @@ class Backtesting(object): if row.buy == 0 or row.sell == 1: continue # skip rows where no buy signal or that would immediately sell off - if not position_stacking: - if pair in lock_pair_until and row.date <= lock_pair_until[pair]: - continue + if (not position_stacking and pair in lock_pair_until + and row.date <= lock_pair_until[pair]): + continue if max_open_trades > 0: # Check if max_open_trades has already been reached for the given date if not trade_count_lock.get(row.date, 0) < max_open_trades: From 32cbb714f9bfe415a737f8c908e41a802c4ac666 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 4 Apr 2019 19:44:03 +0200 Subject: [PATCH 08/14] Improve commenting on backtsting and backtest_multi_tst --- freqtrade/optimize/backtesting.py | 9 +++++++-- freqtrade/tests/optimize/test_backtesting.py | 4 ++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 0fcfd11f1..fc007ce2b 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -329,6 +329,8 @@ class Backtesting(object): end_date = args['end_date'] trades = [] trade_count_lock: Dict = {} + + # Dict of ticker-lists for performance (looping lists is a lot faster than dataframes) ticker: Dict = self._get_ticker_list(processed) lock_pair_until: Dict = {} @@ -345,10 +347,11 @@ class Backtesting(object): try: row = ticker[pair][indexes[pair]] except IndexError: - # missing Data for one pair ... + # missing Data for one pair at the end. # Warnings for this are shown by `validate_backtest_data` continue + # Waits until the time-counter reaches the start of the data for this pair. if row.date > tmp.datetime: continue @@ -359,12 +362,13 @@ class Backtesting(object): if (not position_stacking and pair in lock_pair_until and row.date <= lock_pair_until[pair]): + # without positionstacking, we can only have one open trade per pair. continue + if max_open_trades > 0: # Check if max_open_trades has already been reached for the given date if not trade_count_lock.get(row.date, 0) < max_open_trades: continue - trade_count_lock[row.date] = trade_count_lock.get(row.date, 0) + 1 trade_entry = self._get_sell_trade_entry(pair, row, ticker[pair][indexes[pair]:], @@ -377,6 +381,7 @@ class Backtesting(object): # Set lock_pair_until to end of testing period if trade could not be closed lock_pair_until[pair] = end_date.datetime + # Move time one configured time_interval ahead. tmp += timedelta(minutes=self.ticker_interval_mins) return DataFrame.from_records(trades, columns=BacktestResult._fields) diff --git a/freqtrade/tests/optimize/test_backtesting.py b/freqtrade/tests/optimize/test_backtesting.py index 64a33fae2..edfe02225 100644 --- a/freqtrade/tests/optimize/test_backtesting.py +++ b/freqtrade/tests/optimize/test_backtesting.py @@ -701,9 +701,13 @@ def test_backtest_multi_pair(default_conf, fee, mocker, tres, pair): mocker.patch('freqtrade.exchange.Exchange.get_fee', fee) patch_exchange(mocker) + pairs = ['ADA/BTC', 'DASH/BTC', 'ETH/BTC', 'LTC/BTC', 'NXT/BTC'] data = history.load_data(datadir=None, ticker_interval='5m', pairs=pairs) + # Only use 500 lines to increase performance data = trim_dictlist(data, -500) + + # Remove data for one pair from the beginning of the data data[pair] = data[pair][tres:] # We need to enable sell-signal - otherwise it sells on ROI!! default_conf['experimental'] = {"use_sell_signal": True} From 7010c835d24bdcd5cfa3420d56d68906b2cdb60e Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 4 Apr 2019 20:23:10 +0200 Subject: [PATCH 09/14] Improve commentign --- freqtrade/optimize/backtesting.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index fc007ce2b..bbbda9b1f 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -334,10 +334,11 @@ class Backtesting(object): ticker: Dict = self._get_ticker_list(processed) lock_pair_until: Dict = {} + # Indexes per pair, so some pairs are allowed to have a missing start. indexes: Dict = {} tmp = start_date + timedelta(minutes=self.ticker_interval_mins) - # Loop timerange and test per pair + # Loop timerange and get candle for each pair at that point in time while tmp < end_date: for i, pair in enumerate(ticker): From e3cdc0a05bcdc9ffd3901b73c64c54abf438de44 Mon Sep 17 00:00:00 2001 From: iuvbio Date: Thu, 4 Apr 2019 20:53:28 +0200 Subject: [PATCH 10/14] typos and visual fixes --- docs/sql_cheatsheet.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/sql_cheatsheet.md b/docs/sql_cheatsheet.md index 54f9b8213..803a2b48a 100644 --- a/docs/sql_cheatsheet.md +++ b/docs/sql_cheatsheet.md @@ -1,5 +1,5 @@ # SQL Helper -This page constains some help if you want to edit your sqlite db. +This page contains some help if you want to edit your sqlite db. ## Install sqlite3 **Ubuntu/Debian installation** @@ -66,11 +66,13 @@ SELECT * FROM trades; ## Fix trade still open after a manual sell on the exchange !!! Warning - Manually selling on the exchange should not be done by default, since the bot does not detect this and will try to sell anyway. - /foresell should accomplish the same thing. + Manually selling a pair on the exchange will not be detected by the bot and it will try to sell anyway. + Whenever possible, /forcesell should be used to accomplish the same thing. + + It is strongly advised to backup your database file before making any manual changes. !!! Note - This should not be necessary after /forcesell, as forcesell orders are closed automatically by the bot on the next iteration. + This should not be necessary after /forcesell, as forcesell orders are closed automatically by the bot on the next iteration. ```sql UPDATE trades From 7486cb7c64d6b50b5b934ffb2fa39fb3c215a8f3 Mon Sep 17 00:00:00 2001 From: iuvbio Date: Thu, 4 Apr 2019 21:05:26 +0200 Subject: [PATCH 11/14] fix admonitions --- docs/hyperopt.md | 4 ++-- docs/sql_cheatsheet.md | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/docs/hyperopt.md b/docs/hyperopt.md index e25f35c35..b4e42de16 100644 --- a/docs/hyperopt.md +++ b/docs/hyperopt.md @@ -62,7 +62,7 @@ If you have updated the buy strategy, ie. changed the contents of #### Sell optimization -Similar to the buy-signal above, sell-signals can also be optimized. +Similar to the buy-signal above, sell-signals can also be optimized. Place the corresponding settings into the following methods * Inside `sell_indicator_space()` - the parameters hyperopt shall be optimizing. @@ -163,7 +163,7 @@ running at least several thousand evaluations. The `--spaces all` flag determines that all possible parameters should be optimized. Possibilities are listed below. !!! Warning -When switching parameters or changing configuration options, the file `user_data/hyperopt_results.pickle` should be removed. It's used to be able to continue interrupted calculations, but does not detect changes to settings or the hyperopt file. + When switching parameters or changing configuration options, the file `user_data/hyperopt_results.pickle` should be removed. It's used to be able to continue interrupted calculations, but does not detect changes to settings or the hyperopt file. ### Execute Hyperopt with Different Ticker-Data Source diff --git a/docs/sql_cheatsheet.md b/docs/sql_cheatsheet.md index 803a2b48a..f41520bd9 100644 --- a/docs/sql_cheatsheet.md +++ b/docs/sql_cheatsheet.md @@ -66,9 +66,7 @@ SELECT * FROM trades; ## Fix trade still open after a manual sell on the exchange !!! Warning - Manually selling a pair on the exchange will not be detected by the bot and it will try to sell anyway. - Whenever possible, /forcesell should be used to accomplish the same thing. - + Manually selling a pair on the exchange will not be detected by the bot and it will try to sell anyway. Whenever possible, forcesell should be used to accomplish the same thing. It is strongly advised to backup your database file before making any manual changes. !!! Note From dbb1bbf1019657969d7bc68ff541f6c9ea128c0e Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 5 Apr 2019 06:47:03 +0200 Subject: [PATCH 12/14] Fix webhook documentation --- docs/webhook-config.md | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/docs/webhook-config.md b/docs/webhook-config.md index 2b5365e32..43b036c74 100644 --- a/docs/webhook-config.md +++ b/docs/webhook-config.md @@ -39,32 +39,30 @@ Different payloads can be configured for different events. Not all fields are ne The fields in `webhook.webhookbuy` are filled when the bot executes a buy. Parameters are filled using string.format. Possible parameters are: -* exchange -* pair -* limit -* stake_amount -* stake_amount_fiat -* stake_currency -* fiat_currency +* `exchange` +* `pair` +* `limit` +* `stake_amount` +* `stake_currency` +* `fiat_currency` ### Webhooksell The fields in `webhook.webhooksell` are filled when the bot sells a trade. Parameters are filled using string.format. Possible parameters are: -* exchange -* pair -* gain -* limit -* amount -* open_rate -* current_rate -* profit_amount -* profit_percent -* profit_fiat -* stake_currency -* fiat_currency -* sell_reason +* `exchange` +* `pair` +* `gain` +* `limit` +* `amount` +* `open_rate` +* `current_rate` +* `profit_amount` +* `profit_percent` +* `stake_currency` +* `fiat_currency` +* `sell_reason` ### Webhookstatus From ac1964edb16dd0bf13fd1bef6bc59ce9519b229b Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 5 Apr 2019 06:49:15 +0200 Subject: [PATCH 13/14] Remove unnecessary comment --- docs/telegram-usage.md | 4 ++-- docs/webhook-config.md | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/telegram-usage.md b/docs/telegram-usage.md index 4cc8eaa5c..9d6877318 100644 --- a/docs/telegram-usage.md +++ b/docs/telegram-usage.md @@ -1,13 +1,13 @@ # Telegram usage -This page explains how to command your bot with Telegram. - ## Prerequisite + To control your bot with Telegram, you need first to [set up a Telegram bot](installation.md) and add your Telegram API keys into your config file. ## Telegram commands + Per default, the Telegram bot shows predefined commands. Some commands are only available by sending them to the bot. The table below list the official commands. You can ask at any moment for help with `/help`. diff --git a/docs/webhook-config.md b/docs/webhook-config.md index 43b036c74..811b57f9b 100644 --- a/docs/webhook-config.md +++ b/docs/webhook-config.md @@ -1,7 +1,5 @@ # Webhook usage -This page explains how to configure your bot to talk to webhooks. - ## Configuration Enable webhooks by adding a webhook-section to your configuration file, and setting `webhook.enabled` to `true`. From 13e8f25ca97843baf47b4be38515ae830f3a7a39 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 5 Apr 2019 06:51:16 +0200 Subject: [PATCH 14/14] Improve docs layout --- mkdocs.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index 9a6fec851..ecac265c1 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -3,11 +3,12 @@ nav: - About: index.md - Installation: installation.md - Configuration: configuration.md - - Start the bot: bot-usage.md - - Stoploss: stoploss.md - Custom Strategy: bot-optimization.md - - Telegram: telegram-usage.md - - Web Hook: webhook-config.md + - Stoploss: stoploss.md + - Start the bot: bot-usage.md + - Control the bot: + - Telegram: telegram-usage.md + - Web Hook: webhook-config.md - Backtesting: backtesting.md - Hyperopt: hyperopt.md - Edge positioning: edge.md