This commit is contained in:
fasiondog 2023-12-28 02:21:36 +08:00
parent c88faf51e0
commit 896b3d1ac7
12 changed files with 188 additions and 244 deletions

View File

@ -2,10 +2,10 @@
# -*- coding: utf8 -*- # -*- coding: utf8 -*-
# gb18030 # gb18030
#=============================================================================== # ===============================================================================
# 作者fasiondog # 作者fasiondog
# 历史120130220, Added by fasiondog # 历史120130220, Added by fasiondog
#=============================================================================== # ===============================================================================
import unittest import unittest
@ -56,7 +56,7 @@ class IndicatorTest(unittest.TestCase):
b = toPriceList([1, 2, 3, 4]) b = toPriceList([1, 2, 3, 4])
x = PRICELIST(b) x = PRICELIST(b)
m.get_imp()._calculate(m) m.get_imp()._calculate(m)
m = m(x) # m = m(x)
self.assertEqual(len(m), 4) self.assertEqual(len(m), 4)
self.assertEqual(m.empty(), False) self.assertEqual(m.empty(), False)
self.assert_(abs(m[0] - 2) < 0.0001) self.assert_(abs(m[0] - 2) < 0.0001)
@ -147,7 +147,7 @@ class IndicatorTest(unittest.TestCase):
if not constant.pickle_support: if not constant.pickle_support:
return return
#TODO Python3出错暂未解决 # TODO Python3出错暂未解决
""" """
import pickle as pl import pickle as pl
filename = sm.tmpdir() + '/Indicator.plk' filename = sm.tmpdir() + '/Indicator.plk'

View File

