Merge pull request #1018 from freqtrade/feat/sell_reason

Record sell reason
This commit is contained in:
Janne Sinivirta
2018-07-24 09:09:45 +03:00
committed by GitHub
9 changed files with 162 additions and 43 deletions

View File

@@ -17,6 +17,7 @@ from freqtrade.arguments import Arguments, TimeRange
from freqtrade.optimize.backtesting import (Backtesting, setup_configuration,
start)
from freqtrade.tests.conftest import log_has, patch_exchange
from freqtrade.strategy.interface import SellType
from freqtrade.strategy.default_strategy import DefaultStrategy
@@ -406,6 +407,35 @@ def test_generate_text_table(default_conf, mocker):
assert backtesting._generate_text_table(data={'ETH/BTC': {}}, results=results) == result_str
def test_generate_text_table_sell_reason(default_conf, mocker):
"""
Test Backtesting.generate_text_table_sell_reason() method
"""
patch_exchange(mocker)
backtesting = Backtesting(default_conf)
results = pd.DataFrame(
{
'pair': ['ETH/BTC', 'ETH/BTC', 'ETH/BTC'],
'profit_percent': [0.1, 0.2, 0.3],
'profit_abs': [0.2, 0.4, 0.5],
'trade_duration': [10, 30, 10],
'profit': [2, 0, 0],
'loss': [0, 0, 1],
'sell_reason': [SellType.ROI, SellType.ROI, SellType.STOP_LOSS]
}
)
result_str = (
'| Sell Reason | Count |\n'
'|:--------------|--------:|\n'
'| roi | 2 |\n'
'| stop_loss | 1 |'
)
assert backtesting._generate_text_table_sell_reason(
data={'ETH/BTC': {}}, results=results) == result_str
def test_backtesting_start(default_conf, mocker, caplog) -> None:
"""
Test Backtesting.start() method
@@ -514,7 +544,9 @@ def test_backtest(default_conf, fee, mocker) -> None:
'trade_duration': [240, 50],
'open_at_end': [False, False],
'open_rate': [0.104445, 0.10302485],
'close_rate': [0.105, 0.10359999]})
'close_rate': [0.105, 0.10359999],
'sell_reason': [SellType.ROI, SellType.ROI]
})
pd.testing.assert_frame_equal(results, expected)
data_pair = data_processed[pair]
for _, t in results.iterrows():
@@ -660,7 +692,9 @@ def test_backtest_record(default_conf, fee, mocker):
"open_index": [1, 119, 153, 185],
"close_index": [118, 151, 184, 199],
"trade_duration": [123, 34, 31, 14],
"open_at_end": [False, False, False, True]
"open_at_end": [False, False, False, True],
"sell_reason": [SellType.ROI, SellType.STOP_LOSS,
SellType.ROI, SellType.FORCE_SELL]
})
backtesting._store_backtest_result("backtest-result.json", results)
assert len(results) == 4
@@ -673,7 +707,7 @@ def test_backtest_record(default_conf, fee, mocker):
# Below follows just a typecheck of the schema/type of trade-records
oix = None
for (pair, profit, date_buy, date_sell, buy_index, dur,
openr, closer, open_at_end) in records:
openr, closer, open_at_end, sell_reason) in records:
assert pair == 'UNITTEST/BTC'
assert isinstance(profit, float)
# FIX: buy/sell should be converted to ints
@@ -682,6 +716,7 @@ def test_backtest_record(default_conf, fee, mocker):
assert isinstance(openr, float)
assert isinstance(closer, float)
assert isinstance(open_at_end, bool)
assert isinstance(sell_reason, str)
isinstance(buy_index, pd._libs.tslib.Timestamp)
if oix:
assert buy_index > oix

View File

@@ -20,6 +20,7 @@ from freqtrade.freqtradebot import FreqtradeBot
from freqtrade.persistence import Trade
from freqtrade.rpc import RPCMessageType
from freqtrade.state import State
from freqtrade.strategy.interface import SellType, SellCheckTuple
from freqtrade.tests.conftest import log_has, patch_coinmarketcap, patch_exchange
@@ -1369,7 +1370,7 @@ def test_execute_sell_up(default_conf, ticker, fee, ticker_sell_up, markets, moc
get_ticker=ticker_sell_up
)
freqtrade.execute_sell(trade=trade, limit=ticker_sell_up()['bid'])
freqtrade.execute_sell(trade=trade, limit=ticker_sell_up()['bid'], sell_reason=SellType.ROI)
assert rpc_mock.call_count == 2
last_msg = rpc_mock.call_args_list[-1][0][0]
@@ -1421,7 +1422,8 @@ def test_execute_sell_down(default_conf, ticker, fee, ticker_sell_down, markets,
get_ticker=ticker_sell_down
)
freqtrade.execute_sell(trade=trade, limit=ticker_sell_down()['bid'])
freqtrade.execute_sell(trade=trade, limit=ticker_sell_down()['bid'],
sell_reason=SellType.STOP_LOSS)
assert rpc_mock.call_count == 2
last_msg = rpc_mock.call_args_list[-1][0][0]
@@ -1474,7 +1476,7 @@ def test_execute_sell_without_conf_sell_up(default_conf, ticker, fee,
)
freqtrade.config = {}
freqtrade.execute_sell(trade=trade, limit=ticker_sell_up()['bid'])
freqtrade.execute_sell(trade=trade, limit=ticker_sell_up()['bid'], sell_reason=SellType.ROI)
assert rpc_mock.call_count == 2
last_msg = rpc_mock.call_args_list[-1][0][0]
@@ -1524,7 +1526,8 @@ def test_execute_sell_without_conf_sell_down(default_conf, ticker, fee,
)
freqtrade.config = {}
freqtrade.execute_sell(trade=trade, limit=ticker_sell_down()['bid'])
freqtrade.execute_sell(trade=trade, limit=ticker_sell_down()['bid'],
sell_reason=SellType.STOP_LOSS)
assert rpc_mock.call_count == 2
last_msg = rpc_mock.call_args_list[-1][0][0]
@@ -1577,6 +1580,7 @@ def test_sell_profit_only_enable_profit(default_conf, limit_buy_order,
trade.update(limit_buy_order)
patch_get_signal(freqtrade, value=(False, True))
assert freqtrade.handle_trade(trade) is True
assert trade.sell_reason == SellType.SELL_SIGNAL.value
def test_sell_profit_only_disable_profit(default_conf, limit_buy_order,
@@ -1612,6 +1616,7 @@ def test_sell_profit_only_disable_profit(default_conf, limit_buy_order,
trade.update(limit_buy_order)
patch_get_signal(freqtrade, value=(False, True))
assert freqtrade.handle_trade(trade) is True
assert trade.sell_reason == SellType.SELL_SIGNAL.value
def test_sell_profit_only_enable_loss(default_conf, limit_buy_order, fee, markets, mocker) -> None:
@@ -1640,7 +1645,8 @@ def test_sell_profit_only_enable_loss(default_conf, limit_buy_order, fee, market
freqtrade = FreqtradeBot(conf)
patch_get_signal(freqtrade)
freqtrade.strategy.stop_loss_reached = \
lambda current_rate, trade, current_time, current_profit: False
lambda current_rate, trade, current_time, current_profit: SellCheckTuple(
sell_flag=False, sell_type=SellType.NONE)
freqtrade.create_trade()
trade = Trade.query.first()
@@ -1684,6 +1690,7 @@ def test_sell_profit_only_disable_loss(default_conf, limit_buy_order, fee, marke
trade.update(limit_buy_order)
patch_get_signal(freqtrade, value=(False, True))
assert freqtrade.handle_trade(trade) is True
assert trade.sell_reason == SellType.SELL_SIGNAL.value
def test_ignore_roi_if_buy_signal(default_conf, limit_buy_order, fee, markets, mocker) -> None:
@@ -1724,6 +1731,7 @@ def test_ignore_roi_if_buy_signal(default_conf, limit_buy_order, fee, markets, m
# Test if buy-signal is absent (should sell due to roi = true)
patch_get_signal(freqtrade, value=(False, True))
assert freqtrade.handle_trade(trade) is True
assert trade.sell_reason == SellType.ROI.value
def test_trailing_stop_loss(default_conf, limit_buy_order, fee, markets, caplog, mocker) -> None:
@@ -1762,6 +1770,7 @@ def test_trailing_stop_loss(default_conf, limit_buy_order, fee, markets, caplog,
assert log_has(
f'HIT STOP: current price at 0.000001, stop loss is {trade.stop_loss:.6f}, '
f'initial stop loss was at 0.000010, trade opened at 0.000011', caplog.record_tuples)
assert trade.sell_reason == SellType.TRAILING_STOP_LOSS.value
def test_trailing_stop_loss_positive(default_conf, limit_buy_order, fee, markets,
@@ -1825,6 +1834,7 @@ def test_trailing_stop_loss_positive(default_conf, limit_buy_order, fee, markets
f'HIT STOP: current price at {buy_price + 0.000002:.6f}, '
f'stop loss is {trade.stop_loss:.6f}, '
f'initial stop loss was at 0.000010, trade opened at 0.000011', caplog.record_tuples)
assert trade.sell_reason == SellType.TRAILING_STOP_LOSS.value
def test_disable_ignore_roi_if_buy_signal(default_conf, limit_buy_order,
@@ -1867,6 +1877,7 @@ def test_disable_ignore_roi_if_buy_signal(default_conf, limit_buy_order,
# Test if buy-signal is absent
patch_get_signal(freqtrade, value=(False, True))
assert freqtrade.handle_trade(trade) is True
assert trade.sell_reason == SellType.STOP_LOSS.value
def test_get_real_amount_quote(default_conf, trades_for_order, buy_order_fee, caplog, mocker):

View File

@@ -465,6 +465,9 @@ def test_migrate_new(mocker, default_conf, fee, caplog):
assert trade.max_rate == 0.0
assert trade.stop_loss == 0.0
assert trade.initial_stop_loss == 0.0
assert trade.sell_reason is None
assert trade.strategy is None
assert trade.ticker_interval is None
assert log_has("trying trades_bak1", caplog.record_tuples)
assert log_has("trying trades_bak2", caplog.record_tuples)