mirror of
https://gitee.com/fasiondog/hikyuu.git
synced 2024-12-03 12:27:48 +08:00
SAFTYLOSS 支持动态参数
This commit is contained in:
parent
e115dc98e0
commit
9290a84571
@ -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
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -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() {
|
||||
计算说明:在回溯周期内(一般为10到20天),将所有向下穿越的长度相加除以向下穿越的次数,得到噪音均值(即回溯期内所有最低价低于前一日最低价的长度除以次数),并用今日最低价减去(前日噪音均值乘以一个倍数)得到该止损线。为了抵消波动并且保证止损线的上移,在上述结果的基础上再取起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);
|
||||
|
Loading…
Reference in New Issue
Block a user