mirror of
https://gitee.com/fasiondog/hikyuu.git
synced 2024-12-02 03:48:19 +08:00
Merge pull request #212 from fasiondog/feature/factor
调整 MF get_score 接口; SE/PF/AF 微调; update get_part add *args
This commit is contained in:
commit
7d482d90c1
@ -545,13 +545,14 @@ def remove_hub(name):
|
||||
HubManager().remove_hub(name)
|
||||
|
||||
|
||||
def get_part(name, **kwargs):
|
||||
def get_part(name, *args, **kwargs):
|
||||
"""获取指定策略部件
|
||||
|
||||
:param str name: 策略部件名称
|
||||
:param args: 其他部件相关参数
|
||||
:param kwargs: 其他部件相关参数
|
||||
"""
|
||||
return HubManager().get_part(name, **kwargs)
|
||||
return HubManager().get_part(name, *args, **kwargs)
|
||||
|
||||
|
||||
def get_hub_path(name):
|
||||
|
@ -2,7 +2,8 @@
|
||||
|
||||
from hikyuu.core import (
|
||||
System, SystemPart, ConditionBase, EnvironmentBase, MoneyManagerBase,
|
||||
ProfitGoalBase, SelectorBase, SignalBase, SlippageBase, StoplossBase, AllocateFundsBase
|
||||
ProfitGoalBase, SelectorBase, SignalBase, SlippageBase, StoplossBase, AllocateFundsBase,
|
||||
MultiFactorBase
|
||||
)
|
||||
|
||||
|
||||
@ -180,6 +181,23 @@ def crtAF(allocate_weight_func, params={}, name='crtAF'):
|
||||
return meta_x(name, params)
|
||||
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# multi_factor
|
||||
# ------------------------------------------------------------------
|
||||
def crtMF(calculate_func, params={}, name='crtMF'):
|
||||
"""
|
||||
快速多因子合成算法
|
||||
|
||||
:param calculate_func: 合成算法
|
||||
:param {} params: 参数字典
|
||||
:param str name: 自定义名称
|
||||
:return: 自定义多因子合成算法实例
|
||||
"""
|
||||
meta_x = type(name, (MultiFactorBase, ), {'__init__': part_init, '_clone': part_clone})
|
||||
meta_x._calculate = calculate_func
|
||||
return meta_x(name, params)
|
||||
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# slippage
|
||||
# ------------------------------------------------------------------
|
||||
|
@ -295,7 +295,7 @@ SystemWeightList AllocateFundsBase::_adjust_with_running(
|
||||
} else {
|
||||
// 非延迟卖出的系统,立即强制卖出并回收资金
|
||||
auto tr = sys->sellForceOnClose(date, MAX_DOUBLE, PART_ALLOCATEFUNDS);
|
||||
HKU_DEBUG_IF(trace && tr.isNull(), "[AF] failed to sell: {}", sys->name());
|
||||
// HKU_DEBUG_IF(trace && tr.isNull(), "[AF] failed to sell: {}", sys->name());
|
||||
if (!tr.isNull()) {
|
||||
auto sub_tm = sys->getTM();
|
||||
auto sub_cash = sub_tm->currentCash();
|
||||
|
@ -181,7 +181,8 @@ const ScoreRecordList& MultiFactorBase::getScore(const Datetime& d) {
|
||||
return m_stk_factor_by_date[iter->second];
|
||||
}
|
||||
|
||||
ScoreRecordList MultiFactorBase::getScore(const Datetime& date, size_t start, size_t end) {
|
||||
ScoreRecordList MultiFactorBase::getScores(const Datetime& date, size_t start, size_t end,
|
||||
std::function<bool(const ScoreRecord&)>&& filter) {
|
||||
ScoreRecordList ret;
|
||||
HKU_IF_RETURN(start >= end, ret);
|
||||
|
||||
@ -190,23 +191,44 @@ ScoreRecordList MultiFactorBase::getScore(const Datetime& date, size_t start, si
|
||||
end = cross.size();
|
||||
}
|
||||
|
||||
ret.resize(end - start);
|
||||
for (size_t i = start; i < end; i++) {
|
||||
ret[i] = cross[i];
|
||||
if (filter) {
|
||||
for (size_t i = start; i < end; i++) {
|
||||
if (filter(cross[i])) {
|
||||
ret.emplace_back(cross[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (size_t i = start; i < end; i++) {
|
||||
ret.emplace_back(cross[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ScoreRecordList MultiFactorBase::getScore(const Datetime& date,
|
||||
std::function<bool(const ScoreRecord&)> filter) {
|
||||
ScoreRecordList MultiFactorBase::getScores(
|
||||
const Datetime& date, size_t start, size_t end,
|
||||
std::function<bool(const Datetime&, const ScoreRecord&)>&& filter) {
|
||||
ScoreRecordList ret;
|
||||
const auto& all_scores = getScore(date);
|
||||
for (const auto& score : all_scores) {
|
||||
if (filter(score)) {
|
||||
ret.emplace_back(score);
|
||||
HKU_IF_RETURN(start >= end, ret);
|
||||
|
||||
const auto& cross = getScore(date);
|
||||
if (end == Null<size_t>() || end > cross.size()) {
|
||||
end = cross.size();
|
||||
}
|
||||
|
||||
if (filter) {
|
||||
for (size_t i = start; i < end; i++) {
|
||||
if (filter(date, cross[i])) {
|
||||
ret.emplace_back(cross[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (size_t i = start; i < end; i++) {
|
||||
ret.emplace_back(cross[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -82,10 +82,20 @@ public:
|
||||
/** 获取指定日期截面的所有因子值,已经降序排列 */
|
||||
const ScoreRecordList& getScore(const Datetime&);
|
||||
|
||||
ScoreRecordList getScore(const Datetime& date, size_t start, size_t end = Null<size_t>());
|
||||
/**
|
||||
* 获取指定日期截面 [start, end] 范围内的因子值(评分), 并通过filer进行过滤
|
||||
* @param date 指定日期
|
||||
* @param start 排序起始点
|
||||
* @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&)>());
|
||||
|
||||
/** 获取指定日期截面的所有因子值, 并通过指定的filer进行过滤 */
|
||||
ScoreRecordList getScore(const Datetime& date, 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&)>());
|
||||
|
||||
/** 获取所有截面数据,已按降序排列 */
|
||||
const vector<ScoreRecordList>& getAllScores();
|
||||
|
@ -244,7 +244,7 @@ void Portfolio::_runMoment(const Datetime& date, bool adjust) {
|
||||
//----------------------------------------------------------------------
|
||||
for (auto& sys : m_delay_adjust_sys_list) {
|
||||
auto tr = sys.sys->sellForceOnOpen(date, sys.weight, PART_PORTFOLIO);
|
||||
HKU_DEBUG_IF(trace && tr.isNull(), "[PF] Failed to force sell: {}", sys.sys->name());
|
||||
// HKU_DEBUG_IF(trace && tr.isNull(), "[PF] Failed to force sell: {}", sys.sys->name());
|
||||
if (!tr.isNull()) {
|
||||
HKU_INFO_IF(trace, "[PF] Delay adjust sell: {}", tr);
|
||||
m_tm->addTradeRecord(tr);
|
||||
|
@ -25,23 +25,36 @@ HKU_API std::ostream& operator<<(std::ostream& os, const SelectorPtr& st) {
|
||||
}
|
||||
|
||||
SelectorBase::SelectorBase() : m_name("SelectorBase") {
|
||||
// 是否单独执行原型系统,仅限用于测试目的
|
||||
setParam<bool>("run_proto_sys", false);
|
||||
initParam();
|
||||
}
|
||||
|
||||
SelectorBase::SelectorBase(const string& name) : m_name(name) {
|
||||
// 是否单独执行原型系统
|
||||
setParam<bool>("run_proto_sys", false);
|
||||
initParam();
|
||||
}
|
||||
|
||||
SelectorBase::~SelectorBase() {}
|
||||
|
||||
void SelectorBase::initParam() {
|
||||
// 通常原型系统不参与计算,但某些特殊的场景,需要依赖于伴生系统策略,
|
||||
// 此时可以认为实际执行的系统行为跟随伴生系统的买卖交易,如依赖于SG进行选择
|
||||
// (不过由于仅依赖SG的场景不严谨,因为原型和实际系统的SG是一样的)
|
||||
// 此时,需要在自身计算之前执行原型系统,然后SE自行时可以使用。
|
||||
// 而对于实际系统和被跟随的系统完全不一样的情况,可以自行设计特殊的SE。
|
||||
setParam<bool>("depend_on_proto_sys", false); // 此种情况,需要原型系统可独立运行
|
||||
}
|
||||
|
||||
void SelectorBase::baseCheckParam(const string& name) const {}
|
||||
void SelectorBase::paramChanged() {}
|
||||
|
||||
void SelectorBase::paramChanged() {
|
||||
m_calculated = false;
|
||||
m_proto_calculated = false;
|
||||
}
|
||||
|
||||
void SelectorBase::removeAll() {
|
||||
m_pro_sys_list = SystemList();
|
||||
m_real_sys_list = SystemList();
|
||||
m_pro_sys_list.clear();
|
||||
m_real_sys_list.clear();
|
||||
m_calculated = false;
|
||||
m_proto_calculated = false;
|
||||
}
|
||||
|
||||
void SelectorBase::reset() {
|
||||
@ -52,6 +65,9 @@ void SelectorBase::reset() {
|
||||
|
||||
m_real_sys_list.clear();
|
||||
_reset();
|
||||
|
||||
m_calculated = false;
|
||||
m_proto_calculated = false;
|
||||
}
|
||||
|
||||
SelectorPtr SelectorBase::clone() {
|
||||
@ -70,6 +86,10 @@ SelectorPtr SelectorBase::clone() {
|
||||
|
||||
p->m_params = m_params;
|
||||
p->m_name = m_name;
|
||||
p->m_query = m_query;
|
||||
p->m_proto_query = m_proto_query;
|
||||
p->m_calculated = m_calculated;
|
||||
p->m_proto_calculated = m_proto_calculated;
|
||||
|
||||
p->m_real_sys_list.reserve(m_real_sys_list.size());
|
||||
for (const auto& sys : m_real_sys_list) {
|
||||
@ -83,52 +103,57 @@ SelectorPtr SelectorBase::clone() {
|
||||
return p;
|
||||
}
|
||||
|
||||
void SelectorBase::calculate(const SystemList& sysList, const KQuery& query) {
|
||||
m_real_sys_list = sysList;
|
||||
if (getParam<bool>("run_proto_sys")) {
|
||||
// 用于手工测试
|
||||
void SelectorBase::calculate(const SystemList& pf_realSysList, const KQuery& query) {
|
||||
HKU_IF_RETURN(m_calculated && m_query == query, void());
|
||||
|
||||
m_query = query;
|
||||
m_real_sys_list = pf_realSysList;
|
||||
|
||||
// 需要依赖于运行系统,在自身运算之前完成计算
|
||||
if (getParam<bool>("depend_on_proto_sys")) {
|
||||
calculate_proto(query);
|
||||
}
|
||||
|
||||
_calculate();
|
||||
m_calculated = true;
|
||||
}
|
||||
|
||||
void SelectorBase::calculate_proto(const KQuery& query) {
|
||||
if (m_proto_query != query && !m_proto_calculated) {
|
||||
for (auto& sys : m_pro_sys_list) {
|
||||
sys->run(query);
|
||||
}
|
||||
m_proto_calculated = true;
|
||||
m_proto_query = query;
|
||||
}
|
||||
_calculate();
|
||||
}
|
||||
|
||||
bool SelectorBase::addStock(const Stock& stock, const SystemPtr& protoSys) {
|
||||
HKU_ERROR_IF_RETURN(stock.isNull(), false, "Try add Null stock, will be discard!");
|
||||
HKU_ERROR_IF_RETURN(!protoSys, false, "Try add Null protoSys, will be discard!");
|
||||
HKU_ERROR_IF_RETURN(!protoSys->getMM(), false, "protoSys has not MoneyManager!");
|
||||
HKU_ERROR_IF_RETURN(!protoSys->getSG(), false, "protoSys has not Siganl!");
|
||||
SYSPtr sys = protoSys->clone();
|
||||
// 每个系统独立,不共享 tm
|
||||
sys->setParam<bool>("shared_tm", false);
|
||||
void SelectorBase::addStock(const Stock& stock, const SystemPtr& protoSys) {
|
||||
HKU_CHECK(!stock.isNull(), "The input stock is null!");
|
||||
HKU_CHECK(protoSys, "The input stock is null!");
|
||||
HKU_CHECK(protoSys->getMM(), "protoSys missing MoneyManager!");
|
||||
HKU_CHECK(protoSys->getSG(), "protoSys missing Siganl!");
|
||||
HKU_CHECK(!protoSys->getParam<bool>("shared_tm"), "Unsupport shared TM for protoSys!");
|
||||
if (getParam<bool>("depend_on_proto_sys")) {
|
||||
HKU_CHECK(protoSys->getTM(),
|
||||
"Scenarios that depend on prototype systems need to specify a TM!");
|
||||
}
|
||||
|
||||
auto proto = protoSys;
|
||||
proto->forceResetAll();
|
||||
SYSPtr sys = proto->clone();
|
||||
sys->reset();
|
||||
sys->setStock(stock);
|
||||
m_pro_sys_list.emplace_back(sys);
|
||||
return true;
|
||||
|
||||
m_calculated = false;
|
||||
m_proto_calculated = false;
|
||||
}
|
||||
|
||||
bool SelectorBase::addStockList(const StockList& stkList, const SystemPtr& protoSys) {
|
||||
HKU_ERROR_IF_RETURN(!protoSys, false, "Try add Null protoSys, will be discard!");
|
||||
HKU_ERROR_IF_RETURN(!protoSys->getMM(), false, "protoSys has not MoneyManager!");
|
||||
HKU_ERROR_IF_RETURN(!protoSys->getSG(), false, "protoSys has not Signal!");
|
||||
SYSPtr newProtoSys = protoSys->clone();
|
||||
// 复位清除之前的数据,避免因原有数据过多导致下面循环时速度过慢
|
||||
// 每个系统独立,不共享 tm
|
||||
newProtoSys->setParam<bool>("shared_tm", false);
|
||||
newProtoSys->reset();
|
||||
StockList::const_iterator iter = stkList.begin();
|
||||
for (; iter != stkList.end(); ++iter) {
|
||||
if (iter->isNull()) {
|
||||
HKU_WARN("Try add Null stock, will be discard!");
|
||||
continue;
|
||||
}
|
||||
|
||||
SYSPtr sys = newProtoSys->clone();
|
||||
sys->setStock(*iter);
|
||||
m_pro_sys_list.emplace_back(sys);
|
||||
void SelectorBase::addStockList(const StockList& stkList, const SystemPtr& protoSys) {
|
||||
for (const auto& stk : stkList) {
|
||||
addStock(stk, protoSys);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} /* namespace hku */
|
||||
|
@ -50,7 +50,7 @@ public:
|
||||
* @param protoSys 交易系统策略原型
|
||||
* @return 如果 protoSys 无效 或 stock 无效,则返回 false, 否则返回 true
|
||||
*/
|
||||
bool addStock(const Stock& stock, const SystemPtr& protoSys);
|
||||
void addStock(const Stock& stock, const SystemPtr& protoSys);
|
||||
|
||||
/**
|
||||
* 加入一组相同交易策略的股票
|
||||
@ -59,7 +59,7 @@ public:
|
||||
* @param protoSys 交易系统策略原型
|
||||
* @return 如果 protoSys 无效则返回false,否则返回 true
|
||||
*/
|
||||
bool addStockList(const StockList& stkList, const SystemPtr& protoSys);
|
||||
void addStockList(const StockList& stkList, const SystemPtr& protoSys);
|
||||
|
||||
/**
|
||||
* @brief 获取原型系统列表
|
||||
@ -102,10 +102,20 @@ public:
|
||||
virtual bool isMatchAF(const AFPtr& af) = 0;
|
||||
|
||||
/* 仅供PF调用,由PF通知其实际运行的系统列表,并启动计算 */
|
||||
void calculate(const SystemList& sysList, const KQuery& query);
|
||||
void calculate(const SystemList& pf_realSysList, const KQuery& query);
|
||||
|
||||
void calculate_proto(const KQuery& query);
|
||||
|
||||
private:
|
||||
void initParam();
|
||||
|
||||
protected:
|
||||
string m_name;
|
||||
bool m_calculated{false}; // 是否已计算过
|
||||
bool m_proto_calculated{false};
|
||||
KQuery m_query;
|
||||
KQuery m_proto_query;
|
||||
|
||||
SystemList m_pro_sys_list; // 原型系统列表
|
||||
SystemList m_real_sys_list; // PF组合中实际运行的系统,有PF执行时设定,顺序与原型列表一一对应
|
||||
|
||||
|
@ -29,64 +29,55 @@ TEST_CASE("test_SE_Fixed") {
|
||||
SYSPtr sys = SYS_Simple();
|
||||
SEPtr se = SE_Fixed();
|
||||
|
||||
// /** @arg 试图加入一个不存在的stock */
|
||||
// se->addStock(Stock(), sys);
|
||||
// SystemWeightList result = se->getSelectedOnOpen(Datetime(200001010000L));
|
||||
// CHECK_EQ(result.size(), 0);
|
||||
/** @arg 试图加入一个不存在的stock */
|
||||
CHECK_THROWS_AS(se->addStock(Stock(), sys), std::exception);
|
||||
|
||||
// /** @arg 试图加入一个空的系统策略原型 */
|
||||
// se->addStock(sm["sh600000"], SYSPtr());
|
||||
// result = se->getSelectedOnOpen(Datetime(200001010000L));
|
||||
// CHECK_EQ(result.size(), 0);
|
||||
/** @arg 试图加入一个空的系统策略原型 */
|
||||
CHECK_THROWS_AS(se->addStock(sm["sh600000"], SYSPtr()), std::exception);
|
||||
|
||||
// /** @arg 试图加入一个缺少MM的系统策略原型 */
|
||||
// SGPtr sg = SG_Cross(MA(CLOSE(), 5), MA(CLOSE(), 10));
|
||||
// MMPtr mm = MM_FixedCount(100);
|
||||
// CHECK_UNARY(!se->addStock(sm["sh600000"], sys));
|
||||
// /** @arg 试图加入一个缺少MM | SG的系统策略原型 */
|
||||
SGPtr sg = SG_Cross(MA(CLOSE(), 5), MA(CLOSE(), 10));
|
||||
MMPtr mm = MM_FixedCount(100);
|
||||
sys->setSG(sg);
|
||||
CHECK_THROWS_AS(se->addStock(sm["sh600000"], sys), std::exception);
|
||||
|
||||
// /* @arg 试图加入一个未指定SG的系统原型 */
|
||||
// sys->setMM(mm);
|
||||
// CHECK_UNARY(!se->addStock(sm["sh600000"], sys));
|
||||
sys->setSG(SGPtr());
|
||||
sys->setMM(mm);
|
||||
CHECK_THROWS_AS(se->addStock(sm["sh600000"], sys), std::exception);
|
||||
|
||||
// 目前必须有PF指定实际执行的子系统,下面代码无法执行
|
||||
// /** @arg getSelectedSystemList */
|
||||
// sys->setSG(sg);
|
||||
// se->addStock(sm["sh600000"], sys);
|
||||
// se->addStock(sm["sz000001"], sys);
|
||||
// se->addStock(sm["sz000002"], sys);
|
||||
sys->setSG(sg);
|
||||
se->addStock(sm["sh600000"], sys);
|
||||
se->addStock(sm["sz000001"], sys);
|
||||
se->addStock(sm["sz000002"], sys);
|
||||
|
||||
// se->reset();
|
||||
// result = se->getSelectedSystemList(Datetime(200001010000L));
|
||||
// CHECK_EQ(result.size(), 3);
|
||||
// CHECK_EQ(sm["sh600000"], result[0]->getStock());
|
||||
// CHECK_EQ(sm["sz000001"], result[1]->getStock());
|
||||
// CHECK_EQ(sm["sz000002"], result[2]->getStock());
|
||||
auto proto_sys_list = se->getProtoSystemList();
|
||||
CHECK_EQ(proto_sys_list.size(), 3);
|
||||
|
||||
// /** @arg clear */
|
||||
// se->clear();
|
||||
// result = se->getSelectedSystemList(Datetime(200001010000L));
|
||||
// CHECK_EQ(result.size(), 0);
|
||||
se->calculate(proto_sys_list, KQuery(-20));
|
||||
auto result = se->getSelected(Datetime(200001010000L));
|
||||
CHECK_EQ(result.size(), 3);
|
||||
CHECK_EQ(sm["sh600000"], result[0].sys->getStock());
|
||||
CHECK_EQ(sm["sz000001"], result[1].sys->getStock());
|
||||
CHECK_EQ(sm["sz000002"], result[2].sys->getStock());
|
||||
|
||||
// /** @arg reset */
|
||||
// se->addStock(sm["sh600000"], sys);
|
||||
// se->addStock(sm["sz000001"], sys);
|
||||
// se->addStock(sm["sz000002"], sys);
|
||||
// se->reset();
|
||||
// result = se->getSelectedSystemList(Datetime(200001010000L));
|
||||
// CHECK_EQ(result.size(), 3);
|
||||
// CHECK_EQ(sm["sh600000"], result[0]->getStock());
|
||||
// CHECK_EQ(sm["sz000001"], result[1]->getStock());
|
||||
// CHECK_EQ(sm["sz000002"], result[2]->getStock());
|
||||
/** @arg reset */
|
||||
se->reset();
|
||||
result = se->getSelected(Datetime(200001010000L));
|
||||
CHECK_EQ(result.size(), 0);
|
||||
|
||||
// /** @arg 克隆操作 */
|
||||
// SEPtr se2;
|
||||
// se2 = se->clone();
|
||||
// CHECK_NE(se2.get(), se.get());
|
||||
// result = se2->getSelectedSystemList(Datetime(200001010000L));
|
||||
// CHECK_EQ(result.size(), 3);
|
||||
// CHECK_EQ(sm["sh600000"], result[0]->getStock());
|
||||
// CHECK_EQ(sm["sz000001"], result[1]->getStock());
|
||||
// CHECK_EQ(sm["sz000002"], result[2]->getStock());
|
||||
/** @arg 克隆操作 */
|
||||
proto_sys_list = se->getProtoSystemList();
|
||||
se->calculate(proto_sys_list, KQuery(-20));
|
||||
SEPtr se2;
|
||||
se2 = se->clone();
|
||||
CHECK_NE(se2.get(), se.get());
|
||||
result = se2->getSelected(Datetime(200001010000L));
|
||||
CHECK_EQ(result.size(), 3);
|
||||
CHECK_EQ(sm["sh600000"], result[0].sys->getStock());
|
||||
CHECK_EQ(sm["sz000001"], result[1].sys->getStock());
|
||||
CHECK_EQ(sm["sz000002"], result[2].sys->getStock());
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
@ -13,6 +13,11 @@
|
||||
#include <boost/archive/xml_oarchive.hpp>
|
||||
#include <boost/archive/xml_iarchive.hpp>
|
||||
#include <hikyuu/StockManager.h>
|
||||
#include <hikyuu/trade_manage/crt/crtTM.h>
|
||||
#include <hikyuu/trade_sys/signal/crt/SG_Cross.h>
|
||||
#include <hikyuu/trade_sys/moneymanager/crt/MM_FixedCount.h>
|
||||
#include <hikyuu/indicator/crt/KDATA.h>
|
||||
#include <hikyuu/indicator/crt/MA.h>
|
||||
#include <hikyuu/trade_sys/selector/crt/SE_Fixed.h>
|
||||
#include <hikyuu/trade_sys/system/crt/SYS_Simple.h>
|
||||
|
||||
@ -30,7 +35,13 @@ TEST_CASE("test_SE_FIXED_export") {
|
||||
string filename(sm.tmpdir());
|
||||
filename += "/SE_FIXED.xml";
|
||||
|
||||
TMPtr tm = crtTM(Datetime(20010101), 100000);
|
||||
SGPtr sg = SG_Cross(MA(CLOSE(), 5), MA(CLOSE(), 10));
|
||||
MMPtr mm = MM_FixedCount(100);
|
||||
SYSPtr sys = SYS_Simple();
|
||||
sys->setTM(tm);
|
||||
sys->setSG(sg);
|
||||
sys->setMM(mm);
|
||||
StockList stkList;
|
||||
stkList.push_back(sm["sh600000"]);
|
||||
stkList.push_back(sm["sz000001"]);
|
||||
|
@ -38,7 +38,6 @@ void export_MultiFactor(py::module& m) {
|
||||
.def_readwrite("stock", &ScoreRecord::stock, "时间")
|
||||
.def_readwrite("value", &ScoreRecord::value, "时间");
|
||||
|
||||
size_t null_size = Null<size_t>();
|
||||
py::class_<MultiFactorBase, MultiFactorPtr, PyMultiFactor>(m, "MultiFactorBase",
|
||||
R"(市场环境判定策略基类
|
||||
|
||||
@ -122,11 +121,31 @@ void export_MultiFactor(py::module& m) {
|
||||
.def("clone", &MultiFactorBase::clone, "克隆操作")
|
||||
|
||||
.def(
|
||||
"get_score",
|
||||
[](MultiFactorBase& self, const Datetime& date, size_t start, size_t end) {
|
||||
return self.getScore(date, start, end);
|
||||
"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("datet"), py::arg("start") = 0, py::arg("end") = null_size,
|
||||
py::arg("datet"), py::arg("start") = 0, py::arg("end") = py::none(),
|
||||
py::arg("filter") = py::none(),
|
||||
R"(get_score(self, date[, start=0, end=Null])
|
||||
|
||||
获取指定日期截面的所有因子值,已经降序排列,相当于各证券日期截面评分。
|
||||
@ -134,22 +153,15 @@ void export_MultiFactor(py::module& m) {
|
||||
:param Datetime date: 指定日期
|
||||
:param int start: 取当日排名开始
|
||||
:param int end: 取当日排名结束(不包含本身)
|
||||
:param function func: (ScoreRecord)->bool 或 (Datetime, ScoreRecord)->bool 为原型的可调用对象
|
||||
:rtype: ScoreRecordList)")
|
||||
|
||||
.def("get_score",
|
||||
[](MultiFactorBase& self, const Datetime& date, py::object filter) {
|
||||
HKU_CHECK(py::hasattr(filter, "__call__"), "filter not callable!");
|
||||
py::object filter_func = filter.attr("__call__");
|
||||
return self.getScore(
|
||||
date, [&](const ScoreRecord& score) { return filter_func(score).cast<bool>(); });
|
||||
})
|
||||
|
||||
.def("get_all_scores", &MultiFactorBase::getAllScores, py::return_value_policy::copy,
|
||||
R"(get_all_scores(self)
|
||||
|
||||
获取所有日期的所有评分,长度与参考日期相同
|
||||
|
||||
:return: 每日 ScoreRecordList 结果的 list)")
|
||||
:return: ScoreRecordList)")
|
||||
|
||||
.def("get_all_src_factors", &MultiFactorBase::getAllSrcFactors)
|
||||
|
||||
@ -158,12 +170,15 @@ void export_MultiFactor(py::module& m) {
|
||||
m.def(
|
||||
"MF_EqualWeight",
|
||||
[](const py::sequence& inds, const py::sequence& stks, const KQuery& query,
|
||||
const Stock& ref_stk, int ic_n) {
|
||||
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, ic_n);
|
||||
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::arg("ic_n") = 5,
|
||||
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])
|
||||
|
||||
等权重合成因子
|
||||
@ -171,21 +186,22 @@ void export_MultiFactor(py::module& m) {
|
||||
:param sequense(Indicator) inds: 原始因子列表
|
||||
:param sequense(stock) stks: 计算证券列表
|
||||
:param Query query: 日期范围
|
||||
:param Stock ref_stk: 参考证券
|
||||
:param Stock ref_stk: 参考证券 (未指定时,默认为 sh000300 沪深300)
|
||||
:param int ic_n: 默认 IC 对应的 N 日收益率
|
||||
:rtype: MultiFactor)");
|
||||
|
||||
m.def(
|
||||
"MF_ICWeight",
|
||||
[](const py::sequence& inds, const py::sequence& stks, const KQuery& query,
|
||||
const Stock& ref_stk, int ic_n, int ic_rolling_n) {
|
||||
// MF_EqualWeight
|
||||
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, ic_n, ic_rolling_n);
|
||||
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::arg("ic_n") = 5,
|
||||
py::arg("ic_rolling_n") = 120,
|
||||
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权重合成因子
|
||||
@ -193,7 +209,7 @@ void export_MultiFactor(py::module& m) {
|
||||
:param sequense(Indicator) inds: 原始因子列表
|
||||
:param sequense(stock) stks: 计算证券列表
|
||||
:param Query query: 日期范围
|
||||
:param Stock ref_stk: 参考证券
|
||||
:param Stock ref_stk: (未指定时,默认为 sh000300 沪深300)
|
||||
:param int ic_n: 默认 IC 对应的 N 日收益率
|
||||
:param int ic_rolling_n: IC 滚动周期
|
||||
:rtype: MultiFactor)");
|
||||
@ -201,14 +217,15 @@ void export_MultiFactor(py::module& m) {
|
||||
m.def(
|
||||
"MF_ICIRWeight",
|
||||
[](const py::sequence& inds, const py::sequence& stks, const KQuery& query,
|
||||
const Stock& ref_stk, int ic_n, int ic_rolling_n) {
|
||||
// MF_EqualWeight
|
||||
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, ic_n, ic_rolling_n);
|
||||
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::arg("ic_n") = 5,
|
||||
py::arg("ic_rolling_n") = 120,
|
||||
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权重合成因子
|
||||
@ -216,7 +233,7 @@ void export_MultiFactor(py::module& m) {
|
||||
:param sequense(Indicator) inds: 原始因子列表
|
||||
:param sequense(stock) stks: 计算证券列表
|
||||
:param Query query: 日期范围
|
||||
:param Stock ref_stk: 参考证券
|
||||
:param Stock ref_stk: 参考证券 (未指定时,默认为 sh000300 沪深300)
|
||||
:param int ic_n: 默认 IC 对应的 N 日收益率
|
||||
:param int ic_rolling_n: IC 滚动周期
|
||||
:rtype: MultiFactor)");
|
||||
|
Loading…
Reference in New Issue
Block a user