SAFTYLOSS 支持动态参数

This commit is contained in:
fasiondog 2022-03-05 13:56:01 +08:00
parent e115dc98e0
commit 9290a84571
5 changed files with 171 additions and 12 deletions

View File

@ -24,13 +24,14 @@ namespace hku {
* N日3
* </pre>
* @note
* @param data
* @param n1 10
* @param n2 线n2日内的最高值3
* @param p 2
* @ingroup Indicator
*/
Indicator HKU_API SAFTYLOSS(const Indicator& data, int n1 = 10, int n2 = 3, double p = 2.0);
Indicator HKU_API SAFTYLOSS(int n1 = 10, int n2 = 3, double p = 2.0);
Indicator HKU_API SAFTYLOSS(const IndParam& n1, const IndParam& n2, double p = 2.0);
Indicator HKU_API SAFTYLOSS(const IndParam& n1, const IndParam& n2, const IndParam& p);
/**
*
@ -43,12 +44,35 @@ Indicator HKU_API SAFTYLOSS(const Indicator& data, int n1 = 10, int n2 = 3, doub
* N日3
* </pre>
* @note
* @param data
* @param n1 10
* @param n2 线n2日内的最高值3
* @param p 2
* @ingroup Indicator
*/
Indicator HKU_API SAFTYLOSS(int n1 = 10, int n2 = 3, double p = 2.0);
inline Indicator SAFTYLOSS(const Indicator& data, int n1 = 10, int n2 = 3, double p = 2.0) {
return SAFTYLOSS(n1, n2, p)(data);
}
inline Indicator SAFTYLOSS(const Indicator& data, const IndParam& n1, const IndParam& n2,
double p = 2.0) {
return SAFTYLOSS(n1, n2, p)(data);
}
inline Indicator SAFTYLOSS(const Indicator& data, const IndParam& n1, const IndParam& n2,
const IndParam& p) {
return SAFTYLOSS(n1, n2, p)(data);
}
inline Indicator SAFTYLOSS(const Indicator& data, const Indicator& n1, const Indicator& n2,
double p = 2.0) {
return SAFTYLOSS(IndParam(n1), IndParam(n2), p)(data);
}
inline Indicator SAFTYLOSS(const Indicator& data, const Indicator& n1, const Indicator& n2,
const Indicator& p) {
return SAFTYLOSS(IndParam(n1), IndParam(n2), IndParam(p))(data);
}
} // namespace hku

View File

