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

View File

@ -3,32 +3,14 @@
from hikyuu.util.slice import list_getitem
from hikyuu.cpp.core import SYS_Simple as cpp_SYS_Simple
from hikyuu.cpp.core import (
System, SystemList, SystemWeight, SystemWeightList, ConditionBase, EnvironmentBase, MoneyManagerBase,
System, SystemPart, SystemList, SystemWeightList, ConditionBase, EnvironmentBase, MoneyManagerBase,
ProfitGoalBase, SelectorBase, SignalBase, SlippageBase, StoplossBase
)
#------------------------------------------------------------------
# ------------------------------------------------------------------
# System
#------------------------------------------------------------------
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.Part = SystemPart
System.ENVIRONMENT = System.Part.ENVIRONMENT
System.CONDITION = System.Part.CONDITION
System.SIGNAL = System.Part.SIGNAL
@ -50,7 +32,7 @@ def SYS_Simple(tm=None, mm=None, ev=None, cn=None, sg=None, st=None, tp=None, pg
(run方法
run时没有任何输出
tmsgmm使 run ::
#创建模拟交易账户进行回测初始资金30万
my_tm = crtTM(init_cash = 300000)
@ -64,7 +46,7 @@ def SYS_Simple(tm=None, mm=None, ev=None, cn=None, sg=None, st=None, tp=None, pg
#创建交易系统并运行
sys = SYS_Simple(tm = my_tm, sg = my_sg, mm = my_mm)
sys.run(sm['sz000001'], Query(-150))
:param TradeManager tm:
:param MoneyManager mm:
:param EnvironmentBase ev:
@ -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
#------------------------------------------------------------------
# ------------------------------------------------------------------
# allocatefunds
#------------------------------------------------------------------
# ------------------------------------------------------------------
SystemWeightList.__getitem__ = list_getitem
SystemWeightList.__str__ = lambda self: str(list(self))
SystemWeightList.__repr__ = lambda self: repr(list(self))
#------------------------------------------------------------------
# ------------------------------------------------------------------
# condition
#------------------------------------------------------------------
ConditionBase.__init__.__doc__ = """
__init__(self[, name="ConditionBase"])
:param str name:
"""
# ------------------------------------------------------------------
def cn_init(self, name, params):
super(self.__class__, self).__init__(name)
self._name = name
@ -130,7 +103,7 @@ def cn_init(self, name, params):
def crtCN(func, params={}, name='crtCN'):
"""
:param func:
:param {} params:
:param str name:
@ -142,19 +115,9 @@ def crtCN(func, params={}, name='crtCN'):
return meta_x(name, params)
#------------------------------------------------------------------
# ------------------------------------------------------------------
# environment
#------------------------------------------------------------------
EnvironmentBase.__init__.__doc__ = """
__init__(self[, name='EnvironmentBase'])
:param str name:
"""
# ------------------------------------------------------------------
def ev_init(self, name, params):
super(self.__class__, self).__init__(name)
self._name = name
@ -166,7 +129,7 @@ def ev_init(self, name, params):
def crtEV(func, params={}, name='crtEV'):
"""
:param func:
:param {} params:
:param str name:
@ -178,19 +141,9 @@ def crtEV(func, params={}, name='crtEV'):
return meta_x(name, params)
#------------------------------------------------------------------
# ------------------------------------------------------------------
# moneymanager
#------------------------------------------------------------------
MoneyManagerBase.__init__.__doc__ = """
__init__(self[, name="MoneyManagerBase])
:param str name:
"""
# ------------------------------------------------------------------
def mm_init(self, name, params):
super(self.__class__, self).__init__(name)
self._name = name
@ -202,7 +155,7 @@ def mm_init(self, name, params):
def crtMM(func, params={}, name='crtMM'):
"""
:param func:
:param {} params:
:param str name:
@ -214,19 +167,9 @@ def crtMM(func, params={}, name='crtMM'):
return meta_x(name, params)
#------------------------------------------------------------------
# ------------------------------------------------------------------
# profitgoal
#------------------------------------------------------------------
ProfitGoalBase.__init__.__doc__ = """
__init__(self[, name="ProfitGoalBase"])
:param str name:
"""
# ------------------------------------------------------------------
def pg_init(self, name, params):
super(self.__class__, self).__init__(name)
self._name = name
@ -238,7 +181,7 @@ def pg_init(self, name, params):
def crtPG(func, params={}, name='crtPG'):
"""
:param func:
:param {} params:
:param str name:
@ -250,29 +193,9 @@ def crtPG(func, params={}, name='crtPG'):
return meta_x(name, params)
#------------------------------------------------------------------
# selector
#------------------------------------------------------------------
SelectorBase.__init__.__doc__ = """
__init__(self[, name="SelectorBase])
:param str name:
"""
#------------------------------------------------------------------
# ------------------------------------------------------------------
# signal
#------------------------------------------------------------------
SignalBase.__init__.__doc__ = """
__init__(self[, name="SignalBase"])
:param str name:
"""
# ------------------------------------------------------------------
def sig_init(self, name, params):
super(self.__class__, self).__init__(name)
self._name = name
@ -284,7 +207,7 @@ def sig_init(self, name, params):
def crtSG(func, params={}, name='crtSG'):
"""
:param func:
:param {} params:
:param str name:
@ -296,9 +219,9 @@ def crtSG(func, params={}, name='crtSG'):
return meta_x(name, params)
#------------------------------------------------------------------
# ------------------------------------------------------------------
# Selector
#------------------------------------------------------------------
# ------------------------------------------------------------------
def se_add_stock_list(self, stk_list, proto_sys):
result = True
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
#------------------------------------------------------------------
# ------------------------------------------------------------------
# slippage
#------------------------------------------------------------------
SlippageBase.__init__.__doc__ = """
__init__(self[, name="SlippageBase"])
:param str name:
"""
# ------------------------------------------------------------------
def sl_init(self, name, params):
@ -335,7 +250,7 @@ def sl_init(self, name, params):
def crtSL(func, params={}, name='crtSL'):
"""
:param func:
:param {} params:
:param str name:
@ -347,17 +262,9 @@ def crtSL(func, params={}, name='crtSL'):
return meta_x(name, params)
#------------------------------------------------------------------
# ------------------------------------------------------------------
# stoploss
#------------------------------------------------------------------
StoplossBase.__init__.__doc__ = """
__init__(self[, name="StoplossBase"])
:param str name:
"""
# ------------------------------------------------------------------
def st_init(self, name, params):
super(self.__class__, self).__init__(name)
self._name = name
@ -369,7 +276,7 @@ def st_init(self, name, params):
def crtST(func, params={}, name='crtST'):
"""
/
:param func: /
:param {} params:
:param str name:

View File

@ -29,4 +29,27 @@ void export_DataType(py::module& m) {
m.def("isnan", isnan_func, "是否为非数字");
m.def("isinf", isinf_func, "是否是无穷大或无穷小");
#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("start_of_year", &Datetime::startOfYear, "\n返回年度起始日期")
.def("endOfYear", &Datetime::endOfYear, "\n返回年度结束日期")
.def("min", &Datetime::min, "\n获取支持的最小日期, Datetime(1400, 1, 1)")
.def("max", &Datetime::max, "\n获取支持的最大日期, Datetime(9999, 12, 31)")
.def("now", &Datetime::now, "\n获取系统当前日期时间")
.def("today", &Datetime::today, "\n获取当前的日期")
.def("from_hex", &Datetime::fromHex, "\n兼容oracle用后7个字节表示的datetime")
.def_static("min", &Datetime::min, "\n获取支持的最小日期, Datetime(1400, 1, 1)")
.def_static("max", &Datetime::max, "\n获取支持的最大日期, Datetime(9999, 12, 31)")
.def_static("now", &Datetime::now, "\n获取系统当前日期时间")
.def_static("today", &Datetime::today, "\n获取当前的日期")
.def_static("from_hex", &Datetime::fromHex, "\n兼容oracle用后7个字节表示的datetime")
.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) {
py::class_<Parameter>(m, "Parameter", "参数类,供需要命名参数设定的类使用,类似于 dict")
.def(py::init<>())
.def("__str__", Parameter_to_str)
.def("__repr__", Parameter_to_str)

View File

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

View File

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

View File

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

View File

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

View File

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