Merge pull request #2752 from freqtrade/plotting/indicator_strategy
Allow enhanced plot-dataframe configuration
This commit is contained in:
@@ -13,6 +13,7 @@ from freqtrade.data.btanalysis import create_cum_profit, load_backtest_data
|
||||
from freqtrade.exceptions import OperationalException
|
||||
from freqtrade.plot.plot_utils import start_plot_dataframe, start_plot_profit
|
||||
from freqtrade.plot.plotting import (add_indicators, add_profit,
|
||||
create_plotconfig,
|
||||
generate_candlestick_graph,
|
||||
generate_plot_filename,
|
||||
generate_profit_graph, init_plotscript,
|
||||
@@ -66,8 +67,8 @@ def test_add_indicators(default_conf, testdatadir, caplog):
|
||||
|
||||
data = history.load_pair_history(pair=pair, timeframe='1m',
|
||||
datadir=testdatadir, timerange=timerange)
|
||||
indicators1 = ["ema10"]
|
||||
indicators2 = ["macd"]
|
||||
indicators1 = {"ema10": {}}
|
||||
indicators2 = {"macd": {"color": "red"}}
|
||||
|
||||
# Generate buy/sell signals and indicators
|
||||
strat = DefaultStrategy(default_conf)
|
||||
@@ -86,9 +87,10 @@ def test_add_indicators(default_conf, testdatadir, caplog):
|
||||
macd = find_trace_in_fig_data(figure.data, "macd")
|
||||
assert isinstance(macd, go.Scatter)
|
||||
assert macd.yaxis == "y3"
|
||||
assert macd.line.color == "red"
|
||||
|
||||
# No indicator found
|
||||
fig3 = add_indicators(fig=deepcopy(fig), row=3, indicators=['no_indicator'], data=data)
|
||||
fig3 = add_indicators(fig=deepcopy(fig), row=3, indicators={'no_indicator': {}}, data=data)
|
||||
assert fig == fig3
|
||||
assert log_has_re(r'Indicator "no_indicator" ignored\..*', caplog)
|
||||
|
||||
@@ -108,18 +110,29 @@ def test_plot_trades(testdatadir, caplog):
|
||||
figure = fig1.layout.figure
|
||||
|
||||
# Check buys - color, should be in first graph, ...
|
||||
trade_buy = find_trace_in_fig_data(figure.data, "trade_buy")
|
||||
trade_buy = find_trace_in_fig_data(figure.data, 'Trade buy')
|
||||
assert isinstance(trade_buy, go.Scatter)
|
||||
assert trade_buy.yaxis == 'y'
|
||||
assert len(trades) == len(trade_buy.x)
|
||||
assert trade_buy.marker.color == 'green'
|
||||
assert trade_buy.marker.color == 'cyan'
|
||||
assert trade_buy.marker.symbol == 'circle-open'
|
||||
assert trade_buy.text[0] == '4.0%, roi, 15 min'
|
||||
|
||||
trade_sell = find_trace_in_fig_data(figure.data, "trade_sell")
|
||||
trade_sell = find_trace_in_fig_data(figure.data, 'Sell - Profit')
|
||||
assert isinstance(trade_sell, go.Scatter)
|
||||
assert trade_sell.yaxis == 'y'
|
||||
assert len(trades) == len(trade_sell.x)
|
||||
assert trade_sell.marker.color == 'red'
|
||||
assert trade_sell.text[0] == "4.0%, roi, 15 min"
|
||||
assert len(trades.loc[trades['profitperc'] > 0]) == len(trade_sell.x)
|
||||
assert trade_sell.marker.color == 'green'
|
||||
assert trade_sell.marker.symbol == 'square-open'
|
||||
assert trade_sell.text[0] == '4.0%, roi, 15 min'
|
||||
|
||||
trade_sell_loss = find_trace_in_fig_data(figure.data, 'Sell - Loss')
|
||||
assert isinstance(trade_sell_loss, go.Scatter)
|
||||
assert trade_sell_loss.yaxis == 'y'
|
||||
assert len(trades.loc[trades['profitperc'] <= 0]) == len(trade_sell_loss.x)
|
||||
assert trade_sell_loss.marker.color == 'red'
|
||||
assert trade_sell_loss.marker.symbol == 'square-open'
|
||||
assert trade_sell_loss.text[5] == '-10.4%, stop_loss, 720 min'
|
||||
|
||||
|
||||
def test_generate_candlestick_graph_no_signals_no_trades(default_conf, mocker, testdatadir, caplog):
|
||||
@@ -308,7 +321,7 @@ def test_load_and_plot_trades(default_conf, mocker, caplog, testdatadir):
|
||||
"freqtrade.plot.plotting",
|
||||
generate_candlestick_graph=candle_mock,
|
||||
store_plot_file=store_mock
|
||||
)
|
||||
)
|
||||
load_and_plot_trades(default_conf)
|
||||
|
||||
# Both mocks should be called once per pair
|
||||
@@ -371,3 +384,47 @@ def test_plot_profit(default_conf, mocker, testdatadir, caplog):
|
||||
|
||||
assert profit_mock.call_args_list[0][0][0] == default_conf['pairs']
|
||||
assert store_mock.call_args_list[0][1]['auto_open'] is True
|
||||
|
||||
|
||||
@pytest.mark.parametrize("ind1,ind2,plot_conf,exp", [
|
||||
# No indicators, use plot_conf
|
||||
([], [], {},
|
||||
{'main_plot': {'sma': {}, 'ema3': {}, 'ema5': {}},
|
||||
'subplots': {'Other': {'macd': {}, 'macdsignal': {}}}}),
|
||||
# use indicators
|
||||
(['sma', 'ema3'], ['macd'], {},
|
||||
{'main_plot': {'sma': {}, 'ema3': {}}, 'subplots': {'Other': {'macd': {}}}}),
|
||||
# only main_plot - adds empty subplots
|
||||
([], [], {'main_plot': {'sma': {}}},
|
||||
{'main_plot': {'sma': {}}, 'subplots': {}}),
|
||||
# Main and subplots
|
||||
([], [], {'main_plot': {'sma': {}}, 'subplots': {'RSI': {'rsi': {'color': 'red'}}}},
|
||||
{'main_plot': {'sma': {}}, 'subplots': {'RSI': {'rsi': {'color': 'red'}}}}),
|
||||
# no main_plot, adds empty main_plot
|
||||
([], [], {'subplots': {'RSI': {'rsi': {'color': 'red'}}}},
|
||||
{'main_plot': {}, 'subplots': {'RSI': {'rsi': {'color': 'red'}}}}),
|
||||
# indicator 1 / 2 should have prevelance
|
||||
(['sma', 'ema3'], ['macd'],
|
||||
{'main_plot': {'sma': {}}, 'subplots': {'RSI': {'rsi': {'color': 'red'}}}},
|
||||
{'main_plot': {'sma': {}, 'ema3': {}}, 'subplots': {'Other': {'macd': {}}}}
|
||||
),
|
||||
# indicator 1 - overrides plot_config main_plot
|
||||
(['sma', 'ema3'], [],
|
||||
{'main_plot': {'sma': {}}, 'subplots': {'RSI': {'rsi': {'color': 'red'}}}},
|
||||
{'main_plot': {'sma': {}, 'ema3': {}}, 'subplots': {'RSI': {'rsi': {'color': 'red'}}}}
|
||||
),
|
||||
# indicator 2 - overrides plot_config subplots
|
||||
([], ['macd', 'macd_signal'],
|
||||
{'main_plot': {'sma': {}}, 'subplots': {'RSI': {'rsi': {'color': 'red'}}}},
|
||||
{'main_plot': {'sma': {}}, 'subplots': {'Other': {'macd': {}, 'macd_signal': {}}}}
|
||||
),
|
||||
])
|
||||
def test_create_plotconfig(ind1, ind2, plot_conf, exp):
|
||||
|
||||
res = create_plotconfig(ind1, ind2, plot_conf)
|
||||
assert 'main_plot' in res
|
||||
assert 'subplots' in res
|
||||
assert isinstance(res['main_plot'], dict)
|
||||
assert isinstance(res['subplots'], dict)
|
||||
|
||||
assert res == exp
|
||||
|
Reference in New Issue
Block a user