From c38d94df2d226ede89ab71f88dac5169fcd5b628 Mon Sep 17 00:00:00 2001 From: creslin Date: Fri, 3 Aug 2018 07:33:34 +0000 Subject: [PATCH] Resubmitting - because GIT. This is the last cut that was in #1117 before i closed that PR This PR allows a user to set the flag "ta_on_candle" in their config.json This will change the behaviour of the the bot to only process indicators when there is a new candle to be processed for that pair. The test is made up of "last dataframe row date + pair" is different to last_seen OR ta_on_candle is not True --- docs/configuration.md | 1 + freqtrade/constants.py | 1 + freqtrade/strategy/interface.py | 45 ++++++++++++++++++++++++++++++--- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index ff5ce118c..6f03117ba 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -23,6 +23,7 @@ The table below will list all configuration parameters. | `ticker_interval` | [1m, 5m, 30m, 1h, 1d] | No | The ticker interval to use (1min, 5 min, 30 min, 1 hour or 1 day). Default is 5 minutes | `fiat_display_currency` | USD | Yes | Fiat currency used to show your profits. More information below. | `dry_run` | true | Yes | Define if the bot must be in Dry-run or production mode. +| `ta_on_candle` | false | No | if set to true indicators are processed each new candle. If false each bot loop, this will mean the same candle is processed many times creating system load and buy/sell signals. | `minimal_roi` | See below | No | Set the threshold in percent the bot will use to sell a trade. More information below. If set, this parameter will override `minimal_roi` from your strategy file. | `stoploss` | -0.10 | No | Value of the stoploss in percent used by the bot. More information below. If set, this parameter will override `stoploss` from your strategy file. | `trailing_stoploss` | false | No | Enables trailing stop-loss (based on `stoploss` in either configuration or strategy file). diff --git a/freqtrade/constants.py b/freqtrade/constants.py index 87e354455..189b78617 100644 --- a/freqtrade/constants.py +++ b/freqtrade/constants.py @@ -53,6 +53,7 @@ CONF_SCHEMA = { }, 'fiat_display_currency': {'type': 'string', 'enum': SUPPORTED_FIAT}, 'dry_run': {'type': 'boolean'}, + 'ta_on_candle': {'type': 'boolean'}, 'minimal_roi': { 'type': 'object', 'patternProperties': { diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index dfd624393..e68d484de 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -19,6 +19,24 @@ from freqtrade.persistence import Trade logger = logging.getLogger(__name__) +class CandleAnalyzed: + ''' + Maintains candle_row, the last df ['date'], set by analyze_ticker. + This allows analyze_ticker to test if analysed the candle row in dataframe prior. + To not keep testing the same candle data, which is wasteful in CPU and time + ''' + def __init__(self, candle_row=0): + self.candle_row = candle_row + + def get_candle_row(self): + return self._candle_row + + def set_candle_row(self, row): + self._candle_row = row + + candle_row = property(get_candle_row, set_candle_row) + + class SignalType(Enum): """ Enum to distinguish between buy and sell signals @@ -72,6 +90,7 @@ class IStrategy(ABC): def __init__(self, config: dict) -> None: self.config = config + self.r = CandleAnalyzed() @abstractmethod def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: @@ -112,10 +131,30 @@ class IStrategy(ABC): add several TA indicators and buy signal to it :return DataFrame with ticker data and indicator data """ + + # Test if seen this pair and last candle before. dataframe = parse_ticker_dataframe(ticker_history) - dataframe = self.advise_indicators(dataframe, metadata) - dataframe = self.advise_buy(dataframe, metadata) - dataframe = self.advise_sell(dataframe, metadata) + + last_seen = metadata['pair'] + str(dataframe.iloc[-1]['date']) + last_candle_processed = self.r.get_candle_row() + + if last_candle_processed != last_seen or self.config.get('ta_on_candle') is False: + # Defs that only make change on new candle data. + logging.info("TA Analysis Launched") + dataframe = self.advise_indicators(dataframe, metadata) + dataframe = self.advise_buy(dataframe, metadata) + dataframe = self.advise_sell(dataframe, metadata) + + last_seen = metadata['pair'] + str(dataframe.iloc[-1]['date']) + self.r.set_candle_row(last_seen) + else: + dataframe.loc['buy'] = 0 + dataframe.loc['sell'] = 0 + + # Other Defs in strategy that want to be called every loop here + # twitter_sell = self.watch_twitter_feed(dataframe, metadata) + logging.info("Loop Analysis Launched") + return dataframe def get_signal(self, pair: str, interval: str, ticker_hist: List[Dict]) -> Tuple[bool, bool]: