From c12a9ebd927a1ad166ceeb1a223b5c29955892e1 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Tue, 14 Nov 2017 19:06:03 +0200 Subject: [PATCH 1/7] make signal getting parametrized --- freqtrade/analyze.py | 15 ++++++++++----- freqtrade/main.py | 9 +++++---- freqtrade/tests/test_analyze.py | 6 +++--- freqtrade/tests/test_main.py | 18 +++++++++--------- freqtrade/tests/test_telegram.py | 18 +++++++++--------- 5 files changed, 36 insertions(+), 30 deletions(-) diff --git a/freqtrade/analyze.py b/freqtrade/analyze.py index e13d2b39d..3fdfa4ff2 100644 --- a/freqtrade/analyze.py +++ b/freqtrade/analyze.py @@ -1,3 +1,4 @@ +from enum import Enum import logging from datetime import timedelta @@ -10,6 +11,10 @@ from freqtrade.vendor.qtpylib.indicators import awesome_oscillator logger = logging.getLogger(__name__) +class SignalType(Enum): + BUY = "buy" + SELL = "sell" + def parse_ticker_dataframe(ticker: list) -> DataFrame: """ @@ -90,9 +95,9 @@ def analyze_ticker(pair: str) -> DataFrame: return dataframe -def get_buy_signal(pair: str) -> bool: +def get_signal(pair: str, signal: SignalType) -> bool: """ - Calculates a buy signal based several technical analysis indicators + Calculates current signal based several technical analysis indicators :param pair: pair in format BTC_ANT or BTC-ANT :return: True if pair is good for buying, False otherwise """ @@ -107,6 +112,6 @@ def get_buy_signal(pair: str) -> bool: if signal_date < arrow.now() - timedelta(minutes=10): return False - signal = latest['buy'] == 1 - logger.debug('buy_trigger: %s (pair=%s, signal=%s)', latest['date'], pair, signal) - return signal + result = latest[signal.value] == 1 + logger.debug('%s_trigger: %s (pair=%s, signal=%s)', signal.value, latest['date'], pair, result) + return result diff --git a/freqtrade/main.py b/freqtrade/main.py index 79f39a32f..3fb0dd64d 100755 --- a/freqtrade/main.py +++ b/freqtrade/main.py @@ -13,9 +13,10 @@ from cachetools import cached, TTLCache from jsonschema import validate from freqtrade import __version__, exchange, persistence -from freqtrade.analyze import get_buy_signal -from freqtrade.misc import CONF_SCHEMA, State, get_state, update_state, build_arg_parser, throttle, \ - FreqtradeException +from freqtrade.analyze import get_signal, SignalType +from freqtrade.misc import ( + CONF_SCHEMA, State, get_state, update_state, build_arg_parser, throttle, FreqtradeException +) from freqtrade.persistence import Trade from freqtrade.rpc import telegram @@ -223,7 +224,7 @@ def create_trade(stake_amount: float) -> Optional[Trade]: # Pick pair based on StochRSI buy signals for _pair in whitelist: - if get_buy_signal(_pair): + if get_signal(_pair, SignalType.BUY): pair = _pair break else: diff --git a/freqtrade/tests/test_analyze.py b/freqtrade/tests/test_analyze.py index 3c0ce15b2..741e72191 100644 --- a/freqtrade/tests/test_analyze.py +++ b/freqtrade/tests/test_analyze.py @@ -5,7 +5,7 @@ import pytest from pandas import DataFrame from freqtrade.analyze import parse_ticker_dataframe, populate_buy_trend, populate_indicators, \ - get_buy_signal + get_signal, SignalType @pytest.fixture @@ -32,8 +32,8 @@ def test_populates_buy_trend(result): def test_returns_latest_buy_signal(mocker): buydf = DataFrame([{'buy': 1, 'date': datetime.today()}]) mocker.patch('freqtrade.analyze.analyze_ticker', return_value=buydf) - assert get_buy_signal('BTC-ETH') + assert get_signal('BTC-ETH', SignalType.BUY) buydf = DataFrame([{'buy': 0, 'date': datetime.today()}]) mocker.patch('freqtrade.analyze.analyze_ticker', return_value=buydf) - assert not get_buy_signal('BTC-ETH') + assert not get_signal('BTC-ETH', SignalType.BUY) diff --git a/freqtrade/tests/test_main.py b/freqtrade/tests/test_main.py index 74a776f22..5be1dce3e 100644 --- a/freqtrade/tests/test_main.py +++ b/freqtrade/tests/test_main.py @@ -16,7 +16,7 @@ from freqtrade.persistence import Trade def test_process_trade_creation(default_conf, ticker, health, mocker): mocker.patch.dict('freqtrade.main._CONF', default_conf) mocker.patch.multiple('freqtrade.main.telegram', init=MagicMock(), send_msg=MagicMock()) - mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True) + mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True) mocker.patch.multiple('freqtrade.main.exchange', validate_pairs=MagicMock(), get_ticker=ticker, @@ -45,7 +45,7 @@ def test_process_trade_creation(default_conf, ticker, health, mocker): def test_process_exchange_failures(default_conf, ticker, health, mocker): mocker.patch.dict('freqtrade.main._CONF', default_conf) mocker.patch.multiple('freqtrade.main.telegram', init=MagicMock(), send_msg=MagicMock()) - mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True) + mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True) sleep_mock = mocker.patch('time.sleep', side_effect=lambda _: None) mocker.patch.multiple('freqtrade.main.exchange', validate_pairs=MagicMock(), @@ -62,7 +62,7 @@ def test_process_runtime_error(default_conf, ticker, health, mocker): msg_mock = MagicMock() mocker.patch.dict('freqtrade.main._CONF', default_conf) mocker.patch.multiple('freqtrade.main.telegram', init=MagicMock(), send_msg=msg_mock) - mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True) + mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True) mocker.patch.multiple('freqtrade.main.exchange', validate_pairs=MagicMock(), get_ticker=ticker, @@ -80,7 +80,7 @@ def test_process_runtime_error(default_conf, ticker, health, mocker): def test_process_trade_handling(default_conf, ticker, limit_buy_order, health, mocker): mocker.patch.dict('freqtrade.main._CONF', default_conf) mocker.patch.multiple('freqtrade.main.telegram', init=MagicMock(), send_msg=MagicMock()) - mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True) + mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True) mocker.patch.multiple('freqtrade.main.exchange', validate_pairs=MagicMock(), get_ticker=ticker, @@ -102,7 +102,7 @@ def test_process_trade_handling(default_conf, ticker, limit_buy_order, health, m def test_create_trade(default_conf, ticker, limit_buy_order, mocker): mocker.patch.dict('freqtrade.main._CONF', default_conf) - mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True) + mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True) mocker.patch.multiple('freqtrade.main.telegram', init=MagicMock(), send_msg=MagicMock()) mocker.patch.multiple('freqtrade.main.exchange', validate_pairs=MagicMock(), @@ -132,7 +132,7 @@ def test_create_trade(default_conf, ticker, limit_buy_order, mocker): def test_create_trade_no_stake_amount(default_conf, ticker, mocker): mocker.patch.dict('freqtrade.main._CONF', default_conf) - mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True) + mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True) mocker.patch.multiple('freqtrade.main.telegram', init=MagicMock(), send_msg=MagicMock()) mocker.patch.multiple('freqtrade.main.exchange', validate_pairs=MagicMock(), @@ -145,7 +145,7 @@ def test_create_trade_no_stake_amount(default_conf, ticker, mocker): def test_create_trade_no_pairs(default_conf, ticker, mocker): mocker.patch.dict('freqtrade.main._CONF', default_conf) - mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True) + mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True) mocker.patch.multiple('freqtrade.main.telegram', init=MagicMock(), send_msg=MagicMock()) mocker.patch.multiple('freqtrade.main.exchange', validate_pairs=MagicMock(), @@ -161,7 +161,7 @@ def test_create_trade_no_pairs(default_conf, ticker, mocker): def test_handle_trade(default_conf, limit_buy_order, limit_sell_order, mocker): mocker.patch.dict('freqtrade.main._CONF', default_conf) - mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True) + mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True) mocker.patch.multiple('freqtrade.main.telegram', init=MagicMock(), send_msg=MagicMock()) mocker.patch.multiple('freqtrade.main.exchange', validate_pairs=MagicMock(), @@ -194,7 +194,7 @@ def test_handle_trade(default_conf, limit_buy_order, limit_sell_order, mocker): def test_close_trade(default_conf, ticker, limit_buy_order, limit_sell_order, mocker): mocker.patch.dict('freqtrade.main._CONF', default_conf) - mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True) + mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True) mocker.patch.multiple('freqtrade.main.telegram', init=MagicMock(), send_msg=MagicMock()) mocker.patch.multiple('freqtrade.main.exchange', validate_pairs=MagicMock(), diff --git a/freqtrade/tests/test_telegram.py b/freqtrade/tests/test_telegram.py index 795901ced..c5ca9da3f 100644 --- a/freqtrade/tests/test_telegram.py +++ b/freqtrade/tests/test_telegram.py @@ -79,7 +79,7 @@ def test_authorized_only_exception(default_conf, mocker): def test_status_handle(default_conf, update, ticker, mocker): mocker.patch.dict('freqtrade.main._CONF', default_conf) - mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True) + mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True) msg_mock = MagicMock() mocker.patch.multiple('freqtrade.main.telegram', _CONF=default_conf, @@ -117,7 +117,7 @@ def test_status_handle(default_conf, update, ticker, mocker): def test_status_table_handle(default_conf, update, ticker, mocker): mocker.patch.dict('freqtrade.main._CONF', default_conf) - mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True) + mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True) msg_mock = MagicMock() mocker.patch.multiple( 'freqtrade.main.telegram', @@ -160,7 +160,7 @@ def test_status_table_handle(default_conf, update, ticker, mocker): def test_profit_handle(default_conf, update, ticker, limit_buy_order, limit_sell_order, mocker): mocker.patch.dict('freqtrade.main._CONF', default_conf) - mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True) + mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True) msg_mock = MagicMock() mocker.patch.multiple('freqtrade.main.telegram', _CONF=default_conf, @@ -204,7 +204,7 @@ def test_profit_handle(default_conf, update, ticker, limit_buy_order, limit_sell def test_forcesell_handle(default_conf, update, ticker, mocker): mocker.patch.dict('freqtrade.main._CONF', default_conf) - mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True) + mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True) msg_mock = MagicMock() mocker.patch.multiple('freqtrade.main.telegram', _CONF=default_conf, @@ -232,7 +232,7 @@ def test_forcesell_handle(default_conf, update, ticker, mocker): def test_forcesell_all_handle(default_conf, update, ticker, mocker): mocker.patch.dict('freqtrade.main._CONF', default_conf) - mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True) + mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True) msg_mock = MagicMock() mocker.patch.multiple('freqtrade.main.telegram', _CONF=default_conf, @@ -260,7 +260,7 @@ def test_forcesell_all_handle(default_conf, update, ticker, mocker): def test_forcesell_handle_invalid(default_conf, update, mocker): mocker.patch.dict('freqtrade.main._CONF', default_conf) - mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True) + mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True) msg_mock = MagicMock() mocker.patch.multiple('freqtrade.main.telegram', _CONF=default_conf, @@ -297,7 +297,7 @@ def test_forcesell_handle_invalid(default_conf, update, mocker): def test_performance_handle( default_conf, update, ticker, limit_buy_order, limit_sell_order, mocker): mocker.patch.dict('freqtrade.main._CONF', default_conf) - mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True) + mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True) msg_mock = MagicMock() mocker.patch.multiple('freqtrade.main.telegram', _CONF=default_conf, @@ -331,7 +331,7 @@ def test_performance_handle( def test_count_handle(default_conf, update, ticker, mocker): mocker.patch.dict('freqtrade.main._CONF', default_conf) - mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True) + mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True) msg_mock = MagicMock() mocker.patch.multiple( 'freqtrade.main.telegram', @@ -365,7 +365,7 @@ def test_count_handle(default_conf, update, ticker, mocker): def test_performance_handle_invalid(default_conf, update, mocker): mocker.patch.dict('freqtrade.main._CONF', default_conf) - mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True) + mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True) msg_mock = MagicMock() mocker.patch.multiple('freqtrade.main.telegram', _CONF=default_conf, From 1db0a7d4cefc8f4641c0b320e0a39f38acb0bc87 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Tue, 14 Nov 2017 20:28:31 +0200 Subject: [PATCH 2/7] populate sell signal --- freqtrade/analyze.py | 18 ++++++++++++++++-- freqtrade/tests/test_analyze.py | 10 ++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/freqtrade/analyze.py b/freqtrade/analyze.py index 3fdfa4ff2..b1279071e 100644 --- a/freqtrade/analyze.py +++ b/freqtrade/analyze.py @@ -7,7 +7,7 @@ import talib.abstract as ta from pandas import DataFrame, to_datetime from freqtrade.exchange import get_ticker_history -from freqtrade.vendor.qtpylib.indicators import awesome_oscillator +from freqtrade.vendor.qtpylib.indicators import awesome_oscillator, crossed_above, crossed_below logger = logging.getLogger(__name__) @@ -62,7 +62,7 @@ def populate_indicators(dataframe: DataFrame) -> DataFrame: def populate_buy_trend(dataframe: DataFrame) -> DataFrame: """ - Based on TA indicators, populates the buy trend for the given dataframe + Based on TA indicators, populates the buy signal for the given dataframe :param dataframe: DataFrame :return: DataFrame with buy column """ @@ -77,6 +77,19 @@ def populate_buy_trend(dataframe: DataFrame) -> DataFrame: return dataframe +def populate_sell_trend(dataframe: DataFrame) -> DataFrame: + """ + Based on TA indicators, populates the sell signal for the given dataframe + :param dataframe: DataFrame + :return: DataFrame with buy column + """ + dataframe.ix[ + (crossed_above(dataframe['rsi'], 70)), + 'sell'] = 1 + dataframe.ix[dataframe['sell'] == 1, 'sell_price'] = dataframe['close'] + + return dataframe + def analyze_ticker(pair: str) -> DataFrame: """ @@ -92,6 +105,7 @@ def analyze_ticker(pair: str) -> DataFrame: dataframe = parse_ticker_dataframe(ticker_hist) dataframe = populate_indicators(dataframe) dataframe = populate_buy_trend(dataframe) + dataframe = populate_sell_trend(dataframe) return dataframe diff --git a/freqtrade/tests/test_analyze.py b/freqtrade/tests/test_analyze.py index 741e72191..7b8c07490 100644 --- a/freqtrade/tests/test_analyze.py +++ b/freqtrade/tests/test_analyze.py @@ -37,3 +37,13 @@ def test_returns_latest_buy_signal(mocker): buydf = DataFrame([{'buy': 0, 'date': datetime.today()}]) mocker.patch('freqtrade.analyze.analyze_ticker', return_value=buydf) assert not get_signal('BTC-ETH', SignalType.BUY) + + +def test_returns_latest_sell_signal(mocker): + selldf = DataFrame([{'sell': 1, 'date': datetime.today()}]) + mocker.patch('freqtrade.analyze.analyze_ticker', return_value=selldf) + assert get_signal('BTC-ETH', SignalType.SELL) + + selldf = DataFrame([{'sell': 0, 'date': datetime.today()}]) + mocker.patch('freqtrade.analyze.analyze_ticker', return_value=selldf) + assert not get_signal('BTC-ETH', SignalType.SELL) From 0b8afa12e9955d4d7bcd495749ea5b6c88bdc596 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Tue, 14 Nov 2017 20:33:00 +0200 Subject: [PATCH 3/7] exit strategy after roi check --- freqtrade/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/main.py b/freqtrade/main.py index 3fb0dd64d..b2789ca9f 100755 --- a/freqtrade/main.py +++ b/freqtrade/main.py @@ -183,7 +183,7 @@ def handle_trade(trade: Trade) -> bool: logger.debug('Handling %s ...', trade) current_rate = exchange.get_ticker(trade.pair)['bid'] - if should_sell(trade, current_rate, datetime.utcnow()): + if should_sell(trade, current_rate, datetime.utcnow()) or get_signal(trade.pair, SignalType.SELL): execute_sell(trade, current_rate) return True return False From 6b7afb80b283dfad1f5db25c00bfffab47b74d01 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Wed, 15 Nov 2017 07:05:17 +0200 Subject: [PATCH 4/7] fix failing test --- freqtrade/main.py | 2 +- freqtrade/tests/test_main.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/freqtrade/main.py b/freqtrade/main.py index b2789ca9f..fe25dd204 100755 --- a/freqtrade/main.py +++ b/freqtrade/main.py @@ -183,7 +183,7 @@ def handle_trade(trade: Trade) -> bool: logger.debug('Handling %s ...', trade) current_rate = exchange.get_ticker(trade.pair)['bid'] - if should_sell(trade, current_rate, datetime.utcnow()) or get_signal(trade.pair, SignalType.SELL): + if should_sell(trade, current_rate, datetime.utcnow()) or get_signal(trade.pair, SignalType.SELL) == 1: execute_sell(trade, current_rate) return True return False diff --git a/freqtrade/tests/test_main.py b/freqtrade/tests/test_main.py index 5be1dce3e..ae7402945 100644 --- a/freqtrade/tests/test_main.py +++ b/freqtrade/tests/test_main.py @@ -7,6 +7,7 @@ import requests from sqlalchemy import create_engine from freqtrade.exchange import Exchanges +from freqtrade.analyze import SignalType from freqtrade.main import create_trade, handle_trade, close_trade_if_fulfilled, init, \ get_target_bid, _process from freqtrade.misc import get_state, State, FreqtradeException @@ -80,7 +81,7 @@ def test_process_runtime_error(default_conf, ticker, health, mocker): def test_process_trade_handling(default_conf, ticker, limit_buy_order, health, mocker): mocker.patch.dict('freqtrade.main._CONF', default_conf) mocker.patch.multiple('freqtrade.main.telegram', init=MagicMock(), send_msg=MagicMock()) - mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True) + signal = mocker.patch('freqtrade.main.get_signal', side_effect=lambda *args: False if args[1] == SignalType.SELL else True) mocker.patch.multiple('freqtrade.main.exchange', validate_pairs=MagicMock(), get_ticker=ticker, From c1ef3f526c2c0f68bc46b6eb2d489b2cd0614ce9 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Thu, 16 Nov 2017 07:41:26 +0200 Subject: [PATCH 5/7] remove unnecessary comparison --- freqtrade/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/main.py b/freqtrade/main.py index fe25dd204..b2789ca9f 100755 --- a/freqtrade/main.py +++ b/freqtrade/main.py @@ -183,7 +183,7 @@ def handle_trade(trade: Trade) -> bool: logger.debug('Handling %s ...', trade) current_rate = exchange.get_ticker(trade.pair)['bid'] - if should_sell(trade, current_rate, datetime.utcnow()) or get_signal(trade.pair, SignalType.SELL) == 1: + if should_sell(trade, current_rate, datetime.utcnow()) or get_signal(trade.pair, SignalType.SELL): execute_sell(trade, current_rate) return True return False From b9983149ef645830cecc9c77f384ffab821f9e90 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Thu, 16 Nov 2017 07:45:51 +0200 Subject: [PATCH 6/7] plug sell strategy to backtesting --- freqtrade/tests/test_backtesting.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/freqtrade/tests/test_backtesting.py b/freqtrade/tests/test_backtesting.py index 7f019dd17..7edce3df3 100644 --- a/freqtrade/tests/test_backtesting.py +++ b/freqtrade/tests/test_backtesting.py @@ -33,7 +33,7 @@ def backtest(backtest_conf, backdata, mocker): mocker.patch('arrow.utcnow', return_value=arrow.get('2017-08-20T14:50:00')) for pair, pair_data in backdata.items(): mocked_history.return_value = pair_data - ticker = analyze_ticker(pair)[['close', 'date', 'buy']].copy() + ticker = analyze_ticker(pair)[['close', 'date', 'buy', 'sell']].copy() # for each buy point for row in ticker[ticker.buy == 1].itertuples(index=True): trade = Trade( @@ -44,7 +44,7 @@ def backtest(backtest_conf, backdata, mocker): ) # calculate win/lose forwards from buy point for row2 in ticker[row.Index:].itertuples(index=True): - if should_sell(trade, row2.close, row2.date): + if should_sell(trade, row2.close, row2.date) or row2.sell == 1: current_profit = trade.calc_profit(row2.close) trades.append((pair, current_profit, row2.Index - row.Index)) From a963f1820c6a54fbc44dfc071e47f11d842c3da6 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Thu, 16 Nov 2017 07:49:06 +0200 Subject: [PATCH 7/7] rename should_sell to min_roi_reached --- freqtrade/main.py | 6 +++--- freqtrade/tests/test_backtesting.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/freqtrade/main.py b/freqtrade/main.py index b2789ca9f..316e0c960 100755 --- a/freqtrade/main.py +++ b/freqtrade/main.py @@ -153,9 +153,9 @@ def execute_sell(trade: Trade, limit: float) -> None: telegram.send_msg(message) -def should_sell(trade: Trade, current_rate: float, current_time: datetime) -> bool: +def min_roi_reached(trade: Trade, current_rate: float, current_time: datetime) -> bool: """ - Based an earlier trade and current price and configuration, decides whether bot should sell + Based an earlier trade and current price and ROI configuration, decides whether bot should sell :return True if bot should sell at current rate """ current_profit = trade.calc_profit(current_rate) @@ -183,7 +183,7 @@ def handle_trade(trade: Trade) -> bool: logger.debug('Handling %s ...', trade) current_rate = exchange.get_ticker(trade.pair)['bid'] - if should_sell(trade, current_rate, datetime.utcnow()) or get_signal(trade.pair, SignalType.SELL): + if min_roi_reached(trade, current_rate, datetime.utcnow()) or get_signal(trade.pair, SignalType.SELL): execute_sell(trade, current_rate) return True return False diff --git a/freqtrade/tests/test_backtesting.py b/freqtrade/tests/test_backtesting.py index 7edce3df3..6a8ecacb0 100644 --- a/freqtrade/tests/test_backtesting.py +++ b/freqtrade/tests/test_backtesting.py @@ -9,7 +9,7 @@ from pandas import DataFrame from freqtrade import exchange from freqtrade.analyze import analyze_ticker from freqtrade.exchange import Bittrex -from freqtrade.main import should_sell +from freqtrade.main import min_roi_reached from freqtrade.persistence import Trade logging.disable(logging.DEBUG) # disable debug logs that slow backtesting a lot @@ -44,7 +44,7 @@ def backtest(backtest_conf, backdata, mocker): ) # calculate win/lose forwards from buy point for row2 in ticker[row.Index:].itertuples(index=True): - if should_sell(trade, row2.close, row2.date) or row2.sell == 1: + if min_roi_reached(trade, row2.close, row2.date) or row2.sell == 1: current_profit = trade.calc_profit(row2.close) trades.append((pair, current_profit, row2.Index - row.Index))