Merge pull request #6627 from samgermain/bot-start

Added bot_start callback to strategy interface
This commit is contained in:
Matthias 2022-04-30 09:14:51 +02:00 committed by GitHub
commit bfae732ba4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 43 additions and 0 deletions

View File

@ -7,6 +7,7 @@ Depending on the callback used, they may be called when entering / exiting a tra
Currently available callbacks:
* [`bot_start()`](#bot-start)
* [`bot_loop_start()`](#bot-loop-start)
* [`custom_stake_amount()`](#stake-size-management)
* [`custom_exit()`](#custom-exit-signal)
@ -21,6 +22,29 @@ Currently available callbacks:
!!! Tip "Callback calling sequence"
You can find the callback calling sequence in [bot-basics](bot-basics.md#bot-execution-logic)
## Bot start
A simple callback which is called once when the strategy is loaded.
This can be used to perform actions that must only be performed once and runs after dataprovider and wallet are set
``` python
import requests
class AwesomeStrategy(IStrategy):
# ... populate_* methods
def bot_start(self, **kwargs) -> None:
"""
Called only once after bot instantiation.
:param **kwargs: Ensure to keep this here so updates to this won't break your strategy.
"""
if self.config['runmode'].value in ('live', 'dry_run'):
# Assign this to the class by using self.*
# can then be used by populate_* methods
self.cust_remote_data = requests.get('https://some_remote_source.example.com')
```
## Bot loop start
A simple callback which is called once at the start of every bot throttling iteration (roughly every 5 seconds, unless configured differently).

View File

@ -122,6 +122,8 @@ class FreqtradeBot(LoggingMixin):
self._schedule.every().day.at(t).do(update)
self.last_process = datetime(1970, 1, 1, tzinfo=timezone.utc)
self.strategy.bot_start()
def notify_status(self, msg: str) -> None:
"""
Public method for users of this class (worker, etc.) to send notifications

View File

@ -187,6 +187,7 @@ class Backtesting:
# since a "perfect" stoploss-exit is assumed anyway
# And the regular "stoploss" function would not apply to that case
self.strategy.order_types['stoploss_on_exchange'] = False
self.strategy.bot_start()
def _load_protections(self, strategy: IStrategy):
if self.config.get('enable_protections', False):

View File

@ -44,6 +44,7 @@ class EdgeCli:
self.edge._timerange = TimeRange.parse_timerange(None if self.config.get(
'timerange') is None else str(self.config.get('timerange')))
self.strategy.bot_start()
def start(self) -> None:
result = self.edge.calculate(self.config['exchange']['pair_whitelist'])

View File

@ -610,6 +610,7 @@ def load_and_plot_trades(config: Dict[str, Any]):
exchange = ExchangeResolver.load_exchange(config['exchange']['name'], config)
IStrategy.dp = DataProvider(config, exchange)
strategy.bot_start()
plot_elements = init_plotscript(config, list(exchange.markets), strategy.startup_candle_count)
timerange = plot_elements['timerange']
trades = plot_elements['trades']

View File

@ -193,6 +193,13 @@ class IStrategy(ABC, HyperStrategyMixin):
"""
return self.populate_sell_trend(dataframe, metadata)
def bot_start(self, **kwargs) -> None:
"""
Called only once after bot instantiation.
:param **kwargs: Ensure to keep this here so updates to this won't break your strategy.
"""
pass
def bot_loop_start(self, **kwargs) -> None:
"""
Called at the start of the bot iteration (one loop).

View File

@ -312,6 +312,7 @@ def test_backtesting_init(mocker, default_conf, order_types) -> None:
get_fee.assert_called()
assert backtesting.fee == 0.5
assert not backtesting.strategy.order_types["stoploss_on_exchange"]
assert backtesting.strategy.bot_started is True
def test_backtesting_init_no_timeframe(mocker, default_conf, caplog) -> None:

View File

@ -94,6 +94,7 @@ def test_edge_init(mocker, edge_conf) -> None:
assert edge_cli.config == edge_conf
assert edge_cli.config['stake_amount'] == 'unlimited'
assert callable(edge_cli.edge.calculate)
assert edge_cli.strategy.bot_started is True
def test_edge_init_fee(mocker, edge_conf) -> None:

View File

@ -82,6 +82,11 @@ class StrategyTestV3(IStrategy):
# })
# return prot
bot_started = False
def bot_start(self):
self.bot_started = True
def informative_pairs(self):
return []