在上一篇文章中,我们用talib库来改写了单均线策略,我们已经知道了用get_market_data_ex()来获取股票历史数据、用talib.MA()来计算20日均线、用get_trade_detail_data()来获取帐户信息、用order_target_value()来下单,那么,现在我们只需要再增加一根均线,就可以构建另一个入门级的策略—-双均线策略。

图1
买卖策略:选取两根均线,一根5日均线,另一根20日均线,当5日均线上穿20均线,买入。 当5日均线下穿20均线,卖出。
因为选取的是5日均线和20日均线,所以大家也把它叫做520战法。(碰巧后天就是5月20号了,提前祝大家520快乐!同时顺便也提醒一下各位,别忘了在520到来之际,向自己心爱的人表达一下真情和爱意,生活还是需要一点浪漫和激情的。)
好,言归正传,我们来看代码:
#coding:gbk
#本策略,通过计算5日和20日双均线,在当5日均线上穿20均线时买入,5日均线下穿20均线时做卖出
#注意:本策略仅用于python量化学习,不用于真实交易
import pandas as pd
import numpy as np
import talib
def init(C):
C.stock= C.stockcode + '.' +C.market
#line1和line2分别为两条均线期数
C.line1=5 #快线参数
C.line2=20 #慢线参数
C.accountid = "your accID"
def handlebar(C):
#当前k线日期
bar_date = timetag_to_datetime(C.get_bar_timetag(C.barpos), '%Y%m%d%H%M%S')
local_data = C.get_market_data_ex(['close'], [C.stock], end_time = bar_date, period = C.period, count = max(C.line1, C.line2), subscribe = False)
close_list = list(local_data[C.stock].iloc[:, 0])
line1_mean = round(np.mean(close_list[-C.line1:]), 2)
line2_mean = round(np.mean(close_list[-C.line2:]), 2)
print(f"{bar_date} 短均线{line1_mean} 长均线{line2_mean}")
account = get_trade_detail_data('test', 'stock', 'account')
account = account[0]
available_cash = int(account.m_dAvailable)
holdings = get_trade_detail_data('test', 'stock', 'position')
holdings = {i.m_strInstrumentID + '.' + i.m_strExchangeID : i.m_nVolume for i in holdings}
holding_vol = holdings[C.stock] if C.stock in holdings else 0
#如果目前空仓,同时快线穿过慢线,则买入
if holding_vol == 0 and line1_mean > line2_mean:
vol = int(available_cash / close_list[-1] / 100) * 100
passorder(23, 1101, C.accountid, C.stock, 5, -1, vol, C)
print(f"{bar_date} 开仓")
C.draw_text(1, 1, '开')
#如果目前持仓中,同时快线下穿慢线,则全部平仓
elif holding_vol > 0 and line1_mean < line2_mean:
#状态变更为未持仓
C.holding=False
passorder(24, 1101, C.accountid, C.stock, 5, -1, holding_vol, C)
print(f"{bar_date} 平仓")
C.draw_text(1, 1, '平')
如果大家还记得,上次我们init()函数是这样写:def init(ContextInfo), 而这一次,我们就写成def init(C),“C”是“ContextInfo”的缩写,“ContextInfo.stock”就是“C.stock”,这样是不是简便多了呢?
在“line1_mean = round(np.mean(close_list[-C.line1:]), 2)”,是计算5日均线。round(x,2)是对计算得到的平均值进行四舍五入,并保留两位小数。np.mean()是用numpy库来计算N天的平均值。还记得之前我们用pandas和talib来计算平均值吗?
MA20 = talib.MA(close, timeperiod=ContextInfo.MA_period, matype=0)
MA20 = pd.Series(close).rolling(window=ContextInfo.MA_period).mean()
close_list[-C.line1:]中close_list是收盘价列表,[-C.line1:]是计算平均值的范围,即从 close_list 列表中从倒数 C.line1 开始到最新收盘价,而我们设定了C.line1=5,故“line1_mean = round(np.mean(close_list[-C.line1:]), 2)”,就是计算5日均线。20日均线同理。
holdings = {i.m_strInstrumentID + ‘.’ + i.m_strExchangeID : i.m_nVolume for i in holdings}是通过证券代码和交易所代码快速查找持仓数量。
C.draw_text(1, 1, ‘开’)是在图表上绘制文本,参数 1, 1 指定的位置绘制文本 ‘平’。官方说明如图2。

图2
回测看看,代码能正常运行。



从回测来看,年化收益仅0.0471,胜率也才36%,都不理想。可见,无论是单均线还是双均线,都只能在单边趋势行情中获得好的收益,而在震荡行情中,当你一买入,它就要你止损,等你一卖出,它又要你买进,反反复复,上下打脸。
不管怎么说,我们是不是又收获一些python量化知识了呢?
注:本期代码来源于迅投知识库范例,稍有修改。
发布者:股市刺客,转载请注明出处:https://www.95sca.cn/archives/75126
站内所有文章皆来自网络转载或读者投稿,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。敬请谅解!