@ -5,6 +5,9 @@
* Author: fasiondog
*/
#include "../crt/SLICE.h"
#include "../crt/CVAL.h"
#include "../crt/SAFTYLOSS.h"
#include "ISaftyLoss.h"
#if HKU_SUPPORT_SERIALIZATION
@ -71,6 +74,80 @@ void ISaftyLoss::_calculate(const Indicator& data) {
}
}
void ISaftyLoss::_dyn_one_circle(const Indicator& ind, size_t curPos, int n1, int n2, double p) {
HKU_IF_RETURN(n1 < 2 || n2 < 2, void());
Indicator slice = SLICE(ind, 0, curPos + 1);
Indicator st = SAFTYLOSS(slice, n1, n2, p);
if (st.size() > 0) {
_set(st[st.size() - 1], curPos);
}
}
void ISaftyLoss::_dyn_calculate(const Indicator& ind) {
auto iter = m_ind_params.find("n1");
Indicator n1 =
iter != m_ind_params.end() ? Indicator(iter->second) : CVAL(ind, getParam<int>("n1"));
iter = m_ind_params.find("n2");
Indicator n2 =
iter != m_ind_params.end() ? Indicator(iter->second) : CVAL(ind, getParam<int>("n2"));
iter = m_ind_params.find("p");
Indicator p =
iter != m_ind_params.end() ? Indicator(iter->second) : CVAL(ind, getParam<int>("p"));
HKU_CHECK(n1.size() == ind.size(), "ind_param(n1).size()={}, ind.size()={}!", n1.size(),
ind.size());
HKU_CHECK(n2.size() == ind.size(), "ind_param(n2).size()={}, ind.size()={}!", n2.size(),
ind.size());
HKU_CHECK(p.size() == ind.size(), "ind_param(p).size()={}, ind.size()={}!", p.size(),
ind.size());
m_discard = std::max(ind.discard(), n1.discard());
m_discard = std::max(m_discard, n2.discard());
m_discard = std::max(m_discard, p.discard());
size_t total = ind.size();
HKU_IF_RETURN(0 == total || m_discard >= total, void());
static const size_t minCircleLength = 400;
size_t workerNum = ms_tg->worker_num();
if (total < minCircleLength || workerNum == 1) {
for (size_t i = ind.discard(); i < total; i++) {
_dyn_one_circle(ind, i, n1[i], n2[i], p[i]);
}
_update_discard();
return;
}
size_t circleLength = minCircleLength;
if (minCircleLength * workerNum >= total) {
circleLength = minCircleLength;
} else {
size_t tailCount = total % workerNum;
circleLength = tailCount == 0 ? total / workerNum : total / workerNum + 1;
}
std::vector<std::future<void>> tasks;
for (size_t group = 0; group < workerNum; group++) {
size_t first = circleLength * group;
if (first >= total) {
break;
}
tasks.push_back(ms_tg->submit([=, &ind, &n1, &n2, &p]() {
size_t endPos = first + circleLength;
if (endPos > total) {
endPos = total;
}
for (size_t i = circleLength * group; i < endPos; i++) {
_dyn_one_circle(ind, i, n1[i], n2[i], p[i]);
}
}));
}
for (auto& task : tasks) {
task.get();
}
_update_discard();
}
Indicator HKU_API SAFTYLOSS(int n1, int n2, double p) {
IndicatorImpPtr result = make_shared<ISaftyLoss>();
result->setParam<int>("n1", n1);
@ -79,8 +156,20 @@ Indicator HKU_API SAFTYLOSS(int n1, int n2, double p) {
return Indicator(result);
}
Indicator HKU_API SAFTYLOSS(const Indicator& data, int n1, int n2, double p) {
return SAFTYLOSS(n1, n2, p)(data);
Indicator HKU_API SAFTYLOSS(const IndParam& n1, const IndParam& n2, double p) {
IndicatorImpPtr result = make_shared<ISaftyLoss>();
result->setIndParam("n1", n1);
result->setIndParam("n2", n2);
result->setParam<double>("p", p);
return Indicator(result);
}
Indicator HKU_API SAFTYLOSS(const IndParam& n1, const IndParam& n2, const IndParam& p) {
IndicatorImpPtr result = make_shared<ISaftyLoss>();
result->setIndParam("n1", n1);
result->setIndParam("n2", n2);
result->setIndParam("p", p);
return Indicator(result);
}
} /* namespace hku */

View File

@ -32,6 +32,11 @@ class ISaftyLoss : public hku::IndicatorImp {
public:
ISaftyLoss();
virtual ~ISaftyLoss();
virtual void _dyn_calculate(const Indicator&) override;
private:
void _dyn_one_circle(const Indicator& ind, size_t curPos, int n1, int n2, double p);
};
} /* namespace hku */

View File

@ -9,6 +9,7 @@
#include <fstream>
#include <hikyuu/StockManager.h>
#include <hikyuu/indicator/crt/SAFTYLOSS.h>
#include <hikyuu/indicator/crt/CVAL.h>
#include <hikyuu/indicator/crt/KDATA.h>
using namespace hku;
@ -128,6 +129,32 @@ TEST_CASE("test_SAFTYLOSS") {
}
}
/** @par 检测点 */
TEST_CASE("test_SAFTYLOSS_dyn") {
Stock stock = StockManager::instance().getStock("sh000001");
KData kdata = stock.getKData(KQuery(-50));
// KData kdata = stock.getKData(KQuery(0, Null<size_t>(), KQuery::MIN));
Indicator c = CLOSE(kdata);
Indicator expect = SAFTYLOSS(c, 10, 3, 2.0);
Indicator result = SAFTYLOSS(c, CVAL(c, 10), CVAL(c, 3), CVAL(c, 2.0));
CHECK_EQ(expect.size(), result.size());
for (size_t i = 0; i < result.discard(); i++) {
CHECK_UNARY(std::isnan(result[i]));
}
for (size_t i = result.discard(); i < result.size(); i++) {
CHECK_EQ(expect.get(i, 0), doctest::Approx(result.get(i, 0)));
}
result = SAFTYLOSS(c, IndParam(CVAL(c, 10)), IndParam(CVAL(c, 3)), IndParam(CVAL(c, 2.0)));
CHECK_EQ(expect.size(), result.size());
for (size_t i = 0; i < result.discard(); i++) {
CHECK_UNARY(std::isnan(result[i]));
}
for (size_t i = result.discard(); i < result.size(); i++) {
CHECK_EQ(expect.get(i, 0), doctest::Approx(result.get(i, 0)));
}
}
//-----------------------------------------------------------------------------
// test export
//-----------------------------------------------------------------------------

