使用python计算最大回撤
使用python计算最大回撤
1. 单期简单收益率
R
t
=
P
t
−
P
t
−
1
P
t
−
1
R_{t}=\dfrac {P _{t}-P_{t-1}}{P_{t-1}}
Rt=Pt−1Pt−Pt−1
说明:
- R t R_t Rt 为单期简单收益率
- P t P_t Pt 为t期的价格
- P t − 1 P_{t-1} Pt−1 为t-1期的价格
import datetime
import pandas as pd
pd.core.common.is_list_like = pd.api.types.is_list_like
price = pd.Series([3.42,3.51,3.68,3.43,3.56,3.67], index=[datetime.date(2015,7,x) for x in range(3,9)])
price
2015-07-03 3.42
2015-07-04 3.51
2015-07-05 3.68
2015-07-06 3.43
2015-07-07 3.56
2015-07-08 3.67
dtype: float64
利用ffn库计算单期简单收益
import ffn
r = ffn.to_returns(price)
r
2015-07-03 NaN
2015-07-04 0.026316
2015-07-05 0.048433
2015-07-06 -0.067935
2015-07-07 0.037901
2015-07-08 0.030899
dtype: float64
2. 最大回撤
最大回撤(Maximum Drawdown, MDD) 用来衡量投资(特别是基金)的表现,
2.1 回撤:某资产在时刻T的回撤是指资产在(0,T)的最高峰值与现在价值 P T P_T PT之间的回落值,用数学公式表达为:
D ( T ) = max { 0 , max t ∈ ( 0 , T ) P t − P T } D\left( T\right) =\max \left\{ 0,\max _{t\in (0,T)}P_t-P_{T}\right\} D(T)=max{0,maxt∈(0,T)Pt−PT}
2.2 对应的回撤率为:
d ( T ) = D ( T ) max t ∈ ( 0 , T ) p t d\left(T\right) = \dfrac {D\left( T\right) }{\max _{t\in \left( 0,T\right) }p_{t}} d(T)=maxt∈(0,T)ptD(T)
知道回撤的含义之后,最大回撤就比较容易理解了,资产在T时刻的最大回撤MDD(T),就是资产在时段(0,T)内回撤的最大值,对应的数学公式为:
M D D ( T ) = max τ ∈ ( 0 , T ) D ( τ ) = max τ ∈ ( 0 , T ) [ max t ∈ ( 0 , τ ) P t − P τ ] MDD\left(T\right) = {\max _{\tau \in \left(0,T\right)}} D\left(\tau\right) = {\max _{\tau \in \left(0,T\right)}} \begin{aligned} \left[ \max _{t\in \left( 0,\tau \right) }P_{t}-P_{\tau}\right] \end{aligned} MDD(T)=maxτ∈(0,T)D(τ)=maxτ∈(0,T)[t∈(0,τ)maxPt−Pτ]
相应的最大回撤率为:
m
d
d
(
T
)
=
max
τ
∈
(
0
,
T
)
d
(
τ
)
M
D
D
(
T
)
max
t
∈
(
0
,
T
)
P
t
mdd\left(T\right) = {\max _{\tau \in \left(0,T\right)}} d\left(\tau \right) \dfrac {MDD\left(T\right)}{\max _{t \in \left(0,T\right)}P_t}
mdd(T)=maxτ∈(0,T)d(τ)maxt∈(0,T)PtMDD(T)
直观的讲,MDD(T)对应的是在(0,T)时段内资产价值从最高峰回落到最低谷的幅度。最大回撤常用来描述投资者在持有资产是可能面临的最大亏损。
2.3 利用收益率计算最大回撤
如果某资产的收益率序列为R1,R2,…,RT,在初始时刻0时,我们投资1元在该资产上并一直持有到T时刻,则初始值为1元的资产价值就会随时间变化为:(1+R1),(1+R1)(1+R2),(1+R1)(1+R2)(1+R3),…, ∏ k = 1 T ( 1 + R k ) \prod _{k=1}^{T}\left( 1+R_{k}\right) ∏k=1T(1+Rk)
时刻T对应的回撤值为:
D
(
T
)
=
max
{
0
,
max
t
∈
(
0
,
T
)
∏
k
=
1
t
(
1
+
R
k
)
−
∏
k
=
1
T
(
1
+
R
k
)
}
D(T) = \max \left\{ 0, \max _{t \in (0,T)} \prod _{k=1}^{t}\left( 1+R_{k}\right) - \prod _{k=1}^{T}\left( 1+R_{k}\right) \right\}
D(T)=max{0,maxt∈(0,T)∏k=1t(1+Rk)−∏k=1T(1+Rk)}
相应的回撤率为:
d
(
T
)
=
D
(
T
)
max
t
∈
(
0
,
T
)
∏
k
=
1
t
(
1
+
R
k
)
d(T) = \dfrac {D\left( T\right) }{\max _{t\in \left( 0,T\right) }\prod _{k=1}^{t}\left( 1+R_{k}\right) }
d(T)=maxt∈(0,T)∏k=1t(1+Rk)D(T)
最大回撤为:
M
D
D
(
T
)
=
max
τ
∈
(
0
,
T
)
D
(
τ
)
=
max
τ
∈
(
0
,
T
)
[
max
t
∈
(
0
,
τ
)
∏
k
=
1
t
(
1
+
R
k
)
−
∏
k
=
1
τ
(
1
+
R
k
)
]
MDD(T) = \max _{\tau \in \left( 0,T\right) }D\left( \tau \right) = \max _{\tau \in \left( 0,T\right) } \begin{aligned} \left[\max _{t\in \left( 0,\tau \right) }\prod _{k=1}^{t}\left( 1+R_{k}\right) - \prod _{k=1}^{\tau}\left( 1+R_{k}\right) \right]\end{aligned}
MDD(T)=maxτ∈(0,T)D(τ)=maxτ∈(0,T)[t∈(0,τ)maxk=1∏t(1+Rk)−k=1∏τ(1+Rk)]
相应的最大回撤率为:
m
d
d
(
T
)
=
max
τ
∈
(
0
,
T
)
d
(
τ
)
=
M
D
D
(
T
)
max
t
∈
(
0
,
T
)
∏
k
=
1
t
(
1
+
R
k
)
mdd(T) = \max _{\tau \in \left( 0,T\right) }d(\tau) = \dfrac {MDD(T)}{\max _{t \in \left( 0,T\right) }\prod _{k=1}^{t}\left( 1+R_{k}\right)}
mdd(T)=maxτ∈(0,T)d(τ)=maxt∈(0,T)∏k=1t(1+Rk)MDD(T)
value = (1 + r).cumprod()
value
2015-07-03 NaN
2015-07-04 1.026316
2015-07-05 1.076023
2015-07-06 1.002924
2015-07-07 1.040936
2015-07-08 1.073099
dtype: float64
D = value.cummax() - value
D
2015-07-03 NaN
2015-07-04 0.000000
2015-07-05 0.000000
2015-07-06 0.073099
2015-07-07 0.035088
2015-07-08 0.002924
dtype: float64
d = D / (D + value)
d
2015-07-03 NaN
2015-07-04 0.000000
2015-07-05 0.000000
2015-07-06 0.067935
2015-07-07 0.032609
2015-07-08 0.002717
dtype: float64
MDD = D.max()
MDD
0.07309941520467844
mdd =d.max()
mdd
# 对应的最大回撤率值为
0.06793478260869572
# 采用ffn库计算收益率累积最大回撤
ffn.calc_max_drawdown(value)
-0.06793478260869568
from empyrical import max_drawdown
# 使用 empyrical 计算收益率序列最大回撤
max_drawdown(r)
-0.06793478260869572
3. Java版本的最大回测
import java.util.Arrays;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class MaxDrawdownService {
/**
* 计算最大回撤:某段时间内连续收益率之和最小的值为最大回撤
*
* @Param rates:收益率
*/
@SuppressWarnings("all")
public static double caculateMaxDrawdown(List<Double> rates) {
double s = 0;
double e = 0;
double max = 0;
double temp = 0;
double ts = 0;
// 收益率不为空
if (!rates.isEmpty()) {
for (int i = 0; i < rates.size(); i++) {
// 获得收益率
double r = rates.get(i);
temp = temp + r;
if (temp > 0) {
ts = i + 1;
e = i + 1;
temp = 0;
} else {
if (temp < max) {
s = ts;
e = i;
max = temp;
}
}
}
}
log.info("最大回撤计算结果:maxsum={},start={},end={}", max, s, e);
return max;
}
/**
* 按照资金计算最大回撤
* @param equityValues
* @return
*/
public static double calMaxDrawdown(List<Double> equityValues) {
if (equityValues == null || equityValues.size() < 2)
return 0;
double maxDrawdown = 0; // 最大回撤
double maxEquityValue = equityValues.get(0); // 当日之前的最大资产净值
for (int i = 1; i < equityValues.size(); i++) {
double currentEquityValue = equityValues.get(i); // 当日资产净值
double drawDown = (1 - currentEquityValue / maxEquityValue);
maxDrawdown = Math.max(maxDrawdown, drawDown);
maxEquityValue = Math.max(currentEquityValue, maxEquityValue);
}
log.info("calMaxDrawdown最大回撤计算结果:{}", maxDrawdown);
return maxDrawdown;
}
public static void main(String[] args) {
Double[] c = {0.026316,0.048433,-0.067935,0.037901,0.030899};
caculateMaxDrawdown(Arrays.asList(c));
Double[] c2 = {3.42,3.51,3.68,3.43,3.56,3.67};
calMaxDrawdown(Arrays.asList(c2));
}
}
相关文章
- Python脚本写端口扫描器(socket,python-nmap)
- python中,数字类型计算
- python执行脚本加参数_命令行运行Python脚本时传入参数的三种方式详解以及argparse子命令subparsers()方法
- 机器学习-kmeans(实现步骤、sklearn实现、python自实现、优缺点)
- python+appium自动化测试 —— 滑动到固定的位置停止
- Google Earth Engine(python)——用 Python 修复影像栅格的接缝
- 掌握Python语言能做什么?python对小白友好吗?
- 人生苦短,我用Python!为什么现在越来越多的人转行python?
- Python-OpenCV中不用函数split()的实现图像多通道分离的方法——ndraary对象切片实现
- 《python 与数据挖掘 》一1.3 Python开发环境的搭建
- python 'libinstall' failed [libinstall] Error 1 解决办法
- gyp ERR! stack Error: Can‘t find Python executable “python“, you can set the PYTHON env variable.
- Python 爬虫
- 【Python】解压文件/ZIP等 并实时计算解压进度
- 【Python】计算两个日期相差多少天
- 【Python】【PyPI】twine模块打包python项目上传pypi
- 【python】+循环
- python之函数用法endswith()
- 《趣学Python编程》——第2章 计算与变量 2.1 用Python来做计算
- Python heapq实现大顶堆
- 利用python自动完成网页计算TEC等参数
- 【Computer Vision学习】二、使用pyenv管理多个Python版本(基于Ubuntu16.04)
- 【Python注意事项】如何理解python中间generator functions和yield表情
- (15)python进程与线程(待写)
- Python程序设计题库——第三章
- python爬取淘宝信息,第三方库批量安装
- Python运算符优先级
- 【Python】关于pip源与国内镜像
- 【python养成】:案例练习(判断闰年、删除奇数、偶数降序排序、因式分解、100以内奇数之和、1234组成的素数、分段函数计算、100以内的所有丑数)
- 【VOC格式xml文件解析】——Python
- 学习笔记(09):Python网络编程&并发编程-模拟ssh远程执行命令-代码实现
- Python每日一学 03——计算半径为r的圆的面积