套利类策略
主要依赖不同金融产品价格之间的稳定关系,根据品种间的价差在“某个范围”内的波动,通过“买卖价差”进行获利。
套利策略的主要特点是“赚胜率高的小钱”,每笔交易的确定性较高,盈利相对较小。
本质上,它是一种反趋势(与主流趋势相反)的策略,和趋势跟踪策略互补
常见的套利策略有:期现套利
、跨期套利
、跨市场套利
、跨品种套利
。
学习内容
1) 了解套利和价差套利的概念;
2) 了解价差套利的分类;
3) 掌握跨品种套利策略的原理和实现。
套利的概念
套利通常指的是:某种实物资产或金融资产在(在同一市场或不同市场)拥有两个价格的情况下,以较低的价格买进,较高的价格卖出,从而实现获利的交易方式。
不同平台对同一个产品销售两种不同价格,必然存在一定的套利空间,利用这一点,可以轻松赚到一笔无风险的价格差
不同于普通交易注重资产本身的价格,套利交易更看重同一时间下,不同合约价格之间的差异。
通过不同市场或不同形式、同类或相似的金融产品之间的价差,同时操作进行获利,就是套利交易。
价差套利
在期货交易中,价差是发现套利机会的一种重要方式。
具体操作是,在相同时间节点下,价格高的期货合约减去价格较低的期货合约后得到差值。
!
导入失败
前面的股票策略,我们习惯从标的价格波动中获益,承担的是股票价格波动带来的风险。
而价差套利不同,它是从价差本身,或者价差波动获取收益,承担的是价差消失或价差波动带来的风险。
基于合约间的关系,可将价差套利策略分成:跨市套利、跨期套利、期现套利、还有今天重点要学的跨品种套利。
常见的套利策略
!
导入失败
跨市套利
跨市套利是由于地理或区域等因素,不同交易所对同一标的下,产生了一定的价差,基于此建立套利交易。
例如,伦敦金属交易所(LME)的伦铜,和上海期货交易所(SHEF)的沪铜,若两者价格相差比较大时,就可以做多低价合约,同时,做空高价合约,等价差恢复正常,再平仓获利。
!
导入失败
除此之外,同一标的下,不同交割月份的合约也存在一定的套利空间。
跨期套利
跨期套利指的是同一市场下,对相同标的、交割月份不同的商品期货合约进行长短期套利的策略。
首先,部分期货的价格受季节或供需影响较大,比如冬天的西瓜会比夏天贵,螺纹钢 10 月是传统需求的旺季等等。
其次,通过统计历年的数据发现,不同时期交割的期货价格,有时也存在某种关系和规律。
如近期合约与远期合约之间,存在一定范围的价差,如果出现异常变化,意味着可能出现套利空间。
!
导入失败
跨期套利操作相对复杂,分类也更加多样:牛市套利、熊市套利、牛熊交换套利。
期现套利
期现套利的“期”代表期货,“现”代表现货。
当同一标的,在期货市场和现货市场上出现一定价差,可以低买高卖获利。
跨品种套利
跨品种套利,便是依靠统计套利,发现两种或三种相互关联、交割时间相同的商品期货合约价格之间的规律,从而套利的策略。
现实生活中相互关联的合约,这种关联,似乎也体现在它们的价格中。例如,同一产业链中的产品与原材料:大豆和豆油。又比如,互相替代的产品:豆油、棕榈油、植物油。
!
导入失败
跨品种套利逻辑
想要实现跨品种套利,品种之间的关联性是基础,价差是发现规律的手段。
而价差的均值回归,是跨品种套利的核心原理。
品种的关联性
品种间的关联,或者说关系,为品种之间的价差规律提供了逻辑支撑。
最常见的关系有:同一产业链的供给关系,互为替代的竞争关系。
如豆油和棕榈油是国内主要的消费食用植物油,存在一定的竞争关系。
!
导入失败
将品种的关联性简化为线性关系。
这样可以使用相关系数,对关系进行量化。
注:线性关系指的是正比或者反比关系,一个增加,另一个也跟着增加,或者减少的情况。
例如:路程 = 时间 x 速度
,路程和时间就是一个线性关系,时间增加,路程也会增加。
一般来说,相关系数的绝对值越接近 1,说明两者“线性关系”越强。
!
导入失败
在期货市场,有不少相关性强的品种,比如:
① 黑色系产业链的焦煤、焦炭、动力煤,螺纹钢、铁矿石…
② 化工产业链的塑料、PVC、聚丙烯、PTA、沥青、原油…
发现价格规律
实际上,数据分析和找规律的技能,我们从小就在训练。
通过有关联的标的价差
(标的 1 - 标的 2)或比价
(序列 1 / 序列 2),从而找到数据间的数学规律,进一步发现套利机会,是统计套利的常规手段。
均值回归
均值回归的意思是说,标的价格总是围绕平均值上下波动。
涨多了,大概率就会向平均值移动下跌,跌多了,大概率会向平均值移动上升。
!
导入失败
套利获益
以上下游产业链关系的豆油和大豆为例,从简单的价差公式开始聊起吧:豆油 - 大豆
。
假设,普遍状态下,豆油 - 大豆
价差的均值在 3~5
左右。
既然要赚价差收敛的钱,那么,就要搞清楚,价差扩大或者价差缩小在收敛过程中,豆油和大豆的价格会发生什么样的变化。
!
导入失败
价差扩大
某天,豆油因为供不应求,价格急剧上升。
豆油 - 大豆
的价差达到了 10,超出了稳定合理的范围。
需求旺盛了,油脂企业为了谋利,纷纷加大对豆油的生产。
此时,大豆作为生产豆油的原材料,需求量增大,价格也上涨。
最终 豆油 - 大豆
价差收敛。
!
导入失败
基于这一场景,我们来看,如何套利。
如果均值回归有效,那么,扩大的价差要收敛,就是价差值下降 ⤵️(10 -> 5)。
从数学公式的角度来看,豆油 - 大豆
值下降的方式无非三种:
① 若 豆油
不变,大豆
价格上涨 ⤴️
② 若 大豆
不变,豆油
价格下降 ⤵️
③ 豆油
价格下降 ⤵️ 同时 大豆
价格上涨 ⤴️
既然已经预判了合约未来的发展发现,“套利”的方式也变得明朗:
① 做空豆油 ⏬
② 做多大豆 ⏫
值得注意的是,做空豆油和做多大豆是同时进行的。
价差缩小
因为豆油产量过剩,供大于求,豆油价格急剧下降,豆油 - 大豆
的价差降到了 2,超出了稳定合理的范围。
作为原材料的大豆的需求也骤降,价格回落。
如此一来,两者的价差也回到了稳定合理的范围。
!
导入失败
构建步骤
统计套利的步骤分为以下四个步骤。👇
!
导入失败
寻找套利机会
奔奔最近比较关注农产品方面的行情,通过定期查看行业研报,跟踪了好几组期货品种,比如豆油和棕榈油。
查看它们在期货市场的价格走势。或者借用数学公式,计算不同品种的相关性系数、价差(价格相减)、比价(价格相除)等。
注:你可以用 Python 或软件工具进行计算,这里推荐 2 个可直接计算出期货比价和相关系数的免费网站:生意社、南华。
通过查看“豆油-棕榈油历年相关系数”(数据来源南华),奔奔发现,豆油-棕榈油的相关性系数大多在 0.6 以上,且近两年的数值都在 0.8~1 这一区间徘徊(高相关性)。
!
导入失败
确定套利逻辑
做出假设,是第二步。
奔奔通过查看近年的“豆油-棕榈油品种比价(豆油价格/棕榈油价格)” 图表,发现,豆油/棕榈油
的比价(价格相除)波动确实呈现一定的规律性。
!
导入失败
如豆油/棕榈油
比价处于低值时(如最低值0.99
)将会迎来反弹。反之,豆油/棕榈油
比价处于高值(如最高值1.48
)将会回降。
测算安全边际
安全边际是一种概念,不同市场的安全边际都有所不同。
大豆提油的套利中,安全边际就是期间的利润,需要测算原料和成品之间是否存在盈利空间。
豆油和棕榈油的示例中,安全边际可以是豆油/棕榈油比价的一般范围。
继续观察豆油和棕榈油的比价,发现数值大多围绕 1.1
到 1.2
波动,历年来最低值是 0.99
左右,最高值曾高达1.48
。
制定套利计划,并执行套利
由于行情随时都在变化,在剧烈的行情变化下,人往往需要在很短的时间内做决定,而这时候难免被情绪所左右,使得执行了错误的行动。
所以在执行套利的过程中,注意遵守“计划”,避免行情变动对于人决策的影响。
跨品种套利策略代码讲解
指标模块!
导入失败
代码主要实现 2 个功能:
1)设置默认值。
2)计算指标。
!
导入失败
1)设置默认值
默认值主要有三个:
① 布林带时间窗口(价差的移动平均周期 N)
② 开仓阈值(“套利区”布林带的标准差 M)
③ 止损阈值(“止损区”布林带标准差 K)
布林带时间窗口参数设置为 20
,表示以过去 4 周时间的历史行情计算布林带指标。👉
开仓阈值参数设置为 1.5
,表示价差超过过去 4 周波动率的 1.5 倍标准差,执行套利开仓的操作。👉
止损阈值参数设置为 2
,表示价差超过过去 4 周波动率的 2 倍标准差,执行套利止损的操作。👉
2)计算指标
计算跨品种套利策略需要指标,包括两个标的的价差序列、套利的布林带指标、止损的布林带指标。
在计算具体指标值之前,先遍历标的池,对标的做一个标记。
计算两个标的的价格序列的价格差,螺纹钢的收盘价context.rb_data.close
,减去焦炭的收盘价context.j_data.close
。👉
布林带的调用方法BollingerBands() 类
你在前面的课程里面已经接触过了,不过,这次我们新增了一个参数devfactor
。
!
导入失败
devfactor
是标准差系数,作用是控制上下轨离中轨的距离,默认值为 2。
计算了“套利的布林带指标”,调用BollingerBands
方法,分别输入参数 —— 价差序列、布林带时间窗口、以及开仓阈值。👉
计算了“止损的布林带指标”,同样调用BollingerBands
方法,输入参数 —— 价差序列、布林带时间窗口、以及止损阈值。👉
以对象.属性
的方式,分别获取“套利”和“止损”的布林道轨道。👉
最终得到的结果如下图所示👇:
!
导入失败
最后我们用到了上节课学到的捕获信号交叉的CrossOver()
类,用于捕获价差和轨道间的突破情况。
!
导入失败
标的模块
这里选择了螺纹钢合约(RB2110.XSGE)作为基准标的。当然,你也可以换成焦炭的合约(J2201.XDCE),这并不影响策略本身的运算结果。
def choose_stock(context):
"""标的"""
# 设置基准标的
context.benchmark = "RB2201.XSGE"
# 设置标的
context.symbol_list = ["RB2201.XSGE", "J2201.XDCE"]
择时模块
择时模块主要实现策略的开仓以及平仓逻辑。
!
导入失败
由于跨品种套利策略是对两个标的同时建仓/平仓的,所以,要判断持仓情况。
实际操作过程中,随意择选其中一只标的,获取其持仓数量即可。
首先,判断是否满足开仓信号,如果满足开仓信号,则执行对应的套利开仓交易。
1)价差上涨,开仓,买入价差
!
导入失败
套利入场信号 1:价差序列上穿套利区间的上限:
即context.cross_top_signal[0] == 1.0
。
此时价差(螺纹钢-焦炭)太大了,后面市场就有极大的概率变小,将通过价差回归获利。
a. 做空螺纹钢。
b. 做多焦炭。
2)价差下跌,开仓,卖出价差
!
导入失败
套利入场信号 2:价差序列下穿套利区间的下限:
即context.cross_top_signal[0] == -1.0
。
此时价差(螺纹钢-焦炭)太小了,后面市场就有极大的概率变大,将通过价差回归获利。
a. 做多螺纹钢。
b. 做空焦炭。
然后,待价差收敛,回归正常,则执行价差平仓。
3)价差回归,价差平仓
平仓条件 1:上涨价差回归中轨,即焦炭持多仓并且价差小于中轨。
!
导入失败
平仓条件 2:下跌价差回归中轨,即炭持空仓并且价差大于中轨。
!
导入失败
风控模块
风控模块,包括2个功能:
!
导入失败
1)上涨价差止损
!
导入失败
当价差持续上涨,突破止损布林带上轨,不见回归迹象,应及时止损。
2)下跌价差止损
!
导入失败
当价差持续下跌,突破止损布林带下轨,不见回归迹象,应及时止损。
其中任何一种止损情况发生,都调用 close
方法平仓两个合约。
执行代码
指标模块代码:
def indicators(context):
"""指标"""
# 设置布林带时间窗口
period = 20
# 设置开仓阈值
open_devfactor = 1.5
# 设置止损阈值
stop_devfactor = 2
# 遍历所有标的
for data in context.datas:
# 如果标的为螺纹钢
if data._name == "RB2201.XSGE":
# 记录标的对象
context.rb_data = data
# 如果标的为焦炭
elif data._name == "J2201.XDCE":
# 记录标的对象
context.j_data = data
# 获取两个标的的价差序列
context.diff_close = context.rb_data.close - context.j_data.close
# 计算套利区间上下限
open_boll_band = BollingerBands(context.diff_close,
period=period,
devfactor=open_devfactor)
# 获取套利区间的上轨、下轨、中轨
open_top = open_boll_band.top
open_bot = open_boll_band.bot
context.open_mid = open_boll_band.mid
# 获取价差分别突破上轨、下轨的信号
context.cross_top_signal = CrossOver(context.diff_close, open_top)
context.cross_bot_signal = CrossOver(context.diff_close, open_bot)
# 计算止损区间上下限
stop_boll_band = BollingerBands(context.diff_close,
period=period,
devfactor=stop_devfactor)
# 获取止损区间的上下轨
context.stop_top = stop_boll_band.top
context.stop_bot = stop_boll_band.bot
标的模块代码:
def choose_stock(context):
"""标的"""
# 设置基准标的
context.benchmark = "RB2201.XSGE"
# 设置标的
context.symbol_list = ["RB2201.XSGE", "J2201.XDCE"]
择时模块代码:
def timing(context):
"""择时"""
# 获取焦炭持仓数量
hold_size = context.getposition(context.j_data).size
# 如果未持仓
if hold_size == 0:
# 当价差上穿上轨
if context.cross_top_signal[0] == 1.0:
# 做空螺纹钢
context.sell(data=context.rb_data)
# 做多焦炭
context.buy(data=context.j_data)
# 当价差下穿下轨
elif context.cross_bot_signal[0] == -1.0:
# 做多螺纹钢
context.buy(data=context.rb_data)
# 做空焦炭
context.sell(data=context.j_data)
# 如果对焦炭持多仓并且价差小于等于中轨,或对焦炭持空仓并且价差大于等于中轨
elif hold_size > 0 and context.diff_close[0] <= context.open_mid[0] or hold_size < 0 and context.diff_close[0] >= context.open_mid[0]:
# 对两个合约进行平仓
context.close(data=context.rb_data)
context.close(data=context.j_data)
风控模块代码:
def control_risk(context):
"""风控"""
# 获取焦炭持仓数量
hold_size = context.getposition(context.j_data).size
# 如果对焦炭持多仓并且价差大于上轨,或对焦炭持空仓并且价差小于下轨
if hold_size > 0 and context.diff_close[0] > context.stop_top[0] or hold_size < 0 and context.diff_close[0] < context.stop_bot[0]:
# 对两个合约进行平仓
context.close(data=context.rb_data)
context.close(data=context.j_data)
初次回测
!
导入失败
跨品种套利策略调参逻辑
本次跨品种套利策略,提供可调节的参数有三个:布林带时间窗口、开仓阈值和止损阈值,在调整参数前,需要先理解策略的关键参数,及其含义。
布林带时间窗口、开仓阈值共同决定了套利策略“开仓”
的敏感、频繁程度。
1) 时间窗口越短
,开仓阈值越小
,上下轨离当前的价差就越接近,价差稍有波动,就会触发开仓交易,导致交易频繁。
2) 时间窗口越长
,开仓阈值越大
,上下轨离当前的价差就越远,价差有大的波动,才会触发开仓交易,交易次数降低。
止损阈值决定了套利策略“止损”
的敏感、频繁程度。
1)止损阈值越小
,价差越容易触碰止损上下边界,导致频繁止损。
2)止损阈值太大
,价差越难触碰止损上下边界,止损不及,失去风控的保护意义。
思维导图
!
导入失败
提示:
本公司发布内容均为市场公开信息,不构成投资建议,投资者据此操作,风险自担。市场有风险,投资需谨慎!