.NET精确计算最大回撤算法&&时间复杂度优化

2 篇文章 0 订阅

.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

以上就是本次博客具体内容,如有不足请批评指正

书山有路勤为径,学海无涯苦作舟

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值