Merge pull request #108 from fasiondog/develop

Develop
This commit is contained in:
fasiondog 2023-09-07 00:53:50 +08:00 committed by GitHub
commit 7d6c0886f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 131 additions and 1 deletions

View File

@ -300,4 +300,14 @@ Indicator HKU_API IF(const Indicator& x, price_t a, price_t b) {
return IF(x, CVAL(x, a), CVAL(x, b));
}
Indicator HKU_API CORR(const Indicator& ind1, const Indicator& ind2, int n) {
HKU_ERROR_IF_RETURN(!ind1.getImp() || !ind2.getImp(), Indicator(),
"ind1 or ind2 is Null Indicator!");
HKU_ERROR_IF_RETURN(n < 2, Indicator(), "Invalid param n: {} (need >= 2)", n);
IndicatorImpPtr p = make_shared<IndicatorImp>("CORR");
p->setParam<int>("n", n);
p->add(IndicatorImp::CORR, ind1.getImp(), ind2.getImp());
return p->calculate();
}
} /* namespace hku */

View File

@ -365,6 +365,14 @@ Indicator HKU_API IF(const Indicator& x, price_t a, const Indicator& b);
Indicator HKU_API IF(const Indicator& x, const Indicator& a, price_t b);
Indicator HKU_API IF(const Indicator& x, price_t a, price_t b);
/**
*
* @param ind1 1
* @param ind2 2
* @ingroup Indicator
*/
Indicator HKU_API CORR(const Indicator& ind1, const Indicator& ind2, int n);
} /* namespace hku */
#if FMT_VERSION >= 90000

View File

