%matplotlib inline
%time from hikyuu.interactive.interactive import *
iodog.open()
#use_draw_engine('echarts')
std::cout are redirected to python::stdout std::cerr are redirected to python::stderr [2019-03-16 22:23:59.813] [info] Loading market information... [2019-03-16 22:23:59.815] [info] Loading stock type information... [2019-03-16 22:23:59.816] [info] Loading stock information... [2019-03-16 22:24:00.889] [info] Loading KData... [2019-03-16 22:24:00.894] [info] Preloading all day kdata to buffer! [StockManager::setKDataDriver] [2019-03-16 22:24:06.362] [info] 5.47172s Loaded Data. Wall time: 7.01 s
def getNextWeekDate(week):
"""获取指定日期的下一周周一日期"""
from datetime import timedelta
py_week = week.datetime()
next_week_start = py_week + timedelta(days = 7 - py_week.weekday())
return Datetime(next_week_start)
def DEMO_SG(self):
"""
买入信号:周线MACD零轴下方底部金叉,即周线的DIF>DEA金叉时买入
卖出信号:日线级别 跌破 20日均线
参数:
week_macd_n1:周线dif窗口
week_macd_n2: 周线dea窗口
week_macd_n3: 周线macd平滑窗口
day_n: 日均线窗口
"""
k = self.getTO()
if (len(k) == 0):
return
stk = k.getStock()
#-----------------------------
#计算日线级别的卖出信号
#-----------------------------
day_c = CLOSE(k)
day_ma = MA(day_c, self.getParam("day_n"))
day_x = day_c < day_ma #收盘价小于均线
for i in range(day_x.discard, len(day_x)):
if day_x[i] >= 1.0:
self._addSellSignal(k[i].datetime)
#-----------------------------
#计算周线级别的买入信号
#-----------------------------
week_q = QueryByDate(k[0].datetime, k[-1].datetime.nextDay(), kType=Query.WEEK)
week_k = k.getStock().getKData(week_q)
n1 = self.getParam("week_macd_n1")
n2 = self.getParam("week_macd_n2")
n3 = self.getParam("week_macd_n3")
m = MACD(CLOSE(week_k), n1, n2, n3)
fast = m.getResult(0)
slow = m.getResult(1)
discard = m.discard if m.discard > 1 else 1
for i in range(discard, len(m)):
if (fast[i-1] < slow[i-1] and fast[i] > slow[i]):
#当周计算的结果,只能作为下周一的信号
self._addBuySignal(week_k[i].datetime.nextWeek())
class DEMO_MM(MoneyManagerBase):
"""
买入:30% (不明确,暂且当做当前现金的30%)
卖出:已持仓股票数的50%
"""
def __init__(self):
super(DEMO_MM, self).__init__("MACD_MM")
def _reset(self):
pass
def _clone(self):
return DEMO_MM()
def _getBuyNumber(self, datetime, stk, price, risk, part_from):
tm = self.getTM()
cash = tm.currentCash
#可以不用考虑最小交易单位的问题,已经自动处理
#num = int((cash * 0.3 // price // stk.atom) * stk.atom)
return int(cash*0.3/price) #返回类型必须是int
def _getSellNumber(self, datetime, stk, price, risk, part_from):
tm = self.getTM()
position = tm.getPosition(stk)
total_num = position.number
num = int(total_num * 0.5)
return num if num >= 100 else 0
#账户参数
init_cash = 100000 #账户初始资金
init_date = Datetime('1990-1-1') #账户建立日期
#信号指示器参数
week_n1 = 12
week_n2 = 26
week_n3 = 9
day_n = 20
#选定标的,及测试区间
stk = sm['sz000001']
start_date = Datetime('2017-01-01') #如果是同一级别K线,可以使用索引号,使用了不同级别的K线数据,建议还是使用日期作为参数
end_date = Datetime()
#创建账户
my_tm = crtTM(datetime=init_date, initCash = init_cash, costFunc=TC_FixedA())
#创建系统实例
my_sys = SYS_Simple()
#绑定账户
my_sys.tm = my_tm
#绑定信号指示器
my_sys.sg = crtSG(DEMO_SG,
{'week_macd_n1': week_n1, 'week_macd_n2': week_n2, 'week_macd_n3': week_n3, 'day_n': day_n},
'DEMO_SG')
my_sys.sg.setParam('alternate', False)
#绑定资金管理策略
my_sys.mm = DEMO_MM()
iodog.close()
q = QueryByDate(start_date, end_date, kType=Query.DAY)
my_sys.run(stk, q)
#将交易记录及持仓情况,保存在临时目录,可用Excel查看
#临时目录一般设置在数据所在目录下的 tmp 子目录
#如果打开了excel记录,再次运行系统前,记得先关闭excel文件,否则新的结果没法保存
my_tm.tocsv(sm.tmpdir())
#绘制资金收益曲线(净收益)
x = my_tm.getProfitCurve(stk.getDatetimeList(q), KQuery.DAY)
#x = my_tm.getFundsCurve(stk.getDatetimeList(q), KQuery.DAY) #总资产曲线
x = PRICELIST(x)
x.plot()
#回测统计
per = Performance()
print(per.report(my_tm, Datetime.now()))
帐户初始金额: 100000.00 累计投入本金: 100000.00 累计投入资产: 0.00 累计借入现金: 0.00 累计借入资产: 0.00 累计红利: 0.00 现金余额: 98258.95 未平仓头寸净值: 2200.00 当前总资产: 100458.95 已平仓交易总成本: 0.00 已平仓净利润总额: 0.00 单笔交易最大占用现金比例%: 29.68 交易平均占用现金比例%: 29.45 已平仓帐户收益率%: 0.00 帐户年复合收益率%: 0.25 帐户平均年收益率%: 0.25 赢利交易赢利总额: 0.00 亏损交易亏损总额: 0.00 已平仓交易总数: 0.00 赢利交易数: 0.00 亏损交易数: 0.00 赢利交易比例%: 0.00 赢利期望值: 0.00 赢利交易平均赢利: 0.00 亏损交易平均亏损: 0.00 平均赢利/平均亏损比例: 0.00 净赢利/亏损比例: 0.00 最大单笔赢利: 0.00 最大单笔亏损: 0.00 赢利交易平均持仓时间: 0.00 赢利交易最大持仓时间: 0.00 亏损交易平均持仓时间: 0.00 亏损交易最大持仓时间: 0.00 空仓总时间: 670.00 空仓时间/总时间%: 100.00 平均空仓时间: 670.00 最长空仓时间: 669.00 最大连续赢利笔数: 0.00 最大连续亏损笔数: 0.00 最大连续赢利金额: 0.00 最大连续亏损金额: 0.00 R乘数期望值: 0.00 交易机会频率/年: 0.00 年度期望R乘数: 0.00 赢利交易平均R乘数: 0.00 亏损交易平均R乘数: 0.00 最大单笔赢利R乘数: 0.00 最大单笔亏损R乘数: 0.00 最大连续赢利R乘数: 0.00 最大连续亏损R乘数: 0.00
my_sys.plot()
MA(CLOSE(my_sys.getTO()), 20).plot(new=False)
import pandas as pd
def calTotal(blk, q):
per = Performance()
s_name = []
s_code = []
x = []
for stk in blk:
my_sys.run(stk, q)
per.statistics(my_tm, Datetime.now())
s_name.append(stk.name)
s_code.append(stk.market_code)
x.append(per.get("当前总资产".encode('gb2312')))
return pd.DataFrame({'代码': s_code, '股票': s_name, '当前总资产': x})
%time data = calTotal(blocka, q)
[2019-03-16 22:24:10.042] [info] KData is empty! [System::run] [2019-03-16 22:24:18.171] [info] KData is empty! [System::run] [2019-03-16 22:24:18.568] [info] KData is empty! [System::run] Wall time: 9.85 s
#保存到CSV文件
#data.to_csv(sm.tmpdir() + '/统计.csv')
data[:10]
代码 | 当前总资产 | 股票 | |
---|---|---|---|
0 | SH600605 | 100000.00 | 汇通能源 |
1 | SH600115 | 98511.75 | 东方航空 |
2 | SZ002386 | 99458.37 | 天原集团 |
3 | SH600380 | 97962.76 | 健康元 |
4 | SH600977 | 100000.00 | 中国电影 |
5 | SZ000928 | 99991.18 | 中钢国际 |
6 | SH600146 | 100000.00 | 商赢环球 |
7 | SH603648 | 99585.94 | 畅联股份 |
8 | SZ002676 | 100287.54 | 顺威股份 |
9 | SZ300244 | 100000.00 | 迪安诊断 |