@ -3,32 +3,14 @@
from hikyuu.util.slice import list_getitem from hikyuu.util.slice import list_getitem
from hikyuu.cpp.core import SYS_Simple as cpp_SYS_Simple from hikyuu.cpp.core import SYS_Simple as cpp_SYS_Simple
from hikyuu.cpp.core import ( from hikyuu.cpp.core import (
System, SystemList, SystemWeight, SystemWeightList, ConditionBase, EnvironmentBase, MoneyManagerBase, System, SystemPart, SystemList, SystemWeightList, ConditionBase, EnvironmentBase, MoneyManagerBase,
ProfitGoalBase, SelectorBase, SignalBase, SlippageBase, StoplossBase ProfitGoalBase, SelectorBase, SignalBase, SlippageBase, StoplossBase
) )
#------------------------------------------------------------------ # ------------------------------------------------------------------
# System # System
#------------------------------------------------------------------ # ------------------------------------------------------------------
System.Part = SystemPart
System.Part.__doc__ = """
/
:py:class:`TradeRecord`
使使 System.ENVIRONMENT System.Part.ENVIRONMENT
- System.Part.ENVIRONMENT -
- System.Part.CONDITION -
- System.Part.SIGNAL -
- System.Part.STOPLOSS -
- System.Part.TAKEPROFIT -
- System.Part.MONEYMANAGER -
- System.Part.PROFITGOAL -
- System.Part.SLIPPAGE -
- System.Part.INVALID -
"""
System.ENVIRONMENT = System.Part.ENVIRONMENT System.ENVIRONMENT = System.Part.ENVIRONMENT
System.CONDITION = System.Part.CONDITION System.CONDITION = System.Part.CONDITION
System.SIGNAL = System.Part.SIGNAL System.SIGNAL = System.Part.SIGNAL
@ -98,27 +80,18 @@ def SYS_Simple(tm=None, mm=None, ev=None, cn=None, sg=None, st=None, tp=None, pg
return sys_ins return sys_ins
#------------------------------------------------------------------ # ------------------------------------------------------------------
# allocatefunds # allocatefunds
#------------------------------------------------------------------ # ------------------------------------------------------------------
SystemWeightList.__getitem__ = list_getitem SystemWeightList.__getitem__ = list_getitem
SystemWeightList.__str__ = lambda self: str(list(self)) SystemWeightList.__str__ = lambda self: str(list(self))
SystemWeightList.__repr__ = lambda self: repr(list(self)) SystemWeightList.__repr__ = lambda self: repr(list(self))
#------------------------------------------------------------------
# ------------------------------------------------------------------
# condition # condition
#------------------------------------------------------------------ # ------------------------------------------------------------------
ConditionBase.__init__.__doc__ = """
__init__(self[, name="ConditionBase"])
:param str name:
"""
def cn_init(self, name, params): def cn_init(self, name, params):
super(self.__class__, self).__init__(name) super(self.__class__, self).__init__(name)
self._name = name self._name = name
@ -142,19 +115,9 @@ def crtCN(func, params={}, name='crtCN'):
return meta_x(name, params) return meta_x(name, params)
#------------------------------------------------------------------ # ------------------------------------------------------------------
# environment # environment
#------------------------------------------------------------------ # ------------------------------------------------------------------
EnvironmentBase.__init__.__doc__ = """
__init__(self[, name='EnvironmentBase'])
:param str name:
"""
def ev_init(self, name, params): def ev_init(self, name, params):
super(self.__class__, self).__init__(name) super(self.__class__, self).__init__(name)
self._name = name self._name = name
@ -178,19 +141,9 @@ def crtEV(func, params={}, name='crtEV'):
return meta_x(name, params) return meta_x(name, params)
#------------------------------------------------------------------ # ------------------------------------------------------------------
# moneymanager # moneymanager
#------------------------------------------------------------------ # ------------------------------------------------------------------
MoneyManagerBase.__init__.__doc__ = """
__init__(self[, name="MoneyManagerBase])
:param str name:
"""
def mm_init(self, name, params): def mm_init(self, name, params):
super(self.__class__, self).__init__(name) super(self.__class__, self).__init__(name)
self._name = name self._name = name
@ -214,19 +167,9 @@ def crtMM(func, params={}, name='crtMM'):
return meta_x(name, params) return meta_x(name, params)
#------------------------------------------------------------------ # ------------------------------------------------------------------
# profitgoal # profitgoal
#------------------------------------------------------------------ # ------------------------------------------------------------------
ProfitGoalBase.__init__.__doc__ = """
__init__(self[, name="ProfitGoalBase"])
:param str name:
"""
def pg_init(self, name, params): def pg_init(self, name, params):
super(self.__class__, self).__init__(name) super(self.__class__, self).__init__(name)
self._name = name self._name = name
@ -250,29 +193,9 @@ def crtPG(func, params={}, name='crtPG'):
return meta_x(name, params) return meta_x(name, params)
#------------------------------------------------------------------ # ------------------------------------------------------------------
# selector
#------------------------------------------------------------------
SelectorBase.__init__.__doc__ = """
__init__(self[, name="SelectorBase])
:param str name:
"""
#------------------------------------------------------------------
# signal # signal
#------------------------------------------------------------------ # ------------------------------------------------------------------
SignalBase.__init__.__doc__ = """
__init__(self[, name="SignalBase"])
:param str name:
"""
def sig_init(self, name, params): def sig_init(self, name, params):
super(self.__class__, self).__init__(name) super(self.__class__, self).__init__(name)
self._name = name self._name = name
@ -296,9 +219,9 @@ def crtSG(func, params={}, name='crtSG'):
return meta_x(name, params) return meta_x(name, params)
#------------------------------------------------------------------ # ------------------------------------------------------------------
# Selector # Selector
#------------------------------------------------------------------ # ------------------------------------------------------------------
def se_add_stock_list(self, stk_list, proto_sys): def se_add_stock_list(self, stk_list, proto_sys):
result = True result = True
for stk in stk_list: for stk in stk_list:
@ -311,17 +234,9 @@ def se_add_stock_list(self, stk_list, proto_sys):
SelectorBase.add_stock_list = se_add_stock_list SelectorBase.add_stock_list = se_add_stock_list
#------------------------------------------------------------------ # ------------------------------------------------------------------
# slippage # slippage
#------------------------------------------------------------------ # ------------------------------------------------------------------
SlippageBase.__init__.__doc__ = """
__init__(self[, name="SlippageBase"])
:param str name:
"""
def sl_init(self, name, params): def sl_init(self, name, params):
@ -347,17 +262,9 @@ def crtSL(func, params={}, name='crtSL'):
return meta_x(name, params) return meta_x(name, params)
#------------------------------------------------------------------ # ------------------------------------------------------------------
# stoploss # stoploss
#------------------------------------------------------------------ # ------------------------------------------------------------------
StoplossBase.__init__.__doc__ = """
__init__(self[, name="StoplossBase"])
:param str name:
"""
def st_init(self, name, params): def st_init(self, name, params):
super(self.__class__, self).__init__(name) super(self.__class__, self).__init__(name)
self._name = name self._name = name

View File

@ -29,4 +29,27 @@ void export_DataType(py::module& m) {
m.def("isnan", isnan_func, "是否为非数字"); m.def("isnan", isnan_func, "是否为非数字");
m.def("isinf", isinf_func, "是否是无穷大或无穷小"); m.def("isinf", isinf_func, "是否是无穷大或无穷小");
#endif #endif
py::bind_vector<DatetimeList>(m, "DatetimeList"); //, py::module_local(false));
py::bind_vector<PriceList>(m, "PriceList"); //, py::module_local(false));
py::bind_vector<StringList>(m, "StringList"); //, py::module_local(false));
m.def(
"toPriceList",
[](py::object obj) {
if (py::isinstance<py::list>(obj)) {
py::list x = obj.cast<py::list>();
return python_list_to_vector<price_t>(x);
} else {
py::tuple x = obj.cast<py::tuple>();
auto total = len(x);
std::vector<price_t> vect(total);
for (auto i = 0; i < total; ++i) {
vect[i] = x[i].cast<price_t>();
}
return vect;
}
HKU_THROW("Only support list or tuple");
},
"将 python list/tuple/np.arry 对象转化为 PriceList 对象");
} }