@ -400,6 +400,10 @@ string IndicatorImp::formula() const {
<< m_right->formula() << ")";
break;
case CORR:
buf << m_name << "(" << m_left->formula() << ", " << m_right->formula() << ")";
break;
default:
HKU_ERROR("Wrong optype! {}", int(m_optype));
break;
@ -623,6 +627,10 @@ Indicator IndicatorImp::calculate() {
execute_if();
break;
case CORR:
execute_corr();
break;
default:
HKU_ERROR("Unkown Indicator::OPType! {}", int(m_optype));
break;
@ -1251,6 +1259,98 @@ void IndicatorImp::execute_if() {
}
}
void IndicatorImp::execute_corr() {
m_right->calculate();
m_left->calculate();
IndicatorImp *maxp, *minp;
if (m_right->size() > m_left->size()) {
maxp = m_right.get();
minp = m_left.get();
} else {
maxp = m_left.get();
minp = m_right.get();
}
size_t total = maxp->size();
size_t discard = maxp->size() - minp->size() + minp->discard();
if (discard < maxp->discard()) {
discard = maxp->discard();
}
// 结果 0 存放相关系数结果
// 结果 1 存放协方差COV结果
_readyBuffer(total, 2);
int n = getParam<int>("n");
if (n < 2 || discard + 2 > total) {
setDiscard(total);
return;
}
price_t null_price = Null<price_t>();
vector<price_t> prebufx(total, null_price);
vector<price_t> prebufy(total, null_price);
vector<price_t> prepowx(total, null_price);
vector<price_t> prepowy(total, null_price);
vector<price_t> prepowxy(total, null_price);
price_t kx = maxp->get(discard);
price_t ky = minp->get(discard);
price_t ex = 0.0, ey = 0.0, exy = 0.0, varx = 0.0, vary = 0.0, cov = 0.0;
price_t ex2 = 0.0, ey2 = 0.0, exy2 = 0.0;
prebufx[discard] = 0.0;
prebufy[discard] = 0.0;
prepowx[discard] = 0.0;
prepowy[discard] = 0.0;
prepowxy[discard] = 0.0;
for (size_t i = discard, nobs = 0; i < total; ++i) {
price_t ix = maxp->get(i) - kx;
price_t iy = minp->get(i) - ky;
price_t preix = prebufx[i - nobs];
price_t preiy = prebufy[i - nobs];
price_t prepowix = prepowx[i - nobs];
price_t prepowiy = prepowy[i - nobs];
price_t prepowixy = prepowxy[i - nobs];
HKU_INFO_IF(i % 100 == 0, "{}: ix: {}, iy: {}, preix: {}, preiy: {}", i, ix, iy, preix,
preiy);
if (!std::isnan(preix) && !std::isnan(preiy) && !std::isnan(ix) && !std::isnan(iy)) {
if (nobs < n) {
nobs++;
ex += ix;
ey += iy;
exy += ix * iy;
ex2 += std::pow(ix, 2);
ey2 += std::pow(iy, 2);
varx = nobs == 1 ? 0. : (ex2 - std::pow(ex, 2) / nobs) / (nobs - 1);
vary = nobs == 1 ? 0. : (ey2 - std::pow(ey, 2) / nobs) / (nobs - 1);
cov = nobs == 1 ? 0. : (exy - ex * ey / nobs) / (nobs - 1);
_set(cov / std::sqrt(varx * vary), i, 0);
_set(cov, i, 1);
} else {
ex += ix - preix;
ey += iy - preiy;
ex2 = ex2 - prepowix + std::pow(ix, 2);
ey2 = ey2 - prepowiy + std::pow(iy, 2);
exy = exy + ix * iy - prepowixy;
varx = (ex2 - std::pow(ex, 2) / n) / (n - 1);
vary = (ey2 - std::pow(ey, 2) / n) / (n - 1);
cov = (exy - ex * ey / n) / (n - 1);
_set(cov / std::sqrt(varx * vary), i, 0);
_set(cov, i, 1);
}
prebufx[i] = ix;
prebufy[i] = iy;
prepowx[i] = ex2;
prepowy[i] = ey2;
prepowxy[i] = exy2;
}
}
// 修正 discard
setDiscard(++discard);
}
void IndicatorImp::_dyn_calculate(const Indicator &ind) {
// SPEND_TIME(IndicatorImp__dyn_calculate);
const auto &ind_param = getIndParamImp("n");

View File

@ -77,6 +77,7 @@ public:
OR, ///< 或
WEAVE, ///< 特殊的,需要两个指标作为参数的指标
OP_IF, /// if操作
CORR, ///< 相关系数,需要两个指标作为参数
INVALID
};
@ -211,6 +212,7 @@ private:
void execute_or();
void execute_weave();
void execute_if();
void execute_corr();
protected:
static size_t _get_step_start(size_t pos, size_t step, size_t discard);

View File

@ -728,6 +728,15 @@ void export_Indicator_build_in() {
:param Indicator ind2: 2
:rtype: Indicator)");
def("CORR", CORR, R"(CORR(ind1, ind2, n)
ind1 ind2
:param Indicator ind1: 1
:param Indicator ind2: 2
:param int n: n ind
:rtype: Indicator)");
def("IF", IF_1);
def("IF", IF_2);
def("IF", IF_3);

View File

@ -42,6 +42,7 @@ local boost_version = "1.81.0"
local hdf5_version = "1.12.2"
local mysql_version = "8.0.31"
local fmt_version = "10.0.0"
local flatbuffers_version = "2.0.0"
if is_plat("windows") or (is_plat("linux", "cross") and is_arch("aarch64", "arm64.*")) then mysql_version = "8.0.21" end
add_repositories("project-repo hikyuu_extern_libs")
@ -81,7 +82,7 @@ end
add_requires("spdlog", {system = false, configs = {header_only = true, fmt_external = true, vs_runtime = "MD"}})
add_requireconfs("spdlog.fmt", {override = true, version = fmt_version, configs = {header_only = true}})
add_requires("sqlite3", {system = false, configs = {shared = true, vs_runtime = "MD", cxflags = "-fPIC"}})
add_requires("flatbuffers 2.0.0", {system = false, configs = {vs_runtime = "MD"}})
add_requires("flatbuffers v" .. flatbuffers_version, {system = false, configs = {vs_runtime = "MD"}})
add_requires("nng", {system = false, configs = {vs_runtime = "MD", cxflags = "-fPIC"}})
add_requires("nlohmann_json", {system = false})
add_requires("cpp-httplib", {system = false})