KDJ指数是基于RSV指数的。RSV指数是以N天内最低值为底,当前值与最高值之间的比值。其具体意义为当天相对于N天最高值的比例(取值范围0-1),其值越大说明当天标的价格约高。其中1表示当天就是最高的,0表示当天就是最低的。从计算方法可以看出RSV指数只跟最高值最低值相关,属于支持向量相关的参数。KDJ指数分为K/D/J三个指数。其中K指数表示RSV的惯性累积值、D为K的惯性累积值、J为3K-2D。K为RSV惯性加权值,D为K惯性加权值,J为K与D的差值修正后的K值。K惯性修正与K差值的意义为K在自己的变化趋势上增加了部分。如果把标的价格运动比作线性运动,那么J值应该为K线性运动的预判值。
一下用C++函数式元编程实现了这些值的计算:
#include <vector>
#include <functional>
#include <exception>
#include <algorithm>
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>&)>;
/* 计算N天的RSV值 */
template<int N, typename val_t>
func_t<val_t> rsv_gen()
{
return [](const param_t<val_t>& vec_input)
{
size_t szt_num = vec_input.size() - N;
param_t<val_t> vec_out(szt_num, 0.0);
for (size_t i = 0; i < szt_num; ++i)
{
auto pr = std::minmax_element(vec_input.begin() + i, vec_input.begin() + i + N);
auto Ln = *pr.first;
auto Hn = *pr.second;
if (Hn != Ln)
vec_out[i] = (vec_input[i] - Ln) / (Hn - Ln) * 100.;
else
vec_out[i] = 0.;
}
return vec_out;
};
}
//* 计算N天的惯性加权值
template<int N, typename val_t>
inline val_t inert_weight(const param_t<val_t>& vec_rsv, const int& i_cur)
{
if constexpr (N == 1)
{
if (i_cur >= vec_rsv.size())
{
return vec_rsv.back();
}
return vec_rsv[i_cur];
}
if constexpr (N > 1)
{
if (i_cur >= vec_rsv.size() - 1)
{
return vec_rsv.back();
}
return 2 * vec_rsv[i_cur] / 3. + inert_weight<N - 1, val_t>(vec_rsv, i_cur + 1) / 3.;
}
}
template<int N, int KN, typename val_t>
inline param_t<val_t> deep_inert_weight(const param_t<val_t>& vec_input)
{
if constexpr (N == 0) return vec_input;
if constexpr (N != 0)
{
// * 自己先用K的计算方法惯性加权一次
param_t<val_t> vec_out(vec_input.size() - 1, 0.0);
for (size_t i = 0; i < vec_out.size(); ++i)
{
vec_out[i] = inert_weight<KN, val_t>(vec_input, i);
}
return deep_inert_weight<N - 1, KN, val_t>(vec_out); // * 计算剩下的K算法惯性加权
}
}
template<int N, int RSV_N, int K_N, typename val_t>
func_t<val_t> kdj_gen()
{
return [](const param_t<val_t>& vec)
{
auto rsv = rsv_gen<RSV_N, val_t>();
auto vec_rsv = rsv(vec);
return deep_inert_weight<N, K_N, val_t>(vec_rsv);
};
}
template<int RSV_N, int K_N, typename val_t>
func_t<val_t> k_gen()
{
return kdj_gen<1, RSV_N, K_N, val_t>(); // * k参数只需要用惯性加权算法算一次就行
}
template<int RSV_N, int K_N, typename val_t>
func_t<val_t> d_gen()
{
return kdj_gen<2, RSV_N, K_N, val_t>(); // * d参数需要用惯性加权算法,将结果再次使用惯性加权算法算一次
}
template<int RSV_N, int K_N, typename val_t>
func_t<val_t> j_gen()
{
return [](const param_t<val_t>& vec)
{
auto k = k_gen<RSV_N, K_N, double>();
auto vec_k = k(vec);
auto d = d_gen<RSV_N, K_N, double>();
auto vec_d = d(vec);
size_t szt_short = vec_k.size() < vec_d.size() ? vec_k.size() : vec_d.size();
param_t<val_t> vec_out(szt_short, 0.0);
for (size_t i = 0; i < szt_short; ++i)
{
vec_out[i] = 3. * vec_k[i] - 2. * vec_d[i];
}
return vec_out;
};
}
#include <vector>
#include <algorithm>
#include <random>
// * 价格生成函数
double price_generate()
{
static std::default_random_engine ge;
static std::uniform_real_distribution <double> ud(0., 5.);
return ud(ge);
}
int main()
{
/* 测试数据产生,模拟一个以恒定速度增长的价格 */
std::vector<double> vec;
vec.resize(50, 0.0);
std::generate(vec.begin(), vec.end(), price_generate);
std::reverse(vec.begin(), vec.end()); // * 数据是反向的,第一个是最近的数据
printf("origin:\n");
for(auto v: vec)
{
printf("%3.4lf ", v);
}
printf("\n");
auto kfun = k_gen<9, 3, double>();
auto dfun = d_gen<9, 3, double>();
auto jfun = j_gen<9, 3, double>();
auto veck = kfun(vec);
printf("K:\n");
for(auto v: veck)
{
printf("%3.4lf ", v);
}
printf("\n");
auto vecd = dfun(vec);
printf("D:\n");
for(auto v: vecd)
{
printf("%3.4lf ", v);
}
printf("\n");
auto vecj = jfun(vec);
printf("J:\n");
for(auto v: vecj)
{
printf("%3.4lf ", v);
}
printf("\n");
return 0;
}