hikyuu2/hikyuu_pywrap/trade_sys/_MultiFactor.cpp

266 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) 2024 hikyuu.org
*
* Created on: 2024-03-13
* Author: fasiondog
*/
#include <hikyuu/trade_sys/multifactor/build_in.h>
#include "../pybind_utils.h"
namespace py = pybind11;
using namespace hku;
class PyMultiFactor : public MultiFactorBase {
PY_CLONE(PyMultiFactor, MultiFactorBase)
public:
using MultiFactorBase::MultiFactorBase;
PyMultiFactor(const MultiFactorBase& base) : MultiFactorBase(base) {}
IndicatorList _calculate(const vector<IndicatorList>& all_stk_inds) override {
// PYBIND11_OVERLOAD_PURE_NAME(IndicatorList, MultiFactorBase, "_calculate", _calculate,
// all_stk_inds);
auto self = py::cast(this);
auto func = self.attr("_calculate")();
auto py_all_stk_inds = vector_to_python_list<IndicatorList>(all_stk_inds);
auto py_ret = func(py_all_stk_inds);
return py_ret.cast<IndicatorList>();
}
};
void export_MultiFactor(py::module& m) {
py::class_<ScoreRecord>(m, "ScoreRecord", "")
.def(py::init<>())
.def(py::init<const Stock&, ScoreRecord::value_t>())
.def("__str__", to_py_str<ScoreRecord>)
.def("__repr__", to_py_str<ScoreRecord>)
.def_readwrite("stock", &ScoreRecord::stock, "证券")
.def_readwrite("value", &ScoreRecord::value, "分值");
py::class_<MultiFactorBase, MultiFactorPtr, PyMultiFactor>(m, "MultiFactorBase",
py::dynamic_attr(),
R"(市场环境判定策略基类
- _calculate :
- _clone :
- _reset : )")
.def(py::init<>())
.def(py::init<const MultiFactorBase&>())
.def("__str__", to_py_str<MultiFactorBase>)
.def("__repr__", to_py_str<MultiFactorBase>)
.def_property("name", py::overload_cast<>(&MultiFactorBase::name, py::const_),
py::overload_cast<const string&>(&MultiFactorBase::name),
py::return_value_policy::copy, "名称")
.def_property("query", &MultiFactorBase::getQuery, &MultiFactorBase::setQuery,
py::return_value_policy::copy, R"(查询条件)")
.def("get_param", &MultiFactorBase::getParam<boost::any>, R"(get_param(self, name)
:param str name:
:return:
:raises out_of_range: )")
.def("set_param", &MultiFactorBase::setParam<boost::any>, R"(set_param(self, name, value)
:param str name:
:param value:
:raises logic_error: Unsupported type! )")
.def("have_param", &MultiFactorBase::haveParam, "是否存在指定参数")
.def("get_ref_stock", &MultiFactorBase::getRefStock, py::return_value_policy::copy,
"获取参考证券")
.def("set_ref_stock", &MultiFactorBase::setRefStock, R"(set_ref_stock(self, stk)
:param Stock stk: )")
.def("get_datetime_list", &MultiFactorBase::getDatetimeList, py::return_value_policy::copy,
"获取参考日期列表(由参考证券通过查询条件获得)")
.def("get_stock_list", &MultiFactorBase::getStockList, py::return_value_policy::copy,
"获取创建时指定的证券列表")
.def("set_stock_list", &MultiFactorBase::setStockList, R"(set_stock_list(self, stks)
:param list stks: )")
.def("get_stock_list_num", &MultiFactorBase::getStockListNumber,
"获取创建时指定的证券列表中证券数量")
.def("get_ref_indicators", &MultiFactorBase::getRefIndicators, py::return_value_policy::copy,
"获取创建时输入的原始因子列表")
.def("set_ref_indicators", &MultiFactorBase::setRefIndicators,
R"(set_ref_indicators(self, inds)
:param list inds: )")
.def("get_factor", &MultiFactorBase::getFactor, py::return_value_policy::copy,
py::arg("stock"), R"(get_factor(self, stock)
:param Stock stock: )")
.def("get_all_factors", &MultiFactorBase::getAllFactors, py::return_value_policy::copy,
R"(get_all_factors(self)
:return: [factor1, factor2, ...] )")
.def("get_ic", &MultiFactorBase::getIC, py::arg("ndays") = 0, R"(get_ic(self[, ndays=0])
IC,
ndays 使 IC/ICIR ic_n
使 ic_n
ndays 0, 使 ic_n IC
:rtype: Indicator)")
.def("get_icir", &MultiFactorBase::getICIR, py::arg("ir_n"), py::arg("ic_n") = 0,
R"(get_icir(self, ir_n[, ic_n=0])
ICIR
:param int ir_n: IR n
:param int ic_n: IC n ( get_ic ndays))")
.def("clone", &MultiFactorBase::clone, "克隆操作")
.def(
"get_scores",
[](MultiFactorBase& self, const Datetime& date, size_t start, py::object end,
py::object filter) {
size_t cend = end.is_none() ? Null<size_t>() : end.cast<size_t>();
if (filter.is_none()) {
return self.getScores(date, start, cend, std::function<bool(const ScoreRecord&)>());
}
HKU_CHECK(py::hasattr(filter, "__call__"), "filter not callable!");
py::object filter_func = filter.attr("__call__");
ScoreRecord sc;
try {
filter_func(sc);
return self.getScores(date, start, cend, [&](const ScoreRecord& score_) {
return filter_func(score_).cast<bool>();
});
} catch (...) {
filter_func(date, sc);
return self.getScores(date, start, cend,
[&](const Datetime& date_, const ScoreRecord& score_) {
return filter_func(date_, score_).cast<bool>();
});
}
},
py::arg("date"), py::arg("start") = 0, py::arg("end") = py::none(),
py::arg("filter") = py::none(),
R"(get_score(self, date[, start=0, end=Null])
:param Datetime date:
:param int start:
:param int end: ()
:param function func: (ScoreRecord)->bool (Datetime, ScoreRecord)->bool
:rtype: ScoreRecordList)")
.def("get_all_scores", &MultiFactorBase::getAllScores, py::return_value_policy::copy,
R"(get_all_scores(self)
:return: ScoreRecordList)")
.def("get_all_src_factors", &MultiFactorBase::getAllSrcFactors)
DEF_PICKLE(MultiFactorPtr);
m.def("MF_EqualWeight", py::overload_cast<>(MF_EqualWeight));
m.def(
"MF_EqualWeight",
[](const py::sequence& inds, const py::sequence& stks, const KQuery& query,
const py::object& ref_stk, int ic_n) {
IndicatorList c_inds = python_list_to_vector<Indicator>(inds);
StockList c_stks = python_list_to_vector<Stock>(stks);
return MF_EqualWeight(c_inds, c_stks, query,
ref_stk.is_none() ? getStock("sh000300") : ref_stk.cast<Stock>(),
ic_n);
},
py::arg("inds"), py::arg("stks"), py::arg("query"), py::arg("ref_stk") = py::none(),
py::arg("ic_n") = 5,
R"(MF_EqualWeight(inds, stks, query, ref_stk[, ic_n=5])
:param sequense(Indicator) inds:
:param sequense(stock) stks:
:param Query query:
:param Stock ref_stk: ( sh000300 300)
:param int ic_n: IC N
:rtype: MultiFactor)");
m.def("MF_ICWeight", py::overload_cast<>(MF_ICWeight));
m.def(
"MF_ICWeight",
[](const py::sequence& inds, const py::sequence& stks, const KQuery& query,
const py::object& ref_stk, int ic_n, int ic_rolling_n) {
IndicatorList c_inds = python_list_to_vector<Indicator>(inds);
StockList c_stks = python_list_to_vector<Stock>(stks);
return MF_ICWeight(c_inds, c_stks, query,
ref_stk.is_none() ? getStock("sh000300") : ref_stk.cast<Stock>(), ic_n,
ic_rolling_n);
},
py::arg("inds"), py::arg("stks"), py::arg("query"), py::arg("ref_stk") = py::none(),
py::arg("ic_n") = 5, py::arg("ic_rolling_n") = 120,
R"(MF_EqualWeight(inds, stks, query, ref_stk[, ic_n=5, ic_rolling_n=120])
IC权重合成因子
:param sequense(Indicator) inds:
:param sequense(stock) stks:
:param Query query:
:param Stock ref_stk: ( sh000300 300)
:param int ic_n: IC N
:param int ic_rolling_n: IC
:rtype: MultiFactor)");
m.def("MF_ICIRWeight", py::overload_cast<>(MF_ICIRWeight));
m.def(
"MF_ICIRWeight",
[](const py::sequence& inds, const py::sequence& stks, const KQuery& query,
const py::object& ref_stk, int ic_n, int ic_rolling_n) {
IndicatorList c_inds = python_list_to_vector<Indicator>(inds);
StockList c_stks = python_list_to_vector<Stock>(stks);
return MF_ICIRWeight(c_inds, c_stks, query,
ref_stk.is_none() ? getStock("sh000300") : ref_stk.cast<Stock>(),
ic_n, ic_rolling_n);
},
py::arg("inds"), py::arg("stks"), py::arg("query"), py::arg("ref_stk") = py::none(),
py::arg("ic_n") = 5, py::arg("ic_rolling_n") = 120,
R"(MF_EqualWeight(inds, stks, query, ref_stk[, ic_n=5, ic_rolling_n=120])
ICIR权重合成因子
:param sequense(Indicator) inds:
:param sequense(stock) stks:
:param Query query:
:param Stock ref_stk: ( sh000300 300)
:param int ic_n: IC N
:param int ic_rolling_n: IC
:rtype: MultiFactor)");
}