优化STDED/STDP,使用移位算法

This commit is contained in:
fasiondog 2023-09-03 19:10:05 +08:00
parent 328a4c9408
commit 5bc8d0dc8f
5 changed files with 88 additions and 52 deletions

View File

@ -26,40 +26,54 @@ bool IStdev::check() {
void IStdev::_calculate(const Indicator& data) { void IStdev::_calculate(const Indicator& data) {
size_t total = data.size(); size_t total = data.size();
int n = getParam<int>("n"); m_discard = data.discard();
m_discard = data.discard() + n - 1;
if (m_discard >= total) { if (m_discard >= total) {
m_discard = total; m_discard = total;
return; return;
} }
Indicator ma = MA(data, n); int n = getParam<int>("n");
size_t N = n - 1;
for (size_t i = discard(); i < total; ++i) { vector<price_t> pow_buf(data.size());
price_t mean = ma[i]; price_t ex = 0.0, ex2 = 0.0;
price_t sum = 0.0; size_t num = 0;
for (size_t j = i + 1 - n; j <= i; ++j) { size_t start_pos = m_discard;
sum += std::pow(data[j] - mean, 2); size_t first_end = start_pos + n >= total ? total : start_pos + n;
} price_t k = data[start_pos];
_set(std::sqrt(sum / N), i); for (size_t i = start_pos; i < first_end; i++) {
num++;
price_t d = data[i] - k;
ex += d;
price_t d_pow = std::pow(d, 2);
pow_buf[i] = d_pow;
ex2 += d_pow;
_set(num == 1 ? 0. : std::sqrt((ex2 - std::pow(ex, 2) / num) / (num - 1)), i);
}
for (size_t i = first_end; i < total; i++) {
ex -= data[i - n] - k;
ex2 -= pow_buf[i - n];
price_t d = data[i] - k;
ex += d;
price_t d_pow = std::pow(d, 2);
pow_buf[i] = d_pow;
ex2 += d_pow;
_set(std::sqrt((ex2 - std::pow(ex, 2) / n) / (n - 1)), i);
} }
} }
void IStdev::_dyn_run_one_step(const Indicator& ind, size_t curPos, size_t step) { void IStdev::_dyn_run_one_step(const Indicator& ind, size_t curPos, size_t step) {
HKU_IF_RETURN(step > 0 && curPos < ind.discard() + step - 1, void());
size_t start = _get_step_start(curPos, step, ind.discard()); size_t start = _get_step_start(curPos, step, ind.discard());
price_t sum = 0.0; size_t num = 0;
price_t ex = 0.0, ex2 = 0.0;
price_t k = ind[start];
for (size_t i = start; i <= curPos; i++) { for (size_t i = start; i <= curPos; i++) {
sum += ind[i]; num++;
price_t d = ind[i] - k;
ex += d;
ex2 += std::pow(d, 2);
} }
price_t mean = sum / step; _set(num <= 1 ? 0.0 : std::sqrt((ex2 - std::pow(ex, 2) / num) / (num - 1)), curPos);
sum = 0.0;
size_t N = step - 1;
for (size_t i = start; i <= curPos; i++) {
sum += std::pow(ind[i] - mean, 2);
}
_set(std::sqrt(sum / N), curPos);
} }
Indicator HKU_API STDEV(int n) { Indicator HKU_API STDEV(int n) {

View File

@ -28,38 +28,54 @@ bool IStdp::check() {
void IStdp::_calculate(const Indicator& data) { void IStdp::_calculate(const Indicator& data) {
size_t total = data.size(); size_t total = data.size();
int n = getParam<int>("n"); m_discard = data.discard();
m_discard = data.discard() + n - 1;
if (m_discard >= total) { if (m_discard >= total) {
m_discard = total; m_discard = total;
return; return;
} }
Indicator ma = MA(data, n); int n = getParam<int>("n");
for (size_t i = discard(); i < total; ++i) {
price_t mean = ma[i]; vector<price_t> pow_buf(data.size());
price_t sum = 0.0; price_t ex = 0.0, ex2 = 0.0;
for (size_t j = i + 1 - n; j <= i; ++j) { size_t num = 0;
sum += std::pow(data[j] - mean, 2); size_t start_pos = m_discard;
} size_t first_end = start_pos + n >= total ? total : start_pos + n;
_set(std::sqrt(sum / n), i); price_t k = data[start_pos];
for (size_t i = start_pos; i < first_end; i++) {
num++;
price_t d = data[i] - k;
ex += d;
price_t d_pow = std::pow(d, 2);
pow_buf[i] = d_pow;
ex2 += d_pow;
_set(std::sqrt((ex2 - std::pow(ex, 2) / num) / num), i);
}
for (size_t i = first_end; i < total; i++) {
ex -= data[i - n] - k;
ex2 -= pow_buf[i - n];
price_t d = data[i] - k;
ex += d;
price_t d_pow = std::pow(d, 2);
pow_buf[i] = d_pow;
ex2 += d_pow;
_set(std::sqrt((ex2 - std::pow(ex, 2) / n) / n), i);
} }
} }
void IStdp::_dyn_run_one_step(const Indicator& ind, size_t curPos, size_t step) { void IStdp::_dyn_run_one_step(const Indicator& ind, size_t curPos, size_t step) {
HKU_IF_RETURN(step > 0 && curPos < ind.discard() + step - 1, void());
size_t start = _get_step_start(curPos, step, ind.discard()); size_t start = _get_step_start(curPos, step, ind.discard());
price_t sum = 0.0; size_t num = 0;
price_t ex = 0.0, ex2 = 0.0;
price_t k = ind[start];
for (size_t i = start; i <= curPos; i++) { for (size_t i = start; i <= curPos; i++) {
sum += ind[i]; num++;
price_t d = ind[i] - k;
ex += d;
ex2 += std::pow(d, 2);
} }
price_t mean = sum / step; _set(num == 0 ? 0.0 : std::sqrt((ex2 - std::pow(ex, 2) / num) / num), curPos);
sum = 0.0;
for (size_t i = start; i <= curPos; i++) {
sum += std::pow(ind[i] - mean, 2);
}
_set(std::sqrt(sum / step), curPos);
} }
Indicator HKU_API STDP(int n) { Indicator HKU_API STDP(int n) {

View File

@ -35,13 +35,13 @@ TEST_CASE("test_STDEV") {
Indicator ind = PRICELIST(d); Indicator ind = PRICELIST(d);
Indicator dev = STDEV(ind, 10); Indicator dev = STDEV(ind, 10);
CHECK_EQ(dev.size(), 15); CHECK_EQ(dev.size(), 15);
CHECK_UNARY(std::isnan(dev[8]));
CHECK_LT(std::fabs(dev[9] - 2.923088), 0.000001); vector<price_t> expected{0, 0.707107, 1, 1.29099, 1.58114,
CHECK_LT(std::fabs(dev[10] - 3.142893), 0.000001); 1.47196, 1.97605, 1.83225, 2.44949, 2.92309,
CHECK_LT(std::fabs(dev[11] - 2.830390), 0.000001); 3.14289, 2.83039, 3.26769, 3.653, 4.00139};
CHECK_LT(std::fabs(dev[12] - 3.267686), 0.000001); for (size_t i = 0; i < dev.size(); i++) {
CHECK_LT(std::fabs(dev[13] - 3.653004), 0.000001); CHECK_EQ(dev[i], doctest::Approx(expected[i]).epsilon(0.0001));
CHECK_LT(std::fabs(dev[14] - 4.001388), 0.000001); }
/** @arg n = 1时 */ /** @arg n = 1时 */
dev = STDEV(ind, 1); dev = STDEV(ind, 1);

View File

@ -36,7 +36,13 @@ TEST_CASE("test_STDP") {
Indicator dev = STDP(ind, 10); Indicator dev = STDP(ind, 10);
CHECK_EQ(dev.name(), "STDP"); CHECK_EQ(dev.name(), "STDP");
CHECK_EQ(dev.size(), 15); CHECK_EQ(dev.size(), 15);
CHECK_UNARY(std::isnan(dev[8]));
vector<price_t> expected{0, 0.5, 0.816497, 1.11803, 1.41421, 1.34371, 1.82946, 1.71391,
2.3094, 2.77308, 2.98161, 2.68514, 3.1, 3.46554, 3.79605};
for (size_t i = 0; i < dev.size(); i++) {
CHECK_EQ(dev[i], doctest::Approx(expected[i]).epsilon(0.0001));
}
CHECK_LT(std::fabs(dev[9] - 2.77308), 0.00001); CHECK_LT(std::fabs(dev[9] - 2.77308), 0.00001);
CHECK_LT(std::fabs(dev[10] - 2.98161), 0.00001); CHECK_LT(std::fabs(dev[10] - 2.98161), 0.00001);
CHECK_LT(std::fabs(dev[11] - 2.68514), 0.00001); CHECK_LT(std::fabs(dev[11] - 2.68514), 0.00001);

View File

@ -39,9 +39,9 @@ TEST_CASE("test_VAR") {
CHECK_EQ(dev.name(), "VAR"); CHECK_EQ(dev.name(), "VAR");
CHECK_EQ(dev.size(), 15); CHECK_EQ(dev.size(), 15);
vector<price_t> expected{0., 0.55, 1., 1.666667, 2.5, 2.16667, 3.90476, 3.35714, vector<price_t> expected{0., 0.5, 1., 1.666667, 2.5, 2.16667, 3.90476, 3.35714,
6., 8.54444, 9.87778, 8.01111, 10.6778, 13.3444, 16.0111}; 6., 8.54444, 9.87778, 8.01111, 10.6778, 13.3444, 16.0111};
for (size_t i = 9; i < dev.size(); i++) { for (size_t i = 0; i < dev.size(); i++) {
CHECK_EQ(dev[i], doctest::Approx(expected[i]).epsilon(0.001)); CHECK_EQ(dev[i], doctest::Approx(expected[i]).epsilon(0.001));
} }