Merge pull request #454 from gcarq/replace_matplotlib

Replace matplotlib with Plotly
This commit is contained in:
Samuel Husso 2018-01-28 12:59:10 +02:00 committed by GitHub
commit 3b11459a38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 130 additions and 71 deletions

View File

@ -5,21 +5,34 @@ This page explains how to plot prices, indicator, profits.
- [Plot price and indicators](#plot-price-and-indicators) - [Plot price and indicators](#plot-price-and-indicators)
- [Plot profit](#plot-profit) - [Plot profit](#plot-profit)
## Installation
Plotting scripts use Plotly library. Install/upgrade it with:
```
pip install --upgrade plotly
```
At least version 2.3.0 is required.
## Plot price and indicators ## Plot price and indicators
Usage for the price plotter: Usage for the price plotter:
script/plot_dataframe.py [-h] [-p pair]
```
script/plot_dataframe.py [-h] [-p pair] [--live]
```
Example Example
``` ```
python script/plot_dataframe.py -p BTC_ETH,BTC_LTC python script/plot_dataframe.py -p BTC_ETH
``` ```
The -p pair argument, can be used to specify what The `-p` pair argument, can be used to specify what
pair you would like to plot. pair you would like to plot.
**Advanced use** **Advanced use**
To plot the current live price use the --live flag: To plot the current live price use the `--live` flag:
``` ```
python scripts/plot_dataframe.py -p BTC_ETH --live python scripts/plot_dataframe.py -p BTC_ETH --live
``` ```
@ -51,19 +64,14 @@ The third graph can be useful to spot outliers, events in pairs
that makes profit spikes. that makes profit spikes.
Usage for the profit plotter: Usage for the profit plotter:
script/plot_profit.py [-h] [-p pair] [--datadir directory] [--ticker_interval num]
The -p pair argument, can be used to plot a single pair ```
script/plot_profit.py [-h] [-p pair] [--datadir directory] [--ticker_interval num]
```
The `-p` pair argument, can be used to plot a single pair
Example Example
``` ```
python python scripts/plot_profit.py --datadir ../freqtrade/freqtrade/tests/testdata-20171221/ -p BTC_LTC python python scripts/plot_profit.py --datadir ../freqtrade/freqtrade/tests/testdata-20171221/ -p BTC_LTC
``` ```
**When it goes wrong**
*** Linux: Can't display**
If you are inside an python environment, you might want to set the
DISPLAY variable as so:
$ DISPLAY=:0 python scripts/plot_dataframe.py

View File

@ -22,5 +22,4 @@ tabulate==0.8.2
pymarketcap==3.3.153 pymarketcap==3.3.153
# Required for plotting data # Required for plotting data
#matplotlib==2.1.0 #plotly==2.3.0
#PYQT5==5.9

View File

@ -3,14 +3,16 @@
import sys import sys
import logging import logging
import argparse import argparse
import os
import matplotlib
# matplotlib.use("Qt5Agg")
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
from pandas import DataFrame from pandas import DataFrame
import talib.abstract as ta import talib.abstract as ta
import plotly
from plotly import tools
from plotly.offline import plot
import plotly.graph_objs as go
import freqtrade.vendor.qtpylib.indicators as qtpylib import freqtrade.vendor.qtpylib.indicators as qtpylib
from freqtrade import exchange, analyze from freqtrade import exchange, analyze
from freqtrade.misc import common_args_parser from freqtrade.misc import common_args_parser
@ -36,8 +38,7 @@ def plot_analyzed_dataframe(args) -> None:
:param pair: pair as str :param pair: pair as str
:return: None :return: None
""" """
pair = args.pair pair = args.pair.replace('-', '_')
pairs = [pair]
timerange = misc.parse_timerange(args.timerange) timerange = misc.parse_timerange(args.timerange)
# Init strategy # Init strategy
@ -52,7 +53,7 @@ def plot_analyzed_dataframe(args) -> None:
exchange._API = exchange.Bittrex({'key': '', 'secret': ''}) exchange._API = exchange.Bittrex({'key': '', 'secret': ''})
tickers[pair] = exchange.get_ticker_history(pair, tick_interval) tickers[pair] = exchange.get_ticker_history(pair, tick_interval)
else: else:
tickers = optimize.load_data(args.datadir, pairs=pairs, tickers = optimize.load_data(args.datadir, pairs=[pair],
ticker_interval=tick_interval, ticker_interval=tick_interval,
refresh_pairs=False, refresh_pairs=False,
timerange=timerange) timerange=timerange)
@ -62,38 +63,84 @@ def plot_analyzed_dataframe(args) -> None:
dataframe = analyze.populate_sell_trend(dataframe) dataframe = analyze.populate_sell_trend(dataframe)
dates = misc.datesarray_to_datetimearray(dataframe['date']) dates = misc.datesarray_to_datetimearray(dataframe['date'])
# Two subplots sharing x axis if (len(dataframe.index) > 750):
fig, (ax1, ax2, ax3) = plt.subplots(3, sharex=True) logger.warn('Ticker contained more than 750 candles, clipping.')
fig.suptitle(pair + " " + str(tick_interval), fontsize=14, fontweight='bold') df = dataframe.tail(750)
ax1.plot(dates, dataframe['close'], label='close') candles = go.Candlestick(x=df.date,
# ax1.plot(dates, dataframe['sell'], 'ro', label='sell') open=df.open,
ax1.plot(dates, dataframe['sma'], '--', label='SMA') high=df.high,
ax1.plot(dates, dataframe['tema'], ':', label='TEMA') low=df.low,
ax1.plot(dates, dataframe['blower'], '-.', label='BB low') close=df.close,
ax1.plot(dates, dataframe['close'] * dataframe['buy'], 'bo', label='buy') name='Price')
ax1.plot(dates, dataframe['close'] * dataframe['sell'], 'ro', label='sell')
ax1.legend() df_buy = df[df['buy'] == 1]
buys = go.Scattergl(
x=df_buy.date,
y=df_buy.close,
mode='markers',
name='buy',
marker=dict(symbol='x-dot')
)
df_sell = df[df['sell'] == 1]
sells = go.Scattergl(
x=df_sell.date,
y=df_sell.close,
mode='markers',
name='sell',
marker=dict(symbol='diamond')
)
ax2.plot(dates, dataframe['adx'], label='ADX') bb_lower = go.Scatter(
ax2.plot(dates, dataframe['mfi'], label='MFI') x=df.date,
# ax2.plot(dates, [25] * len(dataframe.index.values)) y=df.bb_lowerband,
ax2.legend() name='BB lower',
line={'color': "transparent"},
)
bb_upper = go.Scatter(
x=df.date,
y=df.bb_upperband,
name='BB upper',
fill="tonexty",
fillcolor="rgba(0,176,246,0.2)",
line={'color': "transparent"},
)
ax3.plot(dates, dataframe['fastk'], label='k') macd = go.Scattergl(
ax3.plot(dates, dataframe['fastd'], label='d') x=df['date'],
ax3.plot(dates, [20] * len(dataframe.index.values)) y=df['macd'],
ax3.legend() name='MACD'
xfmt = mdates.DateFormatter('%d-%m-%y %H:%M') # Dont let matplotlib autoformat date )
ax3.xaxis.set_major_formatter(xfmt) macdsignal = go.Scattergl(
x=df['date'],
y=df['macdsignal'],
name='MACD signal'
)
volume = go.Bar(
x=df['date'],
y=df['volume'],
name='Volume'
)
fig = tools.make_subplots(rows=3, cols=1, shared_xaxes=True, row_width=[1, 1, 4])
fig.append_trace(candles, 1, 1)
fig.append_trace(bb_lower, 1, 1)
fig.append_trace(bb_upper, 1, 1)
fig.append_trace(buys, 1, 1)
fig.append_trace(sells, 1, 1)
fig.append_trace(volume, 2, 1)
fig.append_trace(macd, 3, 1)
fig.append_trace(macdsignal, 3, 1)
fig['layout'].update(title=args.pair)
fig['layout']['yaxis1'].update(title='Price')
fig['layout']['yaxis2'].update(title='Volume')
fig['layout']['yaxis3'].update(title='MACD')
plot(fig, filename='freqtrade-plot.html')
# Fine-tune figure; make subplots close to each other and hide x ticks for
# all but bottom plot.
fig.subplots_adjust(hspace=0)
fig.autofmt_xdate() # Rotate the dates
plt.setp([a.get_xticklabels() for a in fig.axes[:-1]], visible=False)
plt.show()
if __name__ == '__main__': if __name__ == '__main__':
args = plot_parse_args(sys.argv[1:]) args = plot_parse_args(sys.argv[1:])

View File

@ -2,10 +2,13 @@
import sys import sys
import json import json
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import numpy as np import numpy as np
import plotly
from plotly import tools
from plotly.offline import plot
import plotly.graph_objs as go
import freqtrade.optimize as optimize import freqtrade.optimize as optimize
import freqtrade.misc as misc import freqtrade.misc as misc
import freqtrade.exchange as exchange import freqtrade.exchange as exchange
@ -122,30 +125,32 @@ def plot_profit(args) -> None:
# Plot the pairs average close prices, and total profit growth # Plot the pairs average close prices, and total profit growth
# #
fig, (ax1, ax2, ax3) = plt.subplots(3, sharex=True) avgclose = go.Scattergl(
fig.suptitle('total profit') x=dates,
y=avgclose,
name='Avg close price',
)
profit = go.Scattergl(
x=dates,
y=pg,
name='Profit',
)
ax1.plot(dates, avgclose, label='avgclose') fig = tools.make_subplots(rows=3, cols=1, shared_xaxes=True, row_width=[1, 1, 1])
ax2.plot(dates, pg, label='profit')
ax1.legend(loc='upper left') fig.append_trace(avgclose, 1, 1)
ax2.legend(loc='upper left') fig.append_trace(profit, 2, 1)
# FIX if we have one line pair in paris
# then skip the plotting of the third graph,
# or change what we plot
# In third graph, we plot each profit separately
for pair in pairs: for pair in pairs:
pg = make_profit_array(data, max_x, pair) pg = make_profit_array(data, max_x, pair)
ax3.plot(dates, pg, label=pair) pair_profit = go.Scattergl(
ax3.legend(loc='upper left') x=dates,
# black background to easier see multiple colors y=pg,
ax3.set_facecolor('black') name=pair,
xfmt = mdates.DateFormatter('%d-%m-%y %H:%M') # Dont let matplotlib autoformat date )
ax3.xaxis.set_major_formatter(xfmt) fig.append_trace(pair_profit, 3, 1)
fig.subplots_adjust(hspace=0) plot(fig, filename='freqtrade-profit-plot.html')
fig.autofmt_xdate() # Rotate the dates
plt.show()
if __name__ == '__main__': if __name__ == '__main__':