mirror of
https://gitee.com/fasiondog/hikyuu.git
synced 2024-11-30 10:59:43 +08:00
完善资产组合
This commit is contained in:
parent
70ccca946c
commit
7145dfdb66
@ -28,16 +28,14 @@ HKU_API std::ostream& operator<<(std::ostream& os, const AFPtr& af) {
|
||||
AllocateFundsBase::AllocateFundsBase()
|
||||
: m_name("AllocateMoneyBase"), m_count(0), m_pre_date(Datetime::min()), m_reserve_percent(0) {
|
||||
//是否调整之前已经持仓策略的持仓。不调整时,仅使用总账户当前剩余资金进行分配,否则将使用总市值进行分配
|
||||
setParam<bool>("adjust_hold_sys", false);
|
||||
setParam<bool>("adjust_running_sys", false);
|
||||
setParam<int>("max_sys_num", 100000); //最大系统实例数
|
||||
setParam<int>("freq", 1); //调仓频率
|
||||
}
|
||||
|
||||
AllocateFundsBase::AllocateFundsBase(const string& name)
|
||||
: m_name("AllocateMoneyBase"), m_count(0), m_pre_date(Datetime::min()), m_reserve_percent(0) {
|
||||
setParam<bool>("adjust_hold_sys", false);
|
||||
setParam<bool>("adjust_running_sys", false);
|
||||
setParam<int>("max_sys_num", 100000); //最大系统实例数
|
||||
setParam<int>("freq", 1); //调仓频率
|
||||
}
|
||||
|
||||
AllocateFundsBase::~AllocateFundsBase() {}
|
||||
@ -83,49 +81,23 @@ void AllocateFundsBase::setReserverPercent(double percent) {
|
||||
}
|
||||
}
|
||||
|
||||
bool AllocateFundsBase::changed(Datetime date) {
|
||||
if (date <= m_pre_date || date == Null<Datetime>())
|
||||
return false;
|
||||
|
||||
int freq = getParam<int>("freq");
|
||||
if (freq <= 0) {
|
||||
freq = 1;
|
||||
}
|
||||
|
||||
m_count++;
|
||||
if (m_count >= freq) {
|
||||
m_count = 0;
|
||||
m_pre_date = date;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SystemList AllocateFundsBase ::getAllocatedSystemList(const Datetime& date,
|
||||
const SystemList& se_list,
|
||||
const SystemList& hold_list) {
|
||||
SystemList result;
|
||||
|
||||
void AllocateFundsBase ::adjustFunds(const Datetime& date, const SystemList& se_list,
|
||||
const std::list<SYSPtr>& running_list) {
|
||||
int max_num = getParam<int>("max_sys_num");
|
||||
if (max_num <= 0) {
|
||||
HKU_ERROR("param(max_sys_num) need > 0!");
|
||||
return result;
|
||||
return;
|
||||
}
|
||||
|
||||
if (getParam<bool>("adjust_hold_sys")) {
|
||||
_getAllocatedSystemList_adjust_hold(date, se_list, hold_list, result);
|
||||
if (getParam<bool>("adjust_running_sys")) {
|
||||
_adjust_with_running(date, se_list, running_list);
|
||||
} else {
|
||||
_getAllocatedSystemList_not_adjust_hold(date, se_list, hold_list, result);
|
||||
_adjust_without_running(date, se_list, running_list);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void AllocateFundsBase::_getAllocatedSystemList_adjust_hold(const Datetime& date,
|
||||
const SystemList& se_list,
|
||||
const SystemList& hold_list,
|
||||
SystemList& out_sys_list) {
|
||||
void AllocateFundsBase::_adjust_with_running(const Datetime& date, const SystemList& se_list,
|
||||
const std::list<SYSPtr>& running_list) {
|
||||
//计算当前选中系统列表的权重
|
||||
SystemWeightList sw_list = _allocateWeight(date, se_list);
|
||||
if (sw_list.size() == 0) {
|
||||
@ -143,7 +115,7 @@ void AllocateFundsBase::_getAllocatedSystemList_adjust_hold(const Datetime& date
|
||||
}
|
||||
|
||||
//如果当前持仓的系统不在实际的选中系统集合,则强制清仓卖出,如果账户有现金则同时回收现金
|
||||
for (auto iter = hold_list.begin(); iter != hold_list.end(); ++iter) {
|
||||
for (auto iter = running_list.begin(); iter != running_list.end(); ++iter) {
|
||||
const SYSPtr& sys = *iter;
|
||||
if (selected_sets.find(sys) == selected_sets.end()) {
|
||||
KRecord record = sys->getTO().getKRecordByDate(date);
|
||||
@ -251,7 +223,7 @@ void AllocateFundsBase::_getAllocatedSystemList_adjust_hold(const Datetime& date
|
||||
need_sell_num =
|
||||
size_t(need_sell_num / stock.minTradeNumber()) * stock.minTradeNumber();
|
||||
if (position.number >= need_sell_num) {
|
||||
sys->_sellFromAllocateFunds(k, need_sell_num);
|
||||
sys->_sellForce(k, need_sell_num, PART_ALLOCATEFUNDS);
|
||||
}
|
||||
}
|
||||
|
||||
@ -284,30 +256,25 @@ void AllocateFundsBase::_getAllocatedSystemList_adjust_hold(const Datetime& date
|
||||
}
|
||||
}
|
||||
|
||||
void AllocateFundsBase::_getAllocatedSystemList_not_adjust_hold(const Datetime& date,
|
||||
const SystemList& se_list,
|
||||
const SystemList& hold_list,
|
||||
SystemList& out_sys_list) {
|
||||
void AllocateFundsBase::_adjust_without_running(const Datetime& date, const SystemList& se_list,
|
||||
const std::list<SYSPtr>& running_list) {
|
||||
if (se_list.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
//不调整持仓,先将所有持仓系统加入到输出系统列表中
|
||||
out_sys_list.insert(out_sys_list.end(), hold_list.begin(), hold_list.end());
|
||||
|
||||
//如果持仓的系统数已大于等于最大持仓系统数,直接输出已持仓系统列表,并返回
|
||||
int max_num = getParam<int>("max_sys_num");
|
||||
if (hold_list.size() >= max_num) {
|
||||
if (running_list.size() >= max_num) {
|
||||
return;
|
||||
}
|
||||
|
||||
//从当前选中的系统列表中将持仓的系统排除
|
||||
//从当前选中的系统列表中将运行中的子系统排除
|
||||
std::set<SYSPtr> hold_sets;
|
||||
for (auto iter = hold_list.begin(); iter != hold_list.end(); ++iter) {
|
||||
for (auto iter = running_list.begin(); iter != running_list.end(); ++iter) {
|
||||
hold_sets.insert(*iter);
|
||||
}
|
||||
|
||||
SystemList pure_se_list;
|
||||
SystemList pure_se_list; // 不包含运行中系统的子系统列表
|
||||
for (auto iter = se_list.begin(); iter != se_list.end(); ++iter) {
|
||||
if (hold_sets.find(*iter) == hold_sets.end()) {
|
||||
pure_se_list.push_back(*iter);
|
||||
@ -325,8 +292,8 @@ void AllocateFundsBase::_getAllocatedSystemList_not_adjust_hold(const Datetime&
|
||||
boost::bind(std::less<double>(), boost::bind(&SystemWeight::m_weight, _1),
|
||||
boost::bind(&SystemWeight::m_weight, _2)));
|
||||
|
||||
//倒序遍历,计算总权重,并在遇到权重为0或等于最大持仓时
|
||||
size_t remain = max_num - hold_list.size();
|
||||
//倒序遍历,计算总权重,并在遇到权重为0或等于最大持仓时结束遍历
|
||||
size_t remain = max_num - running_list.size();
|
||||
price_t total_weight = 0.0;
|
||||
auto sw_iter = sw_list.rbegin();
|
||||
for (size_t count = 0; sw_iter != sw_list.rend(); ++sw_iter, count++) {
|
||||
@ -348,33 +315,17 @@ void AllocateFundsBase::_getAllocatedSystemList_not_adjust_hold(const Datetime&
|
||||
sw_iter = sw_list.rbegin();
|
||||
for (; sw_iter != end_iter; ++sw_iter) {
|
||||
// 该系统期望分配的资金
|
||||
price_t will_cash = per_cash * sw_iter->getWeight();
|
||||
|
||||
if (will_cash <= 0.0) {
|
||||
price_t will_cash = roundDown(per_cash * sw_iter->getWeight(), precision);
|
||||
if (will_cash <= std::abs(roundDown(0.0, precision))) {
|
||||
break;
|
||||
}
|
||||
|
||||
// 尝试从总账户中取出资金存入子账户
|
||||
SYSPtr sub_sys = sw_iter->getSYS();
|
||||
TMPtr sub_tm = sub_sys->getTM();
|
||||
assert(sub_tm);
|
||||
|
||||
// 计算实际的价格精度(总账户和当前系统账号之间的最小值)
|
||||
int real_precision = sub_tm->getParam<int>("precision");
|
||||
if (precision < real_precision) {
|
||||
real_precision = precision;
|
||||
}
|
||||
|
||||
// 计算该系统实际期望分配的资金,并将总账户中的资金移入该系统账户中
|
||||
will_cash = roundDown(will_cash - sub_tm->currentCash(), real_precision);
|
||||
if (will_cash > 0) {
|
||||
if (!m_tm->checkout(date, will_cash)) {
|
||||
HKU_ERROR("m_tm->checkout failed!");
|
||||
continue;
|
||||
}
|
||||
if (m_tm->checkout(date, will_cash)) {
|
||||
sub_tm->checkin(date, will_cash);
|
||||
}
|
||||
|
||||
out_sys_list.push_back(sub_sys);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,14 +32,14 @@ public:
|
||||
void name(const string& name);
|
||||
|
||||
/**
|
||||
* Portfolio获取实际获得资产分配的系统策略实例
|
||||
* 执行资产分配调整
|
||||
* @param date 指定日期
|
||||
* @param se_list 系统实例选择器选出的系统实例
|
||||
* @param hold_list 当前分配过资金的系统实例
|
||||
* @param running_list 当前运行中的系统实例
|
||||
* @return
|
||||
*/
|
||||
SystemList getAllocatedSystemList(const Datetime& date, const SystemList& se_list,
|
||||
const SystemList& hold_list);
|
||||
void adjustFunds(const Datetime& date, const SystemList& se_list,
|
||||
const std::list<SYSPtr>& running_list);
|
||||
|
||||
/** 获取交易账户 */
|
||||
TMPtr getTM();
|
||||
@ -59,8 +59,6 @@ public:
|
||||
*/
|
||||
void setReserverPercent(double p);
|
||||
|
||||
bool changed(Datetime date);
|
||||
|
||||
/** 复位 */
|
||||
void reset();
|
||||
|
||||
@ -85,11 +83,10 @@ public:
|
||||
|
||||
virtual SystemWeightList _allocateWeight(const Datetime& date, const SystemList& se_list) = 0;
|
||||
|
||||
void _getAllocatedSystemList_adjust_hold(const Datetime& date, const SystemList& se_list,
|
||||
const SystemList& hold_list, SystemList& out_sys_list);
|
||||
void _getAllocatedSystemList_not_adjust_hold(const Datetime& date, const SystemList& se_list,
|
||||
const SystemList& hold_list,
|
||||
SystemList& out_sys_list);
|
||||
void _adjust_with_running(const Datetime& date, const SystemList& se_list,
|
||||
const std::list<SYSPtr>& running_list);
|
||||
void _adjust_without_running(const Datetime& date, const SystemList& se_list,
|
||||
const std::list<SYSPtr>& running_list);
|
||||
|
||||
private:
|
||||
string m_name;
|
||||
|
@ -27,188 +27,184 @@ HKU_API std::ostream& operator<<(std::ostream& os, const PortfolioPtr& pf) {
|
||||
return os;
|
||||
}
|
||||
|
||||
Portfolio::Portfolio() : m_name("Portfolio") {}
|
||||
Portfolio::Portfolio() : m_name("Portfolio"), m_is_ready(false) {}
|
||||
|
||||
Portfolio::Portfolio(const string& name) : m_name(name) {}
|
||||
Portfolio::Portfolio(const string& name) : m_name(name), m_is_ready(false) {}
|
||||
|
||||
Portfolio::Portfolio(const TradeManagerPtr& tm, const SelectorPtr& se, const AFPtr& af)
|
||||
: m_name("Portfolio"), m_tm(tm), m_se(se), m_af(af) {}
|
||||
: m_name("Portfolio"), m_tm(tm), m_se(se), m_af(af), m_is_ready(false) {}
|
||||
|
||||
Portfolio::~Portfolio() {}
|
||||
|
||||
void Portfolio::reset() {
|
||||
m_is_ready = false;
|
||||
m_running_sys_set.clear();
|
||||
m_running_sys_list.clear();
|
||||
m_all_sys_set.clear();
|
||||
if (m_tm)
|
||||
m_tm->reset();
|
||||
if (m_se)
|
||||
m_se->reset();
|
||||
if (m_af)
|
||||
m_af->reset();
|
||||
if (m_tm_shadow)
|
||||
m_tm_shadow->reset();
|
||||
}
|
||||
|
||||
PortfolioPtr Portfolio::clone() {
|
||||
PortfolioPtr p = make_shared<Portfolio>();
|
||||
p->m_params = m_params;
|
||||
p->m_name = m_name;
|
||||
p->m_query = m_query;
|
||||
p->m_running_sys_set = m_running_sys_set;
|
||||
p->m_running_sys_list = m_running_sys_list;
|
||||
p->m_all_sys_set = m_all_sys_set;
|
||||
p->m_is_ready = m_is_ready;
|
||||
if (m_se)
|
||||
p->m_se = m_se->clone();
|
||||
if (m_af)
|
||||
p->m_af = m_af->clone();
|
||||
if (m_tm)
|
||||
p->m_tm = m_tm->clone();
|
||||
if (m_tm_shadow)
|
||||
p->m_tm_shadow = m_tm_shadow->clone();
|
||||
return p;
|
||||
}
|
||||
|
||||
bool Portfolio::readyForRun() {
|
||||
if (!m_se) {
|
||||
HKU_WARN("m_se is null!");
|
||||
m_is_ready = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_tm) {
|
||||
HKU_WARN("m_tm is null!");
|
||||
m_is_ready = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_af) {
|
||||
HKU_WARN("m_am is null!");
|
||||
m_is_ready = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
reset();
|
||||
|
||||
//将影子账户指定给资产分配器
|
||||
m_tm_shadow = m_tm->clone();
|
||||
m_af->setTM(m_tm_shadow);
|
||||
// 将影子账户指定给资产分配器
|
||||
// m_tm_shadow = m_tm->clone();
|
||||
// m_af->setTM(m_tm_shadow);
|
||||
m_af->setTM(m_tm);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Portfolio::runMoment(const Datetime& datetime) {}
|
||||
|
||||
void Portfolio::run(const KQuery& query) {
|
||||
if (!readyForRun()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_af->setQuery(query);
|
||||
// 为资金分配器设置关联查询条件
|
||||
m_af->setQuery(m_query);
|
||||
|
||||
// 获取所有备选子系统,为无关联账户的子系统分配子账号,对所有子系统做好启动准备
|
||||
SystemList all_sys_list = m_se->getAllSystemList();
|
||||
TMPtr pro_tm = crtTM(m_tm->initDatetime(), 0.0, m_tm->costFunc(), "SUB");
|
||||
TMPtr pro_tm = crtTM(m_tm->initDatetime(), 0.0, m_tm->costFunc(), "TM_SUB");
|
||||
auto sys_iter = all_sys_list.begin();
|
||||
for (; sys_iter != all_sys_list.end(); ++sys_iter) {
|
||||
//为每一个系统实例分配子账户
|
||||
SystemPtr& sys = *sys_iter;
|
||||
sys->setTM(pro_tm->clone());
|
||||
|
||||
// 如果子系统没有关联账户,则为其分配一个子账户
|
||||
if (!sys->getTM()) {
|
||||
sys->setTM(pro_tm->clone());
|
||||
}
|
||||
|
||||
if (sys->readyForRun()) {
|
||||
KData k = sys->getStock().getKData(query);
|
||||
KData k = sys->getStock().getKData(m_query);
|
||||
sys->setTO(k);
|
||||
|
||||
// 保存记录子系统
|
||||
m_running_sys_set.insert(sys);
|
||||
m_running_sys_list.push_back(sys);
|
||||
m_all_sys_set.insert(sys);
|
||||
|
||||
} else {
|
||||
HKU_WARN("Exist invalid system, it could not ready for run!");
|
||||
}
|
||||
}
|
||||
|
||||
m_is_ready = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Portfolio::runMoment(const Datetime& date) {
|
||||
HKU_CHECK(isReady(), "Not ready to run! Please perform readyForRun() first!");
|
||||
|
||||
// 当前日期小于账户建立日期,直接忽略
|
||||
if (date < m_tm->initDatetime()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int precision = m_tm->getParam<int>("precision");
|
||||
SystemList cur_selected_list; //当前选中系统列表
|
||||
std::set<SYSPtr> cur_selected_sets; //当前选中系统集合,方便计算使用
|
||||
SystemList cur_allocated_list; //当前分配了资金的系统
|
||||
SystemList cur_hold_sys_list; //当前时刻有持仓的系统,每个时刻重新收集
|
||||
|
||||
// 从选股策略获取当前选中的系统列表
|
||||
cur_selected_list = m_se->getSelectedSystemList(date);
|
||||
|
||||
// 资产分配算法调整各子系统资产分配
|
||||
m_af->adjustFunds(date, cur_selected_list, m_running_sys_list);
|
||||
|
||||
// 遍历当前运行中的子系统,如果已没有分配资金和持仓,则移除
|
||||
SystemList will_remove_sys;
|
||||
for (auto& running_sys : m_running_sys_list) {
|
||||
Stock stock = running_sys->getStock();
|
||||
TMPtr sub_tm = running_sys->getTM();
|
||||
KRecord krecord = running_sys->getTO().getKRecordByDate(date);
|
||||
PositionRecord position = sub_tm->getPosition(stock);
|
||||
running_sys->_sellForce(krecord, position.number, PART_PORTFOLIO);
|
||||
|
||||
price_t cash = sub_tm->currentCash();
|
||||
if (cash > 0) {
|
||||
if (sub_tm->checkout(date, cash)) {
|
||||
m_tm->checkin(date, cash);
|
||||
// 重新获取此时的子账户资金
|
||||
cash = sub_tm->currentCash();
|
||||
}
|
||||
}
|
||||
|
||||
position = sub_tm->getPosition(stock);
|
||||
|
||||
// 已没有持仓且没有现金,则放入待移除列表
|
||||
if (position.number == 0 && cash <= std::abs(roundDown(0, precision))) {
|
||||
will_remove_sys.push_back(running_sys);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& sub_sys : will_remove_sys) {
|
||||
m_running_sys_list.remove(sub_sys);
|
||||
m_running_sys_set.erase(sub_sys);
|
||||
}
|
||||
|
||||
// 遍历本次选择的系统列表,如果存在分配资金且不在运行中列表内,则加入运行列表
|
||||
for (auto& sub_sys : cur_selected_list) {
|
||||
price_t cash = sub_sys->getTM()->currentCash();
|
||||
if (cash > 0 && m_running_sys_set.find(sub_sys) == m_running_sys_set.end()) {
|
||||
m_running_sys_list.push_back(sub_sys);
|
||||
m_running_sys_set.insert(sub_sys);
|
||||
|
||||
if (m_all_sys_set.find(sub_sys) == m_all_sys_set.end()) {
|
||||
m_all_sys_set.insert(sub_sys);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 执行所有运行中的系统
|
||||
for (auto& sub_sys : m_running_sys_list) {
|
||||
sub_sys->runMoment(date);
|
||||
}
|
||||
}
|
||||
|
||||
void Portfolio::run(const KQuery& query) {
|
||||
HKU_CHECK(readyForRun(),
|
||||
"readyForRun fails, check to see if a valid TradeManager, Selector, or "
|
||||
"AllocateFunds instance have been specified.");
|
||||
|
||||
DatetimeList datelist = StockManager::instance().getTradingCalendar(query);
|
||||
DatetimeList::const_iterator date_iter = datelist.begin();
|
||||
for (; date_iter != datelist.end(); ++date_iter) {
|
||||
const Datetime& cur_date = *date_iter;
|
||||
|
||||
//忽略小于账户初始建立日期的交易日
|
||||
if (cur_date < m_tm->initDatetime()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cur_hold_sys_list.clear();
|
||||
|
||||
//----------------------------------------------------------
|
||||
//如果当前时刻选择标的发生变化(此时也一定是资金调整分配的时刻)
|
||||
//----------------------------------------------------------
|
||||
bool selected_changed = m_se->changed(cur_date);
|
||||
if (selected_changed) {
|
||||
//重新计算当前时刻选择的系统实例
|
||||
cur_selected_list = m_se->getSelectedSystemList(cur_date);
|
||||
|
||||
//构建当前时刻选择的系统实例集合,便于后续计算
|
||||
cur_selected_sets.clear();
|
||||
sys_iter = cur_selected_list.begin();
|
||||
for (; sys_iter != cur_selected_list.end(); ++sys_iter) {
|
||||
cur_selected_sets.insert(*sys_iter);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//查找当前已分配资金的系统,如果不在当前选中的系统范围内,则回收期没有持仓的系统资金
|
||||
//----------------------------------------------------------
|
||||
sys_iter = cur_allocated_list.begin();
|
||||
for (; sys_iter != cur_allocated_list.end(); ++sys_iter) {
|
||||
SYSPtr& sys = *sys_iter;
|
||||
TMPtr tm = sys->getTM();
|
||||
|
||||
if (tm->getStockNumber() != 0) {
|
||||
//收集当前仍有持仓的系统
|
||||
cur_hold_sys_list.push_back(sys);
|
||||
|
||||
} else {
|
||||
//如果该系统已没有持仓,且不在当前的选中系统范围内,则回收分配的资金
|
||||
if (cur_selected_sets.find(sys) == cur_selected_sets.end()) {
|
||||
price_t cash = tm->currentCash();
|
||||
if (cash > 0) {
|
||||
//要先存入影子账户再取出子账户资金,否则后续交易记录同步会错误
|
||||
m_tm_shadow->checkin(cur_date, cash);
|
||||
tm->checkout(cur_date, cash);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//如果选择列表更新或调整资金时刻,则调整资金分配
|
||||
//----------------------------------------------------------
|
||||
if (selected_changed || m_af->changed(cur_date)) {
|
||||
cur_allocated_list =
|
||||
m_af->getAllocatedSystemList(cur_date, cur_selected_list, cur_hold_sys_list);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// 运行当前分配了资金的系统
|
||||
//----------------------------------------------------------
|
||||
sys_iter = cur_allocated_list.begin();
|
||||
for (; sys_iter != cur_allocated_list.end(); ++sys_iter) {
|
||||
SYSPtr& sys = *sys_iter;
|
||||
sys->runMoment(cur_date);
|
||||
|
||||
//同步交易记录
|
||||
TradeRecordList tr_list = sys->getTM()->getTradeList(cur_date, Null<Datetime>());
|
||||
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(cur_date, Null<Datetime>());
|
||||
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);
|
||||
}
|
||||
|
||||
if (m_tm->currentCash() != m_tm_shadow->currentCash()) {
|
||||
HKU_INFO("m_tm->currentCash() != m_tm_shadow->currentCash()");
|
||||
HKU_INFO("{:<.4f} == {:<.4f}", m_tm->currentCash(), m_tm_shadow->currentCash());
|
||||
}
|
||||
|
||||
} // for datelist
|
||||
for (auto& date : datelist) {
|
||||
runMoment(date);
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace hku */
|
||||
|
@ -40,9 +40,22 @@ public:
|
||||
m_name = name;
|
||||
}
|
||||
|
||||
bool isReady() const {
|
||||
return m_is_ready;
|
||||
}
|
||||
|
||||
bool readyForRun();
|
||||
void run(const KQuery& query);
|
||||
void runMoment(const Datetime& datetime);
|
||||
|
||||
void setQuery(const KQuery& query) {
|
||||
m_query = query;
|
||||
}
|
||||
|
||||
KQuery getQuery() const {
|
||||
return m_query;
|
||||
}
|
||||
|
||||
TMPtr getTM() {
|
||||
return m_tm;
|
||||
}
|
||||
@ -63,24 +76,30 @@ public:
|
||||
m_af = af;
|
||||
}
|
||||
|
||||
SystemList getAllSystem() const {
|
||||
SystemList result;
|
||||
for (auto& sys : m_all_sys_set) {
|
||||
result.push_back(sys);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void reset();
|
||||
|
||||
typedef shared_ptr<Portfolio> PortfolioPtr;
|
||||
PortfolioPtr clone();
|
||||
|
||||
private:
|
||||
bool readyForRun();
|
||||
|
||||
void rebuildOnlyTotalTM();
|
||||
|
||||
protected:
|
||||
string m_name;
|
||||
TMPtr m_tm;
|
||||
SEPtr m_se;
|
||||
AFPtr m_af;
|
||||
|
||||
//以下为临时变量
|
||||
TMPtr m_tm_shadow; //影子账户,用于内部协调分配资金
|
||||
std::set<SYSPtr> m_running_sys_set; // 当前仍在运行的子系统集合
|
||||
std::list<SYSPtr> m_running_sys_list; // 当前仍在运行的子系统列表
|
||||
std::set<SYSPtr> m_all_sys_set; // 记录所有运行过或运行中的子系统集合
|
||||
KQuery m_query; // 关联的查询条件
|
||||
bool m_is_ready; // 是否已做好运行准备
|
||||
|
||||
//============================================
|
||||
// 序列化支持
|
||||
|
@ -24,14 +24,10 @@ HKU_API std::ostream& operator<<(std::ostream& os, const SelectorPtr& st) {
|
||||
return os;
|
||||
}
|
||||
|
||||
SelectorBase::SelectorBase() : m_name("SelectorBase"), m_count(0), m_pre_date(Datetime::min()) {
|
||||
setParam<int>("freq", 1); //已Bar为单位
|
||||
}
|
||||
SelectorBase::SelectorBase() : m_name("SelectorBase"), m_count(0), m_pre_date(Datetime::min()) {}
|
||||
|
||||
SelectorBase::SelectorBase(const string& name)
|
||||
: m_name(name), m_count(0), m_pre_date(Datetime::min()) {
|
||||
setParam<int>("freq", 1);
|
||||
}
|
||||
: m_name(name), m_count(0), m_pre_date(Datetime::min()) {}
|
||||
|
||||
SelectorBase::~SelectorBase() {}
|
||||
|
||||
@ -75,6 +71,7 @@ SelectorPtr SelectorBase::clone() {
|
||||
|
||||
SystemList::const_iterator iter = m_sys_list.begin();
|
||||
for (; iter != m_sys_list.end(); ++iter) {
|
||||
// TODO
|
||||
p->m_sys_list.push_back((*iter)->clone(true, false));
|
||||
}
|
||||
|
||||
@ -115,23 +112,4 @@ void SelectorBase::addStockList(const StockList& stkList, const SystemPtr& proto
|
||||
}
|
||||
}
|
||||
|
||||
bool SelectorBase::changed(Datetime date) {
|
||||
if (date <= m_pre_date || date == Null<Datetime>())
|
||||
return false;
|
||||
|
||||
int freq = getParam<int>("freq");
|
||||
if (freq <= 0) {
|
||||
freq = 1;
|
||||
}
|
||||
|
||||
m_count++;
|
||||
if (m_count >= freq) {
|
||||
m_count = 0;
|
||||
m_pre_date = date;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} /* namespace hku */
|
||||
|
@ -55,8 +55,6 @@ public:
|
||||
return m_sys_list;
|
||||
}
|
||||
|
||||
bool changed(Datetime date);
|
||||
|
||||
void reset();
|
||||
|
||||
void clear();
|
||||
|
@ -600,7 +600,9 @@ void System::_submitBuyRequest(const KRecord& today, Part from) {
|
||||
}
|
||||
}
|
||||
|
||||
void System::_sellFromAllocateFunds(const KRecord& today, double num) {
|
||||
void System::_sellForce(const KRecord& today, double num, Part from) {
|
||||
HKU_ASSERT_M(from == PART_ALLOCATEFUNDS || from == PART_PORTFOLIO,
|
||||
"Only Allocator or Portfolis can perform this operation!");
|
||||
if (getParam<bool>("delay")) {
|
||||
if (m_sellRequest.valid) {
|
||||
if (m_sellRequest.count > getParam<int>("max_delay_count")) {
|
||||
@ -617,7 +619,7 @@ void System::_sellFromAllocateFunds(const KRecord& today, double num) {
|
||||
}
|
||||
|
||||
PositionRecord position = m_tm->getPosition(m_stock);
|
||||
m_sellRequest.from = PART_ALLOCATEFUNDS;
|
||||
m_sellRequest.from = from;
|
||||
m_sellRequest.datetime = today.datetime;
|
||||
m_sellRequest.stoploss = position.stoploss;
|
||||
m_sellRequest.goal = position.goalPrice;
|
||||
@ -627,7 +629,7 @@ void System::_sellFromAllocateFunds(const KRecord& today, double num) {
|
||||
PositionRecord position = m_tm->getPosition(m_stock);
|
||||
price_t realPrice = _getRealSellPrice(today.datetime, today.closePrice);
|
||||
TradeRecord record = m_tm->sell(today.datetime, m_stock, realPrice, num, position.stoploss,
|
||||
position.goalPrice, today.closePrice, PART_ALLOCATEFUNDS);
|
||||
position.goalPrice, today.closePrice, from);
|
||||
m_trade_list.push_back(record);
|
||||
_sellNotifyAll(record);
|
||||
}
|
||||
|
@ -211,7 +211,9 @@ public:
|
||||
void _sellNow(const KRecord& today, Part from);
|
||||
void _sellDelay(const KRecord& today);
|
||||
void _submitSellRequest(const KRecord& today, Part from);
|
||||
void _sellFromAllocateFunds(const KRecord& today, double num);
|
||||
|
||||
// 强制卖出,用于资金分配管理器和资产组合指示系统进行强制卖出操作
|
||||
void _sellForce(const KRecord& today, double num, Part from);
|
||||
|
||||
void _sellShort(const KRecord& today, Part from);
|
||||
void _sellShortNow(const KRecord& today, Part from);
|
||||
|
@ -28,8 +28,9 @@ enum SystemPart {
|
||||
PART_SLIPPAGE = 7, /**< 移滑价差算法 */
|
||||
|
||||
PART_ALLOCATEFUNDS = 8, /**< 资产分配算法 */
|
||||
PART_PORTFOLIO = 9, /**< 资产组合 */
|
||||
|
||||
PART_INVALID = 9, /**< 无效值 */
|
||||
PART_INVALID = 10, /**< 无效值 */
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user