From 26e288e655b9804c24356ce2158c5a63564af79b Mon Sep 17 00:00:00 2001 From: Jean-Baptiste LE STANG Date: Tue, 30 Jan 2018 15:03:38 +0100 Subject: [PATCH 1/6] Adding the pair name when populating indicators allowing the strategy to have customized context for a pair --- docs/bot-optimization.md | 6 ++--- docs/hyperopt.md | 6 ++--- freqtrade/analyze.py | 22 +++++++++---------- freqtrade/optimize/__init__.py | 2 +- freqtrade/optimize/backtesting.py | 2 +- freqtrade/optimize/hyperopt.py | 4 ++-- freqtrade/strategy/default_strategy.py | 6 ++--- freqtrade/strategy/interface.py | 6 ++--- freqtrade/strategy/strategy.py | 12 +++++----- .../tests/strategy/test_default_strategy.py | 6 ++--- freqtrade/tests/strategy/test_strategy.py | 8 +++---- freqtrade/tests/test_analyze.py | 4 ++-- freqtrade/tests/test_dataframe.py | 2 +- user_data/strategies/test_strategy.py | 6 ++--- 14 files changed, 46 insertions(+), 46 deletions(-) diff --git a/docs/bot-optimization.md b/docs/bot-optimization.md index 7900e6dd2..9a0d8274b 100644 --- a/docs/bot-optimization.md +++ b/docs/bot-optimization.md @@ -51,7 +51,7 @@ update your buy strategy. Sample from `user_data/strategies/test_strategy.py`: ```python -def populate_buy_trend(self, dataframe: DataFrame) -> DataFrame: +def populate_buy_trend(self, dataframe: DataFrame, pair : str) -> DataFrame: """ Based on TA indicators, populates the buy signal for the given dataframe :param dataframe: DataFrame @@ -74,7 +74,7 @@ update your sell strategy. Sample from `user_data/strategies/test_strategy.py`: ```python -def populate_sell_trend(self, dataframe: DataFrame) -> DataFrame: +def populate_sell_trend(self, dataframe: DataFrame, pair : str) -> DataFrame: """ Based on TA indicators, populates the sell signal for the given dataframe :param dataframe: DataFrame @@ -97,7 +97,7 @@ the method `populate_indicators()` from your strategy file. Sample: ```python -def populate_indicators(dataframe: DataFrame) -> DataFrame: +def populate_indicators(dataframe: DataFrame, pair : str) -> DataFrame: """ Adds several different TA indicators to the given DataFrame """ diff --git a/docs/hyperopt.md b/docs/hyperopt.md index 3c3cb7d25..4d6a84b2f 100644 --- a/docs/hyperopt.md +++ b/docs/hyperopt.md @@ -42,7 +42,7 @@ If you have updated the buy strategy, means change the content of As for an example if your `populate_buy_trend()` method is: ```python -def populate_buy_trend(dataframe: DataFrame) -> DataFrame: +def populate_buy_trend(dataframe: DataFrame, pair: str) -> DataFrame: dataframe.loc[ (dataframe['rsi'] < 35) & (dataframe['adx'] > 65), @@ -81,7 +81,7 @@ space = { ... -def populate_buy_trend(self, dataframe: DataFrame) -> DataFrame: +def populate_buy_trend(self, dataframe: DataFrame, pair: str) -> DataFrame: conditions = [] # GUARDS AND TRENDS if params['adx']['enabled']: @@ -280,7 +280,7 @@ at `adx`-block, that translates to the following code block: So translating your whole hyperopt result to as the new buy-signal would be the following: ``` -def populate_buy_trend(self, dataframe: DataFrame) -> DataFrame: +def populate_buy_trend(self, dataframe: DataFrame, pair: str) -> DataFrame: dataframe.loc[ ( (dataframe['adx'] > 15.0) & # adx-value diff --git a/freqtrade/analyze.py b/freqtrade/analyze.py index 70bf40936..787524c6a 100644 --- a/freqtrade/analyze.py +++ b/freqtrade/analyze.py @@ -37,7 +37,7 @@ def parse_ticker_dataframe(ticker: list) -> DataFrame: return frame -def populate_indicators(dataframe: DataFrame) -> DataFrame: +def populate_indicators(dataframe: DataFrame, pair: str) -> DataFrame: """ Adds several different TA indicators to the given DataFrame @@ -46,39 +46,39 @@ def populate_indicators(dataframe: DataFrame) -> DataFrame: or your hyperopt configuration, otherwise you will waste your memory and CPU usage. """ strategy = Strategy() - return strategy.populate_indicators(dataframe=dataframe) + return strategy.populate_indicators(dataframe=dataframe, pair=pair) -def populate_buy_trend(dataframe: DataFrame) -> DataFrame: +def populate_buy_trend(dataframe: DataFrame, pair: str) -> DataFrame: """ Based on TA indicators, populates the buy signal for the given dataframe :param dataframe: DataFrame :return: DataFrame with buy column """ strategy = Strategy() - return strategy.populate_buy_trend(dataframe=dataframe) + return strategy.populate_buy_trend(dataframe=dataframe, pair=pair) -def populate_sell_trend(dataframe: DataFrame) -> DataFrame: +def populate_sell_trend(dataframe: DataFrame, pair: str) -> DataFrame: """ Based on TA indicators, populates the sell signal for the given dataframe :param dataframe: DataFrame :return: DataFrame with buy column """ strategy = Strategy() - return strategy.populate_sell_trend(dataframe=dataframe) + return strategy.populate_sell_trend(dataframe=dataframe, pair=pair) -def analyze_ticker(ticker_history: List[Dict]) -> DataFrame: +def analyze_ticker(ticker_history: List[Dict], pair: str) -> DataFrame: """ Parses the given ticker history and returns a populated DataFrame add several TA indicators and buy signal to it :return DataFrame with ticker data and indicator data """ dataframe = parse_ticker_dataframe(ticker_history) - dataframe = populate_indicators(dataframe) - dataframe = populate_buy_trend(dataframe) - dataframe = populate_sell_trend(dataframe) + dataframe = populate_indicators(dataframe, pair) + dataframe = populate_buy_trend(dataframe, pair) + dataframe = populate_sell_trend(dataframe, pair) return dataframe @@ -96,7 +96,7 @@ def get_signal(pair: str, interval: int) -> (bool, bool): return (False, False) # return False ? try: - dataframe = analyze_ticker(ticker_hist) + dataframe = analyze_ticker(ticker_hist, pair) except ValueError as ex: logger.warning('Unable to analyze ticker for pair %s: %s', pair, str(ex)) return (False, False) # return False ? diff --git a/freqtrade/optimize/__init__.py b/freqtrade/optimize/__init__.py index 52ea55853..f84b13891 100644 --- a/freqtrade/optimize/__init__.py +++ b/freqtrade/optimize/__init__.py @@ -91,7 +91,7 @@ def tickerdata_to_dataframe(data): def preprocess(tickerdata: Dict[str, List]) -> Dict[str, DataFrame]: """Creates a dataframe and populates indicators for given ticker data""" - return {pair: populate_indicators(parse_ticker_dataframe(pair_data)) + return {pair: populate_indicators(parse_ticker_dataframe(pair_data), pair) for pair, pair_data in tickerdata.items()} diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index e8fcec875..bbca45d5d 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -117,7 +117,7 @@ def backtest(args) -> DataFrame: exchange._API = Bittrex({'key': '', 'secret': ''}) for pair, pair_data in processed.items(): pair_data['buy'], pair_data['sell'] = 0, 0 - ticker = populate_sell_trend(populate_buy_trend(pair_data)) + ticker = populate_sell_trend(populate_buy_trend(pair_data, pair), pair) # for each buy point lock_pair_until = None headers = ['buy', 'open', 'close', 'date', 'sell'] diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 76932f7e3..f603c0333 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -61,7 +61,7 @@ TRIALS = Trials() main._CONF = OPTIMIZE_CONFIG -def populate_indicators(dataframe: DataFrame) -> DataFrame: +def populate_indicators(dataframe: DataFrame, pair: str) -> DataFrame: """ Adds several different TA indicators to the given DataFrame """ @@ -320,7 +320,7 @@ def buy_strategy_generator(params: Dict[str, Any]) -> Callable: """ Define the buy strategy parameters to be used by hyperopt """ - def populate_buy_trend(dataframe: DataFrame) -> DataFrame: + def populate_buy_trend(dataframe: DataFrame, pair: str) -> DataFrame: conditions = [] # GUARDS AND TRENDS if 'uptrend_long_ema' in params and params['uptrend_long_ema']['enabled']: diff --git a/freqtrade/strategy/default_strategy.py b/freqtrade/strategy/default_strategy.py index abccf065b..5fdbbbc90 100644 --- a/freqtrade/strategy/default_strategy.py +++ b/freqtrade/strategy/default_strategy.py @@ -29,7 +29,7 @@ class DefaultStrategy(IStrategy): # Optimal ticker interval for the strategy ticker_interval = 5 - def populate_indicators(self, dataframe: DataFrame) -> DataFrame: + def populate_indicators(self, dataframe: DataFrame, pair: str) -> DataFrame: """ Adds several different TA indicators to the given DataFrame @@ -196,7 +196,7 @@ class DefaultStrategy(IStrategy): return dataframe - def populate_buy_trend(self, dataframe: DataFrame) -> DataFrame: + def populate_buy_trend(self, dataframe: DataFrame, pair: str) -> DataFrame: """ Based on TA indicators, populates the buy signal for the given dataframe :param dataframe: DataFrame @@ -217,7 +217,7 @@ class DefaultStrategy(IStrategy): return dataframe - def populate_sell_trend(self, dataframe: DataFrame) -> DataFrame: + def populate_sell_trend(self, dataframe: DataFrame, pair: str) -> DataFrame: """ Based on TA indicators, populates the sell signal for the given dataframe :param dataframe: DataFrame diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index dc9f33244..3c836abb0 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -19,7 +19,7 @@ class IStrategy(ABC): """ @abstractmethod - def populate_indicators(self, dataframe: DataFrame) -> DataFrame: + def populate_indicators(self, dataframe: DataFrame, pair: str) -> DataFrame: """ Populate indicators that will be used in the Buy and Sell strategy :param dataframe: Raw data from the exchange and parsed by parse_ticker_dataframe() @@ -27,7 +27,7 @@ class IStrategy(ABC): """ @abstractmethod - def populate_buy_trend(self, dataframe: DataFrame) -> DataFrame: + def populate_buy_trend(self, dataframe: DataFrame, pair: str) -> DataFrame: """ Based on TA indicators, populates the buy signal for the given dataframe :param dataframe: DataFrame @@ -36,7 +36,7 @@ class IStrategy(ABC): """ @abstractmethod - def populate_sell_trend(self, dataframe: DataFrame) -> DataFrame: + def populate_sell_trend(self, dataframe: DataFrame, pair: str) -> DataFrame: """ Based on TA indicators, populates the sell signal for the given dataframe :param dataframe: DataFrame diff --git a/freqtrade/strategy/strategy.py b/freqtrade/strategy/strategy.py index 427c24fc6..440e87825 100644 --- a/freqtrade/strategy/strategy.py +++ b/freqtrade/strategy/strategy.py @@ -143,27 +143,27 @@ class Strategy(object): return path - def populate_indicators(self, dataframe: DataFrame) -> DataFrame: + def populate_indicators(self, dataframe: DataFrame, pair: str) -> DataFrame: """ Populate indicators that will be used in the Buy and Sell strategy :param dataframe: Raw data from the exchange and parsed by parse_ticker_dataframe() :return: a Dataframe with all mandatory indicators for the strategies """ - return self.custom_strategy.populate_indicators(dataframe) + return self.custom_strategy.populate_indicators(dataframe, pair) - def populate_buy_trend(self, dataframe: DataFrame) -> DataFrame: + def populate_buy_trend(self, dataframe: DataFrame, pair: str) -> DataFrame: """ Based on TA indicators, populates the buy signal for the given dataframe :param dataframe: DataFrame :return: DataFrame with buy column :return: """ - return self.custom_strategy.populate_buy_trend(dataframe) + return self.custom_strategy.populate_buy_trend(dataframe, pair) - def populate_sell_trend(self, dataframe: DataFrame) -> DataFrame: + def populate_sell_trend(self, dataframe: DataFrame, pair: str) -> DataFrame: """ Based on TA indicators, populates the sell signal for the given dataframe :param dataframe: DataFrame :return: DataFrame with buy column """ - return self.custom_strategy.populate_sell_trend(dataframe) + return self.custom_strategy.populate_sell_trend(dataframe, pair) diff --git a/freqtrade/tests/strategy/test_default_strategy.py b/freqtrade/tests/strategy/test_default_strategy.py index f23c1fa48..287bab22e 100644 --- a/freqtrade/tests/strategy/test_default_strategy.py +++ b/freqtrade/tests/strategy/test_default_strategy.py @@ -30,7 +30,7 @@ def test_default_strategy(result): assert type(strategy.minimal_roi) is dict assert type(strategy.stoploss) is float assert type(strategy.ticker_interval) is int - indicators = strategy.populate_indicators(result) + indicators = strategy.populate_indicators(result, None) assert type(indicators) is DataFrame - assert type(strategy.populate_buy_trend(indicators)) is DataFrame - assert type(strategy.populate_sell_trend(indicators)) is DataFrame + assert type(strategy.populate_buy_trend(indicators, None)) is DataFrame + assert type(strategy.populate_sell_trend(indicators, None)) is DataFrame diff --git a/freqtrade/tests/strategy/test_strategy.py b/freqtrade/tests/strategy/test_strategy.py index dd772f784..1ec4fcf42 100644 --- a/freqtrade/tests/strategy/test_strategy.py +++ b/freqtrade/tests/strategy/test_strategy.py @@ -37,7 +37,7 @@ def test_load_strategy(result): assert not hasattr(Strategy, 'custom_strategy') assert hasattr(strategy.custom_strategy, 'populate_indicators') - assert 'adx' in strategy.populate_indicators(result) + assert 'adx' in strategy.populate_indicators(result, None) def test_strategy(result): @@ -51,14 +51,14 @@ def test_strategy(result): assert strategy.stoploss == -0.10 assert hasattr(strategy.custom_strategy, 'populate_indicators') - assert 'adx' in strategy.populate_indicators(result) + assert 'adx' in strategy.populate_indicators(result, None) assert hasattr(strategy.custom_strategy, 'populate_buy_trend') - dataframe = strategy.populate_buy_trend(strategy.populate_indicators(result)) + dataframe = strategy.populate_buy_trend(strategy.populate_indicators(result, None), None) assert 'buy' in dataframe.columns assert hasattr(strategy.custom_strategy, 'populate_sell_trend') - dataframe = strategy.populate_sell_trend(strategy.populate_indicators(result)) + dataframe = strategy.populate_sell_trend(strategy.populate_indicators(result, None), None) assert 'sell' in dataframe.columns diff --git a/freqtrade/tests/test_analyze.py b/freqtrade/tests/test_analyze.py index 2e75b0624..65a28b337 100644 --- a/freqtrade/tests/test_analyze.py +++ b/freqtrade/tests/test_analyze.py @@ -26,7 +26,7 @@ def test_populates_buy_trend(result): # Load the default strategy for the unit test, because this logic is done in main.py Strategy().init({'strategy': 'default_strategy'}) - dataframe = populate_buy_trend(populate_indicators(result)) + dataframe = populate_buy_trend(populate_indicators(result, None), None) assert 'buy' in dataframe.columns @@ -34,7 +34,7 @@ def test_populates_sell_trend(result): # Load the default strategy for the unit test, because this logic is done in main.py Strategy().init({'strategy': 'default_strategy'}) - dataframe = populate_sell_trend(populate_indicators(result)) + dataframe = populate_sell_trend(populate_indicators(result, None), None) assert 'sell' in dataframe.columns diff --git a/freqtrade/tests/test_dataframe.py b/freqtrade/tests/test_dataframe.py index 9af42a30e..7cda7b9bd 100644 --- a/freqtrade/tests/test_dataframe.py +++ b/freqtrade/tests/test_dataframe.py @@ -12,7 +12,7 @@ def load_dataframe_pair(pairs): assert isinstance(ld, dict) assert isinstance(pairs[0], str) dataframe = ld[pairs[0]] - dataframe = analyze.analyze_ticker(dataframe) + dataframe = analyze.analyze_ticker(dataframe, pairs[0]) return dataframe diff --git a/user_data/strategies/test_strategy.py b/user_data/strategies/test_strategy.py index a164812c4..657fdd9f5 100644 --- a/user_data/strategies/test_strategy.py +++ b/user_data/strategies/test_strategy.py @@ -47,7 +47,7 @@ class TestStrategy(IStrategy): # Optimal ticker interval for the strategy ticker_interval = 5 - def populate_indicators(self, dataframe: DataFrame) -> DataFrame: + def populate_indicators(self, dataframe: DataFrame, pair: str) -> DataFrame: """ Adds several different TA indicators to the given DataFrame @@ -214,7 +214,7 @@ class TestStrategy(IStrategy): return dataframe - def populate_buy_trend(self, dataframe: DataFrame) -> DataFrame: + def populate_buy_trend(self, dataframe: DataFrame, pair: str) -> DataFrame: """ Based on TA indicators, populates the buy signal for the given dataframe :param dataframe: DataFrame @@ -230,7 +230,7 @@ class TestStrategy(IStrategy): return dataframe - def populate_sell_trend(self, dataframe: DataFrame) -> DataFrame: + def populate_sell_trend(self, dataframe: DataFrame, pair: str) -> DataFrame: """ Based on TA indicators, populates the sell signal for the given dataframe :param dataframe: DataFrame From c75e5a802072b517ca914f617f66b780e09d6126 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste LE STANG Date: Tue, 30 Jan 2018 17:40:08 +0100 Subject: [PATCH 2/6] Fixing the strategy interface class documentation --- freqtrade/strategy/interface.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index 3c836abb0..9c1829680 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -23,6 +23,7 @@ class IStrategy(ABC): """ Populate indicators that will be used in the Buy and Sell strategy :param dataframe: Raw data from the exchange and parsed by parse_ticker_dataframe() + :param pair: the pair that was is concerned by the dataframe :return: a Dataframe with all mandatory indicators for the strategies """ @@ -31,6 +32,7 @@ class IStrategy(ABC): """ Based on TA indicators, populates the buy signal for the given dataframe :param dataframe: DataFrame + :param pair: the pair that was is concerned by the dataframe :return: DataFrame with buy column :return: """ @@ -40,5 +42,6 @@ class IStrategy(ABC): """ Based on TA indicators, populates the sell signal for the given dataframe :param dataframe: DataFrame + :param pair: the pair that was is concerned by the dataframe :return: DataFrame with buy column """ From dd30a75ea10d7453424d619b31deacfd4a18722c Mon Sep 17 00:00:00 2001 From: Jean-Baptiste LE STANG Date: Tue, 30 Jan 2018 17:56:31 +0100 Subject: [PATCH 3/6] Adding buy/sell events notifications to the strategy --- freqtrade/strategy/default_strategy.py | 14 ++++++++++++++ freqtrade/strategy/interface.py | 14 ++++++++++++++ freqtrade/strategy/strategy.py | 14 ++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/freqtrade/strategy/default_strategy.py b/freqtrade/strategy/default_strategy.py index 5fdbbbc90..3ac72d127 100644 --- a/freqtrade/strategy/default_strategy.py +++ b/freqtrade/strategy/default_strategy.py @@ -238,3 +238,17 @@ class DefaultStrategy(IStrategy): ), 'sell'] = 1 return dataframe + + def did_bought(self, pair: str): + """ + we are notified that a given pair was bought + :param pair: the pair that was is concerned by the dataframe + """ + assert False is not True + + def did_sold(self, pair: str): + """ + we are notified that a given pair was sold + :param pair: the pair that was is concerned by the dataframe + """ + assert False is not True diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index 9c1829680..73614f376 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -45,3 +45,17 @@ class IStrategy(ABC): :param pair: the pair that was is concerned by the dataframe :return: DataFrame with buy column """ + + @abstractmethod + def did_bought(self, pair: str): + """ + we are notified that a given pair was bought + :param pair: the pair that was is concerned by the dataframe + """ + + @abstractmethod + def did_sold(self, pair: str): + """ + we are notified that a given pair was sold + :param pair: the pair that was is concerned by the dataframe + """ diff --git a/freqtrade/strategy/strategy.py b/freqtrade/strategy/strategy.py index 440e87825..e94320aa2 100644 --- a/freqtrade/strategy/strategy.py +++ b/freqtrade/strategy/strategy.py @@ -167,3 +167,17 @@ class Strategy(object): :return: DataFrame with buy column """ return self.custom_strategy.populate_sell_trend(dataframe, pair) + + def did_bought(self, pair: str): + """ + we are notified that a given pair was bought + :param pair: the pair that was is concerned by the dataframe + """ + return self.custom_strategy.did_bought(pair) + + def did_sold(self, pair: str): + """ + we are notified that a given pair was sold + :param pair: the pair that was is concerned by the dataframe + """ + return self.custom_strategy.did_sold(pair) From eacb6b5a035a5a2ff52ae2b0a4a197fb16d46f93 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste LE STANG Date: Tue, 30 Jan 2018 20:54:35 +0100 Subject: [PATCH 4/6] Adding buy/sell notification towards the strategy --- freqtrade/main.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/freqtrade/main.py b/freqtrade/main.py index 6f7a67df2..7e78a3864 100755 --- a/freqtrade/main.py +++ b/freqtrade/main.py @@ -231,6 +231,9 @@ def execute_sell(trade: Trade, limit: float) -> None: order_id = exchange.sell(str(trade.pair), limit, trade.amount) trade.open_order_id = order_id + strategy = Strategy() + strategy.did_sold(trade.pair) + fmt_exp_profit = round(trade.calc_profit_percent(rate=limit) * 100, 2) profit_trade = trade.calc_profit(rate=limit) current_rate = exchange.get_ticker(trade.pair, False)['bid'] @@ -409,6 +412,8 @@ def create_trade(stake_amount: float, interval: int) -> bool: _CONF['stake_currency'], _CONF['fiat_display_currency'] ) + strategy = Strategy() + strategy.did_bought(pair) # Create trade entity and return rpc.send_msg('*{}:* Buying [{}]({}) with limit `{:.8f} ({:.6f} {}, {:.3f} {})` '.format( From b27c8256f44eefeed1c0e1f179c2fa2b0f5e4fbc Mon Sep 17 00:00:00 2001 From: Jean-Baptiste LE STANG Date: Tue, 30 Jan 2018 21:34:26 +0100 Subject: [PATCH 5/6] Adding cancel buy/sell events --- freqtrade/main.py | 4 ++++ freqtrade/strategy/default_strategy.py | 14 ++++++++++++-- freqtrade/strategy/interface.py | 14 ++++++++++++++ freqtrade/strategy/strategy.py | 14 ++++++++++++++ 4 files changed, 44 insertions(+), 2 deletions(-) diff --git a/freqtrade/main.py b/freqtrade/main.py index 7e78a3864..494ddf4f7 100755 --- a/freqtrade/main.py +++ b/freqtrade/main.py @@ -158,6 +158,8 @@ def handle_timedout_limit_buy(trade: Trade, order: Dict) -> bool: logger.info('Buy order timeout for %s.', trade) rpc.send_msg('*Timeout:* Unfilled buy order for {} cancelled'.format( trade.pair.replace('_', '/'))) + strategy = Strategy() + strategy.did_cancel_buy(trade.pair) return True # if trade is partially complete, edit the stake details for the trade @@ -188,6 +190,8 @@ def handle_timedout_limit_sell(trade: Trade, order: Dict) -> bool: rpc.send_msg('*Timeout:* Unfilled sell order for {} cancelled'.format( trade.pair.replace('_', '/'))) logger.info('Sell order timeout for %s.', trade) + strategy = Strategy() + strategy.did_cancel_sell(trade.pair) return True # TODO: figure out how to handle partially complete sell orders diff --git a/freqtrade/strategy/default_strategy.py b/freqtrade/strategy/default_strategy.py index 3ac72d127..ba5bca404 100644 --- a/freqtrade/strategy/default_strategy.py +++ b/freqtrade/strategy/default_strategy.py @@ -244,11 +244,21 @@ class DefaultStrategy(IStrategy): we are notified that a given pair was bought :param pair: the pair that was is concerned by the dataframe """ - assert False is not True def did_sold(self, pair: str): """ we are notified that a given pair was sold :param pair: the pair that was is concerned by the dataframe """ - assert False is not True + + def did_cancel_buy(self, pair: str): + """ + we are notified that a given pair was bought + :param pair: the pair that was is concerned by the dataframe + """ + + def did_cancel_sell(self, pair: str): + """ + we are notified that a given pair was sold + :param pair: the pair that was is concerned by the dataframe + """ diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index 73614f376..4ea3173c1 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -59,3 +59,17 @@ class IStrategy(ABC): we are notified that a given pair was sold :param pair: the pair that was is concerned by the dataframe """ + + @abstractmethod + def did_cancel_buy(self, pair: str): + """ + we are notified that a given buy for a pair was cancelled + :param pair: the pair that was is concerned by the dataframe + """ + + @abstractmethod + def did_cancel_sell(self, pair: str): + """ + we are notified that a given sell for a pair was cancelled + :param pair: the pair that was is concerned by the dataframe + """ diff --git a/freqtrade/strategy/strategy.py b/freqtrade/strategy/strategy.py index e94320aa2..85b8657c8 100644 --- a/freqtrade/strategy/strategy.py +++ b/freqtrade/strategy/strategy.py @@ -181,3 +181,17 @@ class Strategy(object): :param pair: the pair that was is concerned by the dataframe """ return self.custom_strategy.did_sold(pair) + + def did_cancel_buy(self, pair: str): + """ + we are notified that a given pair was bought + :param pair: the pair that was is concerned by the dataframe + """ + return self.custom_strategy.did_cancel_buy(pair) + + def did_cancel_sell(self, pair: str): + """ + we are notified that a given pair was sold + :param pair: the pair that was is concerned by the dataframe + """ + return self.custom_strategy.did_cancel_sell(pair) From 970a4c3bf76de077a27a88ede0331a8a6edd50ea Mon Sep 17 00:00:00 2001 From: Jean-Baptiste LE STANG Date: Tue, 30 Jan 2018 21:41:01 +0100 Subject: [PATCH 6/6] Fix documentation --- freqtrade/strategy/default_strategy.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/freqtrade/strategy/default_strategy.py b/freqtrade/strategy/default_strategy.py index ba5bca404..7a4792307 100644 --- a/freqtrade/strategy/default_strategy.py +++ b/freqtrade/strategy/default_strategy.py @@ -250,15 +250,15 @@ class DefaultStrategy(IStrategy): we are notified that a given pair was sold :param pair: the pair that was is concerned by the dataframe """ - + def did_cancel_buy(self, pair: str): """ - we are notified that a given pair was bought + we are notified that a given pair buy was not filled :param pair: the pair that was is concerned by the dataframe """ def did_cancel_sell(self, pair: str): """ - we are notified that a given pair was sold + we are notified that a given pair was not sold :param pair: the pair that was is concerned by the dataframe """