BOLL线——C++函数式编程实现

目录

BOLL线原理

BOLL线使用

代码试验

试验结果


 

BOLL线原理

BOLL线由上线、中线、下线组成。中线是R_N日内的股票收盘价均值,上线是均值加上2个标准差,下线是均值减去2个标准差。BOLL线的内在逻辑是这样的:收盘价格在采样区间内的分布概率是正态分布,而正态分布大概率是在均值加减2个方差的范围内(约95.45%)。所以明日价格在上线和下线之间事最有可能的,不大可能超过这个范围。一下为2023年2月17日的沪金2303的BOLL线,可以看出来虽然大部分的收盘价格都在上线和下线之间,不过也有部分偏出。

BOLL线使用

 对于标的收盘价格在一定区间内符合正态分布这个先验条件我们需要打一个问号,不过姑且认为是这样的吧,必经大范围的价格波动发生的很少,这个直观感受和正态分布较为类似。那么我们需要了解BOLL线能做什么,看BOLL线能得出什么有用的信息。我觉得BOLL线可以根据上线和中线、下线和中线间的距离变化,直观的感受近期标的价格的稳定性。如果距离较大,说明价格的波动性很大,如果距离较小,说明价格较为稳定;如果距离由大变小,说明价格在趋于稳定,如果距离由小变大说明价格趋于不稳定。

中线和标的价格的对比,中线代表的是区间内的平均情况,如果标的价格线由下向上穿过中线,则说明价格已经超过最近的均值,价格开始上涨了(由于是均值,因此会在价格上涨数天之后才会表现出这个现象)。下行同理。如果标的价格超过上线,则其再上升,其概率不大(如果标的价格服从正态分布继续上涨概率应该是4.55%以下),当然这个概率是不可靠的,但是可供参考,至少是部分服从实践事实的。

代码试验

试验使用N(2,1)生成一组数据,用以模拟标的价格。基于这组数据,计算其BOLL线的上、中、下线,并观察。下面是代码实现:


#include <vector>
#include <functional>
#include <exception>
#include <algorithm>
#include <numeric>
#include <math.h>
 
template<typename val_t>
using param_t = std::vector<val_t>;
 
template<typename val_t>
using func_t = std::function<param_t<val_t>(const param_t<val_t>&)>;

template<int R_N, typename val_t>
val_t mean_cal(const param_t<val_t>& vec, const size_t& siz_begin_index)
{
    auto itr_beg = vec.begin() + siz_begin_index;
    auto itr_end = vec.begin() + siz_begin_index + R_N;
    if (itr_end > vec.end())
    {
        throw std::runtime_error("over range");
    }
    val_t v_sum = std::accumulate(itr_beg, itr_end, 0.0);
    return v_sum / static_cast<const val_t>(R_N);
}

// * 计算数组均值
template<int R_N, typename val_t>
func_t<val_t> ma_gen()
{
    return [](const param_t<val_t>& vec)
    {
        if (vec.size() < R_N)
            throw std::runtime_error("over range...");
        param_t<val_t> vec_ret;
        for (size_t siz_itr = 0; siz_itr < vec.size() - R_N + 1; ++siz_itr)
        {
            vec_ret.push_back(mean_cal<R_N, val_t>(vec, siz_itr));
        }
        return vec_ret;
    };
}

template<int R_N, typename val_t>
val_t varia_cal(const param_t<val_t>& vec, const size_t& siz_begin_index, const val_t& v_mean)
{
    auto itr_beg = vec.begin() + siz_begin_index;
    auto itr_end = vec.begin() + siz_begin_index + R_N;
    if (itr_end > vec.end())
    {
        throw std::runtime_error("over range");
    }
    val_t v_sum = std::accumulate(itr_beg, itr_end, 0.0,
    [&v_mean](val_t a, val_t v)->val_t{return a + (v-v_mean)*(v-v_mean);}
    );
    return sqrt(v_sum / static_cast<const val_t>(R_N - 1));
}

template< int R_N, typename val_t>
func_t<val_t> md_gen()
{
    return [](const param_t<val_t>& vec)
    {
        if (vec.size() < R_N)
            throw std::runtime_error("over range...");
        param_t<val_t> vec_ret;
        auto ma = ma_gen<R_N, val_t>();
        param_t<val_t> vec_ma = ma(vec);
        for (size_t siz_itr = 0; siz_itr < vec_ma.size(); ++siz_itr)
        {
            vec_ret.push_back(varia_cal<R_N, val_t>(vec, siz_itr, vec_ma[siz_itr]));
        }
        return vec_ret;
    };
}

// * 中轨线
template<int R_N, typename val_t>
func_t<val_t> mb_gen()
{
    return [](const param_t<val_t>& vec)
    {
        auto ma = ma_gen<R_N, val_t>();
        return ma;
    };
}

// * 上轨线
template<int R_N, typename val_t>
func_t<val_t> up_gen()
{
    return [](const param_t<val_t>& vec)
    {
        auto ma = ma_gen<R_N, val_t>();
        auto vec_ma = ma(vec);
        auto md = md_gen<R_N, val_t>();
        auto vec_md = md(vec);
        param_t<val_t> vec_ret(vec_md.size(), 0.0);
        std::transform(vec_ma.begin(), vec_ma.end(), vec_md.begin(), vec_ret.begin(), [](const val_t& v1, const val_t& v2)->val_t{return v1 + 2. * v2;});
        return vec_ret;
    };
}

// * 下轨线
template<int R_N, typename val_t>
func_t<val_t> dn_gen()
{
    return [](const param_t<val_t>& vec)
    {
        auto ma = ma_gen<R_N, val_t>();
        auto vec_ma = ma(vec);
        auto md = md_gen<R_N, val_t>();
        auto vec_md = md(vec);
        param_t<val_t> vec_ret(vec_md.size(), 0.0);
        std::transform(vec_ma.begin(), vec_ma.end(), vec_md.begin(), vec_ret.begin(), [](const val_t& v1, const val_t& v2)->val_t{return v1 - 2. * v2;});
        return vec_ret;
    };
}

#include <random>

// * 价格生成函数
double price_generate()
{
    static std::default_random_engine ge;
    static std::normal_distribution<double> ud(2., 1.);
    return ud(ge);
} 

int main(int argc, char** argv)
{
	std::vector<double> vec;
	vec.resize(50, 0.0);
	std::generate(vec.begin(), vec.end(), price_generate);

    auto md = md_gen<20, double>();
    auto vec_md = md(vec);
    printf("div:");
    for(auto v: vec_md)
    {
        printf("%.4lf ", v);
    }
    printf("\n");

    auto up = up_gen<20, double>();
    auto vec_up = up(vec);
    printf("up:");
    for(auto v: vec_up)
    {
        printf("%.4lf ", v);
    }
    printf("\n");

    auto ma = ma_gen<20, double>();
    auto vec_ma = ma(vec);
    printf("mid:");
    for(auto v: vec_ma)
    {
        printf("%.4lf ", v);
    }
    printf("\n");

    auto dn = dn_gen<20, double>();
    auto vec_dn = dn(vec);
    printf("dn:");
    for(auto v: vec_dn)
    {
        printf("%.4lf ", v);
    }
    printf("\n");
    return 0;
}

试验结果

试验结果展示如下:

可见,和我们预料的一直,中线集中于分布均值2附近,上线为4,下线为0。 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

腾昵猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值