diff --git a/scripts/plot_dataframe.py b/scripts/plot_dataframe.py index 99d17c0b6..1a7b5b875 100755 --- a/scripts/plot_dataframe.py +++ b/scripts/plot_dataframe.py @@ -5,12 +5,20 @@ Script to display when the bot will buy a specific pair Mandatory Cli parameters: -p / --pair: pair to examine -Optional Cli parameters +Option but recommended -s / --strategy: strategy to use + + +Optional Cli parameters -d / --datadir: path to pair backtest data --timerange: specify what timerange of data to use. -l / --live: Live, to download the latest ticker for the pair -db / --db-url: Show trades stored in database + + +Indicators recommended +Row 1: sma, ema3, ema5, ema10, ema50 +Row 3: macd, rsi, fisher_rsi, mfi, slowd, slowk, fastd, fastk """ import logging import os @@ -33,20 +41,6 @@ logger = logging.getLogger(__name__) _CONF: Dict[str, Any] = {} -# Update the global variable TO_DISPLAY to select which indicator you want to display -TO_DISPLAY = { - 'sma': False, # On Row 1 - 'ema': True, # On Row 1 - - 'macd': True, # On Row 3 - 'rsi': False, # On Row 3 - 'fisher_rsi': False, # On Row 3 - 'mfi': False, # On Row 3 - 'slow': False, # On Row 3 - 'fast': False # On Row 3 -} - - def plot_analyzed_dataframe(args: Namespace) -> None: """ Calls analyze() and plots the returned dataframe @@ -59,6 +53,15 @@ def plot_analyzed_dataframe(args: Namespace) -> None: # Set the pair to audit pair = args.pair + if pair is None: + logger.critical('Parameter --pair mandatory;. E.g --pair ETH/BTC') + exit() + + if '/' not in pair: + logger.critical('--pair format must be XXX/YYY') + exit() + + # Set timerange to use timerange = Arguments.parse_timerange(args.timerange) @@ -112,13 +115,14 @@ def plot_analyzed_dataframe(args: Namespace) -> None: fig = generate_graph( pair=pair, trades=trades, - data=dataframe.tail(750) + data=dataframe.tail(750), + args=args ) plot(fig, filename=os.path.join('user_data', 'freqtrade-plot.html')) -def generate_graph(pair, trades, data) -> None: +def generate_graph(pair, trades, data, args) -> tools.make_subplots: """ Generate the graph from the data generated by Backtesting or from DB :param pair: Pair to Display on the graph @@ -136,6 +140,9 @@ def generate_graph(pair, trades, data) -> None: vertical_spacing=0.0001, ) fig['layout'].update(title=pair) + fig['layout']['yaxis1'].update(title='Price') + fig['layout']['yaxis2'].update(title='Volume') + fig['layout']['yaxis3'].update(title='Other') # Common information candles = go.Candlestick( @@ -220,21 +227,11 @@ def generate_graph(pair, trades, data) -> None: fig.append_trace(bb_lower, 1, 1) fig.append_trace(bb_upper, 1, 1) - if TO_DISPLAY['sma'] and 'sma' in data: - sma = generate_scattergl(index='sma', name='SMA', data=data) - fig.append_trace(sma, 1, 1) - - if TO_DISPLAY['ema'] and 'ema10' in data and 'ema50' in data: - ema10 = generate_scattergl(index='ema10', name='EMA10', data=data) - ema50 = generate_scattergl(index='ema50', name='EMA50', data=data) - fig.append_trace(ema10, 1, 1) - fig.append_trace(ema50, 1, 1) - + fig = generate_row(fig=fig, row=1, raw_indicators=args.indicators1, data=data) fig.append_trace(buys, 1, 1) fig.append_trace(sells, 1, 1) fig.append_trace(trade_buys, 1, 1) fig.append_trace(trade_sells, 1, 1) - fig['layout']['yaxis1'].update(title='Price') # Row 2 volume = go.Bar( @@ -243,61 +240,33 @@ def generate_graph(pair, trades, data) -> None: name='Volume' ) fig.append_trace(volume, 2, 1) - fig['layout']['yaxis2'].update(title='Volume') - # Row 3 (On Row 3, we can only display one indicator) - if TO_DISPLAY['macd'] and 'macd' in data and 'macdsignal' in data: - macd = generate_scattergl(index='macd', name='MACD', data=data) - macdsignal = generate_scattergl(index='macdsignal', name='MACD Signal', data=data) - fig.append_trace(macd, 3, 1) - fig.append_trace(macdsignal, 3, 1) - fig['layout']['yaxis3'].update(title='MACD') - - elif TO_DISPLAY['fast'] and 'fastd' in data and 'fastk' in data: - fastd = generate_scattergl(index='fastd', name='fastd', data=data) - fastk = generate_scattergl(index='fastk', name='fastk', data=data) - fig.append_trace(fastd, 3, 1) - fig.append_trace(fastk, 3, 1) - fig['layout']['yaxis3'].update(title='Stoch Fast') - - elif TO_DISPLAY['slow'] and 'slowd' in data and 'slowk' in data: - slowd = generate_scattergl(index='slowd', name='slowd', data=data) - slowk = generate_scattergl(index='slowk', name='slowk', data=data) - fig.append_trace(slowd, 3, 1) - fig.append_trace(slowk, 3, 1) - fig['layout']['yaxis3'].update(title='Stoch Slow') - - elif TO_DISPLAY['rsi'] and 'rsi' in data: - rsi = generate_scattergl(index='rsi', name='RSI', data=data) - fig.append_trace(rsi, 3, 1) - fig['layout']['yaxis3'].update(title='RSI') - - elif TO_DISPLAY['mfi'] and 'mfi' in data: - mfi = generate_scattergl(index='mfi', name='MFI', data=data) - fig.append_trace(mfi, 3, 1) - fig['layout']['yaxis3'].update(title='MFI') - - elif TO_DISPLAY['fisher_rsi'] and 'fisher_rsi' in data: - fisher_rsi = generate_scattergl(index='fisher_rsi', name='Fisher RSI', data=data) - fig.append_trace(fisher_rsi, 3, 1) - fig['layout']['yaxis3'].update(title='Fisher RSI') + # Row 3 + fig = generate_row(fig=fig, row=3, raw_indicators=args.indicators2, data=data) return fig -def generate_scattergl(index, name, data) -> go.Scattergl: +def generate_row(fig, row, raw_indicators, data) -> tools.make_subplots: """ - Generate a Scattergl element - :param index: code of the Indicator to generate - :param name: Name that will be display in the graph legend - :param data: Dataframe - :return: Scattergl + Generator all the indicator selected by the user for a specific row """ - return go.Scattergl( - x=data['date'], - y=data[index], - name=name - ) + for indicator in raw_indicators.split(','): + if indicator in data: + scattergl = go.Scattergl( + x=data['date'], + y=data[indicator], + name=indicator + ) + fig.append_trace(scattergl, row, 1) + else: + logger.info( + 'Indicator "%s" ignored. Reason: This indicator is not found ' + 'in your strategy.', + indicator + ) + + return fig def plot_parse_args(args: List[str]) -> Namespace: @@ -308,6 +277,24 @@ def plot_parse_args(args: List[str]) -> Namespace: """ arguments = Arguments(args, 'Graph dataframe') arguments.scripts_options() + arguments.parser.add_argument( + '--indicators1', + help='Set indicators from your strategy you want in the first row of the graph. Separate ' + 'them with a coma. E.g: ema3,ema5 (default: %(default)s)', + type=str, + default='sma,ema3,ema5', + dest='indicators1', + ) + + arguments.parser.add_argument( + '--indicators2', + help='Set indicators from your strategy you want in the third row of the graph. Separate ' + 'them with a coma. E.g: fastd,fastk (default: %(default)s)', + type=str, + default='macd', + dest='indicators2', + ) + arguments.common_args_parser() arguments.optimizer_shared_options(arguments.parser) arguments.backtesting_options(arguments.parser)