学习QMT股票量化系统入门级双均线策略

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

学习QMT股票量化系统入门级双均线策略

图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。

学习QMT股票量化系统入门级双均线策略

图2

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

学习QMT股票量化系统入门级双均线策略

学习QMT股票量化系统入门级双均线策略

学习QMT股票量化系统入门级双均线策略

从回测来看,年化收益仅0.0471,胜率也才36%,都不理想。可见,无论是单均线还是双均线,都只能在单边趋势行情中获得好的收益,而在震荡行情中,当你一买入,它就要你止损,等你一卖出,它又要你买进,反反复复,上下打脸。

不管怎么说,我们是不是又收获一些python量化知识了呢?

注:本期代码来源于迅投知识库范例,稍有修改。

发布者:股市刺客,转载请注明出处:https://www.95sca.cn/archives/75126
站内所有文章皆来自网络转载或读者投稿,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。敬请谅解!

(0)
股市刺客的头像股市刺客
上一篇 2024 年 7 月 11 日
下一篇 2024 年 7 月 11 日

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注