龙听期货论坛's Archiver

龙听 发表于 2024-11-22 14:26

鼎元C++期货量化/程序化教程【波动率(Volatility)计算方法及调用方法】

过内外网搜集与整理,我们可以发现对于波动率有两种计算方式,一是atr计算方法。二是标准差计算方式。波动率做为一种计算证券期货价格无效波动幅度的指标多用到进场与出场模块中,也就是在进场和出场时设定一个免疫的波动幅度,在此波动幅度内是不进场或出场的。

计算历史波动率(calculating historical volatility),计算出来的是加权波动平均率。

1、头文件声明变量:[code]
        double Volatility(string period, string inst, int num);//计算历史波动率(CALCULATING HISTORICAL VOLATILITY)
[/code]2、公式模块增加计算公式:[code]//计算历史波动率(calculating historical volatility)
double test::Volatility(string period, string inst, int num)
{
       double dPreClose = 0;//获取每个bar对前的前一个bar的收盘价
        double tr = 0; //tr的值计算
        vector<double>vtr; //建立一个数组,用来存放每个bar对应的truerange值,它们的下标号与bar的是一致的
        if (mapK[period][inst].size() < num) return 0; //如果数据数量不够返回0;
        map<string, TKVALUE >::iterator it; //建立正迭代器,标号从0开始,一般从左向右开始
        for (it = mapK[period][inst].begin(); it != mapK[period][inst].end(); ++it) //从第一开始的bar数据开始遍历
        {
                if (dPreClose != 0) //如果值不为0说明是在中间的bar,开始在bar数据要素中采集需要的变量数值
                {
                        double d = it->second.dHigh - it->second.dLow;
                        double dHC = abs(it->second.dHigh - dPreClose);
                        double dLC = abs(it->second.dLow - dPreClose);
                        double e = max3(d, dHC, dLC); //获得每一个bar对应的truerange值
                        vtr.push_back(e); //将上面e的值放到tr的vector(数组)里面供下面使用
                }
                dPreClose = it->second.dClose; //将第一个bar的收盘价数值赋给此变量
        }
        for (int i = 0; i < num; i++) //计算tr的num周期指数移动平均值
        {
                tr = tr* (num-1)/(num + 1) + (vtr[vtr.size() - i]) * 2 /(num + 1); // 2/(num + 1)指数移动平均线的平滑因子
        }
        return tr;
}[/code]3、调用方法:[code]Volatility(sPeriod, sInst, length);//计算length周期的历史波动率[/code]

龙听 发表于 2024-11-22 14:26

[C++源码] 波动率(Volatility)相关的程序化策略研究与源码:[url]http://www.qhlt.cn/thread-160439-1-1.html[/url];

龙听 发表于 2024-11-23 16:41

[code] for (int i = 0; i < num; i++) //计算tr的num周期指数移动平均值
        {
                tr = tr* (num-1)/(num + 1) + (vtr[vtr.size() - i]) * 2 /(num + 1); // 2/(num + 1)指数移动平均线的平滑因子
        }[/code]这里做个说明:

若是想用指数移动平均就延续上面。

还可以用简单平均:[code] for (int i = 0; i < num; i++) //计算tr的num周期指数移动平均值
        {
                tr = tr  + (vtr[vtr.size() - i])  / num;
        }[/code]

龙听 发表于 2024-11-23 16:41

有疑问或交流可以在这里回贴或进群交流。

龙听 发表于 2024-12-11 13:23

今天对核心思路做一下修正:[code]
//计算历史波动率(calculating historical volatility)
double test::Volatility(string period, string inst, int num)
{
        double PreClose = 0;//获取每个bar前一个bar的收盘价
        double tr = 0; //tr的值计算
        int key = 0; //计数器
        vector<double>vtr; //建立一个数组,用来存放每个bar对应的truerange值,它们的下标号与bar的是一致的
        if (mapK[period][inst].size() < num) return 0; //如果数据数量不够返回0;
        map<string, TKVALUE >::iterator it; //建立正迭代器,标号从0开始,从左向右开始
        for (it = mapK[period][inst].begin(); it != mapK[period][inst].end(); ++it) //从第一开始的bar数据开始遍历
        {
                if (PreClose != 0) //如果值不为0说明是在中间的bar,开始在bar数据要素中采集需要的变量数值
                {
                        double dHL = it->second.dHigh - it->second.dLow; //当根bar的最高减最低
                        double dHC = abs(it->second.dHigh - PreClose); //当根bar最高减昨日收盘
                        double dLC = abs(it->second.dLow - PreClose); //当根bar最低减昨日收盘
                        double e = max3(dHL, dHC, dLC); //获得每一个bar对应的truerange值(上面三者之最大者)
                        vtr.push_back(e); //将上面e的值放到tr的vector(数组)里面供下面使用
                }
                PreClose = it->second.dClose; //将当前bar的收盘价数值赋给此变量供下一个bar使用
        }
        //计算tr的num周期指数移动平均值
        if (key <= num)
        {
                tr = 0;
                key++;
        }
        else
        {
                tr = (vtr[vtr.size() - 1]) * 2 / (num+1) + tr * (num-1)/(num+1); // 2/(num + 1)指数移动平均线的平滑因子
        }
        return tr;
}
[/code]

龙听 发表于 2024-12-11 13:34

上面修正主要是最后计算指数平均上面,不需要用for循环的。

页: [1]