Move plot-functions to plotting module

This commit is contained in:
Matthias 2019-05-28 07:00:57 +02:00
parent 583d70ec9c
commit 68af6d4151
2 changed files with 185 additions and 162 deletions

View File

@ -1,5 +1,7 @@
import logging import logging
from typing import List
import pandas as pd
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -11,3 +13,178 @@ try:
except ImportError: except ImportError:
logger.exception("Module plotly not found \n Please install using `pip install plotly`") logger.exception("Module plotly not found \n Please install using `pip install plotly`")
exit() exit()
def generate_row(fig, row, indicators: List[str], data: pd.DataFrame) -> tools.make_subplots:
"""
Generator all the indicator selected by the user for a specific row
:param fig: Plot figure to append to
:param row: row number for this plot
:param indicators: List of indicators present in the dataframe
:param data: candlestick DataFrame
"""
for indicator in indicators:
if indicator in data:
# TODO: Replace all Scatter with Scattergl for performance!!
scattergl = go.Scatter(
x=data['date'],
y=data[indicator],
mode='lines',
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_trades(fig, trades: pd.DataFrame):
"""
Plot trades to "fig"
"""
# Trades can be empty
if trades is not None:
trade_buys = go.Scatter(
x=trades["open_time"],
y=trades["open_rate"],
mode='markers',
name='trade_buy',
marker=dict(
symbol='square-open',
size=11,
line=dict(width=2),
color='green'
)
)
trade_sells = go.Scatter(
x=trades["close_time"],
y=trades["close_rate"],
mode='markers',
name='trade_sell',
marker=dict(
symbol='square-open',
size=11,
line=dict(width=2),
color='red'
)
)
fig.append_trace(trade_buys, 1, 1)
fig.append_trace(trade_sells, 1, 1)
return fig
def generate_graph(
pair: str,
data: pd.DataFrame,
trades: pd.DataFrame = None,
indicators1: List[str] = [],
indicators2: List[str] = [],
) -> tools.make_subplots:
"""
Generate the graph from the data generated by Backtesting or from DB
Volume will always be ploted in row2, so Row 1 and are to our disposal for custom indicators
:param pair: Pair to Display on the graph
:param data: OHLCV DataFrame containing indicators and buy/sell signals
:param trades: All trades created
:param indicators1: List containing Main plot indicators
:param indicators2: List containing Sub plot indicators
:return: None
"""
# Define the graph
fig = tools.make_subplots(
rows=3,
cols=1,
shared_xaxes=True,
row_width=[1, 1, 4],
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')
fig['layout']['xaxis']['rangeslider'].update(visible=False)
# Common information
candles = go.Candlestick(
x=data.date,
open=data.open,
high=data.high,
low=data.low,
close=data.close,
name='Price'
)
fig.append_trace(candles, 1, 1)
if 'buy' in data.columns:
df_buy = data[data['buy'] == 1]
buys = go.Scatter(
x=df_buy.date,
y=df_buy.close,
mode='markers',
name='buy',
marker=dict(
symbol='triangle-up-dot',
size=9,
line=dict(width=1),
color='green',
)
)
fig.append_trace(buys, 1, 1)
if 'sell' in data.columns:
df_sell = data[data['sell'] == 1]
sells = go.Scatter(
x=df_sell.date,
y=df_sell.close,
mode='markers',
name='sell',
marker=dict(
symbol='triangle-down-dot',
size=9,
line=dict(width=1),
color='red',
)
)
fig.append_trace(sells, 1, 1)
if 'bb_lowerband' in data and 'bb_upperband' in data:
bb_lower = go.Scatter(
x=data.date,
y=data.bb_lowerband,
name='BB lower',
line={'color': 'rgba(255,255,255,0)'},
)
bb_upper = go.Scatter(
x=data.date,
y=data.bb_upperband,
name='BB upper',
fill="tonexty",
fillcolor="rgba(0,176,246,0.2)",
line={'color': 'rgba(255,255,255,0)'},
)
fig.append_trace(bb_lower, 1, 1)
fig.append_trace(bb_upper, 1, 1)
# Add indicators to main plot
fig = generate_row(fig=fig, row=1, indicators=indicators1, data=data)
fig = plot_trades(fig, trades)
# Volume goes to row 2
volume = go.Bar(
x=data['date'],
y=data['volume'],
name='Volume'
)
fig.append_trace(volume, 2, 1)
# Add indicators to seperate row
fig = generate_row(fig=fig, row=3, indicators=indicators2, data=data)
return fig

View File

@ -31,15 +31,14 @@ from pathlib import Path
from typing import Any, Dict, List from typing import Any, Dict, List
import pandas as pd import pandas as pd
import plotly.graph_objs as go
import pytz import pytz
from plotly import tools
from plotly.offline import plot from plotly.offline import plot
from freqtrade import persistence from freqtrade import persistence
from freqtrade.arguments import Arguments, TimeRange from freqtrade.arguments import Arguments, TimeRange
from freqtrade.data import history from freqtrade.data import history
from freqtrade.data.btanalysis import BT_DATA_COLUMNS, load_backtest_data from freqtrade.data.btanalysis import BT_DATA_COLUMNS, load_backtest_data
from freqtrade.plot.plotting import generate_graph
from freqtrade.exchange import Exchange from freqtrade.exchange import Exchange
from freqtrade.optimize import setup_configuration from freqtrade.optimize import setup_configuration
from freqtrade.persistence import Trade from freqtrade.persistence import Trade
@ -96,7 +95,10 @@ def generate_plot_file(fig, pair, ticker_interval, is_last) -> None:
Path("user_data/plots").mkdir(parents=True, exist_ok=True) Path("user_data/plots").mkdir(parents=True, exist_ok=True)
plot(fig, filename=str(Path('user_data/plots').joinpath(file_name)), auto_open=False) plot(fig, filename=str(Path('user_data/plots').joinpath(file_name)),
auto_open=False,
include_plotlyjs='https://cdn.plot.ly/plotly-1.47.4.min.js'
)
if is_last: if is_last:
plot(fig, filename=str(Path('user_data').joinpath('freqtrade-plot.html')), auto_open=False) plot(fig, filename=str(Path('user_data').joinpath('freqtrade-plot.html')), auto_open=False)
@ -186,162 +188,6 @@ def extract_trades_of_period(dataframe, trades) -> pd.DataFrame:
return trades return trades
def generate_graph(
pair: str,
trades: pd.DataFrame,
data: pd.DataFrame,
indicators1: str,
indicators2: str
) -> tools.make_subplots:
"""
Generate the graph from the data generated by Backtesting or from DB
:param pair: Pair to Display on the graph
:param trades: All trades created
:param data: Dataframe
:indicators1: String Main plot indicators
:indicators2: String Sub plot indicators
:return: None
"""
# Define the graph
fig = tools.make_subplots(
rows=3,
cols=1,
shared_xaxes=True,
row_width=[1, 1, 4],
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')
fig['layout']['xaxis']['rangeslider'].update(visible=False)
# Common information
candles = go.Candlestick(
x=data.date,
open=data.open,
high=data.high,
low=data.low,
close=data.close,
name='Price'
)
df_buy = data[data['buy'] == 1]
buys = go.Scattergl(
x=df_buy.date,
y=df_buy.close,
mode='markers',
name='buy',
marker=dict(
symbol='triangle-up-dot',
size=9,
line=dict(width=1),
color='green',
)
)
df_sell = data[data['sell'] == 1]
sells = go.Scattergl(
x=df_sell.date,
y=df_sell.close,
mode='markers',
name='sell',
marker=dict(
symbol='triangle-down-dot',
size=9,
line=dict(width=1),
color='red',
)
)
trade_buys = go.Scattergl(
x=trades["open_time"],
y=trades["open_rate"],
mode='markers',
name='trade_buy',
marker=dict(
symbol='square-open',
size=11,
line=dict(width=2),
color='green'
)
)
trade_sells = go.Scattergl(
x=trades["close_time"],
y=trades["close_rate"],
mode='markers',
name='trade_sell',
marker=dict(
symbol='square-open',
size=11,
line=dict(width=2),
color='red'
)
)
# Row 1
fig.append_trace(candles, 1, 1)
if 'bb_lowerband' in data and 'bb_upperband' in data:
bb_lower = go.Scatter(
x=data.date,
y=data.bb_lowerband,
name='BB lower',
line={'color': 'rgba(255,255,255,0)'},
)
bb_upper = go.Scatter(
x=data.date,
y=data.bb_upperband,
name='BB upper',
fill="tonexty",
fillcolor="rgba(0,176,246,0.2)",
line={'color': 'rgba(255,255,255,0)'},
)
fig.append_trace(bb_lower, 1, 1)
fig.append_trace(bb_upper, 1, 1)
fig = generate_row(fig=fig, row=1, raw_indicators=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)
# Row 2
volume = go.Bar(
x=data['date'],
y=data['volume'],
name='Volume'
)
fig.append_trace(volume, 2, 1)
# Row 3
fig = generate_row(fig=fig, row=3, raw_indicators=indicators2, data=data)
return fig
def generate_row(fig, row, raw_indicators, data) -> tools.make_subplots:
"""
Generator all the indicator selected by the user for a specific row
"""
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: def plot_parse_args(args: List[str]) -> Namespace:
""" """
Parse args passed to the script Parse args passed to the script
@ -411,10 +257,10 @@ def analyse_and_plot_pairs(args: Namespace):
fig = generate_graph( fig = generate_graph(
pair=pair, pair=pair,
trades=trades,
data=dataframe, data=dataframe,
indicators1=args.indicators1, trades=trades,
indicators2=args.indicators2 indicators1=args.indicators1.split(","),
indicators2=args.indicators2.split(",")
) )
is_last = (False, True)[pair_counter == len(tickers)] is_last = (False, True)[pair_counter == len(tickers)]