实现资产分配算法及资产组合框架(继续)

This commit is contained in:
fasiondog 2018-02-09 01:05:05 +08:00
parent 96d2ccf276
commit 60927dda8b
19 changed files with 462 additions and 60 deletions

View File

@ -5,17 +5,35 @@
* Author: fasiondog
*/
#include <boost/bind.hpp>
#include "AllocateFundsBase.h"
namespace hku {
AllocateFundsBase::AllocateFundsBase(): m_name("AllocateMoneyBase") {
HKU_API std::ostream & operator<<(std::ostream& os, const AllocateFundsBase& af) {
os << "AllocateFunds(" << af.name() << ", " << af.getParameter() << ")";
return os;
}
HKU_API std::ostream & operator<<(std::ostream& os, const AFPtr& af) {
if (af) {
os << *af;
} else {
os << "AllocateFunds(NULL)";
}
return os;
}
AllocateFundsBase::AllocateFundsBase(): m_name("AllocateMoneyBase") {
setParam<bool>("adjust_hold_sys", false); //是否调整之前已经持仓策略的持仓
setParam<int>("max_sys_num", 10); //最大系统实例数
}
AllocateFundsBase::AllocateFundsBase(const string& name)
: m_name("AllocateMoneyBase") {
setParam<bool>("adjust_hold_sys", false);
setParam<int>("max_sys_num", 10); //最大系统实例数
}
AllocateFundsBase::~AllocateFundsBase() {
@ -43,9 +61,71 @@ AFPtr AllocateFundsBase::clone() {
}
SystemList AllocateFundsBase
::getAllocateWeight(const SystemList& se_list, const SystemList& hold_list) {
::getAllocateSystem(const Datetime& date,
const SystemList& se_list, const SystemList& hold_list) {
SystemList result;
SystemWeightList sw_list = allocateWeight(se_list, hold_list);
/*sort(sw_list.begin(), sw_list.end(),
boost::bind(std::less<price_t>(),
boost::bind(&SystemWeight::weight, _1),
boost::bind(&SystemWeight::weight, _2)));
*/
price_t total_weight = 0.0;
auto sw_iter = sw_list.begin();
for (; sw_iter != sw_list.end(); ++sw_iter) {
total_weight += sw_iter->weight;
}
if (total_weight == 0.0) {
return result;
}
int precision = m_tm->getParam<int>("precision");
price_t per_cash = roundDown(m_tm->currentCash() / total_weight, precision);
sw_iter = sw_list.begin();
for (; sw_iter != sw_list.end(); ++sw_iter) {
price_t will_cash = roundDown(per_cash * sw_iter->weight, precision);
if (will_cash == 0.0) {
continue;
}
TMPtr tm = sw_iter->sys->getTM();
precision = tm->getParam<int>("precision");
will_cash = roundDown(will_cash, precision);
if (tm->currentCash() < will_cash) {
price_t cash = will_cash - tm->currentCash();
tm->checkin(date, cash);
m_tm->checkout(date, cash);
}
result.push_back(sw_iter->sys);
}
return result;
}
SystemWeightList AllocateFundsBase
::allocateWeight(const SystemList& se_list, const SystemList& hold_list) {
SystemWeightList result;
result = _allocateWeight(se_list, hold_list);
size_t total = result.size();
if (total <= getParam<int>("max_sys_num")) {
return result;
}
auto iter = result.begin() + total;
SystemWeightList sw_list;
copy(result.begin(), iter, sw_list.begin());
swap(result, sw_list);
return result;
}
} /* namespace hku */

View File

@ -27,6 +27,31 @@ public:
AllocateFundsBase(const string& name);
virtual ~AllocateFundsBase();
string name() const;
void name(const string& name);
/**
* Portfolio获取实际获得资产分配的系统策略实例
* @param date
* @param se_list
* @param hold_list
* @return
*/
SystemList getAllocateSystem(const Datetime& date,
const SystemList& se_list,
const SystemList& hold_list);
/**
*
* @details _allocateWeight
*
* @param se_list
* @param hold_list
* @return
*/
SystemWeightList allocateWeight(const SystemList& se_list,
const SystemList& hold_list);
/** 获取交易账户 */
TMPtr getTM();
@ -44,9 +69,16 @@ public:
virtual void _reset() {}
/** 子类克隆私有变量接口 */
virtual AFPtr _clone() {return AFPtr(); }
virtual AFPtr _clone() = 0;
SystemList getAllocateWeight(const SystemList&, const SystemList&);
/**
*
* @param se_list
* @param hold_list
* @return
*/
virtual SystemWeightList _allocateWeight(const SystemList& se_list,
const SystemList& hold_list) = 0;
private:
string m_name;
@ -77,9 +109,58 @@ private:
#endif /* HKU_SUPPORT_SERIALIZATION */
};
#if HKU_SUPPORT_SERIALIZATION
BOOST_SERIALIZATION_ASSUME_ABSTRACT(SelectorBase)
#endif
#if HKU_SUPPORT_SERIALIZATION
/**
* 使
* @code
* class Drived: public AllocateFundsBase {
* ALLOCATEFUNDS_NO_PRIVATE_MEMBER_SERIALIZATION
*
* public:
* Drived();
* ...
* };
* @endcode
* @ingroup Selector
*/
#define ALLOCATEFUNDS_NO_PRIVATE_MEMBER_SERIALIZATION private:\
friend class boost::serialization::access; \
template<class Archive> \
void serialize(Archive & ar, const unsigned int version) { \
ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(AllocateFundsBase); \
}
#else
#define ALLOCATEFUNDS_NO_PRIVATE_MEMBER_SERIALIZATION
#endif
#define ALLOCATEFUNDS_IMP(classname) public:\
virtual AFPtr _clone() {\
return AFPtr(new classname());\
}\
virtual SystemWeightList _allocateWeight(const SystemList&, const SystemList&);
typedef shared_ptr<AllocateFundsBase> AllocateFundsPtr;
typedef shared_ptr<AllocateFundsBase> AFPtr;
HKU_API std::ostream & operator<<(std::ostream&, const AllocateFundsBase&);
HKU_API std::ostream & operator<<(std::ostream&, const AFPtr&);
inline string AllocateFundsBase::name() const {
return m_name;
}
inline void AllocateFundsBase::name(const string& name) {
m_name = name;
}
inline TMPtr AllocateFundsBase::getTM() {
return m_tm;
}

View File

@ -9,12 +9,30 @@
namespace hku {
SystemWeight::SystemWeight(): m_weight(100) {
HKU_API std::ostream & operator<<(std::ostream & os, const SystemWeight& sw) {
os << std::fixed;
os.precision(4);
string name("NULL");
if (sw.sys) {
name = sw.sys->name();
}
os << "SystemWeight(sys: " << name
<< ", weight: " << sw.weight
<< ")"<< std::endl;
os.unsetf(std::ostream::floatfield);
os.precision();
return os;
}
SystemWeight::SystemWeight(): weight(100) {
}
SystemWeight::SystemWeight(const SystemPtr& sys, price_t weight)
: m_sys(sys), m_weight(weight) {
: sys(sys), weight(weight) {
}

View File

@ -24,9 +24,11 @@ public:
void setWeight(price_t weight);
price_t getWeight() const;
public:
SystemPtr sys;
price_t weight;
private:
SystemPtr m_sys;
price_t m_weight;
//============================================
// 序列化支持
@ -36,14 +38,14 @@ private:
friend class boost::serialization::access;
template<class Archive>
void save(Archive & ar, const unsigned int version) const {
ar & BOOST_SERIALIZATION_NVP(m_sys);
ar & BOOST_SERIALIZATION_NVP(m_weight);
ar & BOOST_SERIALIZATION_NVP(sys);
ar & BOOST_SERIALIZATION_NVP(weight);
}
template<class Archive>
void load(Archive & ar, const unsigned int version) {
ar & BOOST_SERIALIZATION_NVP(m_sys);
ar & BOOST_SERIALIZATION_NVP(m_weight);
ar & BOOST_SERIALIZATION_NVP(sys);
ar & BOOST_SERIALIZATION_NVP(weight);
}
BOOST_SERIALIZATION_SPLIT_MEMBER()
@ -52,22 +54,7 @@ private:
typedef vector<SystemWeight> SystemWeightList;
inline void SystemWeight::setSYS(const SystemPtr& sys) {
m_sys = sys;
}
inline SystemPtr SystemWeight::getSYS() const {
return m_sys;
}
inline void SystemWeight::setWeight(price_t weight) {
m_weight = weight;
}
inline price_t SystemWeight::getWeight() const {
return m_weight;
}
HKU_API std::ostream & operator<<(std::ostream &, const SystemWeight&);
} /* namespace hku */

View File

@ -8,7 +8,7 @@
#ifndef TRADE_SYS_ALLOCATEFUNDS_BUILD_IN_H_
#define TRADE_SYS_ALLOCATEFUNDS_BUILD_IN_H_
#include "crt/AF_EqualWeight.h"
#endif /* TRADE_SYS_ALLOCATEFUNDS_BUILD_IN_H_ */

View File

@ -0,0 +1,21 @@
/*
* AF_EqualWeight.h
*
* Created on: 201828
* Author: fasiondog
*/
#ifndef TRADE_SYS_ALLOCATEFUNDS_CRT_AF_EQUALWEIGHT_H_
#define TRADE_SYS_ALLOCATEFUNDS_CRT_AF_EQUALWEIGHT_H_
#include "../AllocateFundsBase.h"
namespace hku {
AFPtr HKU_API AF_EqualWeight();
} /* namespace hku */
#endif /* TRADE_SYS_ALLOCATEFUNDS_CRT_AF_EQUALWEIGHT_H_ */

View File

@ -0,0 +1,53 @@
/*
* EqualWeightAllocateFunds.cpp
*
* Created on: 201828
* Author: fasiondog
*/
#include "EqualWeightAllocateFunds.h"
namespace hku {
EqualWeightAllocateFunds::EqualWeightAllocateFunds()
:AllocateFundsBase("AF_EqualWeight") {
}
EqualWeightAllocateFunds::~EqualWeightAllocateFunds() {
}
SystemWeightList EqualWeightAllocateFunds
::_allocateWeight(const SystemList& se_list, const SystemList& hold_list) {
SystemWeightList result;
SystemList temp_list;
if (getParam<bool>("adjust_hold_sys")) {
copy(se_list.begin(), se_list.end(), temp_list.begin());
copy(hold_list.begin(), hold_list.end(), temp_list.end());
} else {
copy(se_list.begin(), se_list.end(), temp_list.begin());
}
size_t total = temp_list.size();
if (total == 0) {
return result;
}
price_t weight = 100.0 / total;
for (auto iter = temp_list.begin(); iter != temp_list.end(); ++iter) {
SystemWeight sw;
sw.sys = *iter;
sw.weight = weight;
result.push_back(sw);
}
return result;
}
AFPtr HKU_API AF_EqualWeight() {
return make_shared<EqualWeightAllocateFunds>();
}
} /* namespace hku */

View File

@ -0,0 +1,25 @@
/*
* EqualWeightAllocateFunds.h
*
* Created on: 201828
* Author: fasiondog
*/
#ifndef TRADE_SYS_ALLOCATEFUNDS_IMP_EQUALWEIGHTALLOCATEFUNDS_H_
#define TRADE_SYS_ALLOCATEFUNDS_IMP_EQUALWEIGHTALLOCATEFUNDS_H_
#include "../AllocateFundsBase.h"
namespace hku {
class EqualWeightAllocateFunds: public AllocateFundsBase {
ALLOCATEFUNDS_IMP(EqualWeightAllocateFunds)
public:
EqualWeightAllocateFunds();
virtual ~EqualWeightAllocateFunds();
};
} /* namespace hku */
#endif /* TRADE_SYS_ALLOCATEFUNDS_IMP_EQUALWEIGHTALLOCATEFUNDS_H_ */

View File

@ -37,8 +37,9 @@ Portfolio::Portfolio(const string& name) : m_name(name) {
Portfolio::Portfolio(const TradeManagerPtr& tm,
const SystemPtr& sys,
const SelectorPtr& se)
: m_se(se), m_tm(tm), m_name("Portfolio") {
const SelectorPtr& se,
const AFPtr& af)
: m_name("Portfolio"), m_se(se), m_tm(tm), m_af(af) {
initParam();
}
@ -330,6 +331,13 @@ void Portfolio::run(const KQuery& query) {
} else {
cur_hold_sys_sets.erase(*sys_iter);
}
//同步交易记录
TradeRecordList tr_list = (*sys_iter)->getTM()->getTradeList(*date_iter, Null<Datetime>());
auto tr_iter = tr_list.begin();
for (; tr_iter != tr_list.end(); ++tr_iter) {
m_tm->addTradeRecord(*tr_iter);
}
}
SystemList cur_hold_sys_list;
@ -340,22 +348,7 @@ void Portfolio::run(const KQuery& query) {
//计算当前时刻选择的系统实例
SystemList selected_list = m_se->getSelectedSystemList(*date_iter);
SystemList sw_list = m_af->getAllocateWeight(selected_list, cur_hold_sys_list);
//资金分配都由AF自动处理好 需要调仓卖出的都由AF处理这里只处理调仓完的系统列表
/*auto sw_iter = sw_map.begin();
for (; sw_iter != sw_map.end(); ++sw_iter) {
if (sw_iter->second == 0.0) {
SYSPtr sys = sw_iter->first;
TMPtr tm = sys->getTM();
PositionRecordList pos_list = tm->getPositionList();
auto pos_iter = pos_list.begin();
for (; pos_iter != pos_list.end(); ++pos_iter) {
KRecord kr = pos_iter->stock.getKRecordByDate(*date_iter, query.kType());
sys->_sell(kr, PART_ALLOCATEFUNDS);
}
}
}*/
SystemList sw_list = m_af->getAllocateSystem(*date_iter, selected_list, cur_hold_sys_list);
auto sw_iter = sw_list.begin();
for (; sw_iter != sw_list.end(); ++sw_iter) {

View File

@ -41,7 +41,8 @@ public:
Portfolio(const string& name);
Portfolio(const TradeManagerPtr& tm,
const SystemPtr& sys,
const SelectorPtr& st);
const SelectorPtr& st,
const AFPtr& af);
virtual ~Portfolio();
string name() const { return m_name; }

View File

@ -11,13 +11,15 @@
#include "../Portfolio.h"
#include "../../system/crt/SYS_Simple.h"
#include "../../selector/crt/SE_Fixed.h"
#include "../../allocatefunds/crt/AF_EqualWeight.h"
namespace hku {
PortfolioPtr HKU_API PF_Simple(
const TradeManagerPtr& tm = TradeManagerPtr(),
const SystemPtr& sys = SYS_Simple(),
const SelectorPtr& st = SE_Fixed());
const TMPtr& tm = TradeManagerPtr(),
const SYSPtr& sys = SYS_Simple(),
const SEPtr& st = SE_Fixed(),
const AFPtr& af = AF_EqualWeight());
} /* namespace hku */

View File

@ -10,10 +10,11 @@
namespace hku {
PortfolioPtr HKU_API PF_Simple(
const TradeManagerPtr& tm,
const SystemPtr& sys,
const SelectorPtr& st) {
return make_shared<Portfolio>(tm, sys, st);
const TMPtr& tm,
const SYSPtr& sys,
const SEPtr& st,
const AFPtr& af) {
return make_shared<Portfolio>(tm, sys, st, af);
}
} /* namespace hku */

View File

@ -13,7 +13,7 @@
namespace hku {
class FixedSelector: public SelectorBase {
SELECTOR_IMP(FixedSelector);
SELECTOR_IMP(FixedSelector)
SELECTOR_NO_PRIVATE_MEMBER_SERIALIZATION
public:

View File

@ -0,0 +1,92 @@
/*
* _Selector.cpp
*
* Created on: 2016328
* Author: fasiondog
*/
#include <boost/python.hpp>
#include <hikyuu/trade_sys/allocatefunds/build_in.h>
#include "../_Parameter.h"
#include "../pickle_support.h"
using namespace boost::python;
using namespace hku;
class AllocateFundsBaseWrap : public AllocateFundsBase, public wrapper<AllocateFundsBase> {
public:
AllocateFundsBaseWrap(): AllocateFundsBase() {}
AllocateFundsBaseWrap(const string& name): AllocateFundsBase(name) {}
virtual ~AllocateFundsBaseWrap() {}
void _reset() {
if (override func = this->get_override("_reset")) {
func();
} else {
AllocateFundsBase::_reset();
}
}
void default_reset() {
this->AllocateFundsBase::_reset();
}
SystemWeightList _allocateWeight(const SystemList& se_list,
const SystemList& hold_list) {
return this->get_override("_allocateWeight")(se_list, hold_list);
}
AFPtr _clone() {
return this->get_override("_clone")();
}
};
string (AllocateFundsBase::*af_get_name)() const = &AllocateFundsBase::name;
void (AllocateFundsBase::*af_set_name)(const string&) = &AllocateFundsBase::name;
void export_AllocateFunds() {
class_<SystemWeight>("SystemWeight", init<>())
.def(init<const SystemPtr&, price_t>())
.def(self_ns::str(self))
.def_readwrite("sys", &SystemWeight::sys)
.def_readwrite("weight", &SystemWeight::weight)
#if HKU_PYTHON_SUPPORT_PICKLE
.def_pickle(normal_pickle_suite<SystemWeight>())
#endif
;
SystemWeightList::const_reference (SystemWeightList::*SystemWeightList_at)(SystemWeightList::size_type) const = &SystemWeightList::at;
void (SystemWeightList::*append)(const SystemWeight&) = &SystemWeightList::push_back;
class_<SystemWeightList>("SystemWeightList")
.def("__iter__", iterator<SystemWeightList>())
.def("size", &SystemWeightList::size)
.def("__len__", &SystemWeightList::size)
.def("__getitem__", SystemWeightList_at, return_value_policy<copy_const_reference>())
.def("append", append)
;
class_<AllocateFundsBaseWrap, boost::noncopyable>("AllocateFundsBase", init<>())
.def(init<const string&>())
.def(self_ns::str(self))
.add_property("name", af_get_name, af_set_name)
.def("getParam", &AllocateFundsBase::getParam<boost::any>)
.def("setParam", &AllocateFundsBase::setParam<object>)
.def("reset", &AllocateFundsBase::reset)
.def("clone", &AllocateFundsBase::clone)
.def("_reset", &AllocateFundsBase::_reset, &AllocateFundsBaseWrap::default_reset)
.def("_clone", pure_virtual(&AllocateFundsBase::_clone))
.def("_allocateWeight", pure_virtual(&AllocateFundsBase::_allocateWeight))
#if HKU_PYTHON_SUPPORT_PICKLE
.def_pickle(name_init_pickle_suite<AllocateFundsBase>())
#endif
;
register_ptr_to_python<AFPtr>();
def("AF_EqualWeight", AF_EqualWeight);
}

View File

@ -13,7 +13,7 @@
using namespace boost::python;
using namespace hku;
BOOST_PYTHON_FUNCTION_OVERLOADS(PF_Simple_overload, PF_Simple, 0, 3);
BOOST_PYTHON_FUNCTION_OVERLOADS(PF_Simple_overload, PF_Simple, 0, 4);
void (Portfolio::*pf_set_name)(const string&) = &Portfolio::name;
string (Portfolio::*pf_get_name)() const= &Portfolio::name;
@ -24,7 +24,8 @@ void export_Portfolio() {
.def(init<const string&>())
.def(init<const TradeManagerPtr&,
const SystemPtr&,
const SelectorPtr&>())
const SelectorPtr&,
const AFPtr&>())
.def(self_ns::str(self))
.def("getParam", &Portfolio::getParam<boost::any>)
.def("setParam", &Portfolio::setParam<object>)

View File

@ -19,6 +19,7 @@ void export_Slippage();
void export_System();
void export_Selector();
void export_Portfolio();
void export_AllocateFunds();
BOOST_PYTHON_MODULE(_trade_sys) {
docstring_options doc_options(false);
@ -31,6 +32,7 @@ BOOST_PYTHON_MODULE(_trade_sys) {
export_Slippage();
export_System();
export_Selector();
export_AllocateFunds();
export_Portfolio();
}

View File

@ -47,6 +47,7 @@ from hikyuu.trade_sys.stoploss import *
from hikyuu.trade_sys.profitgoal import *
from hikyuu.trade_sys.slippage import *
from hikyuu.trade_sys.selector import *
from hikyuu.trade_sys.allocatefunds import *
from hikyuu.trade_sys.portfolio import *
from hikyuu.interactive import *

View File

@ -26,5 +26,6 @@
__all__ = ['system', 'environment', 'condition', 'moneymanager', 'signal',
'stoploss', 'profitgoal', 'slippage', 'selector', 'portfolio']
'stoploss', 'profitgoal', 'slippage', 'selector', 'portfolio',
'allocatefunds']

View File

@ -0,0 +1,43 @@
#!/usr/bin/python
# -*- coding: utf8 -*-
# cp936
#
# The MIT License (MIT)
#
# Copyright (c) 2010-2017 fasiondog
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
from ._trade_sys import (AllocateFundsBase, AF_EqualWeight)
from hikyuu.util.unicode import (unicodeFunc, reprFunc)
AllocateFundsBase.__unicode__ = unicodeFunc
AllocateFundsBase.__repr__ = reprFunc
#------------------------------------------------------------------
# add doc-string
#------------------------------------------------------------------
#------------------------------------------------------------------
# add doc-string for build_in func
#------------------------------------------------------------------