spearman(continue)

This commit is contained in:
fasiondog 2024-03-03 18:03:50 +08:00
parent 8cbb5ac918
commit 00a2dfb37c
2 changed files with 204 additions and 13 deletions

View File

@ -1568,7 +1568,7 @@ static void spearmanLevel(const IndicatorImp::value_t *data, IndicatorImp::value
std::sort(
data_index.begin(), data_index.end(),
std::bind(
std::greater<IndicatorImp::value_t>(),
std::less<IndicatorImp::value_t>(),
std::bind(&std::pair<IndicatorImp::value_t, size_t>::first, std::placeholders::_1),
std::bind(&std::pair<IndicatorImp::value_t, size_t>::first, std::placeholders::_2)));
@ -1620,8 +1620,11 @@ void IndicatorImp::execute_spearman() {
return;
}
discard++;
setDiscard(discard);
size_t startPos = discard;
size_t first_end = startPos + n >= total ? total : startPos + n;
size_t first_end = startPos + n - 1 >= total ? total : startPos + n - 1;
auto levela = std::make_unique<value_t[]>(n);
auto levelb = std::make_unique<value_t[]>(n);
@ -1636,8 +1639,8 @@ void IndicatorImp::execute_spearman() {
size_t n1 = 2;
auto const *a = maxdata + startPos + 1 - n1;
auto const *b = mindata + startPos + startPos + 2 - diff - n1;
for (size_t i = startPos + 1; i < first_end; i++) {
auto const *b = mindata + startPos + 1 - diff - n1;
for (size_t i = startPos; i < first_end; i++) {
spearmanLevel(a, ptra, n1);
spearmanLevel(b, ptrb, n1);
value_t sum = 0.0;
@ -1645,16 +1648,12 @@ void IndicatorImp::execute_spearman() {
sum += std::pow(ptra[j] - ptrb[j], 2);
}
dst[i] = 1 - 6.0 * sum / (std::pow(value_t(n1), 3) - n1);
a++;
b++;
n1++;
}
// auto const *a = maxdata + discard - n;
// auto const *b = mindata + discard + discard - diff - n;
for (size_t i = discard; i < total; ++i) {
// auto *ptra = levela.get();
// auto *ptrb = levelb.get();
a++;
b++;
for (size_t i = first_end; i < total; ++i) {
spearmanLevel(a, ptra, n);
spearmanLevel(b, ptrb, n);
value_t sum = 0.0;
@ -1666,8 +1665,6 @@ void IndicatorImp::execute_spearman() {
b++;
}
}
setDiscard(discard + 2);
}
void IndicatorImp::_dyn_calculate(const Indicator &ind) {

View File

@ -0,0 +1,194 @@
/*
* test_COS.cpp
*
* Copyright (c) 2019 hikyuu.org
*
* Created on: 2019-5-1
* Author: fasiondog
*/
#include "../test_config.h"
#include <fstream>
#include <hikyuu/StockManager.h>
#include <hikyuu/indicator/crt/KDATA.h>
#include <hikyuu/indicator/crt/PRICELIST.h>
using namespace hku;
/**
* @defgroup test_indicator_COS test_indicator_CORR
* @ingroup test_hikyuu_indicator_suite
* @{
*/
static void spearmanLevel(const IndicatorImp::value_t *data, IndicatorImp::value_t *level,
size_t total) {
std::vector<std::pair<IndicatorImp::value_t, size_t>> data_index(total);
for (size_t i = 0; i < total; i++) {
data_index[i].first = data[i];
data_index[i].second = i;
}
std::sort(
data_index.begin(), data_index.end(),
std::bind(
std::less<IndicatorImp::value_t>(),
std::bind(&std::pair<IndicatorImp::value_t, size_t>::first, std::placeholders::_1),
std::bind(&std::pair<IndicatorImp::value_t, size_t>::first, std::placeholders::_2)));
size_t i = 0;
while (i < total) {
size_t count = 1;
IndicatorImp::value_t score = i + 1.0;
for (size_t j = i + 1; j < total; j++) {
if (data_index[i].first != data_index[j].first) {
break;
}
count++;
score += j + 1;
}
score = score / count;
for (size_t j = 0; j < count; j++) {
level[data_index[i + j].second] = score;
}
i += count;
}
}
/** @par 检测点 */
TEST_CASE("test_spearmanLevel") {
std::vector<IndicatorImp::value_t> a{3., 8., 4., 7., 2.};
size_t totala = a.size();
auto levela = std::make_unique<IndicatorImp::value_t[]>(totala);
auto *ptra = levela.get();
spearmanLevel(a.data(), levela.get(), totala);
std::vector<IndicatorImp::value_t> expecta = {2., 5., 3., 4., 1.};
for (size_t i = 0; i < totala; i++) {
CHECK_EQ(ptra[i], doctest::Approx(expecta[i]));
}
std::vector<IndicatorImp::value_t> b{5., 10., 8., 10., 6.};
size_t totalb = b.size();
auto levelb = std::make_unique<IndicatorImp::value_t[]>(totalb);
auto *ptrb = levelb.get();
spearmanLevel(b.data(), levelb.get(), totalb);
std::vector<IndicatorImp::value_t> expectb = {1., 4.5, 3., 4.5, 2.};
for (size_t i = 0; i < totalb; i++) {
CHECK_EQ(ptrb[i], doctest::Approx(expectb[i]));
}
}
/** @par 检测点 */
TEST_CASE("test_SPEARMAN") {
Indicator result;
// 空指标
result = SPEARMAN(Indicator(), Indicator(), 10);
CHECK_UNARY(result.empty());
PriceList a{3., 8., 4., 7., 2.};
PriceList b{5., 10., 8., 10., 6.};
Indicator x = PRICELIST(a);
Indicator y = PRICELIST(b);
// 非法参数 n
result = SPEARMAN(x, y, 0);
CHECK_UNARY(result.empty());
result = SPEARMAN(x, y, 1);
CHECK_UNARY(result.empty());
// 正常情况
PriceList expect{Null<price_t>(), 1., 1., 0.95, 0.875};
result = SPEARMAN(x, y, a.size());
CHECK_EQ(result.name(), "SPEARMAN");
CHECK_EQ(result.discard(), 1);
CHECK_EQ(result.size(), a.size());
for (size_t i = result.discard(); i < result.size(); i++) {
CHECK_EQ(result[i], doctest::Approx(expect[i]));
}
result = SPEARMAN(x, y, 4);
CHECK_EQ(result.name(), "SPEARMAN");
CHECK_EQ(result.discard(), 1);
CHECK_EQ(result.size(), a.size());
}
//-----------------------------------------------------------------------------
// benchmark
//-----------------------------------------------------------------------------
#if ENABLE_BENCHMARK_TEST
TEST_CASE("test_SPEARMAN_benchmark") {
// Stock stock = getStock("sh000001");
// KData kdata = stock.getKData(KQuery(0));
// Indicator c = kdata.close();
// int cycle = 1000; // 测试循环次数
// {
// BENCHMARK_TIME_MSG(test_SPEARMAN_benchmark, cycle, fmt::format("data len: {}",
// c.size())); SPEND_TIME_CONTROL(false); for (int i = 0; i < cycle; i++) {
// Indicator ind = ABS();
// Indicator result = ind(c);
// }
// }
}
#endif
//-----------------------------------------------------------------------------
// test export
//-----------------------------------------------------------------------------
#if HKU_SUPPORT_SERIALIZATION
/** @par 检测点 */
TEST_CASE("test_CORR_export") {
StockManager &sm = StockManager::instance();
string filename(sm.tmpdir());
filename += "/COS.xml";
Stock stock = sm.getStock("sh000001");
KData kdata = stock.getKData(KQuery(-20));
Indicator x1 = CORR(CLOSE(kdata), OPEN(kdata), 10);
{
std::ofstream ofs(filename);
boost::archive::xml_oarchive oa(ofs);
oa << BOOST_SERIALIZATION_NVP(x1);
}
Indicator x2;
{
std::ifstream ifs(filename);
boost::archive::xml_iarchive ia(ifs);
ia >> BOOST_SERIALIZATION_NVP(x2);
}
CHECK_EQ(x2.name(), "CORR");
CHECK_EQ(x1.size(), x2.size());
CHECK_EQ(x1.discard(), x2.discard());
CHECK_EQ(x1.getResultNumber(), x2.getResultNumber());
for (size_t i = x1.discard(); i < x1.size(); ++i) {
if (std::isnan(x1[i])) {
CHECK_UNARY(std::isnan(x2[i]));
} else {
CHECK_EQ(x1[i], doctest::Approx(x2[i]));
}
}
Indicator x11 = x1.getResult(1);
Indicator x21 = x2.getResult(1);
CHECK_EQ(x11.size(), x21.size());
CHECK_EQ(x11.discard(), x21.discard());
CHECK_EQ(x11.getResultNumber(), x21.getResultNumber());
for (size_t i = x11.discard(); i < x21.size(); ++i) {
if (std::isnan(x11[i])) {
CHECK_UNARY(std::isnan(x21[i]));
} else {
CHECK_EQ(x11[i], doctest::Approx(x21[i]));
}
}
}
#endif /* #if HKU_SUPPORT_SERIALIZATION */
/** @} */