Python 中最大回撤的开始、结束和持续时间
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22607324/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Start, End and Duration of Maximum Drawdown in Python
提问by siegel
Given a time series, I want to calculate the maximum drawdown, and I also want to locate the beginning and end points of the maximum drawdown so I can calculate the duration. I want to mark the beginning and end of the drawdown on a plot of the timeseries like this:
给定一个时间序列,我想计算最大回撤,我还想找到最大回撤的起点和终点,以便计算持续时间。我想在时间序列图上标记回撤的开始和结束,如下所示:
So far I've got code to generate a random time series, and I've got code to calculate the max drawdown. If anyone knows how to identify the places where the drawdown begins and ends, I'd really appreciate it!
到目前为止,我已经有了生成随机时间序列的代码,并且我已经有了计算最大回撤的代码。如果有人知道如何确定缩编开始和结束的地方,我将不胜感激!
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
# create random walk which I want to calculate maximum drawdown for:
T = 50
mu = 0.05
sigma = 0.2
S0 = 20
dt = 0.01
N = round(T/dt)
t = np.linspace(0, T, N)
W = np.random.standard_normal(size = N)
W = np.cumsum(W)*np.sqrt(dt) ### standard brownian motion ###
X = (mu-0.5*sigma**2)*t + sigma*W
S = S0*np.exp(X) ### geometric brownian motion ###
plt.plot(S)
# Max drawdown function
def max_drawdown(X):
mdd = 0
peak = X[0]
for x in X:
if x > peak:
peak = x
dd = (peak - x) / peak
if dd > mdd:
mdd = dd
return mdd
drawSeries = max_drawdown(S)
MaxDD = abs(drawSeries.min()*100)
print MaxDD
plt.show()
采纳答案by behzad.nouri
Just find out where running maximum minus current value is largest:
只需找出运行最大值减去当前值最大的地方:
n = 1000
xs = np.random.randn(n).cumsum()
i = np.argmax(np.maximum.accumulate(xs) - xs) # end of the period
j = np.argmax(xs[:i]) # start of period
plt.plot(xs)
plt.plot([i, j], [xs[i], xs[j]], 'o', color='Red', markersize=10)


回答by ramcdougal
Your max_drawdown already keeps track of the peak location. Modify the ifto also store the end location mdd_endwhen it stores mdd, and return mdd, peak, mdd_end.
您的 max_drawdown 已经跟踪峰值位置。修改if以mdd_end在存储 mdd 时也存储结束位置,并且return mdd, peak, mdd_end.
回答by Berto
on the back of this I added unerwater analysis if that helps anyone...
在此基础上,如果对任何人有帮助,我添加了水下分析...
def drawdowns(equity_curve):
i = np.argmax(np.maximum.accumulate(equity_curve.values) - equity_curve.values) # end of the period
j = np.argmax(equity_curve.values[:i]) # start of period
drawdown=abs(100.0*(equity_curve[i]-equity_curve[j]))
DT=equity_curve.index.values
start_dt=pd.to_datetime(str(DT[j]))
MDD_start=start_dt.strftime ("%Y-%m-%d")
end_dt=pd.to_datetime(str(DT[i]))
MDD_end=end_dt.strftime ("%Y-%m-%d")
NOW=pd.to_datetime(str(DT[-1]))
NOW=NOW.strftime ("%Y-%m-%d")
MDD_duration=np.busday_count(MDD_start, MDD_end)
try:
UW_dt=equity_curve[i:].loc[equity_curve[i:].values>=equity_curve[j]].index.values[0]
UW_dt=pd.to_datetime(str(UW_dt))
UW_dt=UW_dt.strftime ("%Y-%m-%d")
UW_duration=np.busday_count(MDD_end, UW_dt)
except:
UW_dt="0000-00-00"
UW_duration=np.busday_count(MDD_end, NOW)
return MDD_start, MDD_end, MDD_duration, drawdown, UW_dt, UW_duration
回答by k0rnik
behzad.nouri solution is very clean, but it's not a maximum drawdow (couldn't comment as I just opened my account and I don't have enough reputation atm).
behzad.nouri 解决方案非常干净,但它不是最大的drawdow(无法评论,因为我刚刚开设了我的帐户并且我没有足够的声誉 atm)。
What you end up having is the maximum drop in the nominal value rather than a relative drop in value (percentage drop). For example, if you would apply this to time series that is ascending over the long run (for example stock market index S&P 500), the most recent drop in value (higher nominal value drops) will be prioritized over the older decrease in value as long as the drop in nominal value/points is higher.
你最终得到的是名义价值的最大下降,而不是价值的相对下降(百分比下降)。例如,如果您将此应用于长期上升的时间序列(例如股票市场指数标准普尔 500),则最近的价值下跌(更高的名义价值下跌)将优先于较早的价值下跌,因为只要名义价值/点的下降幅度更大。
For example S&P 500:
例如标准普尔 500 指数:
- 2007-08 financial crisis, drop 56.7%, 888.62 points
- Recent Corona Virus crisis, drop 33.9%, 1,1148.75 points
- 2007-08金融危机,下跌56.7%,888.62点
- 近期危机,下跌 33.9%,1,1148.75 点
By applying this method to period after 2000, you'll see Corona Virus Crisis rather than 2007-08 Financial Crisis
通过将此方法应用于 2000 年之后的时期,您将看到 Corona Virus Crisis 而不是 2007-08 Financial Crisis
Related code (from behzad.nouri) below:
相关代码(来自 behzad.nouri)如下:
n = 1000
xs = np.random.randn(n).cumsum()
i = np.argmax(np.maximum.accumulate(xs) - xs) # end of the period
j = np.argmax(xs[:i]) # start of period
plt.plot(xs)
plt.plot([i, j], [xs[i], xs[j]], 'o', color='Red', markersize=10)
You just need to divide this drop in nominal value by the maximum accumulated amount to get the relative ( % ) drawdown.
您只需将此名义价值的下降除以最大累积金额即可获得相对 (%) 回撤。
( np.maximum.accumulate(xs) - xs ) / np.maximum.accumulate(xs)

