mirror of
https://github.com/freqtrade/freqtrade.git
synced 2024-09-20 01:21:11 +00:00
Remove compatibility layer for calculate_max_drawdown
This commit is contained in:
parent
c79b75ff9a
commit
a6b07ec96f
|
@ -171,7 +171,7 @@ class DrawDownResult:
|
||||||
relative_account_drawdown: float = 0.0
|
relative_account_drawdown: float = 0.0
|
||||||
|
|
||||||
|
|
||||||
def calc_max_drawdown(
|
def calculate_max_drawdown(
|
||||||
trades: pd.DataFrame,
|
trades: pd.DataFrame,
|
||||||
*,
|
*,
|
||||||
date_col: str = "close_date",
|
date_col: str = "close_date",
|
||||||
|
@ -185,7 +185,7 @@ def calc_max_drawdown(
|
||||||
:param date_col: Column in DataFrame to use for dates (defaults to 'close_date')
|
:param date_col: Column in DataFrame to use for dates (defaults to 'close_date')
|
||||||
:param value_col: Column in DataFrame to use for values (defaults to 'profit_abs')
|
:param value_col: Column in DataFrame to use for values (defaults to 'profit_abs')
|
||||||
:param starting_balance: Portfolio starting balance - properly calculate relative drawdown.
|
:param starting_balance: Portfolio starting balance - properly calculate relative drawdown.
|
||||||
:return: Tuple (float, highdate, lowdate, highvalue, lowvalue, relative_drawdown)
|
:return: DrawDownResult object
|
||||||
with absolute max drawdown, high and low time and high and low value,
|
with absolute max drawdown, high and low time and high and low value,
|
||||||
and the relative account drawdown
|
and the relative account drawdown
|
||||||
:raise: ValueError if trade-dataframe was found empty.
|
:raise: ValueError if trade-dataframe was found empty.
|
||||||
|
@ -222,44 +222,6 @@ def calc_max_drawdown(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def calculate_max_drawdown(
|
|
||||||
trades: pd.DataFrame,
|
|
||||||
*,
|
|
||||||
date_col: str = "close_date",
|
|
||||||
value_col: str = "profit_abs",
|
|
||||||
starting_balance: float = 0,
|
|
||||||
relative: bool = False,
|
|
||||||
) -> Tuple[float, pd.Timestamp, pd.Timestamp, float, float, float]:
|
|
||||||
"""
|
|
||||||
Calculate max drawdown and the corresponding close dates
|
|
||||||
Deprecated, favor calc_max_drawdown instead!
|
|
||||||
:param trades: DataFrame containing trades (requires columns close_date and profit_ratio)
|
|
||||||
:param date_col: Column in DataFrame to use for dates (defaults to 'close_date')
|
|
||||||
:param value_col: Column in DataFrame to use for values (defaults to 'profit_abs')
|
|
||||||
:param starting_balance: Portfolio starting balance - properly calculate relative drawdown.
|
|
||||||
:return: Tuple (float, highdate, lowdate, highvalue, lowvalue, relative_drawdown)
|
|
||||||
with absolute max drawdown, high and low time and high and low value,
|
|
||||||
and the relative account drawdown
|
|
||||||
:raise: ValueError if trade-dataframe was found empty.
|
|
||||||
"""
|
|
||||||
# TODO: add deprecation warning
|
|
||||||
res = calc_max_drawdown(
|
|
||||||
trades,
|
|
||||||
date_col=date_col,
|
|
||||||
value_col=value_col,
|
|
||||||
starting_balance=starting_balance,
|
|
||||||
relative=relative,
|
|
||||||
)
|
|
||||||
return (
|
|
||||||
res.drawdown_abs,
|
|
||||||
res.high_date,
|
|
||||||
res.low_date,
|
|
||||||
res.high_value,
|
|
||||||
res.low_value,
|
|
||||||
res.relative_account_drawdown,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def calculate_csum(trades: pd.DataFrame, starting_balance: float = 0) -> Tuple[float, float]:
|
def calculate_csum(trades: pd.DataFrame, starting_balance: float = 0) -> Tuple[float, float]:
|
||||||
"""
|
"""
|
||||||
Calculate min/max cumsum of trades, to show if the wallet/stake amount ratio is sane
|
Calculate min/max cumsum of trades, to show if the wallet/stake amount ratio is sane
|
||||||
|
@ -399,7 +361,7 @@ def calculate_calmar(
|
||||||
|
|
||||||
# calculate max drawdown
|
# calculate max drawdown
|
||||||
try:
|
try:
|
||||||
drawdown = calc_max_drawdown(
|
drawdown = calculate_max_drawdown(
|
||||||
trades, value_col="profit_abs", starting_balance=starting_balance
|
trades, value_col="profit_abs", starting_balance=starting_balance
|
||||||
)
|
)
|
||||||
max_drawdown = drawdown.relative_account_drawdown
|
max_drawdown = drawdown.relative_account_drawdown
|
||||||
|
|
|
@ -9,7 +9,7 @@ from datetime import datetime
|
||||||
|
|
||||||
from pandas import DataFrame
|
from pandas import DataFrame
|
||||||
|
|
||||||
from freqtrade.data.metrics import calc_max_drawdown
|
from freqtrade.data.metrics import calculate_max_drawdown
|
||||||
from freqtrade.optimize.hyperopt import IHyperOptLoss
|
from freqtrade.optimize.hyperopt import IHyperOptLoss
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ class MaxDrawDownHyperOptLoss(IHyperOptLoss):
|
||||||
"""
|
"""
|
||||||
total_profit = results["profit_abs"].sum()
|
total_profit = results["profit_abs"].sum()
|
||||||
try:
|
try:
|
||||||
max_drawdown = calc_max_drawdown(results, value_col="profit_abs")
|
max_drawdown = calculate_max_drawdown(results, value_col="profit_abs")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
# No losing trade, therefore no drawdown.
|
# No losing trade, therefore no drawdown.
|
||||||
return -total_profit
|
return -total_profit
|
||||||
|
|
|
@ -10,7 +10,7 @@ individual needs.
|
||||||
|
|
||||||
from pandas import DataFrame
|
from pandas import DataFrame
|
||||||
|
|
||||||
from freqtrade.data.metrics import calc_max_drawdown
|
from freqtrade.data.metrics import calculate_max_drawdown
|
||||||
from freqtrade.optimize.hyperopt import IHyperOptLoss
|
from freqtrade.optimize.hyperopt import IHyperOptLoss
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ class ProfitDrawDownHyperOptLoss(IHyperOptLoss):
|
||||||
total_profit = results["profit_abs"].sum()
|
total_profit = results["profit_abs"].sum()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
drawdown = calc_max_drawdown(results, value_col="profit_abs")
|
drawdown = calculate_max_drawdown(results, value_col="profit_abs")
|
||||||
relative_account_drawdown = drawdown.relative_account_drawdown
|
relative_account_drawdown = drawdown.relative_account_drawdown
|
||||||
except ValueError:
|
except ValueError:
|
||||||
relative_account_drawdown = 0
|
relative_account_drawdown = 0
|
||||||
|
|
|
@ -8,12 +8,12 @@ from pandas import DataFrame, Series, concat, to_datetime
|
||||||
|
|
||||||
from freqtrade.constants import BACKTEST_BREAKDOWNS, DATETIME_PRINT_FORMAT
|
from freqtrade.constants import BACKTEST_BREAKDOWNS, DATETIME_PRINT_FORMAT
|
||||||
from freqtrade.data.metrics import (
|
from freqtrade.data.metrics import (
|
||||||
calc_max_drawdown,
|
|
||||||
calculate_cagr,
|
calculate_cagr,
|
||||||
calculate_calmar,
|
calculate_calmar,
|
||||||
calculate_csum,
|
calculate_csum,
|
||||||
calculate_expectancy,
|
calculate_expectancy,
|
||||||
calculate_market_change,
|
calculate_market_change,
|
||||||
|
calculate_max_drawdown,
|
||||||
calculate_sharpe,
|
calculate_sharpe,
|
||||||
calculate_sortino,
|
calculate_sortino,
|
||||||
)
|
)
|
||||||
|
@ -497,12 +497,12 @@ def generate_strategy_stats(
|
||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
max_drawdown_legacy = calc_max_drawdown(results, value_col="profit_ratio")
|
max_drawdown_legacy = calculate_max_drawdown(results, value_col="profit_ratio")
|
||||||
drawdown = calc_max_drawdown(
|
drawdown = calculate_max_drawdown(
|
||||||
results, value_col="profit_abs", starting_balance=start_balance
|
results, value_col="profit_abs", starting_balance=start_balance
|
||||||
)
|
)
|
||||||
# max_relative_drawdown = Underwater
|
# max_relative_drawdown = Underwater
|
||||||
underwater = calc_max_drawdown(
|
underwater = calculate_max_drawdown(
|
||||||
results, value_col="profit_abs", starting_balance=start_balance, relative=True
|
results, value_col="profit_abs", starting_balance=start_balance, relative=True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ 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
|
||||||
from freqtrade.data.metrics import (
|
from freqtrade.data.metrics import (
|
||||||
calc_max_drawdown,
|
calculate_max_drawdown,
|
||||||
calculate_underwater,
|
calculate_underwater,
|
||||||
combine_dataframes_with_mean,
|
combine_dataframes_with_mean,
|
||||||
create_cum_profit,
|
create_cum_profit,
|
||||||
|
@ -179,7 +179,7 @@ def add_max_drawdown(
|
||||||
Add scatter points indicating max drawdown
|
Add scatter points indicating max drawdown
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
drawdown = calc_max_drawdown(trades, starting_balance=starting_balance)
|
drawdown = calculate_max_drawdown(trades, starting_balance=starting_balance)
|
||||||
|
|
||||||
drawdown = go.Scatter(
|
drawdown = go.Scatter(
|
||||||
x=[drawdown.high_date, drawdown.low_date],
|
x=[drawdown.high_date, drawdown.low_date],
|
||||||
|
|
|
@ -5,7 +5,7 @@ from typing import Any, Dict, Optional
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
from freqtrade.constants import Config, LongShort
|
from freqtrade.constants import Config, LongShort
|
||||||
from freqtrade.data.metrics import calc_max_drawdown
|
from freqtrade.data.metrics import calculate_max_drawdown
|
||||||
from freqtrade.persistence import Trade
|
from freqtrade.persistence import Trade
|
||||||
from freqtrade.plugins.protections import IProtection, ProtectionReturn
|
from freqtrade.plugins.protections import IProtection, ProtectionReturn
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ class MaxDrawdown(IProtection):
|
||||||
# Drawdown is always positive
|
# Drawdown is always positive
|
||||||
try:
|
try:
|
||||||
# TODO: This should use absolute profit calculation, considering account balance.
|
# TODO: This should use absolute profit calculation, considering account balance.
|
||||||
drawdown_obj = calc_max_drawdown(trades_df, value_col="close_profit")
|
drawdown_obj = calculate_max_drawdown(trades_df, value_col="close_profit")
|
||||||
drawdown = drawdown_obj.drawdown_abs
|
drawdown = drawdown_obj.drawdown_abs
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -21,8 +21,8 @@ from freqtrade.constants import CANCEL_REASON, DEFAULT_DATAFRAME_COLUMNS, Config
|
||||||
from freqtrade.data.history import load_data
|
from freqtrade.data.history import load_data
|
||||||
from freqtrade.data.metrics import (
|
from freqtrade.data.metrics import (
|
||||||
DrawDownResult,
|
DrawDownResult,
|
||||||
calc_max_drawdown,
|
|
||||||
calculate_expectancy,
|
calculate_expectancy,
|
||||||
|
calculate_max_drawdown,
|
||||||
)
|
)
|
||||||
from freqtrade.enums import (
|
from freqtrade.enums import (
|
||||||
CandleType,
|
CandleType,
|
||||||
|
@ -599,7 +599,7 @@ class RPC:
|
||||||
drawdown = DrawDownResult()
|
drawdown = DrawDownResult()
|
||||||
if len(trades_df) > 0:
|
if len(trades_df) > 0:
|
||||||
try:
|
try:
|
||||||
drawdown = calc_max_drawdown(
|
drawdown = calculate_max_drawdown(
|
||||||
trades_df,
|
trades_df,
|
||||||
value_col="profit_abs",
|
value_col="profit_abs",
|
||||||
date_col="close_date_dt",
|
date_col="close_date_dt",
|
||||||
|
|
|
@ -20,7 +20,6 @@ from freqtrade.data.btanalysis import (
|
||||||
)
|
)
|
||||||
from freqtrade.data.history import load_data, load_pair_history
|
from freqtrade.data.history import load_data, load_pair_history
|
||||||
from freqtrade.data.metrics import (
|
from freqtrade.data.metrics import (
|
||||||
calc_max_drawdown,
|
|
||||||
calculate_cagr,
|
calculate_cagr,
|
||||||
calculate_calmar,
|
calculate_calmar,
|
||||||
calculate_csum,
|
calculate_csum,
|
||||||
|
@ -344,7 +343,7 @@ def test_create_cum_profit1(testdatadir):
|
||||||
def test_calculate_max_drawdown(testdatadir):
|
def test_calculate_max_drawdown(testdatadir):
|
||||||
filename = testdatadir / "backtest_results/backtest-result.json"
|
filename = testdatadir / "backtest_results/backtest-result.json"
|
||||||
bt_data = load_backtest_data(filename)
|
bt_data = load_backtest_data(filename)
|
||||||
drawdown = calc_max_drawdown(bt_data, value_col="profit_abs")
|
drawdown = calculate_max_drawdown(bt_data, value_col="profit_abs")
|
||||||
assert isinstance(drawdown.relative_account_drawdown, float)
|
assert isinstance(drawdown.relative_account_drawdown, float)
|
||||||
assert pytest.approx(drawdown.relative_account_drawdown) == 0.29753914
|
assert pytest.approx(drawdown.relative_account_drawdown) == 0.29753914
|
||||||
assert isinstance(drawdown.high_date, Timestamp)
|
assert isinstance(drawdown.high_date, Timestamp)
|
||||||
|
@ -358,7 +357,7 @@ def test_calculate_max_drawdown(testdatadir):
|
||||||
assert isinstance(underwater, DataFrame)
|
assert isinstance(underwater, DataFrame)
|
||||||
|
|
||||||
with pytest.raises(ValueError, match="Trade dataframe empty."):
|
with pytest.raises(ValueError, match="Trade dataframe empty."):
|
||||||
calc_max_drawdown(DataFrame())
|
calculate_max_drawdown(DataFrame())
|
||||||
|
|
||||||
with pytest.raises(ValueError, match="Trade dataframe empty."):
|
with pytest.raises(ValueError, match="Trade dataframe empty."):
|
||||||
calculate_underwater(DataFrame())
|
calculate_underwater(DataFrame())
|
||||||
|
@ -508,7 +507,7 @@ def test_calculate_max_drawdown2():
|
||||||
# sort by profit and reset index
|
# sort by profit and reset index
|
||||||
df = df.sort_values("profit").reset_index(drop=True)
|
df = df.sort_values("profit").reset_index(drop=True)
|
||||||
df1 = df.copy()
|
df1 = df.copy()
|
||||||
drawdown = calc_max_drawdown(df, date_col="open_date", value_col="profit")
|
drawdown = calculate_max_drawdown(df, date_col="open_date", value_col="profit")
|
||||||
# Ensure df has not been altered.
|
# Ensure df has not been altered.
|
||||||
assert df.equals(df1)
|
assert df.equals(df1)
|
||||||
|
|
||||||
|
@ -522,12 +521,12 @@ def test_calculate_max_drawdown2():
|
||||||
|
|
||||||
df = DataFrame(zip(values[:5], dates[:5]), columns=["profit", "open_date"])
|
df = DataFrame(zip(values[:5], dates[:5]), columns=["profit", "open_date"])
|
||||||
with pytest.raises(ValueError, match="No losing trade, therefore no drawdown."):
|
with pytest.raises(ValueError, match="No losing trade, therefore no drawdown."):
|
||||||
calc_max_drawdown(df, date_col="open_date", value_col="profit")
|
calculate_max_drawdown(df, date_col="open_date", value_col="profit")
|
||||||
|
|
||||||
df1 = DataFrame(zip(values[:5], dates[:5]), columns=["profit", "open_date"])
|
df1 = DataFrame(zip(values[:5], dates[:5]), columns=["profit", "open_date"])
|
||||||
df1.loc[:, "profit"] = df1["profit"] * -1
|
df1.loc[:, "profit"] = df1["profit"] * -1
|
||||||
# No winning trade ...
|
# No winning trade ...
|
||||||
drawdown = calc_max_drawdown(df1, date_col="open_date", value_col="profit")
|
drawdown = calculate_max_drawdown(df1, date_col="open_date", value_col="profit")
|
||||||
assert drawdown.drawdown_abs == 0.043965
|
assert drawdown.drawdown_abs == 0.043965
|
||||||
|
|
||||||
|
|
||||||
|
@ -550,7 +549,9 @@ def test_calculate_max_drawdown_abs(profits, relative, highd, lowdays, result, r
|
||||||
# sort by profit and reset index
|
# sort by profit and reset index
|
||||||
df = df.sort_values("profit_abs").reset_index(drop=True)
|
df = df.sort_values("profit_abs").reset_index(drop=True)
|
||||||
df1 = df.copy()
|
df1 = df.copy()
|
||||||
drawdown = calc_max_drawdown(df, date_col="open_date", starting_balance=1000, relative=relative)
|
drawdown = calculate_max_drawdown(
|
||||||
|
df, date_col="open_date", starting_balance=1000, relative=relative
|
||||||
|
)
|
||||||
# Ensure df has not been altered.
|
# Ensure df has not been altered.
|
||||||
assert df.equals(df1)
|
assert df.equals(df1)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user