Merge pull request #2439 from freqtrade/fix/plotprofit
Plot-profit does not work with db file
This commit is contained in:
commit
907baea8b2
@ -150,15 +150,21 @@ def combine_tickers_with_mean(tickers: Dict[str, pd.DataFrame], column: str = "c
|
|||||||
return df_comb
|
return df_comb
|
||||||
|
|
||||||
|
|
||||||
def create_cum_profit(df: pd.DataFrame, trades: pd.DataFrame, col_name: str) -> pd.DataFrame:
|
def create_cum_profit(df: pd.DataFrame, trades: pd.DataFrame, col_name: str,
|
||||||
|
timeframe: str) -> pd.DataFrame:
|
||||||
"""
|
"""
|
||||||
Adds a column `col_name` with the cumulative profit for the given trades array.
|
Adds a column `col_name` with the cumulative profit for the given trades array.
|
||||||
:param df: DataFrame with date index
|
:param df: DataFrame with date index
|
||||||
:param trades: DataFrame containing trades (requires columns close_time and profitperc)
|
:param trades: DataFrame containing trades (requires columns close_time and profitperc)
|
||||||
|
:param col_name: Column name that will be assigned the results
|
||||||
|
:param timeframe: Timeframe used during the operations
|
||||||
:return: Returns df with one additional column, col_name, containing the cumulative profit.
|
:return: Returns df with one additional column, col_name, containing the cumulative profit.
|
||||||
"""
|
"""
|
||||||
# Use groupby/sum().cumsum() to avoid errors when multiple trades sold at the same candle.
|
from freqtrade.exchange import timeframe_to_minutes
|
||||||
df[col_name] = trades.groupby('close_time')['profitperc'].sum().cumsum()
|
ticker_minutes = timeframe_to_minutes(timeframe)
|
||||||
|
# Resample to ticker_interval to make sure trades match candles
|
||||||
|
_trades_sum = trades.resample(f'{ticker_minutes}min', on='close_time')[['profitperc']].sum()
|
||||||
|
df.loc[:, col_name] = _trades_sum.cumsum()
|
||||||
# Set first value to 0
|
# Set first value to 0
|
||||||
df.loc[df.iloc[0].name, col_name] = 0
|
df.loc[df.iloc[0].name, col_name] = 0
|
||||||
# FFill to get continuous
|
# FFill to get continuous
|
||||||
|
@ -264,12 +264,12 @@ def generate_candlestick_graph(pair: str, data: pd.DataFrame, trades: pd.DataFra
|
|||||||
|
|
||||||
|
|
||||||
def generate_profit_graph(pairs: str, tickers: Dict[str, pd.DataFrame],
|
def generate_profit_graph(pairs: str, tickers: Dict[str, pd.DataFrame],
|
||||||
trades: pd.DataFrame) -> go.Figure:
|
trades: pd.DataFrame, timeframe: str) -> go.Figure:
|
||||||
# Combine close-values for all pairs, rename columns to "pair"
|
# Combine close-values for all pairs, rename columns to "pair"
|
||||||
df_comb = combine_tickers_with_mean(tickers, "close")
|
df_comb = combine_tickers_with_mean(tickers, "close")
|
||||||
|
|
||||||
# Add combined cumulative profit
|
# Add combined cumulative profit
|
||||||
df_comb = create_cum_profit(df_comb, trades, 'cum_profit')
|
df_comb = create_cum_profit(df_comb, trades, 'cum_profit', timeframe)
|
||||||
|
|
||||||
# Plot the pairs average close prices, and total profit growth
|
# Plot the pairs average close prices, and total profit growth
|
||||||
avgclose = go.Scatter(
|
avgclose = go.Scatter(
|
||||||
@ -293,7 +293,7 @@ def generate_profit_graph(pairs: str, tickers: Dict[str, pd.DataFrame],
|
|||||||
|
|
||||||
for pair in pairs:
|
for pair in pairs:
|
||||||
profit_col = f'cum_profit_{pair}'
|
profit_col = f'cum_profit_{pair}'
|
||||||
df_comb = create_cum_profit(df_comb, trades[trades['pair'] == pair], profit_col)
|
df_comb = create_cum_profit(df_comb, trades[trades['pair'] == pair], profit_col, timeframe)
|
||||||
|
|
||||||
fig = add_profit(fig, 3, df_comb, profit_col, f"Profit {pair}")
|
fig = add_profit(fig, 3, df_comb, profit_col, f"Profit {pair}")
|
||||||
|
|
||||||
@ -382,9 +382,9 @@ def plot_profit(config: Dict[str, Any]) -> None:
|
|||||||
)
|
)
|
||||||
# Filter trades to relevant pairs
|
# Filter trades to relevant pairs
|
||||||
trades = trades[trades['pair'].isin(plot_elements["pairs"])]
|
trades = trades[trades['pair'].isin(plot_elements["pairs"])]
|
||||||
|
|
||||||
# Create an average close price of all the pairs that were involved.
|
# Create an average close price of all the pairs that were involved.
|
||||||
# this could be useful to gauge the overall market trend
|
# this could be useful to gauge the overall market trend
|
||||||
fig = generate_profit_graph(plot_elements["pairs"], plot_elements["tickers"], trades)
|
fig = generate_profit_graph(plot_elements["pairs"], plot_elements["tickers"],
|
||||||
|
trades, config.get('ticker_interval', '5m'))
|
||||||
store_plot_file(fig, filename='freqtrade-profit-plot.html',
|
store_plot_file(fig, filename='freqtrade-profit-plot.html',
|
||||||
directory=config['user_data_dir'] / "plot", auto_open=True)
|
directory=config['user_data_dir'] / "plot", auto_open=True)
|
||||||
|
@ -2,7 +2,7 @@ from unittest.mock import MagicMock
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from arrow import Arrow
|
from arrow import Arrow
|
||||||
from pandas import DataFrame, to_datetime
|
from pandas import DataFrame, DateOffset, to_datetime
|
||||||
|
|
||||||
from freqtrade.configuration import TimeRange
|
from freqtrade.configuration import TimeRange
|
||||||
from freqtrade.data.btanalysis import (BT_DATA_COLUMNS,
|
from freqtrade.data.btanalysis import (BT_DATA_COLUMNS,
|
||||||
@ -130,7 +130,25 @@ def test_create_cum_profit(testdatadir):
|
|||||||
|
|
||||||
cum_profits = create_cum_profit(df.set_index('date'),
|
cum_profits = create_cum_profit(df.set_index('date'),
|
||||||
bt_data[bt_data["pair"] == 'POWR/BTC'],
|
bt_data[bt_data["pair"] == 'POWR/BTC'],
|
||||||
"cum_profits")
|
"cum_profits", timeframe="5m")
|
||||||
|
assert "cum_profits" in cum_profits.columns
|
||||||
|
assert cum_profits.iloc[0]['cum_profits'] == 0
|
||||||
|
assert cum_profits.iloc[-1]['cum_profits'] == 0.0798005
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_cum_profit1(testdatadir):
|
||||||
|
filename = testdatadir / "backtest-result_test.json"
|
||||||
|
bt_data = load_backtest_data(filename)
|
||||||
|
# Move close-time to "off" the candle, to make sure the logic still works
|
||||||
|
bt_data.loc[:, 'close_time'] = bt_data.loc[:, 'close_time'] + DateOffset(seconds=20)
|
||||||
|
timerange = TimeRange.parse_timerange("20180110-20180112")
|
||||||
|
|
||||||
|
df = load_pair_history(pair="POWR/BTC", ticker_interval='5m',
|
||||||
|
datadir=testdatadir, timerange=timerange)
|
||||||
|
|
||||||
|
cum_profits = create_cum_profit(df.set_index('date'),
|
||||||
|
bt_data[bt_data["pair"] == 'POWR/BTC'],
|
||||||
|
"cum_profits", timeframe="5m")
|
||||||
assert "cum_profits" in cum_profits.columns
|
assert "cum_profits" in cum_profits.columns
|
||||||
assert cum_profits.iloc[0]['cum_profits'] == 0
|
assert cum_profits.iloc[0]['cum_profits'] == 0
|
||||||
assert cum_profits.iloc[-1]['cum_profits'] == 0.0798005
|
assert cum_profits.iloc[-1]['cum_profits'] == 0.0798005
|
||||||
|
@ -234,7 +234,7 @@ def test_add_profit(testdatadir):
|
|||||||
|
|
||||||
cum_profits = create_cum_profit(df.set_index('date'),
|
cum_profits = create_cum_profit(df.set_index('date'),
|
||||||
bt_data[bt_data["pair"] == 'POWR/BTC'],
|
bt_data[bt_data["pair"] == 'POWR/BTC'],
|
||||||
"cum_profits")
|
"cum_profits", timeframe="5m")
|
||||||
|
|
||||||
fig1 = add_profit(fig, row=2, data=cum_profits, column='cum_profits', name='Profits')
|
fig1 = add_profit(fig, row=2, data=cum_profits, column='cum_profits', name='Profits')
|
||||||
figure = fig1.layout.figure
|
figure = fig1.layout.figure
|
||||||
@ -256,7 +256,7 @@ def test_generate_profit_graph(testdatadir):
|
|||||||
)
|
)
|
||||||
trades = trades[trades['pair'].isin(pairs)]
|
trades = trades[trades['pair'].isin(pairs)]
|
||||||
|
|
||||||
fig = generate_profit_graph(pairs, tickers, trades)
|
fig = generate_profit_graph(pairs, tickers, trades, timeframe="5m")
|
||||||
assert isinstance(fig, go.Figure)
|
assert isinstance(fig, go.Figure)
|
||||||
|
|
||||||
assert fig.layout.title.text == "Freqtrade Profit plot"
|
assert fig.layout.title.text == "Freqtrade Profit plot"
|
||||||
|
Loading…
Reference in New Issue
Block a user