.net 精确计算最大回撤算法
一、问题描述 >> 什么是最大回撤
最大回撤率是指在选定周期内任一历史时点往后推,产品净值走到最低点时的收益率回撤幅度的最大值。最大回撤用来描述买入产品后可能出现的最糟糕的情况。最大回撤是一个重要的风险指标,对于对冲基金和数量化策略交易,该指标比波动率还重要。
具体表现
以上是关于最大回撤率的名词解释。用通俗思维在股指期货基金产品认购中可以理解为以下几点。
1.回撤用来衡量该私募产品的抗风险能力。
回撤的意思,是指在某一段时期内产品净值从最高点开始回落到最低点的幅度
最大回撤率,不一定是(最高点净值-最低点净值)/最高点时的净值,也许它会出现在其中某一段的回落。
公式可以这样表达:
D为某一天的净值,i为某一天,j为i后的某一天,Di为第i天的产品净值,Dj则是Di后面某一天的净值
drawdown就是最大回撤率
drawdown=max((Di-Dj)/Di),其实就是对每一个净值进行回撤率求值,然后找出最大的。可以使用程序实现
基本描述就是以上这些,实际情况较为多样,公式的其中一些条件比如:(max-min)/max max为净值高值,min为净值低值,高值一定要在低值的前面,我们拿到一组数据[1,4,6,2,8,4,2,5,7,8,1,9]
这组数据的最大回撤计算为(8-1)/8;为什么不用9-1呢因为,9在低值的后面了,不参与算法的满足条件
最开始 作者想到的原始算法为逐个遍历,记录每一个下标的最大回撤,每次进行迭代直到找不到比前者迭代更高的结果出来就是最大回测,实际中也是可行的,但是我们要考虑到算法的一个时间复杂度的问题!
二、时间复杂度 优化
算法实现有很多,简单粗暴的方法比如把每一天的值和其他天作差值计算,找到差值最大的那一天,但这个方法并不好。从时间复杂度上看是O(n!),差不多算是最差的了。
说到这顺便普及一下时间复杂度的知识。
常见复杂度
除了常数阶、线性阶、平方阶、对数阶,还有如下时间复杂度:
f(n)=nlogn时,时间复杂度为O(nlogn),可以称为nlogn阶。
f(n)=n³时,时间复杂度为O(n³),可以称为立方阶。
f(n)=2ⁿ时,时间复杂度为O(2ⁿ),可以称为指数阶。
f(n)=n!时,时间复杂度为O(n!),可以称为阶乘阶。
f(n)=(√n时,时间复杂度为O(√n),可以称为平方根阶。
下面面将算法中常见的f(n)值根据几种典型的数量级来列成一张表,根据这种表,我们来看看各种算法复杂度的差异。
参考链接:https://blog.csdn.net/itachi85/article/details/54882603
从上表可以看出,O(n)、O(logn)、O(√n )、O(nlogn )随着n的增加,复杂度提升不大,因此这些复杂度属于效率高的算法,反观O(2ⁿ)和O(n!)当n增加到50时,复杂度就突破十位数了,这种效率极差的复杂度最好不要出现在程序中,因此在动手编程时要评估所写算法的最坏情况的复杂度。
O(1) < O(logn) < O(n) < O(nlogn) < O(n²) < O(n³) < O(2ⁿ) < O(n!)
参考链接:https://blog.csdn.net/yangwohenmai1/article/details/94296920
三、代码实现
#region 最大回撤计算
try
{
var evertable = bll.GetEveryData(fid);///查询出基金历史日期的每天的净值以及其他数据
var everydata = DataTableToList<FS_EveryDay_Data>(evertable);///获取默认前30条时间轴数据
//var everydata = DataTableToList<FS_EveryDay_Data>(bll.GetEveryData(fid));/// 以上替代写法
var edtime = everydata.OrderBy(s => s.SomeDay).ToList();///按照日期从小到大排序 升序
decimal max = decimal.MinValue;
decimal min = decimal.MaxValue;
decimal payback = decimal.MinValue;
string oldmax = "";
string oldmin = "";
SortedList<decimal, decimal> SOR = new SortedList<decimal, decimal>();
List<decimal> res = new List<decimal>();
foreach (var item in edtime)
{
decimal netWorth = Convert.ToDecimal(item.NetWorth);
if (max < netWorth)
{
max = netWorth;
min = netWorth;
}
if (min > netWorth)
{
min = netWorth;
}
if ((max - min) / max > payback && max != min)
{
oldmax = max.ToString();
oldmin = min.ToString();
payback = (max - min) / max;
}
}
if (payback is decimal.MinValue || payback is decimal.MaxValue)
payback = 0;///如果没有算出来,通常是数据出问题或者净值全部都一样
ViewBag.drowdown = Math.Round(payback, 2);///最大回撤 两位小数
}
catch (Exception e)
{
ViewBag.drowdown = 0;
}
#endregion
参考链接:https://blog.csdn.net/yangwohenmai1/article/details/94296920
以上就是本次博客具体内容,如有不足请批评指正
书山有路勤为径,学海无涯苦作舟