add SE_Multi_factor, SG_Allways_buy

This commit is contained in:
fasiondog 2024-03-30 19:02:35 +08:00
parent 32af840049
commit ddebb76217
29 changed files with 292 additions and 24 deletions

View File

@ -19,6 +19,6 @@
#include "system/build_in.h"
#include "allocatefunds/build_in.h"
#include "selector/build_in.h"
#include "factor/build_in.h"
#include "multifactor/build_in.h"
#endif /* ALL_TRADE_SYS_H_ */

View File

@ -123,6 +123,14 @@ void MultiFactorBase::paramChanged() {
m_calculated = false;
}
void MultiFactorBase::reset() {
std::lock_guard<std::mutex> lock(m_mutex);
_reset();
// 仅重置 m_calculated其他缓存不重置否则线程不安全
m_calculated = false;
}
MultiFactorPtr MultiFactorBase::clone() {
std::lock_guard<std::mutex> lock(m_mutex);
MultiFactorPtr p;
@ -142,23 +150,23 @@ MultiFactorPtr MultiFactorBase::clone() {
p->m_stks = m_stks;
p->m_ref_stk = m_ref_stk;
p->m_query = m_query;
p->m_stk_map = m_stk_map;
p->m_all_factors = m_all_factors;
p->m_date_index = m_date_index;
p->m_stk_factor_by_date = m_stk_factor_by_date;
p->m_ref_dates = m_ref_dates;
p->m_ic = m_ic.clone();
p->m_calculated = m_calculated;
p->m_inds.reserve(m_inds.size());
for (const auto& ind : m_inds) {
p->m_inds.emplace_back(ind.clone());
}
p->m_all_factors.reserve(m_all_factors.size());
for (const auto& ind : m_all_factors) {
p->m_all_factors.emplace_back(ind.clone());
}
p->m_calculated = false;
// 强制重算,不克隆以下缓存,避免非线程安全
// p->m_stk_map = m_stk_map;
// p->m_date_index = m_date_index;
// p->m_stk_factor_by_date = m_stk_factor_by_date;
// p->m_ic = m_ic.clone();
// p->m_all_factors.reserve(m_all_factors.size());
// for (const auto& ind : m_all_factors) {
// p->m_all_factors.emplace_back(ind.clone());
// }
return p;
}
@ -181,6 +189,22 @@ const ScoreRecordList& MultiFactorBase::getScore(const Datetime& d) {
return m_stk_factor_by_date[iter->second];
}
ScoreRecordList MultiFactorBase::getScores(const Datetime& date, size_t start, size_t end) {
ScoreRecordList ret;
HKU_IF_RETURN(start >= end, ret);
const auto& cross = getScore(date);
if (end == Null<size_t>() || end > cross.size()) {
end = cross.size();
}
for (size_t i = start; i < end; i++) {
ret.emplace_back(cross[i]);
}
return ret;
}
ScoreRecordList MultiFactorBase::getScores(const Datetime& date, size_t start, size_t end,
std::function<bool(const ScoreRecord&)>&& filter) {
ScoreRecordList ret;

View File

@ -82,6 +82,8 @@ public:
/** 获取指定日期截面的所有因子值,已经降序排列 */
const ScoreRecordList& getScore(const Datetime&);
ScoreRecordList getScores(const Datetime& date, size_t start, size_t end = Null<size_t>());
/**
* [start, end] , filer进行过滤
* @param date
@ -89,13 +91,11 @@ public:
* @param end ()
* @param filter
*/
ScoreRecordList getScores(
const Datetime& date, size_t start, size_t end = Null<size_t>(),
std::function<bool(const ScoreRecord&)>&& filter = std::function<bool(const ScoreRecord&)>());
ScoreRecordList getScores(const Datetime& date, size_t start, size_t end,
std::function<bool(const ScoreRecord&)>&& filter);
ScoreRecordList getScores(const Datetime& date, size_t start, size_t end = Null<size_t>(),
std::function<bool(const Datetime&, const ScoreRecord&)>&& filter =
std::function<bool(const Datetime&, const ScoreRecord&)>());
ScoreRecordList getScores(const Datetime& date, size_t start, size_t end,
std::function<bool(const Datetime&, const ScoreRecord&)>&& filter);
/** 获取所有截面数据,已按降序排列 */
const vector<ScoreRecordList>& getAllScores();
@ -123,9 +123,12 @@ public:
*/
vector<IndicatorList> getAllSrcFactors();
void reset();
typedef std::shared_ptr<MultiFactorBase> MultiFactorPtr;
MultiFactorPtr clone();
virtual void _reset() {}
virtual MultiFactorPtr _clone() = 0;
virtual IndicatorList _calculate(const vector<IndicatorList>&) = 0;

View File

@ -10,6 +10,7 @@
#define TRADE_SYS_SELECTOR_BUILD_IN_H_
#include "crt/SE_Fixed.h"
#include "crt/SE_Multi_factor.h"
#include "crt/SE_Signal.h"
#endif /* TRADE_SYS_SELECTOR_BUILD_IN_H_ */

View File

@ -0,0 +1,22 @@
/*
* Copyright (c) 2024 hikyuu.org
*
* Created on: 2024-03-30
* Author: fasiondog
*/
#pragma once
#include "hikyuu/trade_sys/multifactor/MultiFactorBase.h"
#include "../SelectorBase.h"
namespace hku {
SelectorPtr HKU_API SE_Multi_factor(const MFPtr& mf, int topn = 10);
SelectorPtr HKU_API SE_Multi_factor(const IndicatorList& src_inds, const StockList& stks,
const KQuery& query, int topn = 10, int ic_n = 5,
int ic_rolling_n = 120, const Stock& ref_stk = Stock(),
const string& mode = "MF_ICIRWeight");
} // namespace hku

View File

@ -0,0 +1,93 @@
/*
* Copyright (c) 2024 hikyuu.org
*
* Created on: 2024-03-30
* Author: fasiondog
*/
#include "hikyuu/trade_sys/multifactor/build_in.h"
#include "MultiFactorSelector.h"
#if HKU_SUPPORT_SERIALIZATION
BOOST_CLASS_EXPORT(hku::MultiFactorSelector)
#endif
namespace hku {
MultiFactorSelector::MultiFactorSelector() : SelectorBase("SE_Multi_factor") {
setParam<int>("topn", 10);
}
MultiFactorSelector::MultiFactorSelector(const MFPtr& mf, int topn)
: SelectorBase("SE_Multi_factor"), m_mf(mf) {
HKU_CHECK(mf, "mf is null!");
setParam<int>("topn", topn);
checkParam("topn");
}
MultiFactorSelector::~MultiFactorSelector() {}
void MultiFactorSelector::_checkParam(const string& name) const {
if ("topn" == name) {
int topn = getParam<int>("topn");
HKU_ASSERT(topn > 0);
}
}
void MultiFactorSelector::_reset() {
if (m_mf) {
m_mf->reset();
}
m_stk_sys_dict.clear();
}
SelectorPtr MultiFactorSelector::_clone() {
MultiFactorSelector* p = new MultiFactorSelector();
p->m_mf = m_mf->clone();
p->m_stk_sys_dict = m_stk_sys_dict;
return SelectorPtr(p);
}
bool MultiFactorSelector::isMatchAF(const AFPtr& af) {
return true;
}
SystemWeightList MultiFactorSelector::getSelected(Datetime date) {
SystemWeightList ret;
auto scores = m_mf->getScores(date, 0, getParam<int>("topn"),
[](const ScoreRecord& sc) { return !std::isnan(sc.value); });
for (const auto& sc : scores) {
ret.emplace_back(m_stk_sys_dict[sc.stock], sc.value);
}
return ret;
}
void MultiFactorSelector::_calculate() {
for (const auto& sys : m_real_sys_list) {
m_stk_sys_dict[sys->getStock()] = sys;
}
}
SelectorPtr HKU_API SE_Multi_factor(const MFPtr& mf, int topn) {
return make_shared<MultiFactorSelector>(mf, topn);
}
SelectorPtr HKU_API SE_Multi_factor(const IndicatorList& src_inds, const StockList& stks,
const KQuery& query, int topn, int ic_n, int ic_rolling_n,
const Stock& ref_stk, const string& mode) {
Stock n_ref_stk = ref_stk.isNull() ? getStock("sh000300") : ref_stk;
MFPtr mf;
if ("MF_ICIRWeight" == mode) {
mf = MF_ICIRWeight(src_inds, stks, query, n_ref_stk, ic_n, ic_rolling_n);
} else if ("MF_ICWeight" == mode) {
mf = MF_ICWeight(src_inds, stks, query, n_ref_stk, ic_n, ic_rolling_n);
} else if ("MF_EqualWeight" == mode) {
mf = MF_EqualWeight(src_inds, stks, query, n_ref_stk, ic_n);
} else {
HKU_THROW("Invalid mode: {}", mode);
}
return make_shared<MultiFactorSelector>(mf, topn);
}
} // namespace hku

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2024 hikyuu.org
*
* Created on: 2024-03-30
* Author: fasiondog
*/
#pragma once
#include "hikyuu/trade_sys/multifactor/MultiFactorBase.h"
#include "../SelectorBase.h"
namespace hku {
class MultiFactorSelector : public SelectorBase {
public:
MultiFactorSelector();
MultiFactorSelector(const MFPtr& mf, int topn);
virtual ~MultiFactorSelector();
virtual void _checkParam(const string& name) const override;
virtual void _reset() override;
virtual SelectorPtr _clone() override;
virtual SystemWeightList getSelected(Datetime date) override;
virtual bool isMatchAF(const AFPtr& af) override;
virtual void _calculate() override;
private:
MFPtr m_mf;
unordered_map<Stock, SYSPtr> m_stk_sys_dict;
//============================================
// 序列化支持
//============================================
#if HKU_SUPPORT_SERIALIZATION
friend class boost::serialization::access;
template <class Archive>
void serialize(Archive& ar, const unsigned int version) {
ar& BOOST_SERIALIZATION_BASE_OBJECT_NVP(SelectorBase);
ar& BOOST_SERIALIZATION_NVP(m_mf);
}
#endif
};
} // namespace hku

View File

@ -82,7 +82,7 @@ public:
*
* @return (KData)
*/
KData getTO() const;
const KData& getTO() const;
/** 复位操作 */
void reset();
@ -198,7 +198,7 @@ typedef shared_ptr<SignalBase> SGPtr;
HKU_API std::ostream& operator<<(std::ostream&, const SignalBase&);
HKU_API std::ostream& operator<<(std::ostream&, const SignalPtr&);
inline KData SignalBase::getTO() const {
inline const KData& SignalBase::getTO() const {
return m_kdata;
}

View File

@ -9,6 +9,7 @@
#ifndef SIGNAL_BUILD_IN_H_
#define SIGNAL_BUILD_IN_H_
#include "crt/SG_Allways_buy.h"
#include "crt/SG_Cross.h"
#include "crt/SG_CrossGold.h"
#include "crt/SG_Flex.h"

View File

@ -0,0 +1,15 @@
/*
* Copyright (c) 2024 hikyuu.org
*
* Created on: 2024-03-30
* Author: fasiondog
*/
#pragma once
#include "../SignalBase.h"
namespace hku {
SignalPtr HKU_API SG_Allways_buy();
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2024 hikyuu.org
*
* Created on: 2024-03-30
* Author: fasiondog
*/
#include "AllwaysBuySignal.h"
#if HKU_SUPPORT_SERIALIZATION
BOOST_CLASS_EXPORT(hku::AllwaysBuySignal)
#endif
namespace hku {
AllwaysBuySignal::AllwaysBuySignal() : SignalBase("SG_Allways_buy") {
setParam<bool>("alternate", false);
}
void AllwaysBuySignal::_checkParam(const string& name) const {
if ("alternate" == name) {
bool alternate = getParam<bool>(name);
HKU_CHECK(!alternate, "param alternate must be false!");
}
}
void AllwaysBuySignal::_calculate() {
const auto& kdata = getTO();
for (auto iter = kdata.cbegin(); iter != kdata.cend(); ++iter) {
_addBuySignal(iter->datetime);
}
}
SignalPtr HKU_API SG_Allways_buy() {
return SignalPtr(new AllwaysBuySignal);
}
} // namespace hku

View File

@ -0,0 +1,25 @@
/*
* Copyright (c) 2024 hikyuu.org
*
* Created on: 2024-03-30
* Author: fasiondog
*/
#pragma once
#include "../SignalBase.h"
namespace hku {
class AllwaysBuySignal : public SignalBase {
SIGNAL_IMP(AllwaysBuySignal)
SIGNAL_NO_PRIVATE_MEMBER_SERIALIZATION
public:
AllwaysBuySignal();
virtual ~AllwaysBuySignal() = default;
virtual void _checkParam(const string& name) const override;
};
} // namespace hku

View File

@ -14,7 +14,7 @@
#include <hikyuu/indicator/crt/IC.h>
#include <hikyuu/indicator/crt/ROCR.h>
#include <hikyuu/indicator/crt/KDATA.h>
#include <hikyuu/trade_sys/factor/crt/MF_EqualWeight.h>
#include <hikyuu/trade_sys/multifactor/crt/MF_EqualWeight.h>
using namespace hku;

View File

@ -17,7 +17,7 @@
#include <hikyuu/indicator/crt/ROCR.h>
#include <hikyuu/indicator/crt/KDATA.h>
#include <hikyuu/indicator/crt/STDEV.h>
#include <hikyuu/trade_sys/factor/crt/MF_ICIRWeight.h>
#include <hikyuu/trade_sys/multifactor/crt/MF_ICIRWeight.h>
using namespace hku;

View File

@ -16,7 +16,7 @@
#include <hikyuu/indicator/crt/ROCR.h>
#include <hikyuu/indicator/crt/KDATA.h>
#include <hikyuu/indicator/crt/PRICELIST.h>
#include <hikyuu/trade_sys/factor/crt/MF_ICWeight.h>
#include <hikyuu/trade_sys/multifactor/crt/MF_ICWeight.h>
using namespace hku;

View File

@ -5,7 +5,7 @@
* Author: fasiondog
*/
#include <hikyuu/trade_sys/factor/build_in.h>
#include <hikyuu/trade_sys/multifactor/build_in.h>
#include "../pybind_utils.h"
namespace py = pybind11;

View File

@ -51,7 +51,8 @@ void export_Signal(py::module& m) {
.def_property("name", py::overload_cast<>(&SignalBase::name, py::const_),
py::overload_cast<const string&>(&SignalBase::name),
py::return_value_policy::copy, "名称")
.def_property("to", &SignalBase::getTO, &SignalBase::setTO, "设置或获取交易对象")
.def_property("to", &SignalBase::getTO, &SignalBase::setTO, py::return_value_policy::copy,
"设置或获取交易对象")
.def("get_param", &SignalBase::getParam<boost::any>, R"(get_param(self, name)