View File

@ -83,11 +83,11 @@ void export_Datetime(py::module& m) {
.def("end_of_halfyear", &Datetime::endOfHalfyear, "\n返回半年度结束日期") .def("end_of_halfyear", &Datetime::endOfHalfyear, "\n返回半年度结束日期")
.def("start_of_year", &Datetime::startOfYear, "\n返回年度起始日期") .def("start_of_year", &Datetime::startOfYear, "\n返回年度起始日期")
.def("endOfYear", &Datetime::endOfYear, "\n返回年度结束日期") .def("endOfYear", &Datetime::endOfYear, "\n返回年度结束日期")
.def("min", &Datetime::min, "\n获取支持的最小日期, Datetime(1400, 1, 1)") .def_static("min", &Datetime::min, "\n获取支持的最小日期, Datetime(1400, 1, 1)")
.def("max", &Datetime::max, "\n获取支持的最大日期, Datetime(9999, 12, 31)") .def_static("max", &Datetime::max, "\n获取支持的最大日期, Datetime(9999, 12, 31)")
.def("now", &Datetime::now, "\n获取系统当前日期时间") .def_static("now", &Datetime::now, "\n获取系统当前日期时间")
.def("today", &Datetime::today, "\n获取当前的日期") .def_static("today", &Datetime::today, "\n获取当前的日期")
.def("from_hex", &Datetime::fromHex, "\n兼容oracle用后7个字节表示的datetime") .def_static("from_hex", &Datetime::fromHex, "\n兼容oracle用后7个字节表示的datetime")
.def(py::self == py::self) .def(py::self == py::self)
.def(py::self != py::self) .def(py::self != py::self)

View File

@ -23,6 +23,7 @@ static std::string Parameter_to_str(const Parameter& param) {
void export_Parameter(py::module& m) { void export_Parameter(py::module& m) {
py::class_<Parameter>(m, "Parameter", "参数类,供需要命名参数设定的类使用,类似于 dict") py::class_<Parameter>(m, "Parameter", "参数类,供需要命名参数设定的类使用,类似于 dict")
.def(py::init<>())
.def("__str__", Parameter_to_str) .def("__str__", Parameter_to_str)
.def("__repr__", Parameter_to_str) .def("__repr__", Parameter_to_str)

View File

@ -1,133 +1,134 @@
// /* /*
// * Copyright (c) 2023 hikyuu.org * Copyright (c) 2023 hikyuu.org
// * *
// * Created on: 2023-10-10 * Created on: 2023-10-10
// * Author: fasiondog * Author: fasiondog
// */ */
// #include <hikyuu/analysis/combinate.h> #include <hikyuu/analysis/combinate.h>
// #include "pybind_utils.h" #include "pybind_utils.h"
// using namespace hku; using namespace hku;
// namespace py = pybind11; namespace py = pybind11;
// static py::list combinate_index(object seq) { static py::list combinate_index(py::object seq) {
// size_t total = len(seq); size_t total = len(seq);
// std::vector<size_t> index_list(total); std::vector<size_t> index_list(total);
// for (size_t i = 0; i < total; ++i) { for (size_t i = 0; i < total; ++i) {
// index_list[i] = i; index_list[i] = i;
// } }
// py::list result; py::list result;
// std::vector<std::vector<size_t>> comb = combinateIndex(index_list); std::vector<std::vector<size_t>> comb = combinateIndex(index_list);
// for (size_t i = 0, count = comb.size(); i < count; i++) { for (size_t i = 0, count = comb.size(); i < count; i++) {
// py::list tmp = vector_to_py_list<std::vector<size_t>>(comb[i]); py::list tmp = vector_to_python_list<size_t>(comb[i]);
// result.append(tmp); result.append(tmp);
// } }
// return result; return result;
// } }
// static py::list combinate_indicator(object seq, int n) { static py::list combinate_indicator(const py::sequence& seq, int n) {
// size_t total = len(seq); size_t total = len(seq);
// std::vector<Indicator> inds(total); std::vector<Indicator> inds(total);
// for (size_t i = 0; i < total; ++i) { for (size_t i = 0; i < total; ++i) {
// inds[i] = py::extract<Indicator>(seq[i])(); inds[i] = seq[i].cast<Indicator>();
// } }
// auto comb = combinateIndicator(inds, n); auto comb = combinateIndicator(inds, n);
// return vector_to_py_list(comb); return vector_to_python_list(comb);
// } }
// static py::dict combinate_ind_analysis(const Stock& stk, const KQuery& query, TradeManagerPtr tm, static py::dict combinate_ind_analysis(const Stock& stk, const KQuery& query, TradeManagerPtr tm,
// SystemPtr sys, object buy_inds, object sell_inds, int n) { SystemPtr sys, py::sequence buy_inds, py::sequence sell_inds,
// std::vector<Indicator> c_buy_inds; int n) {
// for (size_t i = 0, total = len(buy_inds); i < total; i++) { std::vector<Indicator> c_buy_inds;
// c_buy_inds.emplace_back(py::extract<Indicator>(buy_inds[i])()); for (size_t i = 0, total = len(buy_inds); i < total; i++) {
// } c_buy_inds.emplace_back(buy_inds[i].cast<Indicator>());
}
// std::vector<Indicator> c_sell_inds; std::vector<Indicator> c_sell_inds;
// for (size_t i = 0, total = len(sell_inds); i < total; i++) { for (size_t i = 0, total = len(sell_inds); i < total; i++) {
// c_sell_inds.emplace_back(py::extract<Indicator>(sell_inds[i])()); c_sell_inds.emplace_back(sell_inds[i].cast<Indicator>());
// } }
// py::dict result; py::dict result;
// auto pers = combinateIndicatorAnalysis(stk, query, tm, sys, c_buy_inds, c_sell_inds, n); auto pers = combinateIndicatorAnalysis(stk, query, tm, sys, c_buy_inds, c_sell_inds, n);
// for (auto iter = pers.begin(); iter != pers.end(); ++iter) { for (auto iter = pers.begin(); iter != pers.end(); ++iter) {
// result[iter->first] = std::move(iter->second); result[iter->first.c_str()] = std::move(iter->second);
// } }
// return result; return result;
// } }
// static py::dict combinate_ind_analysis_with_block(const Block& blk, const KQuery& query, static py::dict combinate_ind_analysis_with_block(const Block& blk, const KQuery& query,
// TradeManagerPtr tm, SystemPtr sys, TradeManagerPtr tm, SystemPtr sys,
// object buy_inds, object sell_inds, int n) { const py::sequence& buy_inds,
// std::vector<Indicator> c_buy_inds; const py::sequence& sell_inds, int n) {
// for (size_t i = 0, total = len(buy_inds); i < total; i++) { std::vector<Indicator> c_buy_inds;
// c_buy_inds.emplace_back(py::extract<Indicator>(buy_inds[i])()); for (size_t i = 0, total = len(buy_inds); i < total; i++) {
// } c_buy_inds.emplace_back(buy_inds[i].cast<Indicator>());
}
// std::vector<Indicator> c_sell_inds; std::vector<Indicator> c_sell_inds;
// for (size_t i = 0, total = len(sell_inds); i < total; i++) { for (size_t i = 0, total = len(sell_inds); i < total; i++) {
// c_sell_inds.emplace_back(py::extract<Indicator>(sell_inds[i])()); c_sell_inds.emplace_back(sell_inds[i].cast<Indicator>());
// } }
// auto records = auto records =
// combinateIndicatorAnalysisWithBlock(blk, query, tm, sys, c_buy_inds, c_sell_inds, n); combinateIndicatorAnalysisWithBlock(blk, query, tm, sys, c_buy_inds, c_sell_inds, n);
// std::vector<py::list> tmp; std::vector<py::list> tmp;
// StringList names{"组合名称", "证券代码", "证券名称"}; StringList names{"组合名称", "证券代码", "证券名称"};
// Performance per; Performance per;
// auto keys = per.names(); auto keys = per.names();
// for (const auto& key : keys) { for (const auto& key : keys) {
// names.emplace_back(key); names.emplace_back(key);
// } }
// for (int i = 0, len = names.size(); i < len; i++) { for (size_t i = 0, len = names.size(); i < len; i++) {
// tmp.emplace_back(py::list()); tmp.emplace_back(py::list());
// } }
// for (size_t i = 0, total = records.size(); i < total; i++) { for (size_t i = 0, total = records.size(); i < total; i++) {
// CombinateAnalysisOutput& record = records[i]; CombinateAnalysisOutput& record = records[i];
// tmp[0].append(record.combinateName); tmp[0].append(record.combinateName);
// tmp[1].append(record.code); tmp[1].append(record.code);
// tmp[2].append(record.name); tmp[2].append(record.name);
// HKU_WARN_IF(names.size() != record.values.size() + 3, "lenght invalid: {} {}", HKU_WARN_IF(names.size() != record.values.size() + 3, "lenght invalid: {} {}", names.size(),
// names.size(), record.values.size());
// record.values.size()); for (size_t j = 3, len = names.size(); j < len; j++) {
// for (size_t j = 3, len = names.size(); j < len; j++) { tmp[j].append(record.values[j - 3]);
// tmp[j].append(record.values[j - 3]); }
// } }
// }
// py::dict result; py::dict result;
// for (size_t i = 0, total = names.size(); i < total; i++) { for (size_t i = 0, total = names.size(); i < total; i++) {
// result[names[i]] = tmp[i]; result[names[i].c_str()] = tmp[i];
// } }
// return result; return result;
// } }
// void export_analysis(py::module& m) { void export_analysis(py::module& m) {
// m.def("combinate_index", combinate_index, R"(combinate_index(seq) m.def("combinate_index", combinate_index, R"(combinate_index(seq)
// 获取序列组合的下标索引, 输入序列的长度最大不超过15否则抛出异常 , 15
// :param inds: list 或 tuple 等可使用索引的可迭代对象 :param inds: list tuple 使
// :return: 返回组合的索引,可用于获取输入中相应索引位置的值 :return:
// :rtype: list)"); :rtype: list)");
// m.def("combinate_ind", combinate_indicator, py::arg("inds"), py::arg("n") = 7, m.def("combinate_ind", combinate_indicator, py::arg("inds"), py::arg("n") = 7,
// R"(combinate_ind(inds[, n=7]) R"(combinate_ind(inds[, n=7])
// 对输入的指标序列进行组合, 如输入为 [ind1, ind2], 输出为 [EXIST(ind1,n), EXIST(ind2,n), , [ind1, ind2], [EXIST(ind1,n), EXIST(ind2,n),
// EXIST(ind1,n)&EXIST(ind2,n)] EXIST(ind1,n)&EXIST(ind2,n)]
// :param list|tuple|seq inds: 待组合的指标列表 :param list|tuple|seq inds:
// :param int n: 指标在 n 周期内存在 :param int n: n
// :return: 组合后的指标列表 :return:
// :rtype: list)"); :rtype: list)");
// m.def("_combinate_ind_analysis", combinate_ind_analysis); m.def("_combinate_ind_analysis", combinate_ind_analysis);
// m.def("_combinate_ind_analysis_with_block", combinate_ind_analysis_with_block); m.def("_combinate_ind_analysis_with_block", combinate_ind_analysis_with_block);
// } }

View File

@ -19,7 +19,6 @@ namespace py = pybind11;
void export_DataType(py::module& m); void export_DataType(py::module& m);
void export_Constant(py::module& m); void export_Constant(py::module& m);
void export_util(py::module& m); void export_util(py::module& m);
// void export_analysis(py::module& m);
void export_log(py::module& m); void export_log(py::module& m);
void export_Datetime(py::module& m); void export_Datetime(py::module& m);
void export_TimeDelta(py::module& m); void export_TimeDelta(py::module& m);
@ -44,15 +43,17 @@ void export_SystemPart(py::module& m);
void export_trade_manage_main(py::module& m); void export_trade_manage_main(py::module& m);
void export_trade_sys_main(py::module& m); void export_trade_sys_main(py::module& m);
void export_global_main(py::module& m); void export_global_main(py::module& m);
void export_analysis(py::module& m);
void export_StrategeContext(py::module& m); void export_StrategeContext(py::module& m);
void export_strategy_main(py::module& m); void export_strategy_main(py::module& m);
PYBIND11_MODULE(core, m) { PYBIND11_MODULE(core, m) {
py::register_exception<hku::exception>(m, "HKUException");
export_DataType(m); export_DataType(m);
export_Constant(m); export_Constant(m);
export_util(m); export_util(m);
// export_analysis(m);
export_log(m); export_log(m);
export_Datetime(m); export_Datetime(m);
export_TimeDelta(m); export_TimeDelta(m);
@ -79,6 +80,7 @@ PYBIND11_MODULE(core, m) {
export_trade_manage_main(m); export_trade_manage_main(m);
export_trade_sys_main(m); // must after export_trade_manage_main export_trade_sys_main(m); // must after export_trade_manage_main
export_analysis(m);
export_strategy_main(m); export_strategy_main(m);
export_global_main(m); export_global_main(m);

View File

@ -22,4 +22,6 @@ void export_BorrowRecord(py::module& m) {
.def_readwrite("value", &BorrowRecord::value, "借入总价值") .def_readwrite("value", &BorrowRecord::value, "借入总价值")
DEF_PICKLE(BorrowRecord); DEF_PICKLE(BorrowRecord);
py::bind_vector<BorrowRecordList>(m, "BorrowRecordList");
} }

View File

@ -38,4 +38,6 @@ void export_PositionRecord(py::module& m) {
"累计交易风险float = 各次 (买入价格-止损)*买入数量, 不包含交易成本") "累计交易风险float = 各次 (买入价格-止损)*买入数量, 不包含交易成本")
.def_readwrite("sell_money", &PositionRecord::sellMoney, "累计卖出资金float") .def_readwrite("sell_money", &PositionRecord::sellMoney, "累计卖出资金float")
DEF_PICKLE(PositionRecord); DEF_PICKLE(PositionRecord);
py::bind_vector<PositionRecordList>(m, "PositionRecordList");
} }

View File

@ -65,4 +65,6 @@ void export_TradeRecord(py::module& m) {
"交易指示来源,区别是交易系统哪个部件发出的指示,参见: " "交易指示来源,区别是交易系统哪个部件发出的指示,参见: "
":py:class:`System.Part`") // python中不能用from关键字 ":py:class:`System.Part`") // python中不能用from关键字
DEF_PICKLE(TradeRecord); DEF_PICKLE(TradeRecord);
py::bind_vector<TradeRecordList>(m, "TradeRecordList");
} }

View File

@ -46,6 +46,8 @@ void export_AllocateFunds(py::module& m) {
DEF_PICKLE(SystemWeight); DEF_PICKLE(SystemWeight);
py::bind_vector<SystemWeightList>(m, "SystemWeightList");
py::class_<AllocateFundsBase, AFPtr, PyAllocateFundsBase>( py::class_<AllocateFundsBase, AFPtr, PyAllocateFundsBase>(
m, "AllocateFundsBase", m, "AllocateFundsBase",
R"(资产分配算法基类, 子类接口: R"(资产分配算法基类, 子类接口:

View File

@ -213,4 +213,6 @@ void export_System(py::module& m) {
.def("ready", &System::readyForRun) .def("ready", &System::readyForRun)
DEF_PICKLE(System); DEF_PICKLE(System);
py::bind_vector<SystemList>(m, "SystemList");
} }