定义
双均线策略,通过建立m天移动平均线,n天移动平均线,则这两条均线必有交点。若m>n,n天平均线“上穿越”m天均线则为买入点,反之为卖点。该策略基于不同天数均线的交叉点,抓住股票的强势和弱势时刻,进行交易。
对于每一个交易日,都可以计算出前N天的移动平均值,然后把这些移动平均值连起来,成为一条线,就叫做N日移动平均线。一般由5日均线(MA5),10日均线(MA10)
比如前5个交易日的收盘价分别为10,9,9,10,11元,那么,5日的移动平均股价为9.8元。同理,如果下一个交易日的收盘价为12,那么在下一次计算移动平均值的时候,需要计算9,9,10,11,12元的平均值,也就是10.2元。将这平均值连起来,就是均线。
如下图,收盘价是蓝线,橙色的线表示5日的移动平均线。
可以看到股票价格的波动比5天均线的波动要大,这是因为5天均线取的是前5个交易日的均值,相当于做了一个平滑
双均线
股名思义,就是两条天数不同的移动平均线,比如,一天是5日的移动平均线,另一条是10日的移动平均线。如图,蓝色是5天均线,黄色为10日均线
金叉和死叉
由时间短的均线(如上图蓝色的线)在下方向上穿越时间长一点的均线(如上图黄色的线),为金叉,反之为死叉
双均线策略
构建一个简单的策略:认为双均线金叉的时候,表示股票很强势,反之很弱势,那么我们就在强势的时候买入,弱势的时候卖出即可
使用聚宽平台进行代码的编写与回测
#导入函数库
from jqdata import *
#初始化函数,设定基准等等
def initialize(context):
#设定沪深300作为基准
set_benchmark('000300.XSHG')
#开启动态复权模式(真实价格)
set_option('use_real_price', True)
#输出内容到日志 log.info()
log.info('初始函数开始运行且全局只运行一次')
#过滤掉order系列API产生的比error级别低的log
#log.set_level('order', 'error')
### 股票相关设定 ###
#股票类每笔交易时的手续费是:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税, 每笔交易佣金最低扣5块钱
set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
## 运行函数(reference_security为运行时间的参考标的;传入的标的只做种类区分,因此传入'000300.XSHG'或'510300.XSHG'是一样的)
#开盘前运行
run_daily(before_market_open, time='before_open', reference_security='000300.XSHG')
#开盘时运行
run_daily(market_open, time='open', reference_security='000300.XSHG')
#收盘后运行
run_daily(after_market_close, time='after_close', reference_security='000300.XSHG')
## 开盘前运行函数
def before_market_open(context):
#输出运行时间
log.info('函数运行时间(before_market_open):'+str(context.current_dt.time()))
#给微信发送消息(添加模拟交易,并绑定微信生效)
#send_message('美好的一天~')
#要操作的股票:万科A股(g.为全局变量)
g.security = '000002.XSHE'
## 开盘时运行函数
def market_open(context):
log.info('函数运行时间(market_open):'+str(context.current_dt.time()))
security = g.security
#设置均线窗口长度
n1 = 5
n2 = 10
#获取股票的收盘价
close_date = attribute_history(security,n2+2,'1d',['close'],df = False)
#获取过去ma_n1天的平均价格
ma_n1=close_date['close'][-n1:].mean()
#获取过去ma_n2 天的平均价格
ma_n2=close_date['close'][-n2:].mean()
#取得当前现金
cash = context.portfolio.available_cash
#如果当前有余额,并且n1日均线大于n2日均线
if ma_n1 > ma_n2:
#用掉所有cash买入股票
order_value(security,cash)
#记录此次买入
log.info("Buying %s" %(security))
#如果n1 日均线小于n2 日均线,并且目前有头寸
elif ma_n1 < ma_n2 and context.portfolio.positions[security].closeable_amount > 0:
#全部卖出
order_target(security,0)
#记录此次卖出
log.info("Selling %s" %(security))
#绘制n1日均线价格
record(ma_n1 = ma_n1)
#绘制n2日均线价格
record(ma_n2 = ma_n2)
## 收盘后运行函数
def after_market_close(context):
log.info(str('函数运行时间(after_market_close):'+str(context.current_dt.time())))
#得到当天所有成交记录
trades = get_trades()
for _trade in trades.values():
log.info('成交记录:'+str(_trade))
log.info('一天结束')
log.info('##############################################################')
可以看出该策略从2016/4/25到2018/4/27收益率27.19,策略年化利率13.14%,最大回撤25.64%