Merge pull request #3137 from freqtrade/fix_maxdrawdown
[minor] Fix maxdrawdown
This commit is contained in:
commit
f2b1802666
@ -220,13 +220,15 @@ def calculate_max_drawdown(trades: pd.DataFrame, *, date_col: str = 'close_time'
|
|||||||
"""
|
"""
|
||||||
if len(trades) == 0:
|
if len(trades) == 0:
|
||||||
raise ValueError("Trade dataframe empty.")
|
raise ValueError("Trade dataframe empty.")
|
||||||
profit_results = trades.sort_values(date_col)
|
profit_results = trades.sort_values(date_col).reset_index(drop=True)
|
||||||
max_drawdown_df = pd.DataFrame()
|
max_drawdown_df = pd.DataFrame()
|
||||||
max_drawdown_df['cumulative'] = profit_results[value_col].cumsum()
|
max_drawdown_df['cumulative'] = profit_results[value_col].cumsum()
|
||||||
max_drawdown_df['high_value'] = max_drawdown_df['cumulative'].cummax()
|
max_drawdown_df['high_value'] = max_drawdown_df['cumulative'].cummax()
|
||||||
max_drawdown_df['drawdown'] = max_drawdown_df['cumulative'] - max_drawdown_df['high_value']
|
max_drawdown_df['drawdown'] = max_drawdown_df['cumulative'] - max_drawdown_df['high_value']
|
||||||
|
|
||||||
high_date = profit_results.loc[max_drawdown_df['high_value'].idxmax(), date_col]
|
idxmin = max_drawdown_df['drawdown'].idxmin()
|
||||||
low_date = profit_results.loc[max_drawdown_df['drawdown'].idxmin(), date_col]
|
if idxmin == 0:
|
||||||
|
raise ValueError("No losing trade, therefore no drawdown.")
|
||||||
|
high_date = profit_results.loc[max_drawdown_df.iloc[:idxmin]['high_value'].idxmax(), date_col]
|
||||||
|
low_date = profit_results.loc[idxmin, date_col]
|
||||||
return abs(min(max_drawdown_df['drawdown'])), high_date, low_date
|
return abs(min(max_drawdown_df['drawdown'])), high_date, low_date
|
||||||
|
@ -191,3 +191,28 @@ def test_calculate_max_drawdown(testdatadir):
|
|||||||
assert low == Timestamp('2018-01-30 04:45:00', tz='UTC')
|
assert low == Timestamp('2018-01-30 04:45:00', tz='UTC')
|
||||||
with pytest.raises(ValueError, match='Trade dataframe empty.'):
|
with pytest.raises(ValueError, match='Trade dataframe empty.'):
|
||||||
drawdown, h, low = calculate_max_drawdown(DataFrame())
|
drawdown, h, low = calculate_max_drawdown(DataFrame())
|
||||||
|
|
||||||
|
|
||||||
|
def test_calculate_max_drawdown2():
|
||||||
|
values = [0.011580, 0.010048, 0.011340, 0.012161, 0.010416, 0.010009, 0.020024,
|
||||||
|
-0.024662, -0.022350, 0.020496, -0.029859, -0.030511, 0.010041, 0.010872,
|
||||||
|
-0.025782, 0.010400, 0.012374, 0.012467, 0.114741, 0.010303, 0.010088,
|
||||||
|
-0.033961, 0.010680, 0.010886, -0.029274, 0.011178, 0.010693, 0.010711]
|
||||||
|
|
||||||
|
dates = [Arrow(2020, 1, 1).shift(days=i) for i in range(len(values))]
|
||||||
|
df = DataFrame(zip(values, dates), columns=['profit', 'open_time'])
|
||||||
|
# sort by profit and reset index
|
||||||
|
df = df.sort_values('profit').reset_index(drop=True)
|
||||||
|
df1 = df.copy()
|
||||||
|
drawdown, h, low = calculate_max_drawdown(df, date_col='open_time', value_col='profit')
|
||||||
|
# Ensure df has not been altered.
|
||||||
|
assert df.equals(df1)
|
||||||
|
|
||||||
|
assert isinstance(drawdown, float)
|
||||||
|
# High must be before low
|
||||||
|
assert h < low
|
||||||
|
assert drawdown == 0.091755
|
||||||
|
|
||||||
|
df = DataFrame(zip(values[:5], dates[:5]), columns=['profit', 'open_time'])
|
||||||
|
with pytest.raises(ValueError, match='No losing trade, therefore no drawdown.'):
|
||||||
|
calculate_max_drawdown(df, date_col='open_time', value_col='profit')
|
||||||
|
@ -266,7 +266,7 @@ def test_generate_profit_graph(testdatadir):
|
|||||||
filename = testdatadir / "backtest-result_test.json"
|
filename = testdatadir / "backtest-result_test.json"
|
||||||
trades = load_backtest_data(filename)
|
trades = load_backtest_data(filename)
|
||||||
timerange = TimeRange.parse_timerange("20180110-20180112")
|
timerange = TimeRange.parse_timerange("20180110-20180112")
|
||||||
pairs = ["TRX/BTC", "ADA/BTC"]
|
pairs = ["TRX/BTC", "XLM/BTC"]
|
||||||
trades = trades[trades['close_time'] < pd.Timestamp('2018-01-12', tz='UTC')]
|
trades = trades[trades['close_time'] < pd.Timestamp('2018-01-12', tz='UTC')]
|
||||||
|
|
||||||
data = history.load_data(datadir=testdatadir,
|
data = history.load_data(datadir=testdatadir,
|
||||||
@ -292,7 +292,7 @@ def test_generate_profit_graph(testdatadir):
|
|||||||
|
|
||||||
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 0.00%")
|
profit = find_trace_in_fig_data(figure.data, "Max drawdown 10.45%")
|
||||||
assert isinstance(profit, go.Scatter)
|
assert isinstance(profit, go.Scatter)
|
||||||
|
|
||||||
for pair in pairs:
|
for pair in pairs:
|
||||||
|
Loading…
Reference in New Issue
Block a user