diff --git a/libs/hikyuu/trade_sys/allocatefunds/AllocateFundsBase.cpp b/libs/hikyuu/trade_sys/allocatefunds/AllocateFundsBase.cpp index 06e1f8e2..6172957d 100644 --- a/libs/hikyuu/trade_sys/allocatefunds/AllocateFundsBase.cpp +++ b/libs/hikyuu/trade_sys/allocatefunds/AllocateFundsBase.cpp @@ -28,12 +28,14 @@ HKU_API std::ostream & operator<<(std::ostream& os, const AFPtr& af) { AllocateFundsBase::AllocateFundsBase(): m_name("AllocateMoneyBase") { setParam("adjust_hold_sys", false); //是否调整之前已经持仓策略的持仓 setParam("max_sys_num", 10); //最大系统实例数 + setParam("freq", KQuery::DAY); //调仓频率 } AllocateFundsBase::AllocateFundsBase(const string& name) : m_name("AllocateMoneyBase") { setParam("adjust_hold_sys", false); setParam("max_sys_num", 10); //最大系统实例数 + setParam("freq", KQuery::DAY); //调仓频率 } AllocateFundsBase::~AllocateFundsBase() { diff --git a/libs/hikyuu/trade_sys/portfolio/Portfolio.cpp b/libs/hikyuu/trade_sys/portfolio/Portfolio.cpp index 2c0079ba..dec540f0 100644 --- a/libs/hikyuu/trade_sys/portfolio/Portfolio.cpp +++ b/libs/hikyuu/trade_sys/portfolio/Portfolio.cpp @@ -110,8 +110,11 @@ void Portfolio::run(const KQuery& query) { } } + SystemList pre_selected_list; //上一次的选中标的列表 SystemList pre_ac_list; //上一轮实际获得分配资金的系统列表 + SystemList cur_hold_sys_list; + DatetimeList datelist = StockManager::instance().getTradingCalendar(query); DatetimeList::const_iterator date_iter = datelist.begin(); for(; date_iter != datelist.end(); ++date_iter) { @@ -120,8 +123,92 @@ void Portfolio::run(const KQuery& query) { continue; } + /* + * 资金分配频率应该小于等于选择频率 + * + * (由于有些系统可能是延迟操作,所以有多种情况) + * + * 如果当前时刻选择标的发生变化(此时也一定是资金调整分配的时刻) + * 收集当前仍旧有持仓的系统 + * 回收上一次选中的标的中已没有持仓系统的资金 + * 执行资金分配算法(其中非强制分配的,已有持仓系统如果有剩余现金被取出参与资金重新分配; + * 而强制分配的,已有持仓的系统剩余资金被取出参与重分配同时被强制发出 + * 卖出信号,其中延迟操作的系统卖出操作将在下一时刻才会执行卖出操作) + * + * 如果当前时刻选择标的没有发生变化 + * 收集当前仍旧有持仓的系统 + * 如果是调仓时刻 + * 如果非选中标的的已有持仓策略变成了空仓,则重新执行分配算法分配空仓后多余的资金 + * 否则不执行调仓策略 + * 如果不是调仓时刻 + * 如果是强制调仓,则执行调仓操作 + */ + + cur_hold_sys_list.clear(); + +#if 1 + //如果当前时刻选择标的发生变化(此时也一定是资金调整分配的时刻) + if (m_se->changed(*date_iter)) { + + //收集当前仍旧有持仓的系统,并回收上一次选中的标的中已没有持仓系统的资金 + sys_iter = pre_ac_list.begin(); + for (; sys_iter != pre_ac_list.end(); ++sys_iter) { + SYSPtr& sys = *sys_iter; + TMPtr& tm = sys->getTM(); + if (tm->getStockNumber() != 0) { + cur_hold_sys_list.push_back(sys); + } + } + + std::cout << *date_iter << " " << m_tm_shadow->currentCash() << std::endl; + + //计算当前时刻选择的系统实例 + SystemList selected_list = m_se->_getSelectedSystemList(*date_iter); + SystemList ac_list = m_af->getAllocatedSystemList(*date_iter, + selected_list, cur_hold_sys_list); + + std::cout << selected_list.size() << " " << ac_list.size() << std::endl; + std::cout << m_se << std::endl; + for (sys_iter = ac_list.begin(); sys_iter != ac_list.end(); ++sys_iter) { + SYSPtr& sys = *sys_iter; + sys->runMoment(*date_iter); + + //同步交易记录 + TradeRecordList tr_list = sys->getTM()->getTradeList(*date_iter, Null()); + auto tr_iter = tr_list.begin(); + for (; tr_iter != tr_list.end(); ++tr_iter) { + m_tm_shadow->addTradeRecord(*tr_iter); + } + } + + //同步总账户和影子账户交易记录 + TradeRecordList tr_list = m_tm_shadow->getTradeList(*date_iter, Null()); + auto tr_iter = tr_list.begin(); + for (; tr_iter != tr_list.end(); ++tr_iter) { + if (tr_iter->business == BUSINESS_CHECKIN + || tr_iter->business == BUSINESS_CHECKOUT) { + continue; + } + + m_tm->addTradeRecord(*tr_iter); + } + + swap(pre_ac_list, ac_list); + + if (m_tm->currentCash() != m_tm_shadow->currentCash()) { + HKU_INFO("m_tm->currentCash() != m_tm_shadow->currentCash()"); + HKU_INFO(m_tm->currentCash() << " == " << m_tm_shadow->currentCash()); + } + + } +#endif + +#if 0 //计算当前时刻选择的系统实例 SystemList selected_list = m_se->getSelectedSystemList(*date_iter); + if (selected_list.empty()) { + continue; + } //获取上一轮分配资金的系统中仍旧有持仓或存在延迟请求的系统 std::set selected_sets; @@ -129,13 +216,14 @@ void Portfolio::run(const KQuery& query) { selected_sets.insert(*sys_iter); } - SystemList cur_hold_sys_list; + //SystemList cur_hold_sys_list; auto hold_iter = pre_ac_list.begin(); for (; hold_iter != pre_ac_list.end(); ++hold_iter) { SYSPtr& sys = *hold_iter; if (selected_sets.find(sys) != selected_sets.end()) { TMPtr& tm = sys->getTM(); - if (sys->haveDelayRequest() || tm->have(sys->getStock())) { + if (tm->getStockNumber() != 0) { + //if (sys->haveDelayRequest() || tm->have(sys->getStock())) { cur_hold_sys_list.push_back(sys); } } @@ -143,6 +231,9 @@ void Portfolio::run(const KQuery& query) { SystemList ac_list = m_af->getAllocatedSystemList(*date_iter, selected_list, cur_hold_sys_list); + if (ac_list.empty()) { + continue; + } for (sys_iter = ac_list.begin(); sys_iter != ac_list.end(); ++sys_iter) { SYSPtr& sys = *sys_iter; @@ -170,10 +261,11 @@ void Portfolio::run(const KQuery& query) { swap(pre_ac_list, ac_list); - if (m_tm->currentCash() != m_tm_shadow->currentCash()) { + /*if (m_tm->currentCash() != m_tm_shadow->currentCash()) { HKU_INFO("m_tm->currentCash() != m_tm_shadow->currentCash()"); HKU_INFO(m_tm->currentCash() << " == " << m_tm_shadow->currentCash()); - } + }*/ +#endif } } diff --git a/libs/hikyuu/trade_sys/selector/SelectorBase.cpp b/libs/hikyuu/trade_sys/selector/SelectorBase.cpp index 75e41d37..db018834 100644 --- a/libs/hikyuu/trade_sys/selector/SelectorBase.cpp +++ b/libs/hikyuu/trade_sys/selector/SelectorBase.cpp @@ -72,6 +72,7 @@ SelectorPtr SelectorBase::clone() { p->m_params = m_params; p->m_name = m_name; + p->m_query = m_query; p->m_pre_datetime = m_pre_datetime; p->m_pre_selected_list = m_pre_selected_list; diff --git a/libs/hikyuu/trade_sys/selector/SelectorBase.h b/libs/hikyuu/trade_sys/selector/SelectorBase.h index 8b044192..f97c8990 100644 --- a/libs/hikyuu/trade_sys/selector/SelectorBase.h +++ b/libs/hikyuu/trade_sys/selector/SelectorBase.h @@ -60,8 +60,17 @@ public: virtual SelectorPtr _clone() = 0; + void setQuery(KQuery query) { + m_query = query; + } + + KQuery getQuery() const { + return m_query; + } + protected: string m_name; + KQuery m_query; SystemList m_sys_list; Datetime m_pre_datetime; @@ -78,6 +87,7 @@ private: string name_str(GBToUTF8(m_name)); ar & boost::serialization::make_nvp("name", name_str); ar & BOOST_SERIALIZATION_NVP(m_params); + ar & BOOST_SERIALIZATION_NVP(m_query); ar & BOOST_SERIALIZATION_NVP(m_sys_list); ar & BOOST_SERIALIZATION_NVP(m_pre_datetime); ar & BOOST_SERIALIZATION_NVP(m_pre_selected_list); @@ -87,6 +97,7 @@ private: void load(Archive & ar, const unsigned int version) { ar & boost::serialization::make_nvp("name", m_name); ar & BOOST_SERIALIZATION_NVP(m_params); + ar & BOOST_SERIALIZATION_NVP(m_query); ar & BOOST_SERIALIZATION_NVP(m_sys_list); ar & BOOST_SERIALIZATION_NVP(m_pre_datetime); ar & BOOST_SERIALIZATION_NVP(m_pre_selected_list); diff --git a/test/libs/hikyuu/trade_sys/portfolio/test_PF_for_delay_and_no_adjust.cpp b/test/libs/hikyuu/trade_sys/portfolio/test_PF_for_delay_and_no_adjust.cpp index 16303afa..585fd9a3 100644 --- a/test/libs/hikyuu/trade_sys/portfolio/test_PF_for_delay_and_no_adjust.cpp +++ b/test/libs/hikyuu/trade_sys/portfolio/test_PF_for_delay_and_no_adjust.cpp @@ -67,7 +67,7 @@ BOOST_AUTO_TEST_CASE( test_PF_for_delay_and_no_adjust) { TradeRecordList tr2 = tm->getTradeList(); BOOST_CHECK(tr1.size() == tr2.size()); - /*std::cout << tr1.size() << std::endl; + std::cout << tr1.size() << std::endl; for (auto iter = tr1.begin(); iter != tr1.end(); ++iter) { std::cout << *iter << std::endl; } @@ -81,7 +81,7 @@ BOOST_AUTO_TEST_CASE( test_PF_for_delay_and_no_adjust) { std::cout << sys->getTM()->currentCash() << std::endl; std::cout << tm->currentCash() << std::endl; - */ + }