View File

@ -83,9 +83,17 @@ Indicator (*REF_4)(const Indicator&, const Indicator&) = REF;
Indicator (*REF_5)(const Indicator&, int) = REF;
Indicator (*SAFTYLOSS_1)(int n1, int n2, double p) = SAFTYLOSS;
Indicator (*SAFTYLOSS_2)(const Indicator&, int n1, int n2, double p) = SAFTYLOSS;
// BOOST_PYTHON_FUNCTION_OVERLOADS(SAFTYLOSS_1_overload, SAFTYLOSS, 0, 3);
// BOOST_PYTHON_FUNCTION_OVERLOADS(SAFTYLOSS_2_overload, SAFTYLOSS, 1, 4);
Indicator (*SAFTYLOSS_2)(const IndParam& n1, const IndParam& n2, double p) = SAFTYLOSS;
Indicator (*SAFTYLOSS_3)(const IndParam& n1, const IndParam& n2, const IndParam& p) = SAFTYLOSS;
Indicator (*SAFTYLOSS_4)(const Indicator&, int n1, int n2, double p) = SAFTYLOSS;
Indicator (*SAFTYLOSS_5)(const Indicator&, const IndParam& n1, const IndParam& n2,
double p) = SAFTYLOSS;
Indicator (*SAFTYLOSS_6)(const Indicator&, const IndParam& n1, const IndParam& n2,
const IndParam& p) = SAFTYLOSS;
Indicator (*SAFTYLOSS_7)(const Indicator&, const Indicator& n1, const Indicator& n2,
double p) = SAFTYLOSS;
Indicator (*SAFTYLOSS_8)(const Indicator&, const Indicator& n1, const Indicator& n2,
const Indicator& p) = SAFTYLOSS;
Indicator (*STDEV_1)(int) = STDEV;
Indicator (*STDEV_2)(const IndParam&) = STDEV;
@ -576,7 +584,13 @@ void export_Indicator_build_in() {
:rtype: Indicator)");
def("SAFTYLOSS", SAFTYLOSS_1, (arg("n1") = 10, arg("n2") = 3, arg("p") = 2.0));
def("SAFTYLOSS", SAFTYLOSS_2, (arg("data"), arg("n1") = 10, arg("n2") = 3, arg("p") = 2.0),
def("SAFTYLOSS", SAFTYLOSS_2, (arg("n1"), arg("n2"), arg("p") = 2.0));
def("SAFTYLOSS", SAFTYLOSS_3, (arg("n1"), arg("n2"), arg("p")));
def("SAFTYLOSS", SAFTYLOSS_4, (arg("data"), arg("n1") = 10, arg("n2") = 3, arg("p") = 2.0));
def("SAFTYLOSS", SAFTYLOSS_5, (arg("data"), arg("n1"), arg("n2"), arg("p") = 2.0));
def("SAFTYLOSS", SAFTYLOSS_6, (arg("data"), arg("n1"), arg("n2"), arg("p")));
def("SAFTYLOSS", SAFTYLOSS_7, (arg("data"), arg("n1"), arg("n2"), arg("p") = 2.0));
def("SAFTYLOSS", SAFTYLOSS_8, (arg("data"), arg("n1"), arg("n2"), arg("p")),
R"(SAFTYLOSS([data, n1=10, n2=3, p=2.0])
线 [BOOK2]_
@ -584,9 +598,9 @@ void export_Indicator_build_in() {
1020穿穿线线N日3
:param Indicator data:
:param int n1:
:param int n2: 线n2日内的最高值
:param float p:
:param int|Indicator|IndParam n1:
:param int|Indicator|IndParam n2: 线n2日内的最高值
:param float|Indicator|IndParam p:
:rtype: Indicator)");
def("DIFF", DIFF_1);