parent
c29469decf
commit
a2d97eecfe
@ -283,6 +283,7 @@ The `plot-profit` subcommand shows an interactive graph with three plots:
|
|||||||
* The summarized profit made by backtesting.
|
* The summarized profit made by backtesting.
|
||||||
Note that this is not the real-world profit, but more of an estimate.
|
Note that this is not the real-world profit, but more of an estimate.
|
||||||
* Profit for each individual pair.
|
* Profit for each individual pair.
|
||||||
|
* Parallelism of trades.
|
||||||
|
|
||||||
The first graph is good to get a grip of how the overall market progresses.
|
The first graph is good to get a grip of how the overall market progresses.
|
||||||
|
|
||||||
@ -292,6 +293,8 @@ This graph will also highlight the start (and end) of the Max drawdown period.
|
|||||||
|
|
||||||
The third graph can be useful to spot outliers, events in pairs that cause profit spikes.
|
The third graph can be useful to spot outliers, events in pairs that cause profit spikes.
|
||||||
|
|
||||||
|
The forth graph can help you analyze trade parallelism, showing how often max_open_trades have been maxed out.
|
||||||
|
|
||||||
Possible options for the `freqtrade plot-profit` subcommand:
|
Possible options for the `freqtrade plot-profit` subcommand:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -5,8 +5,9 @@ from typing import Any, Dict, List
|
|||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
from freqtrade.configuration import TimeRange
|
from freqtrade.configuration import TimeRange
|
||||||
from freqtrade.data.btanalysis import (calculate_max_drawdown, combine_dataframes_with_mean,
|
from freqtrade.data.btanalysis import (analyze_trade_parallelism, calculate_max_drawdown,
|
||||||
create_cum_profit, extract_trades_of_period, load_trades)
|
combine_dataframes_with_mean, create_cum_profit,
|
||||||
|
extract_trades_of_period, load_trades)
|
||||||
from freqtrade.data.converter import trim_dataframe
|
from freqtrade.data.converter import trim_dataframe
|
||||||
from freqtrade.data.dataprovider import DataProvider
|
from freqtrade.data.dataprovider import DataProvider
|
||||||
from freqtrade.data.history import get_timerange, load_data
|
from freqtrade.data.history import get_timerange, load_data
|
||||||
@ -185,6 +186,24 @@ def add_max_drawdown(fig, row, trades: pd.DataFrame, df_comb: pd.DataFrame,
|
|||||||
return fig
|
return fig
|
||||||
|
|
||||||
|
|
||||||
|
def add_parallelism(fig, row, trades: pd.DataFrame, timeframe: str) -> make_subplots:
|
||||||
|
"""
|
||||||
|
Add Chart showing trade parallelism
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
result = analyze_trade_parallelism(trades, timeframe)
|
||||||
|
|
||||||
|
drawdown = go.Bar(
|
||||||
|
x=result.index,
|
||||||
|
y=result['open_trades'],
|
||||||
|
name="Parallel trades",
|
||||||
|
)
|
||||||
|
fig.add_trace(drawdown, row, 1)
|
||||||
|
except ValueError:
|
||||||
|
logger.warning("No trades found - not plotting Parallelism.")
|
||||||
|
return fig
|
||||||
|
|
||||||
|
|
||||||
def plot_trades(fig, trades: pd.DataFrame) -> make_subplots:
|
def plot_trades(fig, trades: pd.DataFrame) -> make_subplots:
|
||||||
"""
|
"""
|
||||||
Add trades to "fig"
|
Add trades to "fig"
|
||||||
@ -482,20 +501,27 @@ def generate_profit_graph(pairs: str, data: Dict[str, pd.DataFrame],
|
|||||||
name='Avg close price',
|
name='Avg close price',
|
||||||
)
|
)
|
||||||
|
|
||||||
fig = make_subplots(rows=3, cols=1, shared_xaxes=True,
|
fig = make_subplots(rows=4, cols=1, shared_xaxes=True,
|
||||||
row_width=[1, 1, 1],
|
row_width=[1, 1, 1, 1],
|
||||||
vertical_spacing=0.05,
|
vertical_spacing=0.05,
|
||||||
subplot_titles=["AVG Close Price", "Combined Profit", "Profit per pair"])
|
subplot_titles=[
|
||||||
|
"AVG Close Price",
|
||||||
|
"Combined Profit",
|
||||||
|
"Profit per pair",
|
||||||
|
"Parallelism"
|
||||||
|
])
|
||||||
fig['layout'].update(title="Freqtrade Profit plot")
|
fig['layout'].update(title="Freqtrade Profit plot")
|
||||||
fig['layout']['yaxis1'].update(title='Price')
|
fig['layout']['yaxis1'].update(title='Price')
|
||||||
fig['layout']['yaxis2'].update(title=f'Profit {stake_currency}')
|
fig['layout']['yaxis2'].update(title=f'Profit {stake_currency}')
|
||||||
fig['layout']['yaxis3'].update(title=f'Profit {stake_currency}')
|
fig['layout']['yaxis3'].update(title=f'Profit {stake_currency}')
|
||||||
|
fig['layout']['yaxis4'].update(title='Trade count')
|
||||||
fig['layout']['xaxis']['rangeslider'].update(visible=False)
|
fig['layout']['xaxis']['rangeslider'].update(visible=False)
|
||||||
fig.update_layout(modebar_add=["v1hovermode", "toggleSpikeLines"])
|
fig.update_layout(modebar_add=["v1hovermode", "toggleSpikeLines"])
|
||||||
|
|
||||||
fig.add_trace(avgclose, 1, 1)
|
fig.add_trace(avgclose, 1, 1)
|
||||||
fig = add_profit(fig, 2, df_comb, 'cum_profit', 'Profit')
|
fig = add_profit(fig, 2, df_comb, 'cum_profit', 'Profit')
|
||||||
fig = add_max_drawdown(fig, 2, trades, df_comb, timeframe)
|
fig = add_max_drawdown(fig, 2, trades, df_comb, timeframe)
|
||||||
|
fig = add_parallelism(fig, 4, trades, timeframe)
|
||||||
|
|
||||||
for pair in pairs:
|
for pair in pairs:
|
||||||
profit_col = f'cum_profit_{pair}'
|
profit_col = f'cum_profit_{pair}'
|
||||||
|
@ -336,15 +336,17 @@ def test_generate_profit_graph(testdatadir):
|
|||||||
assert fig.layout.yaxis3.title.text == "Profit BTC"
|
assert fig.layout.yaxis3.title.text == "Profit BTC"
|
||||||
|
|
||||||
figure = fig.layout.figure
|
figure = fig.layout.figure
|
||||||
assert len(figure.data) == 5
|
assert len(figure.data) == 6
|
||||||
|
|
||||||
avgclose = find_trace_in_fig_data(figure.data, "Avg close price")
|
avgclose = find_trace_in_fig_data(figure.data, "Avg close price")
|
||||||
assert isinstance(avgclose, go.Scatter)
|
assert isinstance(avgclose, go.Scatter)
|
||||||
|
|
||||||
profit = find_trace_in_fig_data(figure.data, "Profit")
|
profit = find_trace_in_fig_data(figure.data, "Profit")
|
||||||
assert isinstance(profit, go.Scatter)
|
assert isinstance(profit, go.Scatter)
|
||||||
profit = find_trace_in_fig_data(figure.data, "Max drawdown 10.45%")
|
drawdown = find_trace_in_fig_data(figure.data, "Max drawdown 10.45%")
|
||||||
assert isinstance(profit, go.Scatter)
|
assert isinstance(drawdown, go.Scatter)
|
||||||
|
parallel = find_trace_in_fig_data(figure.data, "Parallel trades")
|
||||||
|
assert isinstance(parallel, go.Bar)
|
||||||
|
|
||||||
for pair in pairs:
|
for pair in pairs:
|
||||||
profit_pair = find_trace_in_fig_data(figure.data, f"Profit {pair}")
|
profit_pair = find_trace_in_fig_data(figure.data, f"Profit {pair}")
|
||||||
|
Loading…
Reference in New Issue
Block a user