mirror of
https://gitee.com/fasiondog/hikyuu.git
synced 2024-11-30 02:48:57 +08:00
commit
2c16b090ef
@ -7,41 +7,42 @@
|
||||
# History: 20160407, Added by fasiondog
|
||||
#===============================================================================
|
||||
|
||||
from hikyuu.trade_sys.signal import SignalBase
|
||||
from hikyuu.indicator import HHV, LLV, CLOSE, REF
|
||||
from hikyuu import *
|
||||
|
||||
|
||||
class TurtleSignal(SignalBase):
|
||||
def __init__(self, n = 20):
|
||||
def __init__(self, n=20):
|
||||
super(TurtleSignal, self).__init__("TurtleSignal")
|
||||
self.setParam("n", 20)
|
||||
|
||||
self.set_param("n", 20)
|
||||
|
||||
def _clone(self):
|
||||
return TurtleSignal()
|
||||
|
||||
def _calculate(self):
|
||||
n = self.getParam("n")
|
||||
k = self.getTO()
|
||||
n = self.get_param("n")
|
||||
k = self.to
|
||||
c = CLOSE(k)
|
||||
h = REF(HHV(c, n), 1) #前n日高点
|
||||
L = REF(LLV(c, n), 1) #前n日低点
|
||||
h = REF(HHV(c, n), 1) #前n日高点
|
||||
L = REF(LLV(c, n), 1) #前n日低点
|
||||
for i in range(h.discard, len(k)):
|
||||
if (c[i] >= h[i]):
|
||||
self._addBuySignal(k[i].datetime)
|
||||
self._add_buy_signal(k[i].datetime)
|
||||
elif (c[i] <= L[i]):
|
||||
self._addSellSignal(k[i].datetime)
|
||||
self._add_sell_signal(k[i].datetime)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from examples_init import *
|
||||
|
||||
|
||||
sg = TurtleSignal()
|
||||
s = getStock("sh000001")
|
||||
k = s.getKData(Query(-500))
|
||||
|
||||
s = get_stock("sh000001")
|
||||
k = s.get_kdata(Query(-500))
|
||||
|
||||
#只有设置交易对象时,才会开始实际计算
|
||||
sg.setTO(k)
|
||||
dates = k.getDatetimeList()
|
||||
sg.to = k
|
||||
dates = k.get_datetime_list()
|
||||
for d in dates:
|
||||
if (sg.shouldBuy(d)):
|
||||
if (sg.should_buy(d)):
|
||||
print("买入:%s" % d)
|
||||
elif (sg.shouldSell(d)):
|
||||
elif (sg.should_sell(d)):
|
||||
print("卖出: %s" % d)
|
||||
|
@ -9,16 +9,20 @@
|
||||
from hikyuu import *
|
||||
|
||||
import os
|
||||
curdir = os.path.dirname(os.path.realpath(__file__))
|
||||
head, tail = os.path.split(curdir)
|
||||
head, tail = os.path.split(head)
|
||||
head, tail = os.path.split(head)
|
||||
|
||||
import sys
|
||||
if sys.platform == 'win32':
|
||||
config_file = os.path.join(head, "test/data/hikyuu_win.ini")
|
||||
else:
|
||||
config_file = os.path.join(head, "test/data/hikyuu_linux.ini")
|
||||
config_file = os.path.expanduser('~') + "/.hikyuu/hikyuu.ini"
|
||||
if not os.path.exists(config_file):
|
||||
#检查老版本配置是否存在,如果存在可继续使用,否则异常终止
|
||||
data_config_file = os.path.expanduser('~') + "/.hikyuu/data_dir.ini"
|
||||
data_config = configparser.ConfigParser()
|
||||
data_config.read(data_config_file)
|
||||
data_dir = data_config['data_dir']['data_dir']
|
||||
if sys.platform == 'win32':
|
||||
config_file = data_dir + "\\hikyuu_win.ini"
|
||||
else:
|
||||
config_file = data_dir + "/hikyuu_linux.ini"
|
||||
if not os.path.exists(config_file):
|
||||
raise("未找到配置文件,请先使用数据导入工具导入数据(将自动生成配置文件)!!!")
|
||||
|
||||
|
||||
#starttime = time.time()
|
||||
|
@ -7,33 +7,34 @@
|
||||
# History: 20160407, Added by fasiondog
|
||||
#===============================================================================
|
||||
|
||||
from hikyuu.trade_sys.signal import crtSG
|
||||
from hikyuu.indicator import HHV, LLV, CLOSE, REF
|
||||
from hikyuu import *
|
||||
|
||||
|
||||
def TurtleSG(self):
|
||||
n = self.getParam("n")
|
||||
k = self.getTO()
|
||||
c = CLOSE(k)
|
||||
h = REF(HHV(c, n), 1) #前n日高点
|
||||
L = REF(LLV(c, n), 1) #前n日低点
|
||||
for i in range(h.discard, len(k)):
|
||||
if (c[i] >= h[i]):
|
||||
self._addBuySignal(k[i].datetime)
|
||||
elif (c[i] <= L[i]):
|
||||
self._addSellSignal(k[i].datetime)
|
||||
n = self.get_param("n")
|
||||
k = self.to
|
||||
c = CLOSE(k)
|
||||
h = REF(HHV(c, n), 1) #前n日高点
|
||||
L = REF(LLV(c, n), 1) #前n日低点
|
||||
for i in range(h.discard, len(k)):
|
||||
if (c[i] >= h[i]):
|
||||
self._add_buy_signal(k[i].datetime)
|
||||
elif (c[i] <= L[i]):
|
||||
self._add_sell_signal(k[i].datetime)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from examples_init import *
|
||||
|
||||
|
||||
sg = crtSG(TurtleSG, {'n': 20}, 'TurtleSG')
|
||||
s = getStock("sh000001")
|
||||
k = s.getKData(Query(-500))
|
||||
|
||||
s = get_stock("sh000001")
|
||||
k = s.get_kdata(Query(-500))
|
||||
|
||||
#只有设置交易对象时,才会开始实际计算
|
||||
sg.setTO(k)
|
||||
dates = k.getDatetimeList()
|
||||
sg.to = k
|
||||
dates = k.get_datetime_list()
|
||||
for d in dates:
|
||||
if (sg.shouldBuy(d)):
|
||||
if (sg.should_buy(d)):
|
||||
print("买入:%s" % d)
|
||||
elif (sg.shouldSell(d)):
|
||||
elif (sg.should_sell(d)):
|
||||
print("卖出: %s" % d)
|
||||
|
BIN
docs/source/_static/indparam.png
Normal file
BIN
docs/source/_static/indparam.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
BIN
docs/source/_static/portfolio.png
Normal file
BIN
docs/source/_static/portfolio.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 41 KiB |
@ -104,7 +104,6 @@ pygments_style = 'sphinx'
|
||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||
todo_include_todos = False
|
||||
|
||||
|
||||
# -- Options for HTML output ----------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
@ -208,25 +207,24 @@ htmlhelp_basename = 'Hikyuudoc'
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#'pointsize': '10pt',
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
|
||||
# Latex figure (float) alignment
|
||||
#'figure_align': 'htbp',
|
||||
# Latex figure (float) alignment
|
||||
#'figure_align': 'htbp',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(master_doc, 'Hikyuu.tex', 'Hikyuu Documentation',
|
||||
'fasiondog', 'manual'),
|
||||
(master_doc, 'Hikyuu.tex', 'Hikyuu Documentation', 'fasiondog', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
@ -249,29 +247,23 @@ latex_documents = [
|
||||
# If false, no module index is generated.
|
||||
#latex_domain_indices = True
|
||||
|
||||
|
||||
# -- Options for manual page output ---------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
(master_doc, 'hikyuu', 'Hikyuu Documentation',
|
||||
[author], 1)
|
||||
]
|
||||
man_pages = [(master_doc, 'hikyuu', 'Hikyuu Documentation', [author], 1)]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#man_show_urls = False
|
||||
|
||||
|
||||
# -- Options for Texinfo output -------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(master_doc, 'Hikyuu', 'Hikyuu Documentation',
|
||||
author, 'Hikyuu', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
(master_doc, 'Hikyuu', 'Hikyuu Documentation', author, 'Hikyuu',
|
||||
'One line description of project.', 'Miscellaneous'),
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
|
@ -318,7 +318,7 @@
|
||||
指数移动平均线(Exponential Moving Average)
|
||||
|
||||
:param data: 输入数据
|
||||
:param int n: 计算均值的周期窗口,必须为大于0的整数
|
||||
:param int|Indciator|IndParam n: 计算均值的周期窗口,必须为大于0的整数
|
||||
:rtype: Indicator
|
||||
|
||||
|
||||
@ -700,7 +700,7 @@
|
||||
变动率指标: (price / prevPrice) * 100
|
||||
|
||||
:param data: 输入数据
|
||||
:param int n: 时间窗口
|
||||
:param int|Indicator|IndParam n: 时间窗口
|
||||
:rtype: Indicator
|
||||
|
||||
|
||||
@ -771,6 +771,16 @@
|
||||
:rtype: Indicator
|
||||
|
||||
|
||||
.. py:function:: SLICE(data, start, end, result_index=0)
|
||||
|
||||
获取某指标中指定范围 [start, end) 的数据,生成新的指标
|
||||
|
||||
:param Indicator|PriceList data: 输入数据
|
||||
:param int start: 起始位置
|
||||
:param int end: 终止位置(不包含本身)
|
||||
:param int result_index: 原输入数据中的结果集
|
||||
|
||||
|
||||
.. py:function:: SMA([data, n=22, m=2])
|
||||
|
||||
求移动平均
|
||||
@ -800,7 +810,7 @@
|
||||
计算N周期内样本标准差
|
||||
|
||||
:param Indicator data: 输入数据
|
||||
:param int n: 时间窗口
|
||||
:param int n|Indicator|IndParam: 时间窗口
|
||||
:rtype: Indicator
|
||||
|
||||
|
||||
@ -809,7 +819,7 @@
|
||||
计算N周期内样本标准差
|
||||
|
||||
:param Indicator data: 输入数据
|
||||
:param int n: 时间窗口
|
||||
:param int|Indicator|IndParam n: 时间窗口
|
||||
:rtype: Indicator
|
||||
|
||||
|
||||
@ -818,7 +828,7 @@
|
||||
总体标准差,STDP(X,N)为X的N日总体标准差
|
||||
|
||||
:param data: 输入数据
|
||||
:param int n: 时间窗口
|
||||
:param int|Indicator|IndParam n: 时间窗口
|
||||
:rtype: Indicator
|
||||
|
||||
|
||||
@ -827,7 +837,7 @@
|
||||
求总和。SUM(X,N),统计N周期中X的总和,N=0则从第一个有效值开始。
|
||||
|
||||
:param Indicator data: 输入数据
|
||||
:param int n: 时间窗口
|
||||
:param int|Indicator|IndParam n: 时间窗口
|
||||
:rtype: Indicator
|
||||
|
||||
|
||||
@ -840,7 +850,7 @@
|
||||
例如:SUMBARS(VOL,CAPITAL)求完全换手到现在的周期数
|
||||
|
||||
:param Indicator data: 输入数据
|
||||
:param float a: 指定累加和
|
||||
:param float|Indicator|IndParam a: 指定累加和
|
||||
:rtype: Indicator
|
||||
|
||||
|
||||
@ -873,7 +883,7 @@
|
||||
连涨周期数, UPNDAY(CLOSE,M)表示连涨M个周期
|
||||
|
||||
:param Indicator data: 输入数据
|
||||
:param int n: 时间窗口
|
||||
:param int|Indicator|IndParam n: 时间窗口
|
||||
:rtype: Indicator
|
||||
|
||||
|
||||
@ -882,7 +892,7 @@
|
||||
估算样本方差, VAR(X,N)为X的N日估算样本方差
|
||||
|
||||
:param Indicator data: 输入数据
|
||||
:param int n: 时间窗口
|
||||
:param int|Indicator|IndParam n: 时间窗口
|
||||
:rtype: Indicator
|
||||
|
||||
|
||||
@ -891,7 +901,7 @@
|
||||
总体样本方差, VARP(X,N)为X的N日总体样本方差
|
||||
|
||||
:param Indicator data: 输入数据
|
||||
:param int n: 时间窗口
|
||||
:param int|Indicator|IndParam n: 时间窗口
|
||||
:rtype: Indicator
|
||||
|
||||
|
||||
|
@ -1,7 +1,87 @@
|
||||
版本发布说明
|
||||
===============
|
||||
=======================
|
||||
|
||||
1.2.0
|
||||
1.2.3 - 2022年3月6日
|
||||
-------------------------
|
||||
|
||||
1. 指标支持动态参数
|
||||
|
||||
在通道信等证券行情软件中,其技术指标中的窗口参数通常支持整数,也支持使用指标,如::
|
||||
|
||||
T1:=HHVBARS(H,120); {120内的最高点距今天的天数}
|
||||
L120:=LLV(L,T1+1); {120内的最高点至今,这个区间的最低点}
|
||||
|
||||
现在,在 Hikyuu 中,也可以使用指标作为参数::
|
||||
|
||||
T1 = HHVBARS(H, 120)
|
||||
L120 = LLV(L, T1+1)
|
||||
L120.set_context(k)
|
||||
L120.plot()
|
||||
|
||||
.. figure:: _static/indparam.png
|
||||
|
||||
**注意事项**
|
||||
|
||||
由于无法区分 Indicator(ind) 形式时,ind 究竟是指标参数还是待计算的输出数据,此时如果希望 ind 作为参数,需要通过 IndParam 进行显示指定,如:EMA(IndParam(ind))。
|
||||
|
||||
最佳的的方式,则是通过指定参数名,来明确说明使用的是参数::
|
||||
|
||||
x = EMA(c) # 以收盘价作为计算的输入
|
||||
y = EMA(IndParam(c)) # 以收盘价作为 n 参数
|
||||
z = EMA(n=c) # 以收盘价作为参数 n
|
||||
|
||||
|
||||
|
||||
2. 完善 PF、AF、SE
|
||||
|
||||
现在可以正常使用资产组合。::
|
||||
|
||||
# 创建一个系统策略
|
||||
my_mm = MM_FixedCount(100)
|
||||
my_sg = my_sg = SG_Flex(EMA(n=5), slow_n=10)
|
||||
my_sys = SYS_Simple(sg=my_sg, mm=my_mm)
|
||||
|
||||
# 创建一个选择算法,用于在每日选定交易系统
|
||||
# 此处是固定选择器,即每日选出的都是指定的交易系统
|
||||
my_se = SE_Fixed([s for s in blocka if s.valid], my_sys)
|
||||
|
||||
# 创建一个资产分配器,用于确定如何在选定的交易系统中进行资产分配
|
||||
# 此处创建的是一个等比例分配资产的分配器,即按相同比例在选出的系统中进行资金分配
|
||||
my_af = AF_EqualWeight()
|
||||
|
||||
# 创建资产组合
|
||||
# 创建一个从2001年1月1日开始的账户,初始资金200万元。这里由于使用的等比例分配器,意味着将账户剩余资金在所有选中的系统中平均分配,
|
||||
# 如果初始资金过小,将导致每个系统都没有充足的资金完成交易。
|
||||
my_tm = crtTM(Datetime(200101010000), 2000000)
|
||||
my_pf = PF_Simple(tm=my_tm, af=my_af, se=my_se)
|
||||
|
||||
# 运行投资组合
|
||||
q = Query(-500)
|
||||
%time my_pf.run(Query(-500))
|
||||
|
||||
x = my_tm.get_funds_curve(sm.get_trading_calendar(q))
|
||||
PRICELIST(x).plot()
|
||||
|
||||
.. figure:: _static/portfolio.png
|
||||
|
||||
3. 修复fedora 34编译找不到路径报错,waning 提示
|
||||
4. fixed mysql 升级脚本错误
|
||||
5. fixed 复权后计算的净收益不对,并在使用前复权数据进行回测时给出警告(前复权回测属于未来函数)
|
||||
|
||||
|
||||
1.2.1 - 2022年2月2日
|
||||
-------------------------
|
||||
|
||||
1. 修复 importdata 无法导入的问题
|
||||
2. 交易系统 System 支持使用复权数据
|
||||
3. KData 增加 getPosInStock 方法
|
||||
4. KQuery 的 recoverType 属性支持设定修改
|
||||
5. 增加 2022 年假日
|
||||
6. 修改 examples,以便在新版本下执行
|
||||
7. 修改其他文档帮助错误
|
||||
|
||||
|
||||
1.2.0 - 2022年1月11日
|
||||
-------------------------
|
||||
|
||||
1. HikyuuTdx 执行导入时自动保存配置,避免第一次使用 hikyuu 必须退出先退出 Hikyuutdx 的问题
|
||||
@ -16,7 +96,7 @@
|
||||
10. 优化 HikyuuTDX GUI控制台日志,捕获子进程日志输出
|
||||
|
||||
|
||||
1.1.9
|
||||
1.1.9 - 2021年11月11日
|
||||
-------------------------
|
||||
|
||||
1. 补充科创板
|
||||
@ -30,13 +110,13 @@
|
||||
9. 取消编译时指定的AVX指令集,防止不支持的CPU架构
|
||||
|
||||
|
||||
1.1.8
|
||||
1.1.8 - 2021年2月27日
|
||||
-------------------------
|
||||
1. HikyuuTDX 切换mysql导入时错误提示目录不存在
|
||||
2. tdx本地导入修复,并支持导入MySQL
|
||||
|
||||
|
||||
1.1.7
|
||||
1.1.7 - 2021年2月13日
|
||||
-------------------------
|
||||
|
||||
1. 更新examples/notebook相关示例
|
||||
|
@ -8,7 +8,6 @@
|
||||
|
||||
公共参数:
|
||||
|
||||
* **reinvest=False** *(bool)* : 红利是否再投资
|
||||
* **precision=2** *(int)* : 价格计算精度
|
||||
* **support_borrow_cash=False** *(bool)* : 是否自动融资
|
||||
* **support_borrow_stock=False** *(bool)* : 是否自动融券
|
||||
@ -174,10 +173,11 @@
|
||||
:param Stock stock: 指定的证券
|
||||
:rtype: int
|
||||
|
||||
.. py:method:: get_position(self, stock)
|
||||
.. py:method:: get_position(self, date, stock)
|
||||
|
||||
获取指定证券的当前持仓记录,如当前未持有该票,返回PositionRecord()
|
||||
获取指定时间证券持仓记录,如当前未持有该票,返回PositionRecord()
|
||||
|
||||
:param Datetime date: 指定时间
|
||||
:param Stock stock: 指定的证券
|
||||
:rtype: PositionRecord
|
||||
|
||||
@ -221,14 +221,7 @@
|
||||
:param float num: 卖出数量
|
||||
:rtype: CostRecord
|
||||
|
||||
.. py:method:: get_funds(self[,ktype = Query.DAY])
|
||||
|
||||
获取账户当前时刻的资产详情
|
||||
|
||||
:param Query.KType ktype: K线类型
|
||||
:rtype: FundsRecord
|
||||
|
||||
get_funds(self, datetime, [ktype = Query.DAY])
|
||||
.. py:method:: get_funds(self, datetime, [ktype = Query.DAY])
|
||||
|
||||
获取指定时刻的资产市值详情
|
||||
|
||||
|
112
docs/source/trade_portfolio/allocate_funds.rst
Normal file
112
docs/source/trade_portfolio/allocate_funds.rst
Normal file
@ -0,0 +1,112 @@
|
||||
.. py:currentmodule:: hikyuu.trade_sys
|
||||
.. highlight:: python
|
||||
|
||||
资产分配算法组件
|
||||
================
|
||||
|
||||
内建资产分配算法
|
||||
------------------
|
||||
|
||||
.. py:function:: AF_FixedWeight(weight)
|
||||
|
||||
固定比例资产分配,每个选中的资产都只占总资产固定的比例
|
||||
|
||||
:param float weight: 指定的资产比例 [0, 1]
|
||||
|
||||
|
||||
.. py:function:: AF_EqualWeight()
|
||||
|
||||
固定比例资产分配,对选中的资产进行等比例分配
|
||||
|
||||
|
||||
系统权重系数结构
|
||||
-----------------
|
||||
|
||||
.. py:class:: SystemWeight
|
||||
|
||||
系统权重系数结构,在资产分配时,指定对应系统的资产占比系数
|
||||
|
||||
.. py:attribute:: sys 对应的 System 实例
|
||||
.. py:attribute:: weight 对应的权重系数,有效范围为 [0, 1]
|
||||
|
||||
|
||||
.. py:class:: SystemWeightList
|
||||
|
||||
由系统权重系数结构组成的列表
|
||||
|
||||
.. py:attribute:: sys
|
||||
|
||||
对应的 System 实例
|
||||
|
||||
.. py::attribute weight
|
||||
|
||||
对应的权重系数,有效范围为 [0, 1]
|
||||
|
||||
|
||||
资产分配算法基类
|
||||
------------------
|
||||
|
||||
.. py:class:: AllocateFundsBase
|
||||
|
||||
资产分配算法基类, 子类接口:
|
||||
|
||||
- _allocateWeight : 【必须】子类资产分配调整实现
|
||||
- _clone : 【必须】克隆接口
|
||||
- _reset : 【可选】重载私有变量
|
||||
|
||||
.. py:attribute:: name 名称
|
||||
|
||||
.. py:method:: __init__(self[, name="AllocateFundsBase])
|
||||
|
||||
初始化构造函数
|
||||
|
||||
:param str name: 名称
|
||||
|
||||
.. py:method:: have_param(self, name)
|
||||
|
||||
指定的参数是否存在
|
||||
|
||||
:param str name: 参数名称
|
||||
:return: True 存在 | False 不存在
|
||||
|
||||
.. py:method:: get_param(self, name)
|
||||
|
||||
获取指定的参数
|
||||
|
||||
:param str name: 参数名称
|
||||
:return: 参数值
|
||||
:raises out_of_range: 无此参数
|
||||
|
||||
.. py:method:: set_param(self, name, value)
|
||||
|
||||
设置参数
|
||||
|
||||
:param str name: 参数名称
|
||||
:param value: 参数值
|
||||
:type value: int | bool | float | string
|
||||
:raises logic_error: Unsupported type! 不支持的参数类型
|
||||
|
||||
.. py:method:: reset(self)
|
||||
|
||||
复位操作
|
||||
|
||||
.. py:method:: clone(self)
|
||||
|
||||
克隆操作
|
||||
|
||||
.. py:method:: _calculate(self)
|
||||
|
||||
【重载接口】子类计算接口
|
||||
|
||||
.. py:method:: _reset(self)
|
||||
|
||||
【重载接口】子类复位接口,复位内部私有变量
|
||||
|
||||
.. py::method:: _allocate_weight(self, date, se_list)
|
||||
|
||||
【重载接口】子类分配权重接口,获取实际分配资产的系统实例及其权重
|
||||
|
||||
:param Datetime date: 当前时间
|
||||
:param SystemList se_list: 当前选中的系统列表
|
||||
:return: 系统权重分配信息列表
|
||||
:rtype: SystemWeightList
|
@ -6,13 +6,13 @@
|
||||
|
||||
目前仅实现了多标的、相同策略的投资组合,还需完善,未来接口可能变化(包括选择器策略)!
|
||||
|
||||
.. py:function:: PF_Simple([tm, sys, se])
|
||||
.. py:function:: PF_Simple([tm, af, se])
|
||||
|
||||
创建一个多标的、单系统策略的投资组合
|
||||
|
||||
:param TradeManager tm: 交易管理
|
||||
:param System sys: 系统策略
|
||||
:param SelectorBase se: 选择器
|
||||
:param AllocateFundsBase af: 资金分配算法
|
||||
|
||||
|
||||
投资组合类定义
|
||||
@ -22,18 +22,45 @@
|
||||
|
||||
实现多标的、多策略的投资组合
|
||||
|
||||
.. py:attribute:: name
|
||||
.. py:attribute:: name 名称
|
||||
|
||||
名称
|
||||
|
||||
.. py:attribute:: tm
|
||||
|
||||
关联的交易管理实例
|
||||
.. py:attribute:: query 运行条件
|
||||
|
||||
.. py:attribute:: tm 关联的交易管理实例
|
||||
|
||||
.. py:attribute:: se
|
||||
|
||||
选择器策略
|
||||
.. py:attribute:: se 选择器策略
|
||||
|
||||
.. py:attribute:: af 资产分配算法
|
||||
|
||||
.. py:attribute:: proto_sys_list 原型系统列表
|
||||
|
||||
.. py:attribute:: real_sys_list 运行时的实际系统列表
|
||||
|
||||
.. py:method:: get_param(self, name)
|
||||
|
||||
获取指定的参数
|
||||
|
||||
:param str name: 参数名称
|
||||
:return: 参数值
|
||||
:raises out_of_range: 无此参数
|
||||
|
||||
.. py:method:: set_param(self, name, value)
|
||||
|
||||
设置参数
|
||||
|
||||
:param str name: 参数名称
|
||||
:param value: 参数值
|
||||
:type value: int | bool | float | string
|
||||
:raises logic_error: Unsupported type! 不支持的参数类型
|
||||
|
||||
.. py:method:: reset(self)
|
||||
|
||||
复位操作
|
||||
|
||||
.. py:method:: clone(self)
|
||||
|
||||
克隆操作
|
||||
|
||||
.. py:method:: run(self, query)
|
||||
|
||||
运行投资组合策略
|
||||
|
@ -13,20 +13,32 @@
|
||||
内建选择器
|
||||
-----------
|
||||
|
||||
.. py:function:: SE_Fixed([stocklist, sys])
|
||||
.. py:function:: SE_Fixed([stk_list, sys])
|
||||
|
||||
固定选择器,即始终选择初始划定的标的及其系统策略原型
|
||||
|
||||
:param StockList stocklist: 初始划定的标的
|
||||
:param list stk_list: 初始划定的标的
|
||||
:param System sys: 系统策略原型
|
||||
:return: SE选择器实例
|
||||
|
||||
.. py:function:: SE_Signal([stk_list, sys])
|
||||
|
||||
信号选择器,仅依靠系统买入信号进行选中
|
||||
|
||||
:param list stk_list: 初始划定的标的
|
||||
:param System sys: 系统策略原型
|
||||
:return: SE选择器实例
|
||||
|
||||
|
||||
自定义选择器策略
|
||||
--------------------
|
||||
|
||||
自定义选择器策略接口:
|
||||
|
||||
* :py:meth:`SelectorBase.get_selected_system_list` - 【必须】获取指定时刻选择的系统实例列表
|
||||
* :py:meth:`SelectorBase.is_match_af` - 【必须】判断是否和AF匹配
|
||||
* :py:meth:`SelectorBase.get_selected_on_open` - 【必须】获取指定时刻开盘时选择的系统实例列表
|
||||
* :py:meth:`SelectorBase.get_selected_on_close` - 【必须】获取指定时刻收盘时选择的系统实例列表
|
||||
* :py:meth:`SelectorBase._calculate` - 【必须】计算接口
|
||||
* :py:meth:`SelectorBase._reset` - 【可选】重置私有属性
|
||||
* :py:meth:`SelectorBase._clone` - 【必须】克隆接口
|
||||
|
||||
@ -38,6 +50,10 @@
|
||||
选择器策略基类,实现标的、系统策略的评估和选取算法
|
||||
|
||||
.. py:attribute:: name 名称
|
||||
|
||||
.. py:attribute:: proto_sys_list 原型系统列表
|
||||
|
||||
.. py:attribute:: real_sys_list 运行时的实际系统列表
|
||||
|
||||
.. py:method:: __init__(self[, name="SelectorBase])
|
||||
|
||||
@ -62,6 +78,14 @@
|
||||
:type value: int | bool | float | string
|
||||
:raises logic_error: Unsupported type! 不支持的参数类型
|
||||
|
||||
.. py:method:: reset(self)
|
||||
|
||||
复位操作
|
||||
|
||||
.. py:method:: clone(self)
|
||||
|
||||
克隆操作
|
||||
|
||||
.. py:method:: add_stock(self, stock, sys)
|
||||
|
||||
加入初始标的及其对应的系统策略原型
|
||||
@ -76,25 +100,44 @@
|
||||
:param StockList stk_list: 加入的初始标的列表
|
||||
:param System sys: 系统策略原型
|
||||
|
||||
.. py:method:: clear(self)
|
||||
.. py:method:: remove_all(self)
|
||||
|
||||
清除已加入的系统策略实例
|
||||
清除所有已加入的原型系统
|
||||
|
||||
.. py:method:: is_match_af(self)
|
||||
|
||||
【重载接口】判断是否和 AF 匹配
|
||||
|
||||
:param AllocateFundsBase af: 资产分配算法
|
||||
|
||||
|
||||
.. py:method:: get_selected_on_open(self, datetime)
|
||||
|
||||
.. py:method:: get_selected_system_list(self, datetime)
|
||||
|
||||
【重载接口】获取指定时刻选取的系统实例
|
||||
【重载接口】获取指定时刻开盘时选取的系统实例
|
||||
|
||||
:param Datetime datetime: 指定时刻
|
||||
:return: 选取的系统实例列表
|
||||
:rtype: SystemList
|
||||
|
||||
.. py:method:: get_selected_on_close(self, datetime)
|
||||
|
||||
【重载接口】获取指定时刻收盘时选取的系统实例
|
||||
|
||||
:param Datetime datetime: 指定时刻
|
||||
:return: 选取的系统实例列表
|
||||
:rtype: SystemList
|
||||
|
||||
.. py:method:: _calculate(self)
|
||||
|
||||
【重载接口】子类计算接口
|
||||
|
||||
.. py:method:: _reset(self)
|
||||
|
||||
【重载接口】子类复位接口,复位内部私有变量
|
||||
|
||||
.. py:method:: _clone(self)
|
||||
|
||||
【重载接口】子类克隆接口
|
||||
【重载接口】子类克隆接口
|
||||
|
||||
|
||||
|
@ -8,3 +8,4 @@
|
||||
|
||||
portfolio
|
||||
selector
|
||||
allocate_funds
|
||||
|
@ -172,7 +172,7 @@
|
||||
|
||||
.. py:method:: get_trade_record_list(self)
|
||||
|
||||
获取交易记录
|
||||
获取实际执行的交易记录,和 TM 的区别是不包含权息调整带来的交易记录
|
||||
|
||||
:rtype: TradeRecordList
|
||||
|
||||
|
@ -13,4 +13,4 @@
|
||||
stoploss
|
||||
money_manager
|
||||
profitgoal
|
||||
slippage
|
||||
slippage
|
@ -1,20 +1,20 @@
|
||||
INSERT INTO `hku_base`."Holiday" (`date`) VALUES (20220103);
|
||||
INSERT INTO `hku_base`."Holiday" (`date`) VALUES (20220131);
|
||||
INSERT INTO `hku_base`."Holiday" (`date`) VALUES (20220201);
|
||||
INSERT INTO `hku_base`."Holiday" (`date`) VALUES (20220202);
|
||||
INSERT INTO `hku_base`."Holiday" (`date`) VALUES (20220203);
|
||||
INSERT INTO `hku_base`."Holiday" (`date`) VALUES (20220204);
|
||||
INSERT INTO `hku_base`."Holiday" (`date`) VALUES (20220205);
|
||||
INSERT INTO `hku_base`."Holiday" (`date`) VALUES (20220404);
|
||||
INSERT INTO `hku_base`."Holiday" (`date`) VALUES (20220405);
|
||||
INSERT INTO `hku_base`."Holiday" (`date`) VALUES (20220502);
|
||||
INSERT INTO `hku_base`."Holiday" (`date`) VALUES (20220503);
|
||||
INSERT INTO `hku_base`."Holiday" (`date`) VALUES (20220504);
|
||||
INSERT INTO `hku_base`."Holiday" (`date`) VALUES (20220603);
|
||||
INSERT INTO `hku_base`."Holiday" (`date`) VALUES (20220912);
|
||||
INSERT INTO `hku_base`."Holiday" (`date`) VALUES (20221003);
|
||||
INSERT INTO `hku_base`."Holiday" (`date`) VALUES (20221004);
|
||||
INSERT INTO `hku_base`."Holiday" (`date`) VALUES (20221005);
|
||||
INSERT INTO `hku_base`."Holiday" (`date`) VALUES (20221006);
|
||||
INSERT INTO `hku_base`."Holiday" (`date`) VALUES (20221007);
|
||||
INSERT INTO `hku_base`.`Holiday` (`date`) VALUES (20220103);
|
||||
INSERT INTO `hku_base`.`Holiday` (`date`) VALUES (20220131);
|
||||
INSERT INTO `hku_base`.`Holiday` (`date`) VALUES (20220201);
|
||||
INSERT INTO `hku_base`.`Holiday` (`date`) VALUES (20220202);
|
||||
INSERT INTO `hku_base`.`Holiday` (`date`) VALUES (20220203);
|
||||
INSERT INTO `hku_base`.`Holiday` (`date`) VALUES (20220204);
|
||||
INSERT INTO `hku_base`.`Holiday` (`date`) VALUES (20220205);
|
||||
INSERT INTO `hku_base`.`Holiday` (`date`) VALUES (20220404);
|
||||
INSERT INTO `hku_base`.`Holiday` (`date`) VALUES (20220405);
|
||||
INSERT INTO `hku_base`.`Holiday` (`date`) VALUES (20220502);
|
||||
INSERT INTO `hku_base`.`Holiday` (`date`) VALUES (20220503);
|
||||
INSERT INTO `hku_base`.`Holiday` (`date`) VALUES (20220504);
|
||||
INSERT INTO `hku_base`.`Holiday` (`date`) VALUES (20220603);
|
||||
INSERT INTO `hku_base`.`Holiday` (`date`) VALUES (20220912);
|
||||
INSERT INTO `hku_base`.`Holiday` (`date`) VALUES (20221003);
|
||||
INSERT INTO `hku_base`.`Holiday` (`date`) VALUES (20221004);
|
||||
INSERT INTO `hku_base`.`Holiday` (`date`) VALUES (20221005);
|
||||
INSERT INTO `hku_base`.`Holiday` (`date`) VALUES (20221006);
|
||||
INSERT INTO `hku_base`.`Holiday` (`date`) VALUES (20221007);
|
||||
UPDATE `hku_base`.`version` set `version` = 7;
|
@ -1,22 +1,22 @@
|
||||
BEGIN TRANSACTION;
|
||||
INSERT INTO "Holiday" (`date`) VALUES (20220103);
|
||||
INSERT INTO "Holiday" (`date`) VALUES (20220131);
|
||||
INSERT INTO "Holiday" (`date`) VALUES (20220201);
|
||||
INSERT INTO "Holiday" (`date`) VALUES (20220202);
|
||||
INSERT INTO "Holiday" (`date`) VALUES (20220203);
|
||||
INSERT INTO "Holiday" (`date`) VALUES (20220204);
|
||||
INSERT INTO "Holiday" (`date`) VALUES (20220205);
|
||||
INSERT INTO "Holiday" (`date`) VALUES (20220404);
|
||||
INSERT INTO "Holiday" (`date`) VALUES (20220405);
|
||||
INSERT INTO "Holiday" (`date`) VALUES (20220502);
|
||||
INSERT INTO "Holiday" (`date`) VALUES (20220503);
|
||||
INSERT INTO "Holiday" (`date`) VALUES (20220504);
|
||||
INSERT INTO "Holiday" (`date`) VALUES (20220603);
|
||||
INSERT INTO "Holiday" (`date`) VALUES (20220912);
|
||||
INSERT INTO "Holiday" (`date`) VALUES (20221003);
|
||||
INSERT INTO "Holiday" (`date`) VALUES (20221004);
|
||||
INSERT INTO "Holiday" (`date`) VALUES (20221005);
|
||||
INSERT INTO "Holiday" (`date`) VALUES (20221006);
|
||||
INSERT INTO "Holiday" (`date`) VALUES (20221007);
|
||||
INSERT INTO `Holiday` (`date`) VALUES (20220103);
|
||||
INSERT INTO `Holiday` (`date`) VALUES (20220131);
|
||||
INSERT INTO `Holiday` (`date`) VALUES (20220201);
|
||||
INSERT INTO `Holiday` (`date`) VALUES (20220202);
|
||||
INSERT INTO `Holiday` (`date`) VALUES (20220203);
|
||||
INSERT INTO `Holiday` (`date`) VALUES (20220204);
|
||||
INSERT INTO `Holiday` (`date`) VALUES (20220205);
|
||||
INSERT INTO `Holiday` (`date`) VALUES (20220404);
|
||||
INSERT INTO `Holiday` (`date`) VALUES (20220405);
|
||||
INSERT INTO `Holiday` (`date`) VALUES (20220502);
|
||||
INSERT INTO `Holiday` (`date`) VALUES (20220503);
|
||||
INSERT INTO `Holiday` (`date`) VALUES (20220504);
|
||||
INSERT INTO `Holiday` (`date`) VALUES (20220603);
|
||||
INSERT INTO `Holiday` (`date`) VALUES (20220912);
|
||||
INSERT INTO `Holiday` (`date`) VALUES (20221003);
|
||||
INSERT INTO `Holiday` (`date`) VALUES (20221004);
|
||||
INSERT INTO `Holiday` (`date`) VALUES (20221005);
|
||||
INSERT INTO `Holiday` (`date`) VALUES (20221006);
|
||||
INSERT INTO `Holiday` (`date`) VALUES (20221007);
|
||||
UPDATE `version` set `version` = 8;
|
||||
COMMIT;
|
@ -30,9 +30,7 @@ def deprecated_attr(name_dict):
|
||||
else:
|
||||
print(
|
||||
#'Deprecated warning: the "{}.{}" will be deprecated, please use: "{}.{}"'.
|
||||
'警告: "{}.{}" 即将被废弃,请使用 "{}.{}" 代替'.format(
|
||||
clzname, name, clzname, name_dict[name]
|
||||
)
|
||||
'警告: "{}.{}" 即将被废弃,请使用 "{}.{}" 代替'.format(clzname, name, clzname, name_dict[name])
|
||||
)
|
||||
return func(self, name_dict[name])
|
||||
if name not in dir(self):
|
||||
@ -529,13 +527,11 @@ def StockManager_getattr(self, name):
|
||||
StockManager.__getattr__ = StockManager_getattr
|
||||
|
||||
|
||||
@deprecated_attr(
|
||||
{
|
||||
'tickValue': 'tick_value',
|
||||
'minTradeNumber': 'min_trade_num',
|
||||
'maxTradeNumber': 'max_trade_num',
|
||||
}
|
||||
)
|
||||
@deprecated_attr({
|
||||
'tickValue': 'tick_value',
|
||||
'minTradeNumber': 'min_trade_num',
|
||||
'maxTradeNumber': 'max_trade_num',
|
||||
})
|
||||
def StockTypeInfo_getattr(self, name):
|
||||
return getattr(self, name)
|
||||
|
||||
|
@ -30,7 +30,8 @@
|
||||
"* [006 TradeManager应用](006-TradeManager.ipynb?flush_cache=True)\n",
|
||||
"* [007 系统策略演示](007-SystemDetails.ipynb?flush_cache=True)\n",
|
||||
"* [008 序列化说明](008-Pickle.ipynb?flush_cache=True)\n",
|
||||
"* [009_获取实时日线数据](009-RealData.ipynb?flush_cache=True)"
|
||||
"* [009_获取实时日线数据](009-RealData.ipynb?flush_cache=True)\n",
|
||||
"* [010_资产组合](010-Portfolio.ipynb?flush_cache=True)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -53,7 +54,7 @@
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
@ -67,7 +68,7 @@
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.8.3"
|
||||
"version": "3.9.7"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
File diff suppressed because one or more lines are too long
160
hikyuu/examples/notebook/010-Portfolio.ipynb
Normal file
160
hikyuu/examples/notebook/010-Portfolio.ipynb
Normal file
File diff suppressed because one or more lines are too long
@ -246,18 +246,9 @@ KData.get_pos = KData_getPos
|
||||
KData.get_pos_in_stock = KData_getPosInStock
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 封装增强其他C++ vector类型的遍历、打印
|
||||
# 封装增强其他C++ vector打印
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
PriceList.__getitem__ = list_getitem
|
||||
StringList.__getitem__ = list_getitem
|
||||
DatetimeList.__getitem__ = list_getitem
|
||||
BlockList.__getitem__ = list_getitem
|
||||
KRecordList.__getitem__ = list_getitem
|
||||
TransList.__getitem__ = list_getitem
|
||||
TimeLineList.__getitem__ = list_getitem
|
||||
StockWeightList.__getitem__ = list_getitem
|
||||
|
||||
PriceList.__str__ = lambda self: str(list(self))
|
||||
PriceList.__repr__ = lambda self: repr(list(self))
|
||||
StringList.__str__ = lambda self: str(list(self))
|
||||
|
@ -31,6 +31,7 @@ from hikyuu.util.singleton import SingletonType
|
||||
from sqlalchemy import (create_engine, Sequence, Column, Integer, String, and_, UniqueConstraint)
|
||||
from sqlalchemy.orm import sessionmaker, scoped_session
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
|
||||
Base = declarative_base()
|
||||
|
||||
|
||||
@ -174,9 +175,7 @@ class HubManager(metaclass=SingletonType):
|
||||
# 创建仓库数据库
|
||||
engine = create_engine("sqlite:///{}/.hikyuu/hub.db".format(usr_dir))
|
||||
Base.metadata.create_all(engine)
|
||||
self._scoped_Session = scoped_session(
|
||||
sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
||||
)
|
||||
self._scoped_Session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine))
|
||||
self._session = None
|
||||
|
||||
@dbsession
|
||||
@ -185,9 +184,8 @@ class HubManager(metaclass=SingletonType):
|
||||
usr_dir = os.path.expanduser('~')
|
||||
|
||||
# 检查并建立远端仓库的本地缓存目录
|
||||
self.remote_cache_dir = self._session.query(ConfigModel.value
|
||||
).filter(ConfigModel.key == 'remote_cache_dir'
|
||||
).first()
|
||||
self.remote_cache_dir = self._session.query(ConfigModel.value).filter(ConfigModel.key == 'remote_cache_dir'
|
||||
).first()
|
||||
if self.remote_cache_dir is None:
|
||||
self.remote_cache_dir = "{}/.hikyuu/hub_cache".format(usr_dir)
|
||||
record = ConfigModel(key='remote_cache_dir', value=self.remote_cache_dir)
|
||||
@ -207,8 +205,7 @@ class HubManager(metaclass=SingletonType):
|
||||
sys.path.append(os.path.dirname(model.local))
|
||||
|
||||
# 检查并下载 hikyuu 默认策略仓库, hikyuu_hub 避免导入时模块和 hikyuu 重名
|
||||
hikyuu_hub_path = self._session.query(HubModel.local).filter(HubModel.name == 'default'
|
||||
).first()
|
||||
hikyuu_hub_path = self._session.query(HubModel.local).filter(HubModel.name == 'default').first()
|
||||
if hikyuu_hub_path is None:
|
||||
self.add_remote_hub('default', 'https://gitee.com/fasiondog/hikyuu_hub.git', 'master')
|
||||
|
||||
@ -236,18 +233,14 @@ class HubManager(metaclass=SingletonType):
|
||||
record = self._session.query(HubModel).filter(HubModel.name == name).first()
|
||||
checkif(record is not None, name, HubNameRepeatError)
|
||||
|
||||
record = self._session.query(HubModel).filter(
|
||||
and_(HubModel.url == url, HubModel.branch == branch)
|
||||
).first()
|
||||
record = self._session.query(HubModel).filter(and_(HubModel.url == url, HubModel.branch == branch)).first()
|
||||
|
||||
# 下载远程仓库
|
||||
local_dir = "{}/{}".format(self.remote_cache_dir, name)
|
||||
self.download_remote_hub(local_dir, url, branch)
|
||||
|
||||
# 导入仓库各部件策略信息
|
||||
record = HubModel(
|
||||
name=name, hub_type='remote', url=url, branch=branch, local_base=name, local=local_dir
|
||||
)
|
||||
record = HubModel(name=name, hub_type='remote', url=url, branch=branch, local_base=name, local=local_dir)
|
||||
self.import_part_to_db(record)
|
||||
|
||||
# 更新仓库记录
|
||||
@ -332,9 +325,7 @@ class HubManager(metaclass=SingletonType):
|
||||
local_dir = hub_model.local
|
||||
if not os.path.lexists(local_dir):
|
||||
self.logger.warning(
|
||||
'The {} hub path ("{}") is not exists! Ignored this hub!'.format(
|
||||
hub_model.name, hub_model.local
|
||||
)
|
||||
'The {} hub path ("{}") is not exists! Ignored this hub!'.format(hub_model.name, hub_model.local)
|
||||
)
|
||||
return
|
||||
|
||||
@ -346,12 +337,9 @@ class HubManager(metaclass=SingletonType):
|
||||
try:
|
||||
with os.scandir(path) as it:
|
||||
for entry in it:
|
||||
if (not entry.name.startswith('.')
|
||||
) and entry.is_dir() and (entry.name != "__pycache__"):
|
||||
if (not entry.name.startswith('.')) and entry.is_dir() and (entry.name != "__pycache__"):
|
||||
# 计算实际的导入模块名
|
||||
module_name = '{}.part.{}.{}.part'.format(
|
||||
base_local, part, entry.name
|
||||
) if part not in (
|
||||
module_name = '{}.part.{}.{}.part'.format(base_local, part, entry.name) if part not in (
|
||||
'prtflo', 'sys'
|
||||
) else '{}.{}.{}.part'.format(base_local, part, entry.name)
|
||||
|
||||
@ -370,9 +358,7 @@ class HubManager(metaclass=SingletonType):
|
||||
self.logger.error('缺失 part 函数!("{}")'.format(entry.path))
|
||||
continue
|
||||
|
||||
name = '{}.{}.{}'.format(
|
||||
hub_model.name, part, entry.name
|
||||
) if part not in (
|
||||
name = '{}.{}.{}'.format(hub_model.name, part, entry.name) if part not in (
|
||||
'prtflo', 'sys'
|
||||
) else '{}.{}.{}'.format(hub_model.name, part, entry.name)
|
||||
|
||||
@ -382,12 +368,9 @@ class HubManager(metaclass=SingletonType):
|
||||
part=part,
|
||||
name=name,
|
||||
module_name=module_name,
|
||||
author=part_module.author.strip()
|
||||
if 'author' in module_vars else 'None',
|
||||
version=part_module.version.strip()
|
||||
if 'version' in module_vars else 'None',
|
||||
doc=part_module.part.__doc__.strip()
|
||||
if part_module.part.__doc__ else "None"
|
||||
author=part_module.author.strip() if 'author' in module_vars else 'None',
|
||||
version=part_module.version.strip() if 'version' in module_vars else 'None',
|
||||
doc=part_module.part.__doc__.strip() if part_module.part.__doc__ else "None"
|
||||
)
|
||||
self._session.add(part_model)
|
||||
except Exception as e:
|
||||
@ -406,10 +389,9 @@ class HubManager(metaclass=SingletonType):
|
||||
"""
|
||||
name_parts = name.split('.')
|
||||
checkif(
|
||||
len(name_parts) < 2 or (
|
||||
name_parts[-2]
|
||||
not in ('af', 'cn', 'ev', 'mm', 'pg', 'se', 'sg', 'sp', 'st', 'prtflo', 'sys')
|
||||
), name, PartNameError
|
||||
len(name_parts) < 2
|
||||
or (name_parts[-2] not in ('af', 'cn', 'ev', 'mm', 'pg', 'se', 'sg', 'sp', 'st', 'prtflo', 'sys')), name,
|
||||
PartNameError
|
||||
)
|
||||
|
||||
# 未指定仓库名,则默认使用 'default' 仓库
|
||||
@ -422,6 +404,7 @@ class HubManager(metaclass=SingletonType):
|
||||
raise PartNotFoundError(part_name, '请检查部件对应路径是否存在')
|
||||
part = part_module.part(**kwargs)
|
||||
part.name = part_model.name
|
||||
part.info = self.get_part_info(part.name)
|
||||
return part
|
||||
|
||||
@dbsession
|
||||
@ -482,9 +465,8 @@ class HubManager(metaclass=SingletonType):
|
||||
elif part_type is None:
|
||||
results = self._session.query(PartModel.name).filter_by(hub_name=hub).all()
|
||||
else:
|
||||
results = self._session.query(PartModel.name).filter(
|
||||
and_(PartModel.hub_name == hub, PartModel.part == part_type)
|
||||
).all()
|
||||
results = self._session.query(PartModel.name
|
||||
).filter(and_(PartModel.hub_name == hub, PartModel.part == part_type)).all()
|
||||
return [record[0] for record in results]
|
||||
|
||||
@dbsession
|
||||
@ -608,8 +590,7 @@ __all__ = [
|
||||
|
||||
if __name__ == "__main__":
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)-15s [%(levelname)s] - %(message)s [%(name)s::%(funcName)s]'
|
||||
level=logging.INFO, format='%(asctime)-15s [%(levelname)s] - %(message)s [%(name)s::%(funcName)s]'
|
||||
)
|
||||
add_local_hub('dev', '/home/fasiondog/workspace/stockhouse')
|
||||
#update_hub('test1')
|
||||
|
File diff suppressed because it is too large
Load Diff
25
hikyuu/test/AllocateFunds.py
Normal file
25
hikyuu/test/AllocateFunds.py
Normal file
@ -0,0 +1,25 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf8 -*-
|
||||
#
|
||||
# Create on: 2022-02-20
|
||||
# Author: fasiondog
|
||||
|
||||
import unittest
|
||||
from test_init import *
|
||||
|
||||
|
||||
class SystemWeightTest(unittest.TestCase):
|
||||
def test_weight(self):
|
||||
x = SystemWeight()
|
||||
self.assertEqual(x.weight, 1.0)
|
||||
|
||||
try:
|
||||
x.weight = 1.2
|
||||
except:
|
||||
self.assertEqual(x.weight, 1.0)
|
||||
|
||||
#print(x)
|
||||
|
||||
|
||||
def suite():
|
||||
return unittest.TestLoader().loadTestsFromTestCase(SystemWeightTest)
|
@ -10,81 +10,86 @@
|
||||
import unittest
|
||||
|
||||
from test_init import *
|
||||
from hikyuu.trade_sys.condition import *
|
||||
from hikyuu.trade_sys.signal import SignalBase
|
||||
from hikyuu import *
|
||||
|
||||
|
||||
class ConditionPython(ConditionBase):
|
||||
def __init__(self):
|
||||
super(ConditionPython, self).__init__("ConditionPython")
|
||||
self.setParam("n", 10)
|
||||
self.set_param("n", 10)
|
||||
self._m_flag = False
|
||||
|
||||
def isValid(self, datetime):
|
||||
|
||||
def is_valid(self, datetime):
|
||||
return self._m_flag
|
||||
|
||||
|
||||
def _reset(self):
|
||||
if self._m_flag:
|
||||
self._m_flag = False
|
||||
else:
|
||||
self._m_flag = True
|
||||
|
||||
|
||||
def _clone(self):
|
||||
p = ConditionPython()
|
||||
p._m_flag = self._m_flag
|
||||
return p
|
||||
|
||||
|
||||
class ConditionTest(unittest.TestCase):
|
||||
def test_ConditionBase(self):
|
||||
p = ConditionPython()
|
||||
self.assertEqual(p.name, "ConditionPython")
|
||||
self.assertEqual(p.getParam("n"), 10)
|
||||
p.setParam("n",20)
|
||||
self.assertEqual(p.getParam("n"), 20)
|
||||
self.assertEqual(p.isValid(Datetime(200101010000)), False)
|
||||
self.assertEqual(p.get_param("n"), 10)
|
||||
p.set_param("n", 20)
|
||||
self.assertEqual(p.get_param("n"), 20)
|
||||
self.assertEqual(p.is_valid(Datetime(200101010000)), False)
|
||||
p.reset()
|
||||
self.assertEqual(p.isValid(Datetime(200101010000)), True)
|
||||
|
||||
self.assertEqual(p.is_valid(Datetime(200101010000)), True)
|
||||
|
||||
p_clone = p.clone()
|
||||
self.assertEqual(p_clone.name, "ConditionPython")
|
||||
self.assertEqual(p_clone.getParam("n"), 20)
|
||||
self.assertEqual(p_clone.isValid(Datetime(200101010000)), True)
|
||||
self.assertEqual(p_clone.get_param("n"), 20)
|
||||
self.assertEqual(p_clone.is_valid(Datetime(200101010000)), True)
|
||||
|
||||
p.set_param("n", 1)
|
||||
p_clone.set_param("n", 3)
|
||||
self.assertEqual(p.get_param("n"), 1)
|
||||
self.assertEqual(p_clone.get_param("n"), 3)
|
||||
|
||||
|
||||
def testCondition(self):
|
||||
self._add_valid(Datetime(200101010000))
|
||||
self._add_valid(Datetime(200101020000))
|
||||
|
||||
|
||||
p.setParam("n", 1)
|
||||
p_clone.setParam("n", 3)
|
||||
self.assertEqual(p.getParam("n"), 1)
|
||||
self.assertEqual(p_clone.getParam("n"), 3)
|
||||
|
||||
def testCondition(self):
|
||||
self._addValid(Datetime(200101010000))
|
||||
self._addValid(Datetime(200101020000))
|
||||
|
||||
class TestCrtCN(unittest.TestCase):
|
||||
def test_crtCN(self):
|
||||
p = crtCN(testCondition, params={'n':10}, name='ConditionPython')
|
||||
self.assertEqual(p.getParam("n"), 10)
|
||||
p.setParam("n",20)
|
||||
self.assertEqual(p.getParam("n"), 20)
|
||||
p = crtCN(testCondition, params={'n': 10}, name='ConditionPython')
|
||||
self.assertEqual(p.get_param("n"), 10)
|
||||
p.set_param("n", 20)
|
||||
self.assertEqual(p.get_param("n"), 20)
|
||||
|
||||
k = sm['sh000001'].getKData(Query(-100))
|
||||
k = sm['sh000001'].get_kdata(Query(-100))
|
||||
self.assertEqual(k.empty(), False)
|
||||
p.setSG(SignalBase()) #cn设置交易对象时,必须已经指定了信号指示器
|
||||
p.setTO(k) #cn在设置交易对象时才会调用_caculate函数
|
||||
self.assertEqual(p.isValid(Datetime(200101010000)), True)
|
||||
self.assertEqual(p.isValid(Datetime(200101020000)), True)
|
||||
self.assertEqual(p.isValid(Datetime(200101030000)), False)
|
||||
|
||||
p.sg = SignalBase() #cn设置交易对象时,必须已经指定了信号指示器
|
||||
p.to = k #cn在设置交易对象时才会调用_caculate函数
|
||||
self.assertEqual(p.is_valid(Datetime(200101010000)), True)
|
||||
self.assertEqual(p.is_valid(Datetime(200101020000)), True)
|
||||
self.assertEqual(p.is_valid(Datetime(200101030000)), False)
|
||||
|
||||
p_clone = p.clone()
|
||||
self.assertEqual(p_clone.name, "ConditionPython")
|
||||
self.assertEqual(p_clone.getParam("n"), 20)
|
||||
self.assertEqual(p_clone.isValid(Datetime(200101010000)), True)
|
||||
self.assertEqual(p_clone.get_param("n"), 20)
|
||||
self.assertEqual(p_clone.is_valid(Datetime(200101010000)), True)
|
||||
|
||||
p.set_param("n", 1)
|
||||
p_clone.set_param("n", 3)
|
||||
self.assertEqual(p.get_param("n"), 1)
|
||||
self.assertEqual(p_clone.get_param("n"), 3)
|
||||
|
||||
|
||||
p.setParam("n", 1)
|
||||
p_clone.setParam("n", 3)
|
||||
self.assertEqual(p.getParam("n"), 1)
|
||||
self.assertEqual(p_clone.getParam("n"), 3)
|
||||
|
||||
def suite():
|
||||
return unittest.TestLoader().loadTestsFromTestCase(ConditionTest)
|
||||
|
||||
|
||||
def suiteTestCrtCN():
|
||||
return unittest.TestLoader().loadTestsFromTestCase(TestCrtCN)
|
||||
|
@ -11,6 +11,7 @@ import unittest
|
||||
|
||||
from test_init import *
|
||||
|
||||
|
||||
class DatetimeTest(unittest.TestCase):
|
||||
def test_Datetime(self):
|
||||
d = Datetime(201209272301)
|
||||
@ -33,17 +34,17 @@ class DatetimeTest(unittest.TestCase):
|
||||
self.assert_(d > Datetime(201209272259))
|
||||
self.assert_(not (d < Datetime(201209272301)))
|
||||
self.assert_(d < Datetime(201209272302))
|
||||
|
||||
|
||||
d = Datetime(200101010159)
|
||||
self.assertEqual(str(d), "2001-1-1 1:59:0")
|
||||
self.assertEqual(str(d), "2001-01-01 01:59:00")
|
||||
self.assertEqual(d, Datetime("2001-Jan-01 01:59:00"))
|
||||
|
||||
|
||||
self.assertEqual(Datetime(), constant.null_datetime)
|
||||
|
||||
|
||||
def test_pickle(self):
|
||||
if not constant.pickle_support:
|
||||
return
|
||||
|
||||
|
||||
import pickle as pl
|
||||
a = Datetime(201001010000)
|
||||
filename = sm.tmpdir() + "/Datetime.plk"
|
||||
@ -54,7 +55,7 @@ class DatetimeTest(unittest.TestCase):
|
||||
b = pl.load(fh)
|
||||
fh.close()
|
||||
self.assertEqual(a, b)
|
||||
|
||||
|
||||
|
||||
|
||||
def suite():
|
||||
return unittest.TestLoader().loadTestsFromTestCase(DatetimeTest)
|
||||
return unittest.TestLoader().loadTestsFromTestCase(DatetimeTest)
|
||||
|
@ -10,76 +10,79 @@
|
||||
import unittest
|
||||
|
||||
from test_init import *
|
||||
from hikyuu.trade_sys.environment import *
|
||||
|
||||
|
||||
class EnvironmentPython(EnvironmentBase):
|
||||
def __init__(self):
|
||||
super(EnvironmentPython, self).__init__("EnvironmentPython")
|
||||
self.setParam("n", 10)
|
||||
self.set_param("n", 10)
|
||||
self._m_flag = False
|
||||
|
||||
def isValid(self, market, datetime):
|
||||
|
||||
def is_valid(self, market, datetime):
|
||||
return self._m_flag
|
||||
|
||||
|
||||
def _reset(self):
|
||||
if self._m_flag:
|
||||
self._m_flag = False
|
||||
else:
|
||||
self._m_flag = True
|
||||
|
||||
|
||||
def _clone(self):
|
||||
p = EnvironmentPython()
|
||||
p._m_flag = self._m_flag
|
||||
return p
|
||||
|
||||
|
||||
class EnvironmentTest(unittest.TestCase):
|
||||
def test_EnvironmentBase(self):
|
||||
p = EnvironmentPython()
|
||||
self.assertEqual(p.name, "EnvironmentPython")
|
||||
self.assertEqual(p.getParam("n"), 10)
|
||||
p.setParam("n",20)
|
||||
self.assertEqual(p.getParam("n"), 20)
|
||||
self.assertEqual(p.isValid("SH", Datetime(200101010000)), False)
|
||||
self.assertEqual(p.get_param("n"), 10)
|
||||
p.set_param("n", 20)
|
||||
self.assertEqual(p.get_param("n"), 20)
|
||||
self.assertEqual(p.is_valid("SH", Datetime(200101010000)), False)
|
||||
p.reset()
|
||||
self.assertEqual(p.isValid("SH", Datetime(200101010000)), True)
|
||||
|
||||
self.assertEqual(p.is_valid("SH", Datetime(200101010000)), True)
|
||||
|
||||
p_clone = p.clone()
|
||||
self.assertEqual(p_clone.name, "EnvironmentPython")
|
||||
self.assertEqual(p_clone.getParam("n"), 20)
|
||||
self.assertEqual(p_clone.isValid("SH", Datetime(200101010000)), True)
|
||||
self.assertEqual(p_clone.get_param("n"), 20)
|
||||
self.assertEqual(p_clone.is_valid("SH", Datetime(200101010000)), True)
|
||||
|
||||
p.set_param("n", 1)
|
||||
p_clone.set_param("n", 3)
|
||||
self.assertEqual(p.get_param("n"), 1)
|
||||
self.assertEqual(p_clone.get_param("n"), 3)
|
||||
|
||||
|
||||
p.setParam("n", 1)
|
||||
p_clone.setParam("n", 3)
|
||||
self.assertEqual(p.getParam("n"), 1)
|
||||
self.assertEqual(p_clone.getParam("n"), 3)
|
||||
|
||||
|
||||
def test_crtEV_func(self):
|
||||
self._addValid(Datetime(200101010000))
|
||||
|
||||
|
||||
self._add_valid(Datetime(200101010000))
|
||||
|
||||
|
||||
class TestCrtEV(unittest.TestCase):
|
||||
def test_crtEV(self):
|
||||
p = crtEV(test_crtEV_func, params={'n':10}, name='EnvironmentPython')
|
||||
p = crtEV(test_crtEV_func, params={'n': 10}, name='EnvironmentPython')
|
||||
self.assertEqual(p.name, "EnvironmentPython")
|
||||
self.assertEqual(p.getParam("n"), 10)
|
||||
p.setParam("n",20)
|
||||
self.assertEqual(p.getParam("n"), 20)
|
||||
p.setQuery(Query(-100)) #ev在设置查询对象时才会调用_caculate函数
|
||||
self.assertEqual(p.isValid(Datetime(200101010000)), True)
|
||||
|
||||
self.assertEqual(p.get_param("n"), 10)
|
||||
p.set_param("n", 20)
|
||||
self.assertEqual(p.get_param("n"), 20)
|
||||
p.query = Query(-100) #ev在设置查询对象时才会调用_caculate函数
|
||||
self.assertEqual(p.is_valid(Datetime(200101010000)), True)
|
||||
|
||||
p_clone = p.clone()
|
||||
self.assertEqual(p_clone.name, "EnvironmentPython")
|
||||
self.assertEqual(p_clone.getParam("n"), 20)
|
||||
self.assertEqual(p_clone.isValid(Datetime(200101010000)), True)
|
||||
self.assertEqual(p_clone.get_param("n"), 20)
|
||||
self.assertEqual(p_clone.is_valid(Datetime(200101010000)), True)
|
||||
|
||||
p.set_param("n", 1)
|
||||
p_clone.set_param("n", 3)
|
||||
self.assertEqual(p.get_param("n"), 1)
|
||||
self.assertEqual(p_clone.get_param("n"), 3)
|
||||
|
||||
|
||||
p.setParam("n", 1)
|
||||
p_clone.setParam("n", 3)
|
||||
self.assertEqual(p.getParam("n"), 1)
|
||||
self.assertEqual(p_clone.getParam("n"), 3)
|
||||
|
||||
def suite():
|
||||
return unittest.TestLoader().loadTestsFromTestCase(EnvironmentTest)
|
||||
|
||||
|
||||
def suiteTestCrtEV():
|
||||
return unittest.TestLoader().loadTestsFromTestCase(TestCrtEV)
|
||||
|
@ -10,25 +10,30 @@
|
||||
import unittest
|
||||
|
||||
from test_init import *
|
||||
from hikyuu.indicator import *
|
||||
|
||||
|
||||
class AddIndicator(IndicatorImp):
|
||||
def __init__(self, indicator):
|
||||
super(AddIndicator, self).__init__("AddIndicator")
|
||||
self._readyBuffer(indicator.size(), 1)
|
||||
self._ready_buffer(len(indicator), 1)
|
||||
self.set_discard(0)
|
||||
for i in range(len(indicator)):
|
||||
self._set(indicator[i] + 1, i)
|
||||
|
||||
def __call__(self, ind):
|
||||
return AddIndicator(ind)
|
||||
def _clone(self):
|
||||
return AddIndicator(Indicator())
|
||||
|
||||
def _calculate(self, ind):
|
||||
self.set_discard(0)
|
||||
for i in range(len(ind)):
|
||||
self._set(ind[i] + 1, i)
|
||||
|
||||
|
||||
class IndicatorTest(unittest.TestCase):
|
||||
def test_PRICELIST(self):
|
||||
a = toPriceList([0, 1, 2, 3])
|
||||
x = PRICELIST(a)
|
||||
self.assertEqual(x.size(), 4)
|
||||
self.assertEqual(len(x), 4)
|
||||
self.assertEqual(x.empty(), False)
|
||||
self.assertEqual(x.discard, 0)
|
||||
self.assertEqual(x[0], 0)
|
||||
@ -41,7 +46,7 @@ class IndicatorTest(unittest.TestCase):
|
||||
x = PRICELIST(a)
|
||||
m = Indicator(AddIndicator(x))
|
||||
self.assertEqual(m.name, "AddIndicator")
|
||||
self.assertEqual(m.size(), 4)
|
||||
self.assertEqual(len(m), 4)
|
||||
self.assertEqual(m.empty(), False)
|
||||
self.assert_(abs(m[0] - 1) < 0.0001)
|
||||
self.assert_(abs(m[1] - 2) < 0.0001)
|
||||
@ -50,15 +55,14 @@ class IndicatorTest(unittest.TestCase):
|
||||
|
||||
b = toPriceList([1, 2, 3, 4])
|
||||
x = PRICELIST(b)
|
||||
m.get_imp()._calculate(m)
|
||||
m = m(x)
|
||||
self.assertEqual(m.size(), 4)
|
||||
self.assertEqual(len(m), 4)
|
||||
self.assertEqual(m.empty(), False)
|
||||
self.assert_(abs(m[0] - 2) < 0.0001)
|
||||
self.assert_(abs(m[1] - 3) < 0.0001)
|
||||
self.assert_(abs(m[2] - 4) < 0.0001)
|
||||
self.assert_(abs(m[3] - 5) < 0.0001)
|
||||
#print m.name
|
||||
#print m
|
||||
|
||||
def test_operator(self):
|
||||
a = toPriceList([0, 1, 2, 3])
|
||||
@ -84,7 +88,7 @@ class IndicatorTest(unittest.TestCase):
|
||||
self.assertEqual(a[3], 12)
|
||||
|
||||
a = x2 / x1
|
||||
self.assertEqual(a[0], constant.null_price)
|
||||
self.assert_(isnan(a[0]))
|
||||
self.assertEqual(a[1], 2)
|
||||
self.assertEqual(a[2], 1.5)
|
||||
self.assertEqual(a[3], 4.0 / 3.0)
|
||||
@ -92,7 +96,7 @@ class IndicatorTest(unittest.TestCase):
|
||||
def test_IKDATA(self):
|
||||
s = sm['sh000001']
|
||||
q = Query(0, 10)
|
||||
k = s.getKData(q)
|
||||
k = s.get_kdata(q)
|
||||
o = OPEN(k)
|
||||
h = HIGH(k)
|
||||
l = LOW(k)
|
||||
@ -100,12 +104,12 @@ class IndicatorTest(unittest.TestCase):
|
||||
a = AMO(k)
|
||||
v = VOL(k)
|
||||
|
||||
self.assertEqual(o.size(), 10)
|
||||
self.assertEqual(h.size(), 10)
|
||||
self.assertEqual(l.size(), 10)
|
||||
self.assertEqual(c.size(), 10)
|
||||
self.assertEqual(a.size(), 10)
|
||||
self.assertEqual(v.size(), 10)
|
||||
self.assertEqual(len(o), 10)
|
||||
self.assertEqual(len(h), 10)
|
||||
self.assertEqual(len(l), 10)
|
||||
self.assertEqual(len(c), 10)
|
||||
self.assertEqual(len(a), 10)
|
||||
self.assertEqual(len(v), 10)
|
||||
|
||||
self.assertEqual(o.empty(), False)
|
||||
self.assertEqual(h.empty(), False)
|
||||
@ -132,7 +136,7 @@ class IndicatorTest(unittest.TestCase):
|
||||
a = toPriceList([0, 1, 2, 3])
|
||||
x = PRICELIST(a)
|
||||
m = MA(x, 2)
|
||||
self.assertEqual(m.size(), 4)
|
||||
self.assertEqual(len(m), 4)
|
||||
self.assertEqual(m.discard, 0)
|
||||
self.assert_(abs(m[0] - 0.0) < 0.0001)
|
||||
self.assert_(abs(m[1] - 0.5) < 0.0001)
|
||||
|
@ -10,29 +10,28 @@
|
||||
import unittest
|
||||
|
||||
from test_init import *
|
||||
from hikyuu.trade_sys import *
|
||||
|
||||
|
||||
class KDataTest(unittest.TestCase):
|
||||
def test_null_kdata(self):
|
||||
k = KData()
|
||||
self.assertEqual(k.size(), 0)
|
||||
self.assertEqual(len(k), 0)
|
||||
self.assertEqual(k.empty(), True)
|
||||
self.assertEqual(k.startPos, 0)
|
||||
self.assertEqual(k.endPos, 0)
|
||||
self.assertEqual(k.lastPos, 0)
|
||||
stock = k.getStock()
|
||||
self.assertEqual(stock.isNull(), True)
|
||||
self.assertEqual(k.start_pos, 0)
|
||||
self.assertEqual(k.end_pos, 0)
|
||||
self.assertEqual(k.last_pos, 0)
|
||||
stock = k.get_stock()
|
||||
self.assertEqual(stock.is_null(), True)
|
||||
|
||||
def test_kdata(self):
|
||||
stock = sm["Sh000001"]
|
||||
q = Query(0, 10)
|
||||
k = stock.getKData(q)
|
||||
self.assertEqual(k.size(), 10)
|
||||
k = stock.get_kdata(q)
|
||||
self.assertEqual(len(k), 10)
|
||||
self.assertEqual(k.empty(), False)
|
||||
self.assertEqual(k.startPos, 0)
|
||||
self.assertEqual(k.endPos, 10)
|
||||
self.assertEqual(k.lastPos, 9)
|
||||
self.assertEqual(k.start_pos, 0)
|
||||
self.assertEqual(k.end_pos, 10)
|
||||
self.assertEqual(k.last_pos, 9)
|
||||
self.assertEqual(k[0].datetime, Datetime(199012190000))
|
||||
self.assert_(abs(k[0].open - 96.05) < 0.0001)
|
||||
self.assert_(abs(k[0].high - 99.980) < 0.0001)
|
||||
@ -50,13 +49,13 @@ class KDataTest(unittest.TestCase):
|
||||
import pickle as pl
|
||||
filename = sm.tmpdir() + "/KData.plk"
|
||||
fh = open(filename, 'wb')
|
||||
kdata = sm['sh000001'].getKData(Query(10, 20))
|
||||
kdata = sm['sh000001'].get_kdata(Query(10, 20))
|
||||
pl.dump(kdata, fh)
|
||||
fh.close()
|
||||
fh = open(filename, 'rb')
|
||||
b = pl.load(fh)
|
||||
fh.close()
|
||||
self.assertEqual(kdata.size(), b.size())
|
||||
self.assertEqual(len(kdata), len(b))
|
||||
for i in range(len(kdata)):
|
||||
self.assertEqual(kdata[i], b[i])
|
||||
|
||||
|
@ -14,12 +14,12 @@ from test_init import *
|
||||
|
||||
class MarketInfoTest(unittest.TestCase):
|
||||
def test_market(self):
|
||||
market = sm.getMarketInfo("Sh")
|
||||
market = sm.get_market_info("Sh")
|
||||
self.assertEqual(market.market, "SH")
|
||||
self.assertEqual(market.name, u"上海证劵交易所")
|
||||
self.assertEqual(market.description, u"上海市场")
|
||||
self.assertEqual(market.code, "000001")
|
||||
self.assertEqual(market.lastDate, Datetime(201112060000))
|
||||
self.assertEqual(market.last_datetime, Datetime(201112060000))
|
||||
|
||||
|
||||
def suite():
|
||||
|
@ -10,73 +10,79 @@
|
||||
import unittest
|
||||
|
||||
from test_init import *
|
||||
from hikyuu.trade_sys.moneymanager import *
|
||||
|
||||
|
||||
class MoneyManagerPython(MoneyManagerBase):
|
||||
def __init__(self):
|
||||
super(MoneyManagerPython, self).__init__("MoneyManagerPython")
|
||||
self.setParam("n", 10)
|
||||
self.set_param("n", 10)
|
||||
self._m_flag = False
|
||||
|
||||
|
||||
def getBuyNumber(self, datetime, stock, price, risk):
|
||||
if self._m_flag:
|
||||
return 10
|
||||
else:
|
||||
return 20
|
||||
|
||||
|
||||
def _reset(self):
|
||||
if self._m_flag:
|
||||
self._m_flag = False
|
||||
else:
|
||||
self._m_flag = True
|
||||
|
||||
|
||||
def _clone(self):
|
||||
p = MoneyManagerPython()
|
||||
p._m_flag = self._m_flag
|
||||
return p
|
||||
|
||||
|
||||
class MoneyManagerTest(unittest.TestCase):
|
||||
def test_ConditionBase(self):
|
||||
stock = sm['sh000001']
|
||||
p = MoneyManagerPython()
|
||||
self.assertEqual(p.name, "MoneyManagerPython")
|
||||
self.assertEqual(p.getParam("n"), 10)
|
||||
p.setParam("n",20)
|
||||
self.assertEqual(p.getParam("n"), 20)
|
||||
self.assertEqual(p.get_param("n"), 10)
|
||||
p.set_param("n", 20)
|
||||
self.assertEqual(p.get_param("n"), 20)
|
||||
self.assertEqual(p.getBuyNumber(Datetime(200101010000), stock, 10.0, 0.0), 20)
|
||||
p.reset()
|
||||
self.assertEqual(p.getBuyNumber(Datetime(200101010000), stock, 10.0, 0.0), 10)
|
||||
|
||||
|
||||
p_clone = p.clone()
|
||||
self.assertEqual(p_clone.name, "MoneyManagerPython")
|
||||
self.assertEqual(p_clone.getParam("n"), 20)
|
||||
self.assertEqual(p_clone.get_param("n"), 20)
|
||||
self.assertEqual(p_clone.getBuyNumber(Datetime(200101010000), stock, 10, 0.0), 10)
|
||||
|
||||
p.setParam("n", 1)
|
||||
p_clone.setParam("n", 3)
|
||||
self.assertEqual(p.getParam("n"), 1)
|
||||
self.assertEqual(p_clone.getParam("n"), 3)
|
||||
|
||||
p.set_param("n", 1)
|
||||
p_clone.set_param("n", 3)
|
||||
self.assertEqual(p.get_param("n"), 1)
|
||||
self.assertEqual(p_clone.get_param("n"), 3)
|
||||
|
||||
|
||||
def testCrtMM(self):
|
||||
pass
|
||||
|
||||
|
||||
def testgetBuyNumber(self, datetime, stock, price, risk):
|
||||
return 10.0 if datetime == Datetime(200101010000) else 0.0
|
||||
|
||||
|
||||
class TestCrtMM(unittest.TestCase):
|
||||
def test_crt_mm(self):
|
||||
p = crtMM(testCrtMM, params={'n':10}, name="TestMM")
|
||||
p = crtMM(testCrtMM, params={'n': 10}, name="TestMM")
|
||||
p.getBuyNumber = testgetBuyNumber
|
||||
self.assertEqual(p.name, "TestMM")
|
||||
stock = sm['sh000001']
|
||||
self.assertEqual(p.getBuyNumber(p, Datetime(200101010000), stock, 1.0, 1.0), 10.0)
|
||||
self.assertEqual(p.getBuyNumber(p, Datetime(200101020000), stock, 1.0, 1.0), 0.0)
|
||||
|
||||
|
||||
p_clone = p.clone()
|
||||
self.assertEqual(p_clone.name, "TestMM")
|
||||
|
||||
self.assertEqual(p_clone.name, "TestMM")
|
||||
|
||||
|
||||
def suite():
|
||||
return unittest.TestLoader().loadTestsFromTestCase(MoneyManagerTest)
|
||||
|
||||
|
||||
def suiteTestCrtMM():
|
||||
return unittest.TestLoader().loadTestsFromTestCase(TestCrtMM)
|
@ -11,51 +11,52 @@ from test_init import *
|
||||
import unittest
|
||||
from hikyuu import Parameter
|
||||
|
||||
|
||||
class ParameterTest(unittest.TestCase):
|
||||
def test_Parameter(self):
|
||||
p = Parameter()
|
||||
self.assertEqual(p.have("n"), False)
|
||||
self.assertEqual(p.have("b"), False)
|
||||
self.assertEqual(p.have("d"), False)
|
||||
self.assertEqual(p.have("s"), False)
|
||||
p.set("n", 10)
|
||||
p.set("b", True)
|
||||
p.set("d", 10.01)
|
||||
p.set("s", "string")
|
||||
self.assertEqual(p.have("n"), True)
|
||||
self.assertEqual(p.have("b"), True)
|
||||
self.assertEqual(p.have("d"), True)
|
||||
self.assertEqual(p.have("s"), True)
|
||||
self.assertEqual(p.get("n"), 10)
|
||||
self.assertEqual(p.get("b"), True)
|
||||
self.assertEqual(p.get("d"), 10.01)
|
||||
self.assertEqual(p.get("s"), "string")
|
||||
|
||||
p.set("n", 20)
|
||||
p.set("b", False)
|
||||
p.set("d", 10.001)
|
||||
p.set("s", "string2")
|
||||
self.assertEqual(p.get("n"), 20)
|
||||
self.assertEqual(p.get("b"), False)
|
||||
self.assertEqual(p.get("d"), 10.001)
|
||||
self.assertEqual(p.get("s"), "string2")
|
||||
|
||||
def test_pickle(self):
|
||||
if not constant.pickle_support:
|
||||
return
|
||||
tmpdir = sm.tmpdir()
|
||||
fh = open(tmpdir + "/Parameter.plk", "wb")
|
||||
a = Parameter()
|
||||
a.set("bool", True)
|
||||
a.set("string", "This is Parameter")
|
||||
import pickle as pl
|
||||
pl.dump(a, fh)
|
||||
fh.close()
|
||||
fh = open(tmpdir + "/Parameter.plk", "rb")
|
||||
b = pl.load(fh)
|
||||
self.assertEqual(b.get("bool"), True)
|
||||
self.assertEqual(b.get("string"), "This is Parameter")
|
||||
|
||||
|
||||
self.assertEqual("n" in p, False)
|
||||
self.assertEqual("b" in p, False)
|
||||
self.assertEqual("d" in p, False)
|
||||
self.assertEqual("s" in p, False)
|
||||
p["n"] = 10
|
||||
p["b"] = True
|
||||
p["d"] = 10.01
|
||||
p["s"] = "string"
|
||||
self.assertEqual("n" in p, True)
|
||||
self.assertEqual("b" in p, True)
|
||||
self.assertEqual("d" in p, True)
|
||||
self.assertEqual("s" in p, True)
|
||||
self.assertEqual(p["n"], 10)
|
||||
self.assertEqual(p["b"], True)
|
||||
self.assertEqual(p["d"], 10.01)
|
||||
self.assertEqual(p["s"], "string")
|
||||
|
||||
p["n"] = 20
|
||||
p["b"] = False
|
||||
p["d"] = 10.001
|
||||
p["s"] = "string2"
|
||||
self.assertEqual(p["n"], 20)
|
||||
self.assertEqual(p["b"], False)
|
||||
self.assertEqual(p["d"], 10.001)
|
||||
self.assertEqual(p["s"], "string2")
|
||||
|
||||
# def test_pickle(self):
|
||||
# if not constant.pickle_support:
|
||||
# return
|
||||
# tmpdir = sm.tmpdir()
|
||||
# fh = open(tmpdir + "/Parameter.plk", "wb")
|
||||
# a = Parameter()
|
||||
# a["bool"] = True
|
||||
# a["string"] = "This is Parameter"
|
||||
# import pickle as pl
|
||||
# pl.dump(a, fh)
|
||||
# fh.close()
|
||||
# fh = open(tmpdir + "/Parameter.plk", "rb")
|
||||
# b = pl.load(fh)
|
||||
# self.assertEqual(b["bool"], True)
|
||||
# self.assertEqual(b["string"], "This is Parameter")
|
||||
|
||||
|
||||
def suite():
|
||||
return unittest.TestLoader().loadTestsFromTestCase(ParameterTest)
|
@ -10,42 +10,43 @@
|
||||
import unittest
|
||||
|
||||
from test_init import *
|
||||
from hikyuu.trade_sys.profitgoal import *
|
||||
|
||||
|
||||
class ProfitGoalPython(ProfitGoalBase):
|
||||
def __init__(self):
|
||||
super(ProfitGoalPython, self).__init__("ProfitGoalPython")
|
||||
self._x = 0
|
||||
|
||||
|
||||
def getGoal(self, datetime, price):
|
||||
if self._x < 10:
|
||||
return 0.0
|
||||
return 1.0
|
||||
|
||||
|
||||
def _reset(self):
|
||||
self._x = 0
|
||||
|
||||
|
||||
def _clone(self):
|
||||
p = ProfitGoalPython()
|
||||
p._x = self._x
|
||||
return p
|
||||
|
||||
|
||||
def _calculate(self):
|
||||
""" do nothing """
|
||||
|
||||
|
||||
class ProfitGoalTest(unittest.TestCase):
|
||||
def test_ProfitGoalBase(self):
|
||||
p = ProfitGoalPython()
|
||||
self.assertEqual(p.name, "ProfitGoalPython")
|
||||
self.assertEqual(p.getGoal(Datetime(200101010000), 1.0), 0.0)
|
||||
|
||||
|
||||
self.assertEqual(p._x, 0)
|
||||
p._x = 10
|
||||
self.assertEqual(p._x, 10)
|
||||
self.assertEqual(p.getGoal(Datetime(200101010000), 1.0), 1.0)
|
||||
p.reset()
|
||||
self.assertEqual(p._x, 0)
|
||||
|
||||
|
||||
p._x = 10
|
||||
p_clone = p.clone()
|
||||
self.assertEqual(p_clone._x, 10)
|
||||
@ -57,22 +58,26 @@ class ProfitGoalTest(unittest.TestCase):
|
||||
def testCrtPG(self):
|
||||
pass
|
||||
|
||||
|
||||
def testGetGoal(self, datetime, price):
|
||||
return 10.0 if datetime == Datetime(200101010000) else 0.0
|
||||
|
||||
|
||||
class TestCrtPG(unittest.TestCase):
|
||||
def test_crt_pg(self):
|
||||
p = crtPG(testCrtPG, params={'n':10}, name="ProfitGoalPython")
|
||||
p = crtPG(testCrtPG, params={'n': 10}, name="ProfitGoalPython")
|
||||
p.getGoal = testGetGoal
|
||||
self.assertEqual(p.name, "ProfitGoalPython")
|
||||
self.assertEqual(p.getGoal(p, Datetime(200101010000), 1.0), 10.0)
|
||||
self.assertEqual(p.getGoal(p, Datetime(200101020000), 1.0), 0.0)
|
||||
|
||||
|
||||
p_clone = p.clone()
|
||||
self.assertEqual(p_clone.name, "ProfitGoalPython")
|
||||
|
||||
|
||||
|
||||
def suite():
|
||||
return unittest.TestLoader().loadTestsFromTestCase(ProfitGoalTest)
|
||||
|
||||
|
||||
def suiteTestCrtPG():
|
||||
return unittest.TestLoader().loadTestsFromTestCase(TestCrtPG)
|
@ -10,134 +10,136 @@
|
||||
import unittest
|
||||
|
||||
from test_init import *
|
||||
from hikyuu.trade_sys.signal import *
|
||||
|
||||
|
||||
class SignalPython(SignalBase):
|
||||
def __init__(self):
|
||||
super(SignalPython, self).__init__("SignalPython")
|
||||
self._x = 0
|
||||
self.setParam("test", 30)
|
||||
|
||||
self.set_param("test", 30)
|
||||
|
||||
def _reset(self):
|
||||
self._x = 0
|
||||
|
||||
|
||||
def _clone(self):
|
||||
p = SignalPython()
|
||||
p._x = self._x
|
||||
return p
|
||||
|
||||
|
||||
def _calculate(self):
|
||||
self._addBuySignal(Datetime(201201210000))
|
||||
self._addSellSignal(Datetime(201201300000))
|
||||
|
||||
|
||||
self._add_buy_signal(Datetime(201201210000))
|
||||
self._add_sell_signal(Datetime(201201300000))
|
||||
|
||||
|
||||
class SignalTest(unittest.TestCase):
|
||||
def test_SignalBase(self):
|
||||
p = SignalPython()
|
||||
self.assertEqual(p.name, "SignalPython")
|
||||
p.name = "SignalPythonTest"
|
||||
self.assertEqual(p.name, "SignalPythonTest")
|
||||
|
||||
self.assertEqual(p.shouldBuy(Datetime(201201210000)), False)
|
||||
self.assertEqual(p.shouldSell(Datetime(201201300000)), False)
|
||||
k = sm['sh000001'].getKData(Query(-100))
|
||||
|
||||
self.assertEqual(p.should_buy(Datetime(201201210000)), False)
|
||||
self.assertEqual(p.should_sell(Datetime(201201300000)), False)
|
||||
k = sm['sh000001'].get_kdata(Query(-100))
|
||||
self.assertEqual(k.empty(), False)
|
||||
p.setTO(k)
|
||||
self.assertEqual(p.shouldBuy(Datetime(201201210000)), True)
|
||||
self.assertEqual(p.shouldSell(Datetime(201201300000)), True)
|
||||
|
||||
self.assertEqual(p.shouldBuy(Datetime(200101010000)), False)
|
||||
p._addBuySignal(Datetime(200101010000))
|
||||
self.assertEqual(p.shouldBuy(Datetime(200101010000)), True)
|
||||
|
||||
self.assertEqual(p.shouldSell(Datetime(200101030000)), False)
|
||||
p._addSellSignal(Datetime(200101030000))
|
||||
self.assertEqual(p.shouldSell(Datetime(200101030000)), True)
|
||||
|
||||
d = p.getBuySignal()
|
||||
p.to = k
|
||||
self.assertEqual(p.should_buy(Datetime(201201210000)), True)
|
||||
self.assertEqual(p.should_sell(Datetime(201201300000)), True)
|
||||
|
||||
self.assertEqual(p.should_buy(Datetime(200101010000)), False)
|
||||
p._add_buy_signal(Datetime(200101010000))
|
||||
self.assertEqual(p.should_buy(Datetime(200101010000)), True)
|
||||
|
||||
self.assertEqual(p.should_sell(Datetime(200101030000)), False)
|
||||
p._add_sell_signal(Datetime(200101030000))
|
||||
self.assertEqual(p.should_sell(Datetime(200101030000)), True)
|
||||
|
||||
d = p.get_buy_signal()
|
||||
for i in range(len(d)):
|
||||
self.assertIn(d[i], [Datetime(201201210000), Datetime(200101010000)])
|
||||
|
||||
d = p.getSellSignal()
|
||||
|
||||
d = p.get_sell_signal()
|
||||
for i in range(len(d)):
|
||||
self.assertIn(d[i], [Datetime(201201300000), Datetime(200101030000)])
|
||||
|
||||
|
||||
p_clone = p.clone()
|
||||
d = p_clone.getBuySignal()
|
||||
d = p_clone.get_buy_signal()
|
||||
for i in range(len(d)):
|
||||
self.assertIn(d[i], [Datetime(201201210000), Datetime(200101010000)])
|
||||
|
||||
d = p_clone.getSellSignal()
|
||||
|
||||
d = p_clone.get_sell_signal()
|
||||
for i in range(len(d)):
|
||||
self.assertIn(d[i], [Datetime(201201300000), Datetime(200101030000)])
|
||||
|
||||
|
||||
self.assertEqual(p._x, 0)
|
||||
p._x = 10
|
||||
self.assertEqual(p._x, 10)
|
||||
p.reset()
|
||||
self.assertEqual(p._x, 0)
|
||||
|
||||
|
||||
p._x = 20
|
||||
p_clone = p.clone()
|
||||
self.assertEqual(p_clone._x, 20)
|
||||
p.reset()
|
||||
self.assertEqual(p._x, 0)
|
||||
self.assertEqual(p_clone._x, 20)
|
||||
|
||||
self.assertEqual(p.getParam("test"), 30)
|
||||
self.assertEqual(p_clone.getParam("test"), 30)
|
||||
p.setParam("test", 10)
|
||||
self.assertEqual(p.getParam("test"), 10)
|
||||
self.assertEqual(p_clone.getParam("test"), 30)
|
||||
|
||||
|
||||
self.assertEqual(p.get_param("test"), 30)
|
||||
self.assertEqual(p_clone.get_param("test"), 30)
|
||||
p.set_param("test", 10)
|
||||
self.assertEqual(p.get_param("test"), 10)
|
||||
self.assertEqual(p_clone.get_param("test"), 30)
|
||||
|
||||
|
||||
def testSignal(self):
|
||||
self._addBuySignal(Datetime(201201210000))
|
||||
self._addSellSignal(Datetime(201201300000))
|
||||
|
||||
class TestCrtSG(unittest.TestCase):
|
||||
self._add_buy_signal(Datetime(201201210000))
|
||||
self._add_sell_signal(Datetime(201201300000))
|
||||
|
||||
|
||||
class TestCrtSG(unittest.TestCase):
|
||||
def test_crtSG(self):
|
||||
p = crtSG(testSignal, params={'test':30}, name='SG_TEST')
|
||||
p = crtSG(testSignal, params={'test': 30}, name='SG_TEST')
|
||||
self.assertEqual(p.name, "SG_TEST")
|
||||
p.name = "SignalPythonTest"
|
||||
self.assertEqual(p.name, "SignalPythonTest")
|
||||
|
||||
self.assertEqual(p.shouldBuy(Datetime(201201210000)), False)
|
||||
self.assertEqual(p.shouldSell(Datetime(201201300000)), False)
|
||||
k = sm['sh000001'].getKData(Query(-100))
|
||||
|
||||
self.assertEqual(p.should_buy(Datetime(201201210000)), False)
|
||||
self.assertEqual(p.should_sell(Datetime(201201300000)), False)
|
||||
k = sm['sh000001'].get_kdata(Query(-100))
|
||||
self.assertEqual(k.empty(), False)
|
||||
p.setTO(k)
|
||||
self.assertEqual(p.shouldBuy(Datetime(201201210000)), True)
|
||||
self.assertEqual(p.shouldSell(Datetime(201201300000)), True)
|
||||
|
||||
self.assertEqual(p.shouldBuy(Datetime(200101010000)), False)
|
||||
p._addBuySignal(Datetime(200101010000))
|
||||
self.assertEqual(p.shouldBuy(Datetime(200101010000)), True)
|
||||
|
||||
self.assertEqual(p.shouldSell(Datetime(200101030000)), False)
|
||||
p._addSellSignal(Datetime(200101030000))
|
||||
self.assertEqual(p.shouldSell(Datetime(200101030000)), True)
|
||||
|
||||
d = p.getBuySignal()
|
||||
p.to = k
|
||||
self.assertEqual(p.should_buy(Datetime(201201210000)), True)
|
||||
self.assertEqual(p.should_sell(Datetime(201201300000)), True)
|
||||
|
||||
self.assertEqual(p.should_buy(Datetime(200101010000)), False)
|
||||
p._add_buy_signal(Datetime(200101010000))
|
||||
self.assertEqual(p.should_buy(Datetime(200101010000)), True)
|
||||
|
||||
self.assertEqual(p.should_sell(Datetime(200101030000)), False)
|
||||
p._add_sell_signal(Datetime(200101030000))
|
||||
self.assertEqual(p.should_sell(Datetime(200101030000)), True)
|
||||
|
||||
d = p.get_buy_signal()
|
||||
for i in range(len(d)):
|
||||
self.assertIn(d[i], [Datetime(201201210000), Datetime(200101010000)])
|
||||
|
||||
d = p.getSellSignal()
|
||||
|
||||
d = p.get_sell_signal()
|
||||
for i in range(len(d)):
|
||||
self.assertIn(d[i], [Datetime(201201300000), Datetime(200101030000)])
|
||||
|
||||
|
||||
p_clone = p.clone()
|
||||
d = p_clone.getBuySignal()
|
||||
d = p_clone.get_buy_signal()
|
||||
for i in range(len(d)):
|
||||
self.assertIn(d[i], [Datetime(201201210000), Datetime(200101010000)])
|
||||
|
||||
d = p_clone.getSellSignal()
|
||||
|
||||
d = p_clone.get_sell_signal()
|
||||
for i in range(len(d)):
|
||||
self.assertIn(d[i], [Datetime(201201300000), Datetime(200101030000)])
|
||||
|
||||
|
||||
|
||||
|
||||
def suite():
|
||||
return unittest.TestLoader().loadTestsFromTestCase(SignalTest)
|
||||
|
||||
|
||||
def suiteTestCrtSG():
|
||||
return unittest.TestLoader().loadTestsFromTestCase(TestCrtSG)
|
||||
|
@ -10,41 +10,42 @@
|
||||
import unittest
|
||||
|
||||
from test_init import *
|
||||
from hikyuu.trade_sys.slippage import *
|
||||
|
||||
|
||||
class SlippagePython(SlippageBase):
|
||||
def __init__(self):
|
||||
super(SlippagePython, self).__init__("SlippagePython")
|
||||
self._x = 0
|
||||
|
||||
|
||||
def getRealBuyPrice(self, datetime, price):
|
||||
if self._x < 10:
|
||||
return 0.0
|
||||
return 1.0
|
||||
|
||||
|
||||
def getRealSellPrice(self, datetime, price):
|
||||
if self._x < 10:
|
||||
return 0.0
|
||||
return 1.0
|
||||
|
||||
return 1.0
|
||||
|
||||
def _reset(self):
|
||||
self._x = 0
|
||||
|
||||
|
||||
def _clone(self):
|
||||
p = SlippagePython()
|
||||
p._x = self._x
|
||||
return p
|
||||
|
||||
|
||||
def _calculate(self):
|
||||
""" do nothin """
|
||||
|
||||
|
||||
class SlippageTest(unittest.TestCase):
|
||||
def test_SlippageBase(self):
|
||||
p = SlippagePython()
|
||||
self.assertEqual(p.name, "SlippagePython")
|
||||
self.assertEqual(p.getRealBuyPrice(Datetime(200101010000), 1.0), 0.0)
|
||||
self.assertEqual(p.getRealSellPrice(Datetime(200101010000), 1.0), 0.0)
|
||||
|
||||
|
||||
self.assertEqual(p._x, 0)
|
||||
p._x = 10
|
||||
self.assertEqual(p._x, 10)
|
||||
@ -52,7 +53,7 @@ class SlippageTest(unittest.TestCase):
|
||||
self.assertEqual(p.getRealSellPrice(Datetime(200101010000), 1.0), 1.0)
|
||||
p.reset()
|
||||
self.assertEqual(p._x, 0)
|
||||
|
||||
|
||||
p._x = 10
|
||||
p_clone = p.clone()
|
||||
self.assertEqual(p_clone._x, 10)
|
||||
@ -60,26 +61,30 @@ class SlippageTest(unittest.TestCase):
|
||||
self.assertEqual(p._x, 0)
|
||||
self.assertEqual(p_clone._x, 10)
|
||||
|
||||
|
||||
def test_crtSL_func(self):
|
||||
pass
|
||||
|
||||
|
||||
def test_getRealBuyPrice_func(self, datetime, price):
|
||||
return 10.0 if datetime == Datetime(200101010000) else 0.0
|
||||
|
||||
|
||||
class TestCrtSL(unittest.TestCase):
|
||||
def test_crtSL(self):
|
||||
p = crtSL(test_crtSL_func, params={'n':10}, name="TestSL")
|
||||
p = crtSL(test_crtSL_func, params={'n': 10}, name="TestSL")
|
||||
p.getRealBuyPrice = test_getRealBuyPrice_func
|
||||
self.assertEqual(p.name, "TestSL")
|
||||
self.assertEqual(p.getRealBuyPrice(p, Datetime(200101010000), 1.0), 10.0)
|
||||
self.assertEqual(p.getRealBuyPrice(p, Datetime(200101020000), 1.0), 0.0)
|
||||
|
||||
|
||||
p_clone = p.clone()
|
||||
self.assertEqual(p_clone.name, "TestSL")
|
||||
|
||||
|
||||
|
||||
|
||||
def suite():
|
||||
return unittest.TestLoader().loadTestsFromTestCase(SlippageTest)
|
||||
|
||||
|
||||
def suiteTestCrtSL():
|
||||
return unittest.TestLoader().loadTestsFromTestCase(TestCrtSL)
|
@ -20,19 +20,19 @@ class StockTest(unittest.TestCase):
|
||||
self.assertEqual(stock.market_code, "SH000001")
|
||||
self.assertEqual(stock.name, u"上证指数")
|
||||
self.assertEqual(stock.type, 2)
|
||||
self.assertEqual(stock.startDatetime, Datetime(199012190000))
|
||||
self.assertEqual(stock.lastDatetime, constant.null_datetime)
|
||||
self.assertEqual(stock.start_datetime, Datetime(199012190000))
|
||||
self.assertEqual(stock.last_datetime, constant.null_datetime)
|
||||
self.assertEqual(stock.tick, 0.001)
|
||||
self.assertEqual(stock.tickValue, 0.001)
|
||||
self.assertEqual(stock.tick_value, 0.001)
|
||||
self.assertEqual(stock.unit, 1.0)
|
||||
self.assertEqual(stock.precision, 3)
|
||||
self.assertEqual(stock.atom, 1)
|
||||
self.assertEqual(stock.minTradeNumber, 1)
|
||||
self.assertEqual(stock.maxTradeNumber, 1000000)
|
||||
self.assertEqual(stock.getCount(), 5121)
|
||||
self.assertEqual(stock.getCount(Query.MIN), 682823)
|
||||
self.assertEqual(stock.getKRecord(0).datetime, Datetime(199012190000))
|
||||
self.assertEqual(stock.getKRecord(1, Query.MIN).datetime, Datetime(200001040932))
|
||||
self.assertEqual(stock.min_trade_number, 1)
|
||||
self.assertEqual(stock.max_trade_number, 1000000)
|
||||
self.assertEqual(stock.get_count(), 5121)
|
||||
self.assertEqual(stock.get_count(Query.MIN), 682823)
|
||||
self.assertEqual(stock.get_krecord(0).datetime, Datetime(199012190000))
|
||||
self.assertEqual(stock.get_krecord(1, Query.MIN).datetime, Datetime(200001040932))
|
||||
|
||||
s1 = sm['sh000001']
|
||||
s2 = sm['sh000001']
|
||||
|
@ -14,15 +14,15 @@ from test_init import *
|
||||
|
||||
class StockTypeInfoTest(unittest.TestCase):
|
||||
def test_stockType(self):
|
||||
stockType = sm.getStockTypeInfo(1)
|
||||
stockType = sm.get_stock_type_info(1)
|
||||
self.assertEqual(stockType.type, 1)
|
||||
self.assertEqual(stockType.description, u"A股")
|
||||
self.assertEqual(stockType.tick, 0.01)
|
||||
self.assertEqual(stockType.tickValue, 0.01)
|
||||
self.assertEqual(stockType.tick_value, 0.01)
|
||||
self.assertEqual(stockType.unit, 1.0)
|
||||
self.assertEqual(stockType.precision, 2)
|
||||
self.assertEqual(stockType.minTradeNumber, 100)
|
||||
self.assertEqual(stockType.maxTradeNumber, 1000000)
|
||||
self.assertEqual(stockType.min_trade_num, 100)
|
||||
self.assertEqual(stockType.max_trade_num, 1000000)
|
||||
|
||||
def test_pickle(self):
|
||||
if not constant.pickle_support:
|
||||
|
@ -10,45 +10,46 @@
|
||||
import unittest
|
||||
|
||||
from test_init import *
|
||||
from hikyuu.trade_sys.stoploss import *
|
||||
|
||||
|
||||
class StoplossPython(StoplossBase):
|
||||
def __init__(self):
|
||||
super(StoplossPython, self).__init__()
|
||||
self._x = 0
|
||||
|
||||
|
||||
def name(self):
|
||||
return "StoplossPython"
|
||||
|
||||
|
||||
def getPrice(self, datetime, price):
|
||||
if self._x < 10:
|
||||
return 0.0
|
||||
return 1.0
|
||||
|
||||
|
||||
def _reset(self):
|
||||
self._x = 0
|
||||
|
||||
|
||||
def _clone(self):
|
||||
p = StoplossPython()
|
||||
p._x = self._x
|
||||
return p
|
||||
|
||||
|
||||
def _calculate(self):
|
||||
""" do nothin """
|
||||
|
||||
|
||||
class StoplossTest(unittest.TestCase):
|
||||
def test_StoplossBase(self):
|
||||
p = StoplossPython()
|
||||
self.assertEqual(p.name(), "StoplossPython")
|
||||
self.assertEqual(p.getPrice(Datetime(200101010000), 1.0), 0.0)
|
||||
|
||||
|
||||
self.assertEqual(p._x, 0)
|
||||
p._x = 10
|
||||
self.assertEqual(p._x, 10)
|
||||
self.assertEqual(p.getPrice(Datetime(200101010000), 1.0), 1.0)
|
||||
p.reset()
|
||||
self.assertEqual(p._x, 0)
|
||||
|
||||
|
||||
p._x = 10
|
||||
p_clone = p.clone()
|
||||
self.assertEqual(p_clone._x, 10)
|
||||
@ -60,22 +61,26 @@ class StoplossTest(unittest.TestCase):
|
||||
def test_crtST_func(self):
|
||||
pass
|
||||
|
||||
|
||||
def test_getPrice_func(self, datetime, price):
|
||||
return 10.0 if datetime == Datetime(200101010000) else 0.0
|
||||
|
||||
|
||||
class TestCrtST(unittest.TestCase):
|
||||
def test_crtST(self):
|
||||
p = crtST(test_crtST_func, params={'n':10}, name="StoplossPython")
|
||||
p = crtST(test_crtST_func, params={'n': 10}, name="StoplossPython")
|
||||
p.getPrice = test_getPrice_func
|
||||
self.assertEqual(p.name, "StoplossPython")
|
||||
self.assertEqual(p.getPrice(p, Datetime(200101010000), 1.0), 10.0)
|
||||
self.assertEqual(p.getPrice(p, Datetime(200101020000), 1.0), 0.0)
|
||||
|
||||
|
||||
p_clone = p.clone()
|
||||
self.assertEqual(p_clone.name, "StoplossPython")
|
||||
|
||||
|
||||
|
||||
def suite():
|
||||
return unittest.TestLoader().loadTestsFromTestCase(StoplossTest)
|
||||
|
||||
|
||||
def suiteTestCrtST():
|
||||
return unittest.TestLoader().loadTestsFromTestCase(TestCrtST)
|
@ -10,20 +10,17 @@
|
||||
import unittest
|
||||
|
||||
from test_init import *
|
||||
from hikyuu.trade_manage import *
|
||||
|
||||
|
||||
class PythonTradeCost(TradeCostBase):
|
||||
def __init__(self):
|
||||
super(PythonTradeCost, self).__init__("PythonTradeCost")
|
||||
|
||||
def getBuyCost(self, date, stock, price, num):
|
||||
return CostRecord(1.0, 1.0, 1.0, 1.0, 4.0)
|
||||
|
||||
def getSellCost(self, date, stock, price, num):
|
||||
def get_sell_cost(self, date, stock, price, num):
|
||||
return CostRecord(2.0, 2.0, 2.0, 2.0, 8.0)
|
||||
|
||||
|
||||
def _clone(self):
|
||||
return PythonTradeCost();
|
||||
return PythonTradeCost()
|
||||
|
||||
|
||||
class TradeCostTest(unittest.TestCase):
|
||||
@ -31,49 +28,44 @@ class TradeCostTest(unittest.TestCase):
|
||||
stock = sm['sh000001']
|
||||
tc = PythonTradeCost()
|
||||
self.assertEqual(tc.name, "PythonTradeCost")
|
||||
cost = tc.getBuyCost(Datetime(201001010000), stock, 10.0, 100)
|
||||
self.assertEqual(cost, CostRecord(1,1,1,1,4))
|
||||
|
||||
cost = tc.getSellCost(Datetime(201001010000), stock, 10.0, 100)
|
||||
self.assertEqual(cost, CostRecord(2,2,2,2,8))
|
||||
#print tc
|
||||
|
||||
cost = tc.get_sell_cost(Datetime(201001010000), stock, 10.0, 100)
|
||||
self.assertEqual(cost, CostRecord(2, 2, 2, 2, 8))
|
||||
#print tc
|
||||
|
||||
clone_tc = tc.clone()
|
||||
self.assertEqual(clone_tc.name, "PythonTradeCost")
|
||||
cost = clone_tc.getBuyCost(Datetime(201001010000), stock, 10.0, 100)
|
||||
self.assertEqual(cost, CostRecord(1,1,1,1,4))
|
||||
cost = clone_tc.getSellCost(Datetime(201001010000), stock, 10.0, 100)
|
||||
self.assertEqual(cost, CostRecord(2,2,2,2,8))
|
||||
|
||||
cost = clone_tc.get_sell_cost(Datetime(201001010000), stock, 10.0, 100)
|
||||
self.assertEqual(cost, CostRecord(2, 2, 2, 2, 8))
|
||||
|
||||
def test_ZeroTC(self):
|
||||
stock = sm['sh000001']
|
||||
tc = TC_Zero()
|
||||
cost = tc.getBuyCost(Datetime(201001010000), stock, 10.0, 100)
|
||||
self.assertEqual(cost, CostRecord(0,0,0,0,0))
|
||||
cost = tc.getSellCost(Datetime(201001010000), stock, 10.0, 100)
|
||||
self.assertEqual(cost, CostRecord(0,0,0,0,0))
|
||||
|
||||
cost = tc.get_sell_cost(Datetime(201001010000), stock, 10.0, 100)
|
||||
self.assertEqual(cost, CostRecord(0, 0, 0, 0, 0))
|
||||
cost = tc.get_sell_cost(Datetime(201001010000), stock, 10.0, 100)
|
||||
self.assertEqual(cost, CostRecord(0, 0, 0, 0, 0))
|
||||
|
||||
clone_tc = tc.clone()
|
||||
cost = clone_tc.getBuyCost(Datetime(201001010000), stock, 10.0, 100)
|
||||
self.assertEqual(cost, CostRecord(0,0,0,0,0))
|
||||
cost = clone_tc.getSellCost(Datetime(201001010000), stock, 10.0, 100)
|
||||
self.assertEqual(cost, CostRecord(0,0,0,0,0))
|
||||
|
||||
cost = clone_tc.get_sell_cost(Datetime(201001010000), stock, 10.0, 100)
|
||||
self.assertEqual(cost, CostRecord(0, 0, 0, 0, 0))
|
||||
cost = clone_tc.get_sell_cost(Datetime(201001010000), stock, 10.0, 100)
|
||||
self.assertEqual(cost, CostRecord(0, 0, 0, 0, 0))
|
||||
|
||||
def test_FixedATC(self):
|
||||
stock = sm['sh000001']
|
||||
tc = TC_FixedA()
|
||||
cost = tc.getBuyCost(Datetime(200101010000), stock, 10.0, 2100)
|
||||
cost = tc.get_sell_cost(Datetime(200101010000), stock, 10.0, 2100)
|
||||
self.assertEqual(cost, CostRecord(37.8, 0, 2.1, 0, 39.9))
|
||||
cost = tc.getSellCost(Datetime(200101010000), stock, 10.0, 2100)
|
||||
cost = tc.get_sell_cost(Datetime(200101010000), stock, 10.0, 2100)
|
||||
self.assertEqual(cost, CostRecord(37.8, 0, 2.1, 0, 39.9))
|
||||
|
||||
clone_tc = tc.clone()
|
||||
cost = clone_tc.getBuyCost(Datetime(200101010000), stock, 10.0, 2100)
|
||||
cost = clone_tc.get_sell_cost(Datetime(200101010000), stock, 10.0, 2100)
|
||||
self.assertEqual(cost, CostRecord(37.8, 0, 2.1, 0, 39.9))
|
||||
cost = clone_tc.getSellCost(Datetime(200101010000), stock, 10.0, 2100)
|
||||
cost = clone_tc.get_sell_cost(Datetime(200101010000), stock, 10.0, 2100)
|
||||
self.assertEqual(cost, CostRecord(37.8, 0, 2.1, 0, 39.9))
|
||||
|
||||
|
||||
|
||||
|
||||
def suite():
|
||||
return unittest.TestLoader().loadTestsFromTestCase(TradeCostTest)
|
@ -25,21 +25,21 @@ import Signal
|
||||
import Stoploss
|
||||
import ProfitGoal
|
||||
import Slippage
|
||||
|
||||
import AllocateFunds
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
|
||||
suite = unittest.TestSuite()
|
||||
suite.addTest(Datetime.suite())
|
||||
suite.addTest(Parameter.suite())
|
||||
|
||||
|
||||
suite.addTest(MarketInfo.suite())
|
||||
suite.addTest(StockTypeInfo.suite())
|
||||
suite.addTest(Stock.suite())
|
||||
suite.addTest(KData.suite())
|
||||
suite.addTest(Indicator.suite())
|
||||
suite.addTest(TradeCost.suite())
|
||||
|
||||
|
||||
suite.addTest(Environment.suite())
|
||||
suite.addTest(Environment.suiteTestCrtEV())
|
||||
suite.addTest(Condition.suite())
|
||||
@ -54,6 +54,8 @@ if __name__ == "__main__":
|
||||
suite.addTest(ProfitGoal.suiteTestCrtPG())
|
||||
suite.addTest(Slippage.suite())
|
||||
suite.addTest(Slippage.suiteTestCrtSL())
|
||||
|
||||
|
||||
suite.addTest(AllocateFunds.suite())
|
||||
|
||||
unittest.TextTestRunner(verbosity=2).run(suite)
|
||||
#unittest.main()
|
||||
|
@ -20,7 +20,7 @@ int main(int argc, char* argv[]) {
|
||||
#endif
|
||||
|
||||
//配置文件的位置自行修改
|
||||
hikyuu_init("C:\\Users\\Administrator\\.hikyuu\\hikyuu.ini");
|
||||
hikyuu_init("C:\\Users\\admin\\.hikyuu\\hikyuu.ini");
|
||||
|
||||
StockManager& sm = StockManager::instance();
|
||||
|
||||
@ -42,6 +42,6 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
#if defined(_WIN32)
|
||||
SetConsoleOutputCP(old_cp);
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
@ -23,10 +23,12 @@ class HKU_API KData {
|
||||
public:
|
||||
KData() {}
|
||||
KData(const KData&);
|
||||
KData(KData&&);
|
||||
KData(const Stock& stock, const KQuery& query);
|
||||
virtual ~KData() {}
|
||||
|
||||
KData& operator=(const KData&);
|
||||
KData& operator=(KData&&);
|
||||
|
||||
size_t size() const;
|
||||
bool empty() const;
|
||||
@ -149,6 +151,8 @@ KData HKU_API getKData(const string& market_code, int64_t start = 0, int64_t end
|
||||
|
||||
inline KData::KData(const KData& x) : m_imp(x.m_imp) {}
|
||||
|
||||
inline KData::KData(KData&& x) : m_imp(std::move(x.m_imp)) {}
|
||||
|
||||
inline KData& KData::operator=(const KData& x) {
|
||||
if (this == &x)
|
||||
return *this;
|
||||
@ -156,6 +160,13 @@ inline KData& KData::operator=(const KData& x) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline KData& KData::operator=(KData&& x) {
|
||||
if (this == &x)
|
||||
return *this;
|
||||
m_imp = std::move(x.m_imp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline DatetimeList KData::getDatetimeList() const {
|
||||
DatetimeList result;
|
||||
if (empty()) {
|
||||
|
@ -73,7 +73,7 @@ Stock::Data::Data()
|
||||
|
||||
Stock::Data::Data(const string& market, const string& code, const string& name, uint32_t type,
|
||||
bool valid, const Datetime& startDate, const Datetime& lastDate, price_t tick,
|
||||
price_t tickValue, int precision, size_t minTradeNumber, size_t maxTradeNumber)
|
||||
price_t tickValue, int precision, double minTradeNumber, double maxTradeNumber)
|
||||
: m_market(market),
|
||||
m_code(code),
|
||||
m_name(name),
|
||||
@ -123,6 +123,8 @@ Stock::~Stock() {}
|
||||
|
||||
Stock::Stock(const Stock& x) : m_data(x.m_data), m_kdataDriver(x.m_kdataDriver) {}
|
||||
|
||||
Stock::Stock(Stock&& x) : m_data(std::move(x.m_data)), m_kdataDriver(std::move(x.m_kdataDriver)) {}
|
||||
|
||||
Stock& Stock::operator=(const Stock& x) {
|
||||
HKU_IF_RETURN(this == &x, *this);
|
||||
m_data = x.m_data;
|
||||
@ -130,6 +132,13 @@ Stock& Stock::operator=(const Stock& x) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Stock& Stock::operator=(Stock&& x) {
|
||||
HKU_IF_RETURN(this == &x, *this);
|
||||
m_data = std::move(x.m_data);
|
||||
m_kdataDriver = std::move(x.m_kdataDriver);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Stock::Stock(const string& market, const string& code, const string& name) {
|
||||
m_data =
|
||||
shared_ptr<Data>(new Data(market, code, name, default_type, default_valid, default_startDate,
|
||||
@ -206,15 +215,15 @@ int Stock::precision() const {
|
||||
return m_data ? m_data->m_precision : default_precision;
|
||||
}
|
||||
|
||||
size_t Stock::atom() const {
|
||||
double Stock::atom() const {
|
||||
return m_data ? m_data->m_minTradeNumber : default_minTradeNumber;
|
||||
}
|
||||
|
||||
size_t Stock::minTradeNumber() const {
|
||||
double Stock::minTradeNumber() const {
|
||||
return m_data ? m_data->m_minTradeNumber : default_minTradeNumber;
|
||||
}
|
||||
|
||||
size_t Stock::maxTradeNumber() const {
|
||||
double Stock::maxTradeNumber() const {
|
||||
return m_data ? m_data->m_maxTradeNumber : default_maxTradeNumber;
|
||||
}
|
||||
|
||||
|
@ -55,6 +55,7 @@ public:
|
||||
Stock();
|
||||
|
||||
Stock(const Stock&);
|
||||
Stock(Stock&&);
|
||||
Stock(const string& market, const string& code, const string& name);
|
||||
|
||||
Stock(const string& market, const string& code, const string& name, uint32_t type, bool valid,
|
||||
@ -64,6 +65,7 @@ public:
|
||||
int precision, size_t minTradeNumber, size_t maxTradeNumber);
|
||||
virtual ~Stock();
|
||||
Stock& operator=(const Stock&);
|
||||
Stock& operator=(Stock&&);
|
||||
bool operator==(const Stock&) const;
|
||||
bool operator!=(const Stock&) const;
|
||||
|
||||
@ -110,13 +112,13 @@ public:
|
||||
int precision() const;
|
||||
|
||||
/** 获取最小交易数量,同minTradeNumber */
|
||||
size_t atom() const;
|
||||
double atom() const;
|
||||
|
||||
/** 获取最小交易数量 */
|
||||
size_t minTradeNumber() const;
|
||||
double minTradeNumber() const;
|
||||
|
||||
/** 获取最大交易量 */
|
||||
size_t maxTradeNumber() const;
|
||||
double maxTradeNumber() const;
|
||||
|
||||
/**
|
||||
* 获取指定时间段[start,end)内的权息信息
|
||||
@ -247,8 +249,8 @@ struct HKU_API Stock::Data {
|
||||
price_t m_tickValue;
|
||||
price_t m_unit;
|
||||
int m_precision;
|
||||
size_t m_minTradeNumber;
|
||||
size_t m_maxTradeNumber;
|
||||
double m_minTradeNumber;
|
||||
double m_maxTradeNumber;
|
||||
|
||||
unordered_map<string, KRecordList*> pKData;
|
||||
unordered_map<string, std::shared_mutex*> pMutex;
|
||||
@ -256,7 +258,7 @@ struct HKU_API Stock::Data {
|
||||
Data();
|
||||
Data(const string& market, const string& code, const string& name, uint32_t type, bool valid,
|
||||
const Datetime& startDate, const Datetime& lastDate, price_t tick, price_t tickValue,
|
||||
int precision, size_t minTradeNumber, size_t maxTradeNumber);
|
||||
int precision, double minTradeNumber, double maxTradeNumber);
|
||||
|
||||
virtual ~Data();
|
||||
};
|
||||
|
@ -32,7 +32,7 @@ public:
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
* @param param 驱动原型,所有权将被转移至该 pool
|
||||
* @param prototype 驱动原型,所有权将被转移至该 pool
|
||||
* @param maxConnect 允许的最大连接数,为 0 表示不限制
|
||||
* @param maxIdleConnect 运行的最大空闲连接数,等于 0 时表示立刻释放,默认为CPU数
|
||||
*/
|
||||
|
@ -26,10 +26,10 @@ void hikyuu_init(const string& config_file_name, bool ignore_preload,
|
||||
config.read(config_file_name);
|
||||
|
||||
} catch (std::invalid_argument& e) {
|
||||
HKU_FATAL("Reading configure error!\n{}", e.what());
|
||||
HKU_FATAL("Reading configure error! {}", e.what());
|
||||
exit(1);
|
||||
} catch (std::logic_error& e) {
|
||||
HKU_FATAL("Reading configure error!\n{}", e.what());
|
||||
HKU_FATAL("Reading configure error! {}", e.what());
|
||||
exit(1);
|
||||
} catch (...) {
|
||||
HKU_WARN("Reading configure error! Don't know error!");
|
||||
|
@ -27,6 +27,7 @@ namespace hku {
|
||||
* @param config_file_name 配置信息文件名
|
||||
* @param ignore_preload 忽略配置信息中的预加载设置,即不加载数据至内存。
|
||||
* 用于某些场合启动hikyuu,但仅用于获取数据库的基本信息。
|
||||
* @param context 指定加载数据上下文,用于独立策略时仅加载指定的股票数据
|
||||
*/
|
||||
void HKU_API hikyuu_init(const string& config_file_name, bool ignore_preload = false,
|
||||
const StrategyContext& context = StrategyContext({"all"}));
|
||||
|
@ -19,6 +19,8 @@ Indicator::Indicator(const IndicatorImpPtr& imp) : m_imp(imp) {}
|
||||
|
||||
Indicator::Indicator(const Indicator& indicator) : m_imp(indicator.m_imp) {}
|
||||
|
||||
Indicator::Indicator(Indicator&& ind) : m_imp(std::move(ind.m_imp)) {}
|
||||
|
||||
Indicator::~Indicator() {}
|
||||
|
||||
string Indicator::formula() const {
|
||||
@ -51,6 +53,12 @@ Indicator& Indicator::operator=(const Indicator& indicator) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Indicator& Indicator::operator=(Indicator&& indicator) {
|
||||
HKU_IF_RETURN(this == &indicator, *this);
|
||||
m_imp = std::move(indicator.m_imp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
PriceList Indicator::getResultAsPriceList(size_t num) const {
|
||||
HKU_WARN_IF_RETURN(!m_imp, PriceList(), "indicator imptr is null!");
|
||||
return m_imp->getResultAsPriceList(num);
|
||||
|
@ -43,10 +43,12 @@ class HKU_API Indicator {
|
||||
public:
|
||||
Indicator() {}
|
||||
Indicator(const IndicatorImpPtr& imp);
|
||||
Indicator(const Indicator&);
|
||||
Indicator(const Indicator& ind);
|
||||
Indicator(Indicator&& ind);
|
||||
virtual ~Indicator();
|
||||
|
||||
Indicator& operator=(const Indicator&);
|
||||
Indicator& operator=(Indicator&&);
|
||||
|
||||
/** 使用已有参数计算新值,返回全新的Indicator */
|
||||
Indicator operator()(const Indicator& ind);
|
||||
|
@ -103,7 +103,7 @@ IndParam IndicatorImp::getIndParam(const string &name) const {
|
||||
return IndParam(m_ind_params.at(name));
|
||||
}
|
||||
|
||||
const IndicatorImpPtr IndicatorImp::getIndParamImp(const string &name) const {
|
||||
const IndicatorImpPtr &IndicatorImp::getIndParamImp(const string &name) const {
|
||||
return m_ind_params.at(name);
|
||||
}
|
||||
|
||||
@ -1255,7 +1255,7 @@ void IndicatorImp::_dyn_calculate(const Indicator &ind) {
|
||||
const auto &ind_param = getIndParamImp("n");
|
||||
HKU_CHECK(ind_param->size() == ind.size(), "ind_param->size()={}, ind.size()={}!",
|
||||
ind_param->size(), ind.size());
|
||||
m_discard = ind.discard();
|
||||
m_discard = std::max(ind.discard(), ind_param->discard());
|
||||
size_t total = ind.size();
|
||||
HKU_IF_RETURN(0 == total || m_discard >= total, void());
|
||||
|
||||
@ -1267,7 +1267,7 @@ void IndicatorImp::_dyn_calculate(const Indicator &ind) {
|
||||
size_t step = size_t(ind_param->get(i));
|
||||
_dyn_run_one_step(ind, i, step);
|
||||
}
|
||||
_after_dyn_calculate(ind);
|
||||
_update_discard();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1302,7 +1302,23 @@ void IndicatorImp::_dyn_calculate(const Indicator &ind) {
|
||||
task.get();
|
||||
}
|
||||
|
||||
_after_dyn_calculate(ind);
|
||||
_update_discard();
|
||||
}
|
||||
|
||||
void IndicatorImp::_update_discard() {
|
||||
size_t total = size();
|
||||
for (size_t result_index = 0; result_index < m_result_num; result_index++) {
|
||||
size_t discard = m_discard;
|
||||
for (size_t i = m_discard; i < total; i++) {
|
||||
if (!std::isnan(get(i, result_index))) {
|
||||
break;
|
||||
}
|
||||
discard++;
|
||||
}
|
||||
if (discard > m_discard) {
|
||||
m_discard = discard;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace hku */
|
||||
|
@ -157,7 +157,7 @@ public:
|
||||
void setIndParam(const string& name, const Indicator& ind);
|
||||
void setIndParam(const string& name, const IndParam& ind);
|
||||
IndParam getIndParam(const string& name) const;
|
||||
const IndicatorImpPtr getIndParamImp(const string& name) const;
|
||||
const IndicatorImpPtr& getIndParamImp(const string& name) const;
|
||||
const unordered_map<string, IndicatorImpPtr>& getIndParams() const;
|
||||
|
||||
price_t* data(size_t result_num = 0);
|
||||
@ -173,9 +173,6 @@ public:
|
||||
|
||||
virtual void _dyn_run_one_step(const Indicator& ind, size_t curPos, size_t step) {}
|
||||
|
||||
/** 动态指标参数计算完毕后处理,主要用于修正 m_discard */
|
||||
virtual void _after_dyn_calculate(const Indicator& ind) {}
|
||||
|
||||
/** 是否支持指标动态参数 */
|
||||
virtual bool supportIndParam() const {
|
||||
return false;
|
||||
@ -194,6 +191,8 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void _dyn_calculate(const Indicator&);
|
||||
|
||||
private:
|
||||
void initContext();
|
||||
bool needCalculate();
|
||||
@ -212,11 +211,13 @@ private:
|
||||
void execute_or();
|
||||
void execute_weave();
|
||||
void execute_if();
|
||||
void _dyn_calculate(const Indicator&);
|
||||
|
||||
protected:
|
||||
static size_t _get_step_start(size_t pos, size_t step, size_t discard);
|
||||
|
||||
// 用于动态参数时,更新 discard
|
||||
void _update_discard();
|
||||
|
||||
protected:
|
||||
string m_name;
|
||||
size_t m_discard;
|
||||
@ -346,7 +347,7 @@ public: \
|
||||
return make_shared<classname>(); \
|
||||
}
|
||||
|
||||
#define INDICATOR_IMP_SUPPORT_IND_PARAM(classname) \
|
||||
#define INDICATOR_IMP_SUPPORT_DYNAMIC_STEP(classname) \
|
||||
public: \
|
||||
virtual bool check() override; \
|
||||
virtual void _calculate(const Indicator& ind) override; \
|
||||
|
@ -76,6 +76,7 @@
|
||||
#include "crt/ROUNDUP.h"
|
||||
#include "crt/SAFTYLOSS.h"
|
||||
#include "crt/SIN.h"
|
||||
#include "crt/SLICE.h"
|
||||
#include "crt/SGN.h"
|
||||
#include "crt/SMA.h"
|
||||
#include "crt/SQRT.h"
|
||||
|
@ -21,6 +21,14 @@ namespace hku {
|
||||
* @ingroup Indicator 具有2个结果集,result(0)为AMA,result(1)为ER
|
||||
*/
|
||||
Indicator HKU_API AMA(int n = 10, int fast_n = 2, int slow_n = 30);
|
||||
Indicator HKU_API AMA(int n, int fast_n, const IndParam& slow_n);
|
||||
Indicator HKU_API AMA(int n, const IndParam& fast_n, int slow_n = 30);
|
||||
Indicator HKU_API AMA(int n, const IndParam& fast_n, const IndParam& slow_n);
|
||||
|
||||
Indicator HKU_API AMA(const IndParam& n, int fast_n = 2, int slow_n = 30);
|
||||
Indicator HKU_API AMA(const IndParam& n, int fast_n, const IndParam& slow_n);
|
||||
Indicator HKU_API AMA(const IndParam& n, const IndParam& fast_n, int slow_n = 30);
|
||||
Indicator HKU_API AMA(const IndParam& n, const IndParam& fast_n, const IndParam& slow_n);
|
||||
|
||||
/**
|
||||
* 佩里.J 考夫曼(Perry J.Kaufman)自适应移动平均,参见《精明交易者》(2006年 广东经济出版社)
|
||||
@ -30,7 +38,75 @@ Indicator HKU_API AMA(int n = 10, int fast_n = 2, int slow_n = 30);
|
||||
* @param slow_n 对应慢速EMA线的N值,默认为30,不过当超过60左右该指标会收敛不会有太大的影响
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator HKU_API AMA(const Indicator& indicator, int n = 10, int fast_n = 2, int slow_n = 30);
|
||||
inline Indicator HKU_API AMA(const Indicator& ind, int n = 10, int fast_n = 2, int slow_n = 30) {
|
||||
return AMA(n, fast_n, slow_n)(ind);
|
||||
}
|
||||
|
||||
inline Indicator HKU_API AMA(const Indicator& ind, int n, const IndParam& fast_n, int slow_n = 30) {
|
||||
return AMA(n, fast_n, slow_n)(ind);
|
||||
}
|
||||
|
||||
inline Indicator HKU_API AMA(const Indicator& ind, int n, int fast_n, const IndParam& slow_n) {
|
||||
return AMA(n, fast_n, slow_n)(ind);
|
||||
}
|
||||
|
||||
inline Indicator HKU_API AMA(const Indicator& ind, int n, const IndParam& fast_n,
|
||||
const IndParam& slow_n) {
|
||||
return AMA(n, fast_n, slow_n)(ind);
|
||||
}
|
||||
|
||||
inline Indicator HKU_API AMA(const Indicator& ind, const IndParam& n, int fast_n = 2,
|
||||
int slow_n = 30) {
|
||||
return AMA(n, fast_n, slow_n)(ind);
|
||||
}
|
||||
|
||||
inline Indicator HKU_API AMA(const Indicator& ind, const IndParam& n, const IndParam& fast_n,
|
||||
int slow_n = 30) {
|
||||
return AMA(n, fast_n, slow_n)(ind);
|
||||
}
|
||||
|
||||
inline Indicator HKU_API AMA(const Indicator& ind, const IndParam& n, int fast_n,
|
||||
const IndParam& slow_n) {
|
||||
return AMA(n, fast_n, slow_n)(ind);
|
||||
}
|
||||
|
||||
inline Indicator HKU_API AMA(const Indicator& ind, const IndParam& n, const IndParam& fast_n,
|
||||
const IndParam& slow_n) {
|
||||
return AMA(n, fast_n, slow_n)(ind);
|
||||
}
|
||||
|
||||
inline Indicator HKU_API AMA(const Indicator& ind, int n, const Indicator& fast_n, int slow_n) {
|
||||
return AMA(n, IndParam(fast_n), slow_n)(ind);
|
||||
}
|
||||
|
||||
inline Indicator HKU_API AMA(const Indicator& ind, int n, int fast_n, const Indicator& slow_n) {
|
||||
return AMA(n, fast_n, IndParam(slow_n))(ind);
|
||||
}
|
||||
|
||||
inline Indicator HKU_API AMA(const Indicator& ind, int n, const Indicator& fast_n,
|
||||
const Indicator& slow_n) {
|
||||
return AMA(n, IndParam(fast_n), IndParam(slow_n))(ind);
|
||||
}
|
||||
|
||||
inline Indicator HKU_API AMA(const Indicator& ind, const Indicator& n, int fast_n = 2,
|
||||
int slow_n = 30) {
|
||||
return AMA(IndParam(n), fast_n, slow_n)(ind);
|
||||
}
|
||||
|
||||
inline Indicator HKU_API AMA(const Indicator& ind, const Indicator& n, const Indicator& fast_n,
|
||||
int slow_n = 30) {
|
||||
return AMA(IndParam(n), IndParam(fast_n), slow_n)(ind);
|
||||
}
|
||||
|
||||
inline Indicator HKU_API AMA(const Indicator& ind, const Indicator& n, int fast_n,
|
||||
const Indicator& slow_n) {
|
||||
return AMA(IndParam(n), fast_n, IndParam(slow_n))(ind);
|
||||
}
|
||||
|
||||
inline Indicator HKU_API AMA(const Indicator& ind, const Indicator& n, const Indicator& fast_n,
|
||||
const Indicator& slow_n) {
|
||||
return AMA(IndParam(n), IndParam(fast_n), IndParam(slow_n))(ind);
|
||||
}
|
||||
|
||||
} // namespace hku
|
||||
|
||||
|
@ -19,6 +19,7 @@ namespace hku {
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator HKU_API ATR(int n = 14);
|
||||
Indicator HKU_API ATR(const IndParam& n);
|
||||
|
||||
/**
|
||||
* 平均真实波幅(Average True Range)
|
||||
@ -26,7 +27,17 @@ Indicator HKU_API ATR(int n = 14);
|
||||
* @param n 计算均值的周期窗口,必须为大于1的整数
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator HKU_API ATR(const Indicator& data, int n = 14);
|
||||
inline Indicator HKU_API ATR(const Indicator& data, int n = 14) {
|
||||
return ATR(n)(data);
|
||||
}
|
||||
|
||||
inline Indicator HKU_API ATR(const Indicator& data, const IndParam& n) {
|
||||
return ATR(n)(data);
|
||||
}
|
||||
|
||||
inline Indicator HKU_API ATR(const Indicator& data, const Indicator& n) {
|
||||
return ATR(IndParam(n))(data);
|
||||
}
|
||||
|
||||
} // namespace hku
|
||||
|
||||
|
@ -19,6 +19,7 @@ namespace hku {
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator HKU_API EMA(int n = 22);
|
||||
Indicator HKU_API EMA(const IndParam& n);
|
||||
|
||||
/**
|
||||
* 指数移动平均线(Exponential Moving Average)
|
||||
@ -26,7 +27,17 @@ Indicator HKU_API EMA(int n = 22);
|
||||
* @param n 计算均值的周期窗口,必须为大于0的整数
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator HKU_API EMA(const Indicator& data, int n = 22);
|
||||
inline Indicator HKU_API EMA(const Indicator& data, int n = 22) {
|
||||
return EMA(n)(data);
|
||||
}
|
||||
|
||||
inline Indicator HKU_API EMA(const Indicator& data, const IndParam& n) {
|
||||
return EMA(n)(data);
|
||||
}
|
||||
|
||||
inline Indicator HKU_API EMA(const Indicator& data, const Indicator& n) {
|
||||
return EMA(IndParam(n))(data);
|
||||
}
|
||||
|
||||
} // namespace hku
|
||||
|
||||
|
@ -13,6 +13,9 @@
|
||||
|
||||
#include "EVERY.h"
|
||||
#include "REF.h"
|
||||
#include "MAX.h"
|
||||
#include "MIN.h"
|
||||
#include "CVAL.h"
|
||||
|
||||
namespace hku {
|
||||
|
||||
@ -26,10 +29,7 @@ namespace hku {
|
||||
* </pre>
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator LAST(int m = 10, int n = 5);
|
||||
Indicator LAST(const Indicator& ind, int m = 10, int n = 5);
|
||||
|
||||
inline Indicator LAST(int m, int n) {
|
||||
inline Indicator LAST(int m = 10, int n = 5) {
|
||||
int max = std::max(m, n);
|
||||
int min = std::min(m, n);
|
||||
Indicator result = REF(EVERY(max - min + 1), min);
|
||||
@ -37,10 +37,64 @@ inline Indicator LAST(int m, int n) {
|
||||
return result;
|
||||
}
|
||||
|
||||
inline Indicator LAST(const Indicator& ind, int m, int n) {
|
||||
inline Indicator LAST(const IndParam& m, int n = 5) {
|
||||
Indicator ind_m = m.get();
|
||||
Indicator ind_n = CVAL(ind_m, 5);
|
||||
Indicator max = MAX(ind_m, ind_n);
|
||||
Indicator min = MIN(ind_m, ind_n);
|
||||
Indicator result = REF(EVERY(max - min + 1), min);
|
||||
result.name("LAST");
|
||||
return result;
|
||||
}
|
||||
|
||||
inline Indicator LAST(int m, const IndParam& n) {
|
||||
Indicator ind_n = n.get();
|
||||
Indicator ind_m = CVAL(ind_n, 5);
|
||||
Indicator max = MAX(ind_m, ind_n);
|
||||
Indicator min = MIN(ind_m, ind_n);
|
||||
Indicator result = REF(EVERY(max - min + 1), min);
|
||||
result.name("LAST");
|
||||
return result;
|
||||
}
|
||||
|
||||
inline Indicator LAST(const IndParam& m, const IndParam& n) {
|
||||
Indicator ind_m = m.get();
|
||||
Indicator ind_n = n.get();
|
||||
Indicator max = MAX(ind_m, ind_n);
|
||||
Indicator min = MIN(ind_m, ind_n);
|
||||
Indicator result = REF(EVERY(max - min + 1), min);
|
||||
result.name("LAST");
|
||||
return result;
|
||||
}
|
||||
|
||||
inline Indicator LAST(const Indicator& ind, int m = 10, int n = 5) {
|
||||
return LAST(m, n)(ind);
|
||||
}
|
||||
|
||||
inline Indicator LAST(const Indicator& ind, const IndParam& m, int n = 5) {
|
||||
return LAST(m, n)(ind);
|
||||
}
|
||||
|
||||
inline Indicator LAST(const Indicator& ind, int m, const IndParam& n) {
|
||||
return LAST(m, n)(ind);
|
||||
}
|
||||
|
||||
inline Indicator LAST(const Indicator& ind, const IndParam& m, const IndParam& n) {
|
||||
return LAST(m, n)(ind);
|
||||
}
|
||||
|
||||
inline Indicator LAST(const Indicator& ind, const Indicator& m, int n = 5) {
|
||||
return LAST(IndParam(m), n)(ind);
|
||||
}
|
||||
|
||||
inline Indicator LAST(const Indicator& ind, int m, const Indicator& n) {
|
||||
return LAST(m, IndParam(n))(ind);
|
||||
}
|
||||
|
||||
inline Indicator LAST(const Indicator& ind, const Indicator& m, const Indicator& n) {
|
||||
return LAST(IndParam(m), IndParam(n))(ind);
|
||||
}
|
||||
|
||||
} // namespace hku
|
||||
|
||||
#endif /* INDICATOR_CRT_LAST_H_ */
|
||||
|
@ -26,26 +26,40 @@ namespace hku {
|
||||
* </pre>
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator LONGCROSS(const Indicator& x, const Indicator& y, int n = 3);
|
||||
Indicator LONGCROSS(const Indicator& x, price_t, int n = 3);
|
||||
Indicator LONGCROSS(price_t, const Indicator& y, int n = 3);
|
||||
Indicator LONGCROSS(price_t, price_t, int n = 3);
|
||||
|
||||
inline Indicator LONGCROSS(const Indicator& x, const Indicator& y, int n) {
|
||||
inline Indicator LONGCROSS(const Indicator& x, const Indicator& y, int n = 3) {
|
||||
Indicator result = EVERY((REF(x, 1) < REF(y, 1)), n) & (x > y);
|
||||
result.name("LONGCROSS");
|
||||
return result;
|
||||
}
|
||||
|
||||
inline Indicator LONGCROSS(const Indicator& x, price_t y, int n) {
|
||||
inline Indicator LONGCROSS(const Indicator& x, const Indicator& y, const Indicator& n) {
|
||||
Indicator result = EVERY((REF(x, 1) < REF(y, 1)), n) & (x > y);
|
||||
result.name("LONGCROSS");
|
||||
return result;
|
||||
}
|
||||
|
||||
inline Indicator LONGCROSS(const Indicator& x, price_t y, int n = 3) {
|
||||
return LONGCROSS(x, CVAL(x, y), n);
|
||||
}
|
||||
|
||||
inline Indicator LONGCROSS(price_t x, const Indicator& y, int n) {
|
||||
inline Indicator LONGCROSS(const Indicator& x, price_t y, const Indicator& n) {
|
||||
return LONGCROSS(x, CVAL(x, y), n);
|
||||
}
|
||||
|
||||
inline Indicator LONGCROSS(price_t x, const Indicator& y, int n = 3) {
|
||||
return LONGCROSS(CVAL(y, x), y, n);
|
||||
}
|
||||
|
||||
inline Indicator LONGCROSS(price_t x, price_t y, int n) {
|
||||
inline Indicator LONGCROSS(price_t x, const Indicator& y, const Indicator& n) {
|
||||
return LONGCROSS(CVAL(y, x), y, n);
|
||||
}
|
||||
|
||||
inline Indicator LONGCROSS(price_t x, price_t y, int n = 3) {
|
||||
return LONGCROSS(CVAL(x), CVAL(y), n);
|
||||
}
|
||||
|
||||
inline Indicator LONGCROSS(price_t x, price_t y, const Indicator& n) {
|
||||
return LONGCROSS(CVAL(x), CVAL(y), n);
|
||||
}
|
||||
|
||||
|
@ -15,13 +15,18 @@ namespace hku {
|
||||
|
||||
/**
|
||||
* 简单移动平均
|
||||
* @param data 待计算的数据
|
||||
* @param n 计算均值的周期窗口,n为0时从第一个有效数据开始计算
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator HKU_API MA(int n = 22);
|
||||
Indicator HKU_API MA(const IndParam& n);
|
||||
|
||||
/**
|
||||
* 简单移动平均
|
||||
* @param ind 待计算的数据
|
||||
* @param n 计算均值的周期窗口,n为0时从第一个有效数据开始计算
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
inline Indicator HKU_API MA(const Indicator& ind, int n = 22) {
|
||||
return MA(n)(ind);
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ namespace hku {
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator HKU_API MACD(int n1 = 12, int n2 = 26, int n3 = 9);
|
||||
Indicator HKU_API MACD(const IndParam& n1, const IndParam& n2, const IndParam& n3);
|
||||
|
||||
/**
|
||||
* MACD平滑异同移动平均线
|
||||
@ -42,7 +43,19 @@ Indicator HKU_API MACD(int n1 = 12, int n2 = 26, int n3 = 9);
|
||||
* </pre>
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator HKU_API MACD(const Indicator& data, int n1 = 12, int n2 = 26, int n3 = 9);
|
||||
inline Indicator MACD(const Indicator& data, int n1 = 12, int n2 = 26, int n3 = 9) {
|
||||
return MACD(n1, n2, n3)(data);
|
||||
}
|
||||
|
||||
inline Indicator MACD(const Indicator& data, const IndParam& n1, const IndParam& n2,
|
||||
const IndParam& n3) {
|
||||
return MACD(n1, n2, n3)(data);
|
||||
}
|
||||
|
||||
inline Indicator MACD(const Indicator& data, const Indicator& n1, const Indicator& n2,
|
||||
const Indicator& n3) {
|
||||
return MACD(IndParam(n1), IndParam(n2), IndParam(n3))(data);
|
||||
}
|
||||
|
||||
} // namespace hku
|
||||
|
||||
|
@ -22,10 +22,6 @@ namespace hku {
|
||||
* </pre>
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator MAX(const Indicator&, const Indicator&);
|
||||
Indicator MAX(const Indicator&, price_t val);
|
||||
Indicator MAX(price_t val, const Indicator& ind);
|
||||
|
||||
inline Indicator MAX(const Indicator& ind1, const Indicator& ind2) {
|
||||
Indicator result = IF(ind1 > ind2, ind1, ind2);
|
||||
result.name("MAX");
|
||||
|
@ -22,10 +22,6 @@ namespace hku {
|
||||
* </pre>
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator MIN(const Indicator&, const Indicator&);
|
||||
Indicator MIN(const Indicator&, price_t val);
|
||||
Indicator MIN(price_t val, const Indicator& ind);
|
||||
|
||||
inline Indicator MIN(const Indicator& ind1, const Indicator& ind2) {
|
||||
Indicator result = IF(ind1 < ind2, ind1, ind2);
|
||||
result.name("MIN");
|
||||
|
@ -21,6 +21,7 @@ namespace hku {
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator HKU_API REF(int n);
|
||||
Indicator HKU_API REF(const IndParam& n);
|
||||
|
||||
/**
|
||||
* REF 向前引用 (即右移)
|
||||
@ -30,7 +31,17 @@ Indicator HKU_API REF(int n);
|
||||
* @param n 引用n周期前的值,即右移n位
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator HKU_API REF(const Indicator& ind, int n);
|
||||
inline Indicator HKU_API REF(const Indicator& ind, int n) {
|
||||
return REF(n)(ind);
|
||||
}
|
||||
|
||||
inline Indicator HKU_API REF(const Indicator& ind, const IndParam& n) {
|
||||
return REF(n)(ind);
|
||||
}
|
||||
|
||||
inline Indicator HKU_API REF(const Indicator& ind, const Indicator& n) {
|
||||
return REF(IndParam(n))(ind);
|
||||
}
|
||||
|
||||
} /* namespace hku */
|
||||
|
||||
|
@ -20,12 +20,20 @@ namespace hku {
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator HKU_API ROCR100(int n = 10);
|
||||
Indicator ROCR100(const Indicator& ind, int n = 10);
|
||||
Indicator HKU_API ROCR100(const IndParam& n);
|
||||
|
||||
inline Indicator ROCR100(const Indicator& ind, int n) {
|
||||
inline Indicator ROCR100(const Indicator& ind, int n = 10) {
|
||||
return ROCR100(n)(ind);
|
||||
}
|
||||
|
||||
inline Indicator ROCR100(const Indicator& ind, const IndParam& n) {
|
||||
return ROCR100(n)(ind);
|
||||
}
|
||||
|
||||
inline Indicator ROCR100(const Indicator& ind, const Indicator& n) {
|
||||
return ROCR100(IndParam(n))(ind);
|
||||
}
|
||||
|
||||
} // namespace hku
|
||||
|
||||
#endif /* INDICATOR_CRT_ROCR100_H_ */
|
||||
|
@ -24,13 +24,14 @@ namespace hku {
|
||||
* 上移,在上述结果的基础上再取起N日(一般为3天)内的最高值
|
||||
* </pre>
|
||||
* @note:返回结果中前(回溯周期宽度+去最高值的宽度)个点是无效的
|
||||
* @param data 输入数据,单一输入
|
||||
* @param n1 计算平均噪音的回溯时间窗口,默认为10天
|
||||
* @param n2 对初步止损线去n2日内的最高值,默认为3
|
||||
* @param p 噪音系数,默认为2
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator HKU_API SAFTYLOSS(const Indicator& data, int n1 = 10, int n2 = 3, double p = 2.0);
|
||||
Indicator HKU_API SAFTYLOSS(int n1 = 10, int n2 = 3, double p = 2.0);
|
||||
Indicator HKU_API SAFTYLOSS(const IndParam& n1, const IndParam& n2, double p = 2.0);
|
||||
Indicator HKU_API SAFTYLOSS(const IndParam& n1, const IndParam& n2, const IndParam& p);
|
||||
|
||||
/**
|
||||
* 亚历山大 艾尔德安全地带止损
|
||||
@ -43,12 +44,35 @@ Indicator HKU_API SAFTYLOSS(const Indicator& data, int n1 = 10, int n2 = 3, doub
|
||||
* 上移,在上述结果的基础上再取起N日(一般为3天)内的最高值
|
||||
* </pre>
|
||||
* @note:返回结果中前(回溯周期宽度+去最高值的宽度)个点是无效的
|
||||
* @param data 输入数据,单一输入
|
||||
* @param n1 计算平均噪音的回溯时间窗口,默认为10天
|
||||
* @param n2 对初步止损线去n2日内的最高值,默认为3
|
||||
* @param p 噪音系数,默认为2
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator HKU_API SAFTYLOSS(int n1 = 10, int n2 = 3, double p = 2.0);
|
||||
inline Indicator SAFTYLOSS(const Indicator& data, int n1 = 10, int n2 = 3, double p = 2.0) {
|
||||
return SAFTYLOSS(n1, n2, p)(data);
|
||||
}
|
||||
|
||||
inline Indicator SAFTYLOSS(const Indicator& data, const IndParam& n1, const IndParam& n2,
|
||||
double p = 2.0) {
|
||||
return SAFTYLOSS(n1, n2, p)(data);
|
||||
}
|
||||
|
||||
inline Indicator SAFTYLOSS(const Indicator& data, const IndParam& n1, const IndParam& n2,
|
||||
const IndParam& p) {
|
||||
return SAFTYLOSS(n1, n2, p)(data);
|
||||
}
|
||||
|
||||
inline Indicator SAFTYLOSS(const Indicator& data, const Indicator& n1, const Indicator& n2,
|
||||
double p = 2.0) {
|
||||
return SAFTYLOSS(IndParam(n1), IndParam(n2), p)(data);
|
||||
}
|
||||
|
||||
inline Indicator SAFTYLOSS(const Indicator& data, const Indicator& n1, const Indicator& n2,
|
||||
const Indicator& p) {
|
||||
return SAFTYLOSS(IndParam(n1), IndParam(n2), IndParam(p))(data);
|
||||
}
|
||||
|
||||
} // namespace hku
|
||||
|
||||
|
44
hikyuu_cpp/hikyuu/indicator/crt/SLICE.h
Normal file
44
hikyuu_cpp/hikyuu/indicator/crt/SLICE.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2019 hikyuu.org
|
||||
*
|
||||
* Created on: 2022-02-27
|
||||
* Author: fasiondog
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Indicator.h"
|
||||
|
||||
namespace hku {
|
||||
|
||||
/**
|
||||
* 获取 PriceList 中指定范围 [start, end) 的数据
|
||||
* @param data 源数据
|
||||
* @param start 起始范围,可为负数
|
||||
* @param end 终止范围(不包含本身),可为负数
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator HKU_API SLICE(const PriceList& data, int64_t start, int64_t end);
|
||||
|
||||
/**
|
||||
* 获取某指标中指定范围的数据
|
||||
* @param start 起始范围,可为负数
|
||||
* @param end 终止范围(不包含本身),可为负数
|
||||
* @param result_index 源数据中指定的结果集
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator HKU_API SLICE(int64_t start, int64_t end, int result_index = 0);
|
||||
|
||||
/**
|
||||
* 获取某指标中指定范围的数据
|
||||
* @param ind 源数据
|
||||
* @param start 起始范围,可为负数
|
||||
* @param end 终止范围(不包含本身),可为负数
|
||||
* @param result_index 源数据中指定的结果集
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
inline Indicator SLICE(const Indicator& ind, int64_t start, int64_t end, int result_index = 0) {
|
||||
return SLICE(start, end, result_index)(ind);
|
||||
}
|
||||
|
||||
} // namespace hku
|
@ -13,6 +13,21 @@
|
||||
|
||||
namespace hku {
|
||||
|
||||
/**
|
||||
* 求移动平均
|
||||
* @details
|
||||
* <pre>
|
||||
* 用法:若Y=SMA(X,N,M) 则 Y=[M*X+(N-M)*Y')/N,其中Y'表示上一周期Y值
|
||||
* </pre>
|
||||
* @param n 计算均值的周期窗口,必须为大于0的整数
|
||||
* @param m 系数
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator HKU_API SMA(int n = 22, double m = 2.0);
|
||||
Indicator HKU_API SMA(int, const IndParam& m);
|
||||
Indicator HKU_API SMA(const IndParam& n, double m = 2.0);
|
||||
Indicator HKU_API SMA(const IndParam& n, const IndParam& m);
|
||||
|
||||
/**
|
||||
* 求移动平均
|
||||
* @details
|
||||
@ -24,13 +39,34 @@ namespace hku {
|
||||
* @param m 系数
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator SMA(const Indicator& data, int n = 22, double m = 2.0);
|
||||
Indicator HKU_API SMA(int n = 22, double m = 2.0);
|
||||
|
||||
inline Indicator SMA(const Indicator& ind, int n, double m) {
|
||||
inline Indicator SMA(const Indicator& ind, int n = 22, double m = 2.0) {
|
||||
return SMA(n, m)(ind);
|
||||
}
|
||||
|
||||
inline Indicator SMA(const Indicator& ind, int n, const IndParam& m) {
|
||||
return SMA(n, m)(ind);
|
||||
}
|
||||
|
||||
inline Indicator SMA(const Indicator& ind, const IndParam& n, double m = 2.0) {
|
||||
return SMA(n, m)(ind);
|
||||
}
|
||||
|
||||
inline Indicator SMA(const Indicator& ind, const IndParam& n, const IndParam& m) {
|
||||
return SMA(n, m)(ind);
|
||||
}
|
||||
|
||||
inline Indicator SMA(const Indicator& ind, int n, const Indicator& m) {
|
||||
return SMA(n, IndParam(m))(ind);
|
||||
}
|
||||
|
||||
inline Indicator SMA(const Indicator& ind, const Indicator& n, double m = 2.0) {
|
||||
return SMA(IndParam(n), m)(ind);
|
||||
}
|
||||
|
||||
inline Indicator SMA(const Indicator& ind, const Indicator& n, const Indicator& m) {
|
||||
return SMA(IndParam(n), IndParam(m))(ind);
|
||||
}
|
||||
|
||||
} // namespace hku
|
||||
|
||||
#endif /* INDICATOR_CRT_SMA_H_ */
|
||||
|
@ -19,6 +19,7 @@ namespace hku {
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator HKU_API STDEV(int n = 10);
|
||||
Indicator HKU_API STDEV(const IndParam& n);
|
||||
|
||||
/**
|
||||
* 计算N周期内样本标准差
|
||||
@ -26,7 +27,17 @@ Indicator HKU_API STDEV(int n = 10);
|
||||
* @param n N日时间窗口
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator HKU_API STDEV(const Indicator& data, int n = 10);
|
||||
inline Indicator HKU_API STDEV(const Indicator& data, int n = 10) {
|
||||
return STDEV(n)(data);
|
||||
}
|
||||
|
||||
inline Indicator HKU_API STDEV(const Indicator& data, const IndParam& n) {
|
||||
return STDEV(n)(data);
|
||||
}
|
||||
|
||||
inline Indicator HKU_API STDEV(const Indicator& data, const Indicator& n) {
|
||||
return STDEV(IndParam(n))(data);
|
||||
}
|
||||
|
||||
} // namespace hku
|
||||
|
||||
|
@ -19,12 +19,20 @@ namespace hku {
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator HKU_API STDP(int n = 10);
|
||||
Indicator STDP(const Indicator& data, int n = 10);
|
||||
Indicator HKU_API STDP(const IndParam& n);
|
||||
|
||||
inline Indicator STDP(const Indicator& data, int n) {
|
||||
inline Indicator STDP(const Indicator& data, int n = 10) {
|
||||
return STDP(n)(data);
|
||||
}
|
||||
|
||||
inline Indicator STDP(const Indicator& data, const IndParam& n) {
|
||||
return STDP(n)(data);
|
||||
}
|
||||
|
||||
inline Indicator STDP(const Indicator& data, const Indicator& n) {
|
||||
return STDP(IndParam(n))(data);
|
||||
}
|
||||
|
||||
} // namespace hku
|
||||
|
||||
#endif /* INDICATOR_CRT_STDP_H_ */
|
||||
|
@ -19,6 +19,7 @@ namespace hku {
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator HKU_API SUM(int n = 20);
|
||||
Indicator HKU_API SUM(const IndParam& n);
|
||||
|
||||
/**
|
||||
* 求总和。SUM(X,N),统计N周期中X的总和,N=0则从第一个有效值开始。
|
||||
@ -26,12 +27,18 @@ Indicator HKU_API SUM(int n = 20);
|
||||
* @param n N日时间窗口
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator SUM(const Indicator& ind, int n = 20);
|
||||
|
||||
inline Indicator SUM(const Indicator& ind, int n) {
|
||||
inline Indicator SUM(const Indicator& ind, int n = 20) {
|
||||
return SUM(n)(ind);
|
||||
}
|
||||
|
||||
inline Indicator SUM(const Indicator& ind, const IndParam& n) {
|
||||
return SUM(n)(ind);
|
||||
}
|
||||
|
||||
inline Indicator SUM(const Indicator& ind, const Indicator& n) {
|
||||
return SUM(IndParam(n))(ind);
|
||||
}
|
||||
|
||||
} // namespace hku
|
||||
|
||||
#endif /* INDICATOR_CRT_SUM_H_ */
|
||||
|
@ -25,12 +25,20 @@ namespace hku {
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator HKU_API SUMBARS(double a);
|
||||
Indicator SUMBARS(const Indicator& ind, double a);
|
||||
Indicator HKU_API SUMBARS(const IndParam& a);
|
||||
|
||||
inline Indicator SUMBARS(const Indicator& ind, double a) {
|
||||
return SUMBARS(a)(ind);
|
||||
}
|
||||
|
||||
inline Indicator SUMBARS(const Indicator& ind, const IndParam& a) {
|
||||
return SUMBARS(a)(ind);
|
||||
}
|
||||
|
||||
inline Indicator SUMBARS(const Indicator& ind, const Indicator& a) {
|
||||
return SUMBARS(IndParam(a))(ind);
|
||||
}
|
||||
|
||||
} // namespace hku
|
||||
|
||||
#endif /* INDICATOR_CRT_SUMBARS_H_ */
|
||||
|
@ -20,9 +20,19 @@ namespace hku {
|
||||
* 连涨周期, UPNDAY(CLOSE,M)表示连涨M个周期
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator UPNDAY(const Indicator& ind, int n = 3);
|
||||
inline Indicator UPNDAY(const Indicator& ind, int n = 3) {
|
||||
Indicator result = EVERY(ind > REF(ind, 1), n);
|
||||
result.name("UPDAY");
|
||||
return result;
|
||||
}
|
||||
|
||||
inline Indicator UPNDAY(const Indicator& ind, int n) {
|
||||
inline Indicator UPNDAY(const Indicator& ind, const IndParam& n) {
|
||||
Indicator result = EVERY(ind > REF(ind, 1), n);
|
||||
result.name("UPDAY");
|
||||
return result;
|
||||
}
|
||||
|
||||
inline Indicator UPNDAY(const Indicator& ind, const Indicator& n) {
|
||||
Indicator result = EVERY(ind > REF(ind, 1), n);
|
||||
result.name("UPDAY");
|
||||
return result;
|
||||
|
@ -21,12 +21,20 @@ namespace hku {
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator HKU_API VAR(int n = 10);
|
||||
Indicator VAR(const Indicator& data, int n = 10);
|
||||
Indicator HKU_API VAR(const IndParam& n);
|
||||
|
||||
inline Indicator VAR(const Indicator& data, int n) {
|
||||
inline Indicator VAR(const Indicator& data, int n = 10) {
|
||||
return VAR(n)(data);
|
||||
}
|
||||
|
||||
inline Indicator VAR(const Indicator& data, const IndParam& n) {
|
||||
return VAR(n)(data);
|
||||
}
|
||||
|
||||
inline Indicator VAR(const Indicator& data, const Indicator& n) {
|
||||
return VAR(IndParam(n))(data);
|
||||
}
|
||||
|
||||
} // namespace hku
|
||||
|
||||
#endif /* INDICATOR_CRT_VAR_H_ */
|
||||
|
@ -21,12 +21,20 @@ namespace hku {
|
||||
* @ingroup Indicator
|
||||
*/
|
||||
Indicator HKU_API VARP(int n = 10);
|
||||
Indicator VARP(const Indicator& data, int n = 10);
|
||||
Indicator HKU_API VARP(const IndParam& n);
|
||||
|
||||
inline Indicator VARP(const Indicator& data, int n) {
|
||||
inline Indicator VARP(const Indicator& data, int n = 10) {
|
||||
return VARP(n)(data);
|
||||
}
|
||||
|
||||
inline Indicator VARP(const Indicator& data, const IndParam& n) {
|
||||
return VARP(n)(data);
|
||||
}
|
||||
|
||||
inline Indicator VARP(const Indicator& data, const Indicator& n) {
|
||||
return VARP(IndParam(n))(data);
|
||||
}
|
||||
|
||||
} // namespace hku
|
||||
|
||||
#endif /* INDICATOR_CRT_VARP_H_ */
|
||||
|
@ -6,6 +6,9 @@
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
#include "../crt/AMA.h"
|
||||
#include "../crt/CVAL.h"
|
||||
#include "../crt/SLICE.h"
|
||||
#include "IAma.h"
|
||||
|
||||
#if HKU_SUPPORT_SERIALIZATION
|
||||
@ -76,6 +79,91 @@ void IAma::_calculate(const Indicator& data) {
|
||||
}
|
||||
}
|
||||
|
||||
void IAma::_dyn_one_circle(const Indicator& ind, size_t curPos, int n, int fast_n, int slow_n) {
|
||||
if (n < 1) {
|
||||
n = 1;
|
||||
}
|
||||
|
||||
if (fast_n < 0) {
|
||||
fast_n = 0;
|
||||
}
|
||||
|
||||
if (slow_n < 0) {
|
||||
slow_n = 0;
|
||||
}
|
||||
|
||||
Indicator slice = SLICE(ind, 0, curPos + 1);
|
||||
Indicator ama = AMA(slice, n, fast_n, slow_n);
|
||||
if (ama.size() > 0) {
|
||||
size_t index = ama.size() - 1;
|
||||
_set(ama.get(index, 0), curPos, 0);
|
||||
_set(ama.get(index, 1), curPos, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void IAma::_dyn_calculate(const Indicator& ind) {
|
||||
auto iter = m_ind_params.find("fast_n");
|
||||
Indicator fast_n =
|
||||
iter != m_ind_params.end() ? Indicator(iter->second) : CVAL(ind, getParam<int>("fast_n"));
|
||||
iter = m_ind_params.find("slow_n");
|
||||
Indicator slow_n =
|
||||
iter != m_ind_params.end() ? Indicator(iter->second) : CVAL(ind, getParam<int>("slow_n"));
|
||||
iter = m_ind_params.find("n");
|
||||
Indicator n =
|
||||
iter != m_ind_params.end() ? Indicator(iter->second) : CVAL(ind, getParam<int>("n"));
|
||||
|
||||
HKU_CHECK(fast_n.size() == ind.size(), "ind_param(fast_n).size()={}, ind.size()={}!",
|
||||
fast_n.size(), ind.size());
|
||||
HKU_CHECK(slow_n.size() == ind.size(), "ind_param(slow_n).size()={}, ind.size()={}!",
|
||||
slow_n.size(), ind.size());
|
||||
|
||||
m_discard = std::max(ind.discard(), fast_n.discard());
|
||||
m_discard = std::max(m_discard, slow_n.discard());
|
||||
m_discard = std::max(m_discard, n.discard());
|
||||
size_t total = ind.size();
|
||||
HKU_IF_RETURN(0 == total || m_discard >= total, void());
|
||||
|
||||
static const size_t minCircleLength = 400;
|
||||
size_t workerNum = ms_tg->worker_num();
|
||||
if (total < minCircleLength || workerNum == 1) {
|
||||
for (size_t i = ind.discard(); i < total; i++) {
|
||||
_dyn_one_circle(ind, i, n[i], fast_n[i], slow_n[i]);
|
||||
}
|
||||
_update_discard();
|
||||
return;
|
||||
}
|
||||
|
||||
size_t circleLength = minCircleLength;
|
||||
if (minCircleLength * workerNum >= total) {
|
||||
circleLength = minCircleLength;
|
||||
} else {
|
||||
size_t tailCount = total % workerNum;
|
||||
circleLength = tailCount == 0 ? total / workerNum : total / workerNum + 1;
|
||||
}
|
||||
|
||||
std::vector<std::future<void>> tasks;
|
||||
for (size_t group = 0; group < workerNum; group++) {
|
||||
size_t first = circleLength * group;
|
||||
if (first >= total) {
|
||||
break;
|
||||
}
|
||||
tasks.push_back(ms_tg->submit([=, &ind, &n, &fast_n, &slow_n]() {
|
||||
size_t endPos = first + circleLength;
|
||||
if (endPos > total) {
|
||||
endPos = total;
|
||||
}
|
||||
for (size_t i = circleLength * group; i < endPos; i++) {
|
||||
_dyn_one_circle(ind, i, n[i], fast_n[i], slow_n[i]);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
for (auto& task : tasks) {
|
||||
task.get();
|
||||
}
|
||||
_update_discard();
|
||||
}
|
||||
|
||||
Indicator HKU_API AMA(int n, int fast_n, int slow_n) {
|
||||
IndicatorImpPtr p = make_shared<IAma>();
|
||||
p->setParam<int>("n", n);
|
||||
@ -84,8 +172,60 @@ Indicator HKU_API AMA(int n, int fast_n, int slow_n) {
|
||||
return Indicator(p);
|
||||
}
|
||||
|
||||
Indicator HKU_API AMA(const Indicator& ind, int n, int fast_n, int slow_n) {
|
||||
return AMA(n, fast_n, slow_n)(ind);
|
||||
Indicator HKU_API AMA(int n, const IndParam& fast_n, int slow_n) {
|
||||
IndicatorImpPtr p = make_shared<IAma>();
|
||||
p->setParam<int>("n", n);
|
||||
p->setIndParam("fast_n", fast_n);
|
||||
p->setParam<int>("slow_n", slow_n);
|
||||
return Indicator(p);
|
||||
}
|
||||
|
||||
Indicator HKU_API AMA(int n, const IndParam& fast_n, const IndParam& slow_n) {
|
||||
IndicatorImpPtr p = make_shared<IAma>();
|
||||
p->setParam<int>("n", n);
|
||||
p->setIndParam("fast_n", fast_n);
|
||||
p->setIndParam("slow_n", slow_n);
|
||||
return Indicator(p);
|
||||
}
|
||||
|
||||
Indicator HKU_API AMA(int n, int fast_n, const IndParam& slow_n) {
|
||||
IndicatorImpPtr p = make_shared<IAma>();
|
||||
p->setParam<int>("n", n);
|
||||
p->setParam<int>("fast_n", fast_n);
|
||||
p->setIndParam("slow_n", slow_n);
|
||||
return Indicator(p);
|
||||
}
|
||||
|
||||
Indicator HKU_API AMA(const IndParam& n, int fast_n, int slow_n) {
|
||||
IndicatorImpPtr p = make_shared<IAma>();
|
||||
p->setIndParam("n", n);
|
||||
p->setParam<int>("fast_n", fast_n);
|
||||
p->setParam<int>("slow_n", slow_n);
|
||||
return Indicator(p);
|
||||
}
|
||||
|
||||
Indicator HKU_API AMA(const IndParam& n, const IndParam& fast_n, int slow_n) {
|
||||
IndicatorImpPtr p = make_shared<IAma>();
|
||||
p->setIndParam("n", n);
|
||||
p->setIndParam("fast_n", fast_n);
|
||||
p->setParam<int>("slow_n", slow_n);
|
||||
return Indicator(p);
|
||||
}
|
||||
|
||||
Indicator HKU_API AMA(const IndParam& n, int fast_n, const IndParam& slow_n) {
|
||||
IndicatorImpPtr p = make_shared<IAma>();
|
||||
p->setIndParam("n", n);
|
||||
p->setParam<int>("fast_n", fast_n);
|
||||
p->setIndParam("slow_n", slow_n);
|
||||
return Indicator(p);
|
||||
}
|
||||
|
||||
Indicator HKU_API AMA(const IndParam& n, const IndParam& fast_n, const IndParam& slow_n) {
|
||||
IndicatorImpPtr p = make_shared<IAma>();
|
||||
p->setIndParam("n", n);
|
||||
p->setIndParam("fast_n", fast_n);
|
||||
p->setIndParam("slow_n", slow_n);
|
||||
return Indicator(p);
|
||||
}
|
||||
|
||||
} /* namespace hku */
|
||||
|
@ -26,6 +26,11 @@ class IAma : public IndicatorImp {
|
||||
public:
|
||||
IAma();
|
||||
virtual ~IAma();
|
||||
|
||||
virtual void _dyn_calculate(const Indicator&) override;
|
||||
|
||||
private:
|
||||
void _dyn_one_circle(const Indicator& ind, size_t curPos, int n, int fast_n, int slow_n);
|
||||
};
|
||||
|
||||
} /* namespace hku */
|
||||
|
@ -5,6 +5,8 @@
|
||||
* Author: Administrator
|
||||
*/
|
||||
|
||||
#include "../crt/ATR.h"
|
||||
#include "../crt/SLICE.h"
|
||||
#include "IAtr.h"
|
||||
|
||||
#if HKU_SUPPORT_SERIALIZATION
|
||||
@ -43,14 +45,25 @@ void IAtr::_calculate(const Indicator& indicator) {
|
||||
}
|
||||
}
|
||||
|
||||
void IAtr::_dyn_run_one_step(const Indicator& ind, size_t curPos, size_t step) {
|
||||
HKU_IF_RETURN(step < 1, void());
|
||||
Indicator slice = SLICE(ind, 0, curPos + 1);
|
||||
Indicator atr = ATR(slice, step);
|
||||
if (atr.size() > 0) {
|
||||
_set(atr[atr.size() - 1], curPos);
|
||||
}
|
||||
}
|
||||
|
||||
Indicator HKU_API ATR(int n) {
|
||||
IndicatorImpPtr p = make_shared<IAtr>();
|
||||
p->setParam<int>("n", n);
|
||||
return Indicator(p);
|
||||
}
|
||||
|
||||
Indicator HKU_API ATR(const Indicator& data, int n) {
|
||||
return ATR(n)(data);
|
||||
Indicator HKU_API ATR(const IndParam& n) {
|
||||
IndicatorImpPtr p = make_shared<IAtr>();
|
||||
p->setIndParam("n", n);
|
||||
return Indicator(p);
|
||||
}
|
||||
|
||||
} /* namespace hku */
|
||||
|
@ -14,7 +14,7 @@
|
||||
namespace hku {
|
||||
|
||||
class IAtr : public IndicatorImp {
|
||||
INDICATOR_IMP(IAtr)
|
||||
INDICATOR_IMP_SUPPORT_DYNAMIC_STEP(IAtr)
|
||||
INDICATOR_IMP_NO_PRIVATE_MEMBER_SERIALIZATION
|
||||
|
||||
public:
|
||||
|
@ -16,7 +16,7 @@
|
||||
namespace hku {
|
||||
|
||||
class IBackset : public IndicatorImp {
|
||||
INDICATOR_IMP_SUPPORT_IND_PARAM(IBackset)
|
||||
INDICATOR_IMP_SUPPORT_DYNAMIC_STEP(IBackset)
|
||||
INDICATOR_IMP_NO_PRIVATE_MEMBER_SERIALIZATION
|
||||
|
||||
public:
|
||||
|
@ -97,22 +97,6 @@ void ICount::_dyn_run_one_step(const Indicator& ind, size_t curPos, size_t step)
|
||||
_set(count, curPos);
|
||||
}
|
||||
|
||||
void ICount::_after_dyn_calculate(const Indicator& ind) {
|
||||
size_t total = ind.size();
|
||||
HKU_IF_RETURN(m_discard == total, void());
|
||||
|
||||
size_t discard = m_discard;
|
||||
for (size_t i = total - 1; i > discard; i--) {
|
||||
if (std::isnan(get(i))) {
|
||||
m_discard = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (m_discard == discard && std::isnan(get(discard))) {
|
||||
m_discard = discard + 1;
|
||||
}
|
||||
}
|
||||
|
||||
Indicator HKU_API COUNT(int n) {
|
||||
IndicatorImpPtr p = make_shared<ICount>();
|
||||
p->setParam<int>("n", n);
|
||||
|
@ -19,14 +19,12 @@ namespace hku {
|
||||
* COUNT(CLOSE>OPEN,20)表示统计20周期内收阳的周期数
|
||||
*/
|
||||
class ICount : public IndicatorImp {
|
||||
INDICATOR_IMP_SUPPORT_IND_PARAM(ICount)
|
||||
INDICATOR_IMP_SUPPORT_DYNAMIC_STEP(ICount)
|
||||
INDICATOR_IMP_NO_PRIVATE_MEMBER_SERIALIZATION
|
||||
|
||||
public:
|
||||
ICount();
|
||||
virtual ~ICount();
|
||||
|
||||
virtual void _after_dyn_calculate(const Indicator& ind) override;
|
||||
};
|
||||
|
||||
} /* namespace hku */
|
||||
|
@ -16,7 +16,7 @@
|
||||
namespace hku {
|
||||
|
||||
class IDevsq : public hku::IndicatorImp {
|
||||
INDICATOR_IMP_SUPPORT_IND_PARAM(IDevsq)
|
||||
INDICATOR_IMP_SUPPORT_DYNAMIC_STEP(IDevsq)
|
||||
INDICATOR_IMP_NO_PRIVATE_MEMBER_SERIALIZATION
|
||||
|
||||
public:
|
||||
|
@ -5,6 +5,8 @@
|
||||
* Author: fasiondog
|
||||
*/
|
||||
|
||||
#include "../crt/SLICE.h"
|
||||
#include "../crt/EMA.h"
|
||||
#include "IEma.h"
|
||||
|
||||
#if HKU_SUPPORT_SERIALIZATION
|
||||
@ -43,14 +45,24 @@ void IEma::_calculate(const Indicator& indicator) {
|
||||
}
|
||||
}
|
||||
|
||||
void IEma::_dyn_run_one_step(const Indicator& ind, size_t curPos, size_t step) {
|
||||
Indicator slice = SLICE(ind, 0, curPos + 1);
|
||||
Indicator ema = EMA(slice, step);
|
||||
if (ema.size() > 0) {
|
||||
_set(ema[ema.size() - 1], curPos);
|
||||
}
|
||||
}
|
||||
|
||||
Indicator HKU_API EMA(int n) {
|
||||
IndicatorImpPtr p = make_shared<IEma>();
|
||||
p->setParam<int>("n", n);
|
||||
return Indicator(p);
|
||||
}
|
||||
|
||||
Indicator HKU_API EMA(const Indicator& data, int n) {
|
||||
return EMA(n)(data);
|
||||
Indicator HKU_API EMA(const IndParam& n) {
|
||||
IndicatorImpPtr p = make_shared<IEma>();
|
||||
p->setIndParam("n", n);
|
||||
return Indicator(p);
|
||||
}
|
||||
|
||||
} /* namespace hku */
|
||||
|
@ -17,7 +17,7 @@ namespace hku {
|
||||
* 抛弃数 = 0
|
||||
*/
|
||||
class IEma : public IndicatorImp {
|
||||
INDICATOR_IMP(IEma)
|
||||
INDICATOR_IMP_SUPPORT_DYNAMIC_STEP(IEma)
|
||||
INDICATOR_IMP_NO_PRIVATE_MEMBER_SERIALIZATION
|
||||
|
||||
public:
|
||||
|
@ -107,22 +107,6 @@ void IEvery::_dyn_run_one_step(const Indicator& ind, size_t curPos, size_t step)
|
||||
_set(every, curPos);
|
||||
}
|
||||
|
||||
void IEvery::_after_dyn_calculate(const Indicator& ind) {
|
||||
size_t total = ind.size();
|
||||
HKU_IF_RETURN(m_discard == total, void());
|
||||
|
||||
size_t discard = m_discard;
|
||||
for (size_t i = total - 1; i > discard; i--) {
|
||||
if (std::isnan(get(i))) {
|
||||
m_discard = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (m_discard == discard && std::isnan(get(discard))) {
|
||||
m_discard = discard + 1;
|
||||
}
|
||||
}
|
||||
|
||||
Indicator HKU_API EVERY(int n) {
|
||||
IndicatorImpPtr p = make_shared<IEvery>();
|
||||
p->setParam<int>("n", n);
|
||||
|
@ -19,14 +19,12 @@ namespace hku {
|
||||
* 一直存在, EVERY (X,N) 表示条件X在N周期一直存在
|
||||
*/
|
||||
class IEvery : public IndicatorImp {
|
||||
INDICATOR_IMP_SUPPORT_IND_PARAM(IEvery)
|
||||
INDICATOR_IMP_SUPPORT_DYNAMIC_STEP(IEvery)
|
||||
INDICATOR_IMP_NO_PRIVATE_MEMBER_SERIALIZATION
|
||||
|
||||
public:
|
||||
IEvery();
|
||||
virtual ~IEvery();
|
||||
|
||||
virtual void _after_dyn_calculate(const Indicator& ind) override;
|
||||
};
|
||||
|
||||
} /* namespace hku */
|
||||
|
@ -107,22 +107,6 @@ void IExist::_dyn_run_one_step(const Indicator& ind, size_t curPos, size_t step)
|
||||
_set(exist, curPos);
|
||||
}
|
||||
|
||||
void IExist::_after_dyn_calculate(const Indicator& ind) {
|
||||
size_t total = ind.size();
|
||||
HKU_IF_RETURN(m_discard == total, void());
|
||||
|
||||
size_t discard = m_discard;
|
||||
for (size_t i = total - 1; i > discard; i--) {
|
||||
if (std::isnan(get(i))) {
|
||||
m_discard = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (m_discard == discard && std::isnan(get(discard))) {
|
||||
m_discard = discard + 1;
|
||||
}
|
||||
}
|
||||
|
||||
Indicator HKU_API EXIST(int n) {
|
||||
IndicatorImpPtr p = make_shared<IExist>();
|
||||
p->setParam<int>("n", n);
|
||||
|
@ -19,14 +19,12 @@ namespace hku {
|
||||
* 存在, EXIST(X,N) 表示条件X在N周期有存在
|
||||
*/
|
||||
class IExist : public IndicatorImp {
|
||||
INDICATOR_IMP_SUPPORT_IND_PARAM(IExist)
|
||||
INDICATOR_IMP_SUPPORT_DYNAMIC_STEP(IExist)
|
||||
INDICATOR_IMP_NO_PRIVATE_MEMBER_SERIALIZATION
|
||||
|
||||
public:
|
||||
IExist();
|
||||
virtual ~IExist();
|
||||
|
||||
virtual void _after_dyn_calculate(const Indicator& ind) override;
|
||||
};
|
||||
|
||||
} /* namespace hku */
|
||||
|
@ -16,7 +16,7 @@
|
||||
namespace hku {
|
||||
|
||||
class IFilter : public IndicatorImp {
|
||||
INDICATOR_IMP_SUPPORT_IND_PARAM(IFilter)
|
||||
INDICATOR_IMP_SUPPORT_DYNAMIC_STEP(IFilter)
|
||||
INDICATOR_IMP_NO_PRIVATE_MEMBER_SERIALIZATION
|
||||
|
||||
public:
|
||||
|
@ -16,7 +16,7 @@
|
||||
namespace hku {
|
||||
|
||||
class IHhvbars : public IndicatorImp {
|
||||
INDICATOR_IMP_SUPPORT_IND_PARAM(IHhvbars)
|
||||
INDICATOR_IMP_SUPPORT_DYNAMIC_STEP(IHhvbars)
|
||||
INDICATOR_IMP_NO_PRIVATE_MEMBER_SERIALIZATION
|
||||
|
||||
public:
|
||||
|
@ -20,7 +20,7 @@ namespace hku {
|
||||
* 参数: n: N日时间窗口
|
||||
*/
|
||||
class IHighLine : public IndicatorImp {
|
||||
INDICATOR_IMP_SUPPORT_IND_PARAM(IHighLine)
|
||||
INDICATOR_IMP_SUPPORT_DYNAMIC_STEP(IHighLine)
|
||||
INDICATOR_IMP_NO_PRIVATE_MEMBER_SERIALIZATION
|
||||
|
||||
public:
|
||||
|
@ -16,7 +16,7 @@
|
||||
namespace hku {
|
||||
|
||||
class ILowLine : public IndicatorImp {
|
||||
INDICATOR_IMP_SUPPORT_IND_PARAM(ILowLine)
|
||||
INDICATOR_IMP_SUPPORT_DYNAMIC_STEP(ILowLine)
|
||||
INDICATOR_IMP_NO_PRIVATE_MEMBER_SERIALIZATION
|
||||
|
||||
public:
|
||||
|
@ -16,7 +16,7 @@
|
||||
namespace hku {
|
||||
|
||||
class ILowLineBars : public IndicatorImp {
|
||||
INDICATOR_IMP_SUPPORT_IND_PARAM(ILowLineBars)
|
||||
INDICATOR_IMP_SUPPORT_DYNAMIC_STEP(ILowLineBars)
|
||||
INDICATOR_IMP_NO_PRIVATE_MEMBER_SERIALIZATION
|
||||
|
||||
public:
|
||||
|
@ -32,7 +32,7 @@ void IMa::_calculate(const Indicator& indicator) {
|
||||
}
|
||||
|
||||
int n = getParam<int>("n");
|
||||
if (0 == n) {
|
||||
if (n <= 0) {
|
||||
price_t sum = 0.0;
|
||||
for (size_t i = m_discard; i < total; i++) {
|
||||
sum += indicator[i];
|
||||
|
@ -14,7 +14,7 @@
|
||||
namespace hku {
|
||||
|
||||
class IMa : public IndicatorImp {
|
||||
INDICATOR_IMP_SUPPORT_IND_PARAM(IMa)
|
||||
INDICATOR_IMP_SUPPORT_DYNAMIC_STEP(IMa)
|
||||
INDICATOR_IMP_NO_PRIVATE_MEMBER_SERIALIZATION
|
||||
|
||||
public:
|
||||
|
@ -7,6 +7,9 @@
|
||||
|
||||
#include "IMacd.h"
|
||||
#include "../crt/EMA.h"
|
||||
#include "../crt/MACD.h"
|
||||
#include "../crt/SLICE.h"
|
||||
#include "../crt/CVAL.h"
|
||||
|
||||
#if HKU_SUPPORT_SERIALIZATION
|
||||
BOOST_CLASS_EXPORT(hku::IMacd)
|
||||
@ -66,6 +69,84 @@ void IMacd::_calculate(const Indicator& data) {
|
||||
}
|
||||
}
|
||||
|
||||
void IMacd::_dyn_one_circle(const Indicator& ind, size_t curPos, int n1, int n2, int n3) {
|
||||
HKU_IF_RETURN(n1 <= 0 || n2 <= 0 || n3 <= 0, void());
|
||||
Indicator slice = SLICE(ind, 0, curPos + 1);
|
||||
Indicator macd = MACD(slice, n1, n2, n3);
|
||||
if (macd.size() > 0) {
|
||||
size_t index = macd.size() - 1;
|
||||
_set(macd.get(index, 0), curPos, 0);
|
||||
_set(macd.get(index, 1), curPos, 1);
|
||||
_set(macd.get(index, 2), curPos, 2);
|
||||
}
|
||||
}
|
||||
|
||||
void IMacd::_dyn_calculate(const Indicator& ind) {
|
||||
auto iter = m_ind_params.find("n1");
|
||||
Indicator n1 =
|
||||
iter != m_ind_params.end() ? Indicator(iter->second) : CVAL(ind, getParam<int>("n1"));
|
||||
iter = m_ind_params.find("n2");
|
||||
Indicator n2 =
|
||||
iter != m_ind_params.end() ? Indicator(iter->second) : CVAL(ind, getParam<int>("n2"));
|
||||
iter = m_ind_params.find("n3");
|
||||
Indicator n3 =
|
||||
iter != m_ind_params.end() ? Indicator(iter->second) : CVAL(ind, getParam<int>("n3"));
|
||||
|
||||
HKU_CHECK(n1.size() == ind.size(), "ind_param(n2).size()={}, ind.size()={}!", n2.size(),
|
||||
ind.size());
|
||||
HKU_CHECK(n2.size() == ind.size(), "ind_param(n2).size()={}, ind.size()={}!", n2.size(),
|
||||
ind.size());
|
||||
HKU_CHECK(n3.size() == ind.size(), "ind_param(n3).size()={}, ind.size()={}!", n3.size(),
|
||||
ind.size());
|
||||
|
||||
m_discard = std::max(ind.discard(), n2.discard());
|
||||
m_discard = std::max(m_discard, n3.discard());
|
||||
m_discard = std::max(m_discard, n1.discard());
|
||||
size_t total = ind.size();
|
||||
HKU_IF_RETURN(0 == total || m_discard >= total, void());
|
||||
|
||||
static const size_t minCircleLength = 400;
|
||||
size_t workerNum = ms_tg->worker_num();
|
||||
if (total < minCircleLength || workerNum == 1) {
|
||||
for (size_t i = ind.discard(); i < total; i++) {
|
||||
_dyn_one_circle(ind, i, n1[i], n2[i], n3[i]);
|
||||
}
|
||||
_update_discard();
|
||||
return;
|
||||
}
|
||||
|
||||
size_t circleLength = minCircleLength;
|
||||
if (minCircleLength * workerNum >= total) {
|
||||
circleLength = minCircleLength;
|
||||
} else {
|
||||
size_t tailCount = total % workerNum;
|
||||
circleLength = tailCount == 0 ? total / workerNum : total / workerNum + 1;
|
||||
}
|
||||
|
||||
std::vector<std::future<void>> tasks;
|
||||
for (size_t group = 0; group < workerNum; group++) {
|
||||
size_t first = circleLength * group;
|
||||
if (first >= total) {
|
||||
break;
|
||||
}
|
||||
tasks.push_back(ms_tg->submit([=, &ind, &n1, &n2, &n3]() {
|
||||
size_t endPos = first + circleLength;
|
||||
if (endPos > total) {
|
||||
endPos = total;
|
||||
}
|
||||
for (size_t i = circleLength * group; i < endPos; i++) {
|
||||
_dyn_one_circle(ind, i, n1[i], n2[i], n3[i]);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
for (auto& task : tasks) {
|
||||
task.get();
|
||||
}
|
||||
|
||||
_update_discard();
|
||||
}
|
||||
|
||||
Indicator HKU_API MACD(int n1, int n2, int n3) {
|
||||
IndicatorImpPtr p = make_shared<IMacd>();
|
||||
p->setParam<int>("n1", n1);
|
||||
@ -74,8 +155,12 @@ Indicator HKU_API MACD(int n1, int n2, int n3) {
|
||||
return Indicator(p);
|
||||
}
|
||||
|
||||
Indicator HKU_API MACD(const Indicator& data, int n1, int n2, int n3) {
|
||||
return MACD(n1, n2, n3)(data);
|
||||
Indicator HKU_API MACD(const IndParam& n1, const IndParam& n2, const IndParam& n3) {
|
||||
IndicatorImpPtr p = make_shared<IMacd>();
|
||||
p->setIndParam("n1", n1);
|
||||
p->setIndParam("n2", n2);
|
||||
p->setIndParam("n3", n3);
|
||||
return Indicator(p);
|
||||
}
|
||||
|
||||
} /* namespace hku */
|
||||
|
@ -29,6 +29,11 @@ class IMacd : public IndicatorImp {
|
||||
public:
|
||||
IMacd();
|
||||
virtual ~IMacd();
|
||||
|
||||
virtual void _dyn_calculate(const Indicator&) override;
|
||||
|
||||
private:
|
||||
void _dyn_one_circle(const Indicator& ind, size_t curPos, int n1, int n2, int n3);
|
||||
};
|
||||
|
||||
} /* namespace hku */
|
||||
|
@ -19,7 +19,7 @@ namespace hku {
|
||||
* 乘幂
|
||||
*/
|
||||
class IPow : public IndicatorImp {
|
||||
INDICATOR_IMP_SUPPORT_IND_PARAM(IPow)
|
||||
INDICATOR_IMP_SUPPORT_DYNAMIC_STEP(IPow)
|
||||
INDICATOR_IMP_NO_PRIVATE_MEMBER_SERIALIZATION
|
||||
|
||||
public:
|
||||
|
@ -37,14 +37,22 @@ void IRef::_calculate(const Indicator& data) {
|
||||
}
|
||||
}
|
||||
|
||||
void IRef::_dyn_run_one_step(const Indicator& ind, size_t curPos, size_t step) {
|
||||
if (curPos >= step) {
|
||||
_set(ind[curPos - step], curPos);
|
||||
}
|
||||
}
|
||||
|
||||
Indicator HKU_API REF(int n) {
|
||||
IndicatorImpPtr p = make_shared<IRef>();
|
||||
p->setParam<int>("n", n);
|
||||
return Indicator(p);
|
||||
}
|
||||
|
||||
Indicator HKU_API REF(const Indicator& ind, int n) {
|
||||
return REF(n)(ind);
|
||||
Indicator HKU_API REF(const IndParam& n) {
|
||||
IndicatorImpPtr p = make_shared<IRef>();
|
||||
p->setIndParam("n", n);
|
||||
return Indicator(p);
|
||||
}
|
||||
|
||||
} /* namespace hku */
|
||||
|
@ -20,7 +20,7 @@ namespace hku {
|
||||
* 例如: REF(CLOSE,1) 表示上一周期的收盘价,在日线上就是昨收。
|
||||
*/
|
||||
class IRef : public IndicatorImp {
|
||||
INDICATOR_IMP(IRef)
|
||||
INDICATOR_IMP_SUPPORT_DYNAMIC_STEP(IRef)
|
||||
INDICATOR_IMP_NO_PRIVATE_MEMBER_SERIALIZATION
|
||||
|
||||
public:
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user