雪球App,作者: 金融小法师,(https://xueqiu.com/3234495588/257225220)
双均线策略:双均线策略是最经典的趋势策略之一,被广泛应用于股票、期货、外汇、期权、数字货币等交易领域,与传统的趋势策略一样,同时具有低胜率和高盈亏比(高赔率)的特征。趋势追踪策略和均值回归策略一直是量化投资两大永恒的主题。并且以网格策略为例勾勒了均值回归策略的一般形式。这类策略适用于震荡行情,即价格在一个相对固定的区间往复的行情。而这次我们将以经典的双均线策略来为各位展现趋势追踪策略。
先有了趋势,才有了双均线交易系统。双均线交易系统有效或者无效都不代表它本身,而是取决于周期和级别是否对应。
这里补充下,交易者都是自由的,市场就像一片沙漠,虽说跋涉千里,但你可以选择前进的方向。但这也是极端不自由的,因为你必须穿过荒漠到达彼岸,没有其他选择,但无论走哪个方向都必然要经历跋涉的过程
在这片交易的荒原,大家的出发点和目的地不尽相同,但市场对每个人的考验是相同的:
1、系统完整性,自洽性。 固化进场/离场的原则。
2、资金管理,仓位输缩赢冲,回撤控制。
3、风控策略,止损成本、胜率、交易频率。
4、预期管理, 情绪调控,抗逆力,抗压力。
5、学习能力,计划预案、复盘总结,认知迭代。
这是交易中可有可无的细节吗? 不,是必然要经历的过程, 是每个交易者把自己所思所想的一盘散沙,凝聚成一个城堡的过程。
1. 原理(1)均线的“前世今生”均线,一个进行形态分析时总也绕不过去的指标。
均线最早由美国投资专家Joseph E.Granville(格兰威尔)于20世纪中期提出,现在仍然广泛为人们使用,成为判断买卖信号的一大重要指标。从统计角度来说,均线就是历史价格的平均值,可以代表过去N日股价的平均走势。
1962年7月,Joseph E.Granville在他的书中提出了著名的Granville八大买卖法则。只利用股价和均线即可进行择时,方法简单有效,一经提出,迅速受到市场追捧。尤其是其中的金叉和死叉信号,更是沿用至今。
Granville 八大法则其中有四条是用于判断买进时机,另外四条是用于判断卖出时机。买进和卖出法则一一对应,分布在高点的左右两侧(除买4和卖4以外)。法则内容如下所示:
买1:均线整体上行,股价由下至上上穿均线,此为黄金交叉,形成第一个买点。买2:股价出现下跌迹象,但尚未跌破均线,此时均线变成支撑线,形成第二个买点。买3:股价仍处于均线上方,但呈现急剧下跌趋势。当跌破均线时,出现第三个买点。买4:(右侧)股价和均线都处于下降通道,且股价处于均线下方,严重远离均线,出现第四个买点。
卖1:均线由上升状态变为缓慢下降的状态,股价也开始下降。当股价跌破均线时,此为死亡交叉,形成第一个卖点。卖2:股价仍处于均线之下,但股价开始呈现上涨趋势,当股价无限接近均线但尚未突破时,此时均线变成阻力线,形成第二个卖点。卖3:股价终于突破均线,处于均线上方。但持续时间不长,股价开始下跌,直至再一次跌破均线,此为第三个卖点。卖4:(左侧)股价和均线都在上涨,股价上涨的速度远快于均线上涨的速度。当股价严重偏离均线时,出现第四个卖点。
(图片来源于网络)
(2)均线理论为什么有效?Shiller(1981)在研究中发现,资产的长期价格呈现均值回复的特征,即从长期来看,资产的价格会回归均值。这也是均线理论被广泛应用的前提。
(3)均线理论的缺陷均线归根到底是一种平均值,平均值在应用过程中存在最大的问题就是其滞后性。当出现买入卖出信号时,最佳时机早已过去。举例来说,如果A股票最新价格出现了较大的涨幅,股价和均线都上涨,但均线的速度慢于股价上涨速度。此时,从形态上来看,金叉出现,为买入信号。次日,股价回调,股价下降的速度快于均线下降的速度,形成死叉,为卖点。这样一买一卖不仅没有盈利,反而出现亏损。均线策略比较容易捕捉大型的趋势行情,能够在较早的点位入场。在震荡行情中产生很多交易信号,从而造成反复止损,形成大幅亏损。选择合适的双均线的参数是解决该问题的最直观的方式。不过更复杂的,应该加入其它过滤信号,使得策略收益更优。
(4)胜率和盈亏比在说双均线策略时,需要理解胜率和盈亏比
胜率 = 100% * 盈利次数 / 总交易次数盈亏比 =总盈利金额 / 总亏损金额
一个策略能否盈利,其中的衡量方法之一,就是【胜率】和【盈亏比+1】的乘积是否大于1.0。
举个通俗的例子,你跟小伙伴抛硬币打赌,正面朝上你赢1块钱,反面朝上你输1块钱,正常情况下,大家的胜率都是五五开,此时你的胜率是50%,盈亏比为1.0,50%*(1+1)=1,刚好处在临界点上,大家的预期收益都为0。
如果你有特殊的抛硬币技法或是对硬币做了手脚(提高了胜率),或者你的小伙伴是土豪,无聊得很,为了吸引你来玩抛硬币游戏,输钱你给1块,赢钱可以拿1块1(提高了盈亏比),此时【胜率】和【盈亏比+1】的乘积是大于1.0的,非常有利于你,就是很费小伙伴。
确切来说,预期收益率=胜率 – (1-胜率)/盈亏比,知道了这个式子,在仅知胜率和盈亏比的情况下,就可以快速选择预期收益率更高的交易策略。例如,在“胜率70%,盈亏比1:3”和“胜率30%,盈亏比3:1”这两个策略之间,你会选哪个呢?
回过头来看双均线策略。
在大部分市场当中,大部分时间都是震荡市,趋势市占的时间很少,对于双均线这种趋势策略而言,大部分时间都是出错,开仓不久就会打止损,因此胜率比较低(一般是在20%~40%左右),但只要抓住一次大波段,就可以弥补好几次亏损,因此胜率比较高,通常都在2.0之上。
要提高双均线策略的绩效,就要提高【胜率】和【盈亏比+1】的乘积,最好的办法就是同时提高胜率和盈亏比。
重新把目光转到胜率和盈亏比的计算公式的分母上,如果我们能过滤掉部分亏损的信号,那就可以同时减小“总交易次数”和“总亏损金额”,胜率和盈亏比也就同时提高了。
(5)均线理论的改进平常我们使用双均线,都是“金叉多,死叉空”,现在可以在出现金叉/死叉时,不马上开仓,比如等到在观察期内突破了设定的上轨/下轨才开仓。针对均线的缺点,市场上提出了各种各样的改进方法。
1.对均线的计算方法进行改正。
加权移动平均线是在移动平均线的基础上按照时间进行加权。越靠近当前日期的价格对未来价格的影响越大,赋予更大的权重;越远离当前日期价格,赋予越小的权重。
2.调整均线周期
利用不同周期均线得到的结果也不同。许多有经验的投资者发现,在不同的市场中,有些均线的效果显著优于其他周期均线。有些长线投资者还会将股价替换成短周期均线进行趋势判断。
2. 策略逻辑第一步:获取数据,计算长短期均线第二步:设置交易信号
当短期均线由上向下穿越长期均线时做空当短期均线由下向上穿越长期均线时做多
回测数据: SHFE.rb2101的60s频度bar数据回测时间: 2020-04-01 到 2020-05-31回测初始资金:3万
3.常见均线指标均线是最常用的分析指标之一,所反映的是过去一段时间内市场的平均成本变化情况。我们常用的是5日均线、10日均线、20日均线、30日均线、60日均线、120日均线等。下面,我们将各种均线在交易中的作用和使用技巧逐一归纳总结,仅供参考:
5日均线,即攻击线
其主要作用是推动价格在短期内形成攻击态势,不断引导价格上涨或下跌。
如果攻击线上涨角度陡峭有力,则说明价格短线爆发力强。反之,则弱。
同样,在价格进入下跌阶段时,攻击线也是重要的杀跌武器,如果向下角度陡峭,则杀跌力度极强。在实战中,当价格突破攻击线,攻击线呈陡峭向上的攻击状态时,则意味着短线行情已经启动,此时应短线积极做多。
10日均线,即操盘线
主要作用是推动价格在一轮中级波段行情中持续上涨或下跌。
如果操盘线上涨角度陡峭有力,则说明价格中期上涨力度强。反之,则弱。
同样,在价格进入下跌波段时,操盘线同样可促使价格反复盘整。在实战中,当价格突破操盘线,操盘线呈持续向上的攻击状态时,则意味着波段性中线行情已经启动,此时应短线积极做多。
同理,当价格击穿操盘线,操盘线呈向下拐头状态时,则意味着上涨行情已经结束,大波段性调整或下跌行情已经展开,此时应中线做空。
20日均线,即辅助线
主要作用是协助操盘线,推动并修正价格运行力度与趋势角度,稳定价格趋势运行方向。
在一轮波段性上涨行情中,如果辅助线上涨角度较大并陡峭有力,则说明价格中线波段上涨力度极强。
同样,价格在下跌阶段时,辅助线更是价格反弹时的强大阻力,并可修正价格下跌轨道。
在实战中,当价格突破辅助线,辅助线呈持续向上的攻击状态时,则意味着波段性中线行情已经启动,此时应积极做多。
同理,当价格击穿辅助线,辅助线呈向下拐头状态时,则意味着阶段性中线上涨行情已经结束,而阶段性调整或下跌行情已经展开,此时应中线做空。
30日均线,即生命线
主要作用是指明价格的中期运行趋势。在一个中期波段性上涨趋势中,生命线有极强的支撑和阻力作用。
如果生命线上涨角度陡峭有力,则说明价格中期上涨趋势强烈。
同样,在价格进入下跌趋势时,生命线同样可压制价格的反弹行为,促使价格持续走弱。
在实战中,当价格突破生命线,生命线呈拐头向上攻击状态时,则意味着中线大波段行情已经启动,此时应积极做多。
然而,一旦当价格击穿生命线,生命线呈拐头向下状态时,则意味着更大级别的调整或下跌行情已经展开,此时应积极做空。
60日均线,即决策线
60日均线,也有决策线之称。主要作用是指明价格的中期趋势,指导价格大波段级别运行于既定的趋势之中。当价格向上或向下突破决策线时,则说明一级别的反转行情已经启动,临盘应做出相应的操盘决策。
在实战中,当价格突破决策线,决策线呈拐头向上的攻击状态时,则意味着中线大趋势多头行情已经形成,此时应中线积极做多。
然而,一旦当价格向下击穿决策线,决策线呈向下拐头状态时,则意味着一级别的下跌行情已经展开,此时应中线果断做空。
120日均线,即趋势线
120日均线,也有趋势线之称。和决策线一样,趋势线的主要作用也是指明价格中长期的趋势,引导或指导价格大波段大级别运行于既定的趋势之中。
当价格向上或向下突破趋势线时,则说明价格大趋势已经发生逆转,临盘应做出相应的操盘决策;
价格突破趋势线时,一般情况下不会在较短时间内出现反方向运行。
4. 策略代码# coding=utf-8
from __future__ import print_function, absolute_import
from gm.api import *
import talib
'''
本策略以SHFE.rb2101为交易标的,根据其一分钟(即60s频度)bar数据建立双均线模型,
短周期为20,长周期为60,当短期均线由上向下穿越长期均线时做空,
当短期均线由下向上穿越长期均线时做多,每次开仓前先平掉所持仓位,再开仓。
注:为了适用于仿真和实盘,在策略中增加了一个“先判断是否平仓成功再开仓”的判断逻辑,以避免出现未平仓成功,可用资金不足的情况。
回测数据为:SHFE.rb2101的60s频度bar数据
回测时间为:2020-04-01 09:00:00到2020-05-31 15:00:00
'''
def init(context):
context.short = 20 # 短周期均线
context.long = 60 # 长周期均线
context.symbol = 'SHFE.rb2101' # 订阅交易标的
context.period = context.long + 1 # 订阅数据滑窗长度
context.open_long = False # 开多单标记
context.open_short = False # 开空单标记
subscribe(context.symbol, '60s', count=context.period) # 订阅行情
def on_bar(context, bars):
# 获取通过subscribe订阅的数据
prices = context.data(context.symbol, '60s', context.period, fields='close')
# 利用talib库计算长短周期均线
short_avg = talib.SMA(prices.values.reshape(context.period), context.short)
long_avg = talib.SMA(prices.values.reshape(context.period), context.long)
# 查询持仓
position_long = context.account().position(symbol=context.symbol, side=1)
position_short = context.account().position(symbol=context.symbol, side=2)
# 短均线下穿长均线,做空(即当前时间点短均线处于长均线下方,前一时间点短均线处于长均线上方)
if long_avg[-2] < short_avg[-2] and long_avg[-1] >= short_avg[-1]:
# 无多仓情况下,直接开空
if not position_long:
order_volume(symbol=context.symbol, volume=1, side=OrderSide_Sell, position_effect=PositionEffect_Open,
order_type=OrderType_Market)
print(context.symbol, '以市价单调空仓到仓位')
# 有多仓情况下,先平多,再开空(开空命令放在on_order_status里面)
else:
context.open_short = True
# 以市价平多仓
order_volume(symbol=context.symbol, volume=1, side=OrderSide_Sell, position_effect=PositionEffect_Close,
order_type=OrderType_Market)
print(context.symbol, '以市价单平多仓')
# 短均线上穿长均线,做多(即当前时间点短均线处于长均线上方,前一时间点短均线处于长均线下方)
if short_avg[-2] < long_avg[-2] and short_avg[-1] >= long_avg[-1]:
# 无空仓情况下,直接开多
if not position_short:
order_volume(symbol=context.symbol, volume=1, side=OrderSide_Buy, position_effect=PositionEffect_Open,
order_type=OrderType_Market)
print(context.symbol, '以市价单调多仓到仓位')
# 有空仓的情况下,先平空,再开多(开多命令放在on_order_status里面)
else:
context.open_long = True
# 以市价平空仓
order_volume(symbol=context.symbol, volume=1, side=OrderSide_Buy,
position_effect=PositionEffect_Close, order_type=OrderType_Market)
print(context.symbol, '以市价单平空仓')
def on_order_status(context, order):
# 查看下单后的委托状态
status = order['status']
# 成交命令的方向
side = order['side']
# 交易类型
effect = order['position_effect']
# 当平仓委托全成后,再开仓
if status == 3:
# 以市价开空仓,需等到平仓成功无仓位后再开仓
# 如果无多仓且side=2(说明平多仓成功),开空仓
if effect == 2 and side == 2 and context.open_short:
context.open_short = False
order_volume(symbol=context.symbol, volume=1, side=OrderSide_Sell, position_effect=PositionEffect_Open,
order_type=OrderType_Market)
print(context.symbol, '以市价单调空仓到仓位')
# 以市价开多仓,需等到平仓成功无仓位后再开仓
# 如果无空仓且side=1(说明平空仓成功),开多仓
if effect == 2 and side == 1 and context.open_long:
context.open_long = False
order_volume(symbol=context.symbol, volume=1, side=OrderSide_Buy, position_effect=PositionEffect_Open,
order_type=OrderType_Market)
print(context.symbol, '以市价单调多仓到仓位')
if __name__ == '__main__':
'''
strategy_id策略ID,由系统生成
filename文件名,请与