
定量取引とプログラム取引の分野では、「ヘッジ」という言葉は非常に基本的な概念です。デジタル通貨の定量取引では、先物ヘッジ、期間間ヘッジ、スポットヘッジが一般的に使用されるヘッジ戦略です。差額取引の場合。ヘッジの概念、原理、詳細に関しては、定量取引の分野に入ったばかりの学生の多くはあまり明確ではないかもしれません。それは問題ではありません。Inventor Quantitativeが提供する「研究環境」ツールを使用しましょう。取引プラットフォームを簡単に学習できます。この知識を習得してください。
Inventor Quant Control Center で、「Research Environment」をクリックすると、このツールのページに移動します。

ここでは、この分析ファイルを直接アップロードしました。
この分析ファイルは、バックテスト中のスポット先物ヘッジのオープンおよびクローズポジションのプロセス分析です。先物取引所は OKEX 先物で、契約は四半期契約です。quarter。スポット取引はOKEXの通貨対通貨取引であり、取引ペアはBTC_USDT先物・スポットヘッジの動作プロセスを分析するには、以下の具体的な研究環境ファイルを参照してください。Python で記述されたバージョンと JavaScript で記述されたバージョンの 2 つがあります。
from fmz import *
task = VCtx('''backtest
start: 2019-09-19 00:00:00
end: 2019-09-28 12:00:00
period: 15m
exchanges: [{"eid":"Futures_OKCoin","currency":"BTC_USD", "stocks":1}, {"eid":"OKEX","currency":"BTC_USDT","balance":10000,"stocks":0}]
''')
# 创建回测环境
import matplotlib.pyplot as plt
import numpy as np
# 导入画图的库 matplotlib 和 numpy 库exchanges[0].SetContractType("quarter") # 第一个交易所对象OKEX期货(eid:Futures_OKCoin)调用设置当前合约的函数,设置为季度合约
initQuarterAcc = exchanges[0].GetAccount() # OKEX期货交易所初始时的账户信息,记录在变量initQuarterAcc
initQuarterAcc{'Balance': 0.0, 'FrozenBalance': 0.0, 'Stocks': 1.0, 'FrozenStocks': 0.0}initSpotAcc = exchanges[1].GetAccount() # OKEX现货交易所初始时的账户信息,记录在变量initSpotAcc initSpotAcc
{'Balance': 10000.0, 'FrozenBalance': 0.0, 'Stocks': 0.0, 'FrozenStocks': 0.0}quarterTicker1 = exchanges[0].GetTicker() # 获取期货交易所行情,记录在变量quarterTicker1 quarterTicker1
{'Time': 1568851210000,
'High': 10441.25002,
'Low': 10441.25,
'Sell': 10441.25002,
'Buy': 10441.25,
'Last': 10441.25001,
'Volume': 1772.0,
'OpenInterest': 0.0}spotTicker1 = exchanges[1].GetTicker() # 获取现货交易所行情,记录在变量spotTicker1 spotTicker1
{'Time': 1568851210000,
'High': 10156.60000002,
'Low': 10156.6,
'Sell': 10156.60000002,
'Buy': 10156.6,
'Last': 10156.60000001,
'Volume': 7.4443,
'OpenInterest': 0.0}quarterTicker1.Buy - spotTicker1.Sell # 期货做空,现货做多的差价
284.64999997999985
exchanges[0].SetDirection("sell") # 设置期货交易所,交易方向为做空
quarterId1 = exchanges[0].Sell(quarterTicker1.Buy, 10) # 期货做空下单,下单量为10张合约,返回的订单ID记录在变量quarterId1
exchanges[0].GetOrder(quarterId1) # 查询期货订单ID为quarterId1的订单详情{'Id': 1,
'Price': 10441.25,
'Amount': 10.0,
'DealAmount': 10.0,
'AvgPrice': 10441.25,
'Type': 1,
'Offset': 0,
'Status': 1,
'ContractType': b'quarter'}spotAmount = 10 * 100 / quarterTicker1.Buy # 计算10张合约等值的币数,作为现货的下单量 spotId1 = exchanges[1].Buy(spotTicker1.Sell, spotAmount) # 现货交易所下单 exchanges[1].GetOrder(spotId1) # 查询现货订单ID为spotId1的订单详情
{'Id': 1,
'Price': 10156.60000002,
'Amount': 0.0957,
'DealAmount': 0.0957,
'AvgPrice': 10156.60000002,
'Type': 0,
'Offset': 0,
'Status': 1,
'ContractType': b'BTC_USDT_OKEX'}可以看到订单quarterId1、spotId1订单都完全成交,即对冲开仓完成。
Sleep(1000 * 60 * 60 * 24 * 7) # 持仓一段时间,等待差价变小平仓。
等待时间过后,准备平仓。获取当前的行情
quarterTicker2、spotTicker2并且打印。 期货交易所对象的交易方向设置为平空仓:exchanges[0].SetDirection("closesell")下单平仓。 打印平仓订单的详情,显示平仓订单完全成交,平仓完成。
quarterTicker2 = exchanges[0].GetTicker() # 获取当前期货交易所的行情,记录在变量quarterTicker2 quarterTicker2
{'Time': 1569456010000,
'High': 8497.20002,
'Low': 8497.2,
'Sell': 8497.20002,
'Buy': 8497.2,
'Last': 8497.20001,
'Volume': 4311.0,
'OpenInterest': 0.0}spotTicker2 = exchanges[1].GetTicker() # 获取当前现货交易所的行情,记录在变量spotTicker2 spotTicker2
{'Time': 1569456114600,
'High': 8444.70000001,
'Low': 8444.69999999,
'Sell': 8444.70000001,
'Buy': 8444.69999999,
'Last': 8444.7,
'Volume': 78.6273,
'OpenInterest': 0.0}quarterTicker2.Sell - spotTicker2.Buy # 期货空头仓位平仓,现货多头仓位平仓的差价
52.5000200100003
exchanges[0].SetDirection("closesell") # 设置期货交易所当前交易方向为平空仓
quarterId2 = exchanges[0].Buy(quarterTicker2.Sell, 10) # 期货交易所下单平仓,并且记录下单ID,记录到变量quarterId2
exchanges[0].GetOrder(quarterId2) # 查询期货平仓订单详情{'Id': 2,
'Price': 8497.20002,
'Amount': 10.0,
'DealAmount': 10.0,
'AvgPrice': 8493.95335,
'Type': 0,
'Offset': 1,
'Status': 1,
'ContractType': b'quarter'}spotId2 = exchanges[1].Sell(spotTicker2.Buy, spotAmount) # 现货交易所下单平仓,并且记录下单ID,记录到变量spotId2 exchanges[1].GetOrder(spotId2) # 查询现货平仓订单详情
{'Id': 2,
'Price': 8444.69999999,
'Amount': 0.0957,
'DealAmount': 0.0957,
'AvgPrice': 8444.69999999,
'Type': 1,
'Offset': 0,
'Status': 1,
'ContractType': b'BTC_USDT_OKEX'}nowQuarterAcc = exchanges[0].GetAccount() # 获取当前期货交易所账户信息,记录在变量nowQuarterAcc nowQuarterAcc
{'Balance': 0.0,
'FrozenBalance': 0.0,
'Stocks': 1.021786026184,
'FrozenStocks': 0.0}nowSpotAcc = exchanges[1].GetAccount() # 获取当前现货交易所账户信息,记录在变量nowSpotAcc nowSpotAcc
{'Balance': 9834.74705446,
'FrozenBalance': 0.0,
'Stocks': 0.0,
'FrozenStocks': 0.0}通过对比最初账户和当前账户,计算出此次对冲操作的收益盈亏。
diffStocks = abs(nowQuarterAcc.Stocks - initQuarterAcc.Stocks)
diffBalance = nowSpotAcc.Balance - initSpotAcc.Balance
if nowQuarterAcc.Stocks - initQuarterAcc.Stocks > 0 :
print("收益:", diffStocks * spotTicker2.Buy + diffBalance)
else :
print("收益:", diffBalance - diffStocks * spotTicker2.Buy)收益: 18.72350977580652
下面我们看下为什么此次对冲是盈利的。我们可以看到画出的图表,期货价格是蓝色的线,现货价格是橙色的线,两个价格都是下降的,期货价格下降的比现货价格快。
xQuarter = [1, 2] yQuarter = [quarterTicker1.Buy, quarterTicker2.Sell] xSpot = [1, 2] ySpot = [spotTicker1.Sell, spotTicker2.Buy] plt.plot(xQuarter, yQuarter, linewidth=5) plt.plot(xSpot, ySpot, linewidth=5) plt.show()
<Figure size 432x288 with 1 Axes>
我们再看下差价的变化情况,差价是从对冲开仓时的284(即期货做空,现货最多),到平仓时的52(期货空头持仓平仓,现货多仓平仓)。差价是从大到小。
xDiff = [1, 2] yDiff = [quarterTicker1.Buy - spotTicker1.Sell, quarterTicker2.Sell - spotTicker2.Buy] plt.plot(xDiff, yDiff, linewidth=5) plt.show()
<Figure size 432x288 with 1 Axes>
我们举个例子,a1为时刻1的期货价格,b1为时刻1的现货价格。a2为时刻2的期货价格,b2为时刻2的现货价格。
只要a1-b1即时刻1的期货现货差价大于a2-b2即时刻2时的期货现货差价,就可以推出a1 - a2 > b1 - b2。 有三种情况:(期货现货持仓头寸规模相同)
1、a1 - a2大于0,b1 - b2大于0 a1 - a2为期货盈利的差价,b1 - b2为现货亏损的差价(因为现货做多,开始买入的价格比卖出平仓的价格高,所以亏钱),但是期货盈利的大于现货亏损的。所以整体是盈利。这种情况对应的就是步骤In[8]中的图表情况。
2、a1 - a2大于0,b1 - b2小于0 a1 - a2为期货盈利的差价,b1 - b2为现货盈利的差价(b1 - b2 小于0,说明b2大于b1,即开仓买入的价格低,卖出平仓的价格高,所以盈利)
3、a1 - a2小于0,b1 - b2小于0 a1 - a2为期货亏损的差价,b1 - b2为现货盈利的差价由于a1 - a2 > b1 - b2,a1 - a2的绝对值小于b1 - b2的绝对值,现货的盈利大于期货的亏损。整体为盈利。
不存在 a1 - a2小于0,b1 - b2大于0这种情况,因为已经限定了a1 - a2 > b1 - b2。同样如果a1 - a2等于0,由于a1 - a2 > b1 - b2限定,b1 - b2就一定是小于0的。所以只要是期货做空,现货做多的对冲方式,符合条件a1 - b1 > a2 - b2,的开仓平仓操作,即为盈利对冲。
例如以下模型为其中一种情况:
a1 = 10 b1 = 5 a2 = 11 b2 = 9 # a1 - b1 > a2 - b2 推出 : a1 - a2 > b1 - b2 xA = [1, 2] yA = [a1, a2] xB = [1, 2] yB = [b1, b2] plt.plot(xA, yA, linewidth=5) plt.plot(xB, yB, linewidth=5) plt.show()
<Figure size 432x288 with 1 Axes>
研究環境はPythonだけでなくJavaScriptもサポートしています 以下に、JavaScript 研究環境の例も示します。
// 导入需要的程序包, 在发明者 "策略编辑页面" 点击 "保存回测设置" 即可获取字符串配置, 转换为对象即可
var fmz = require("fmz") // 引入后自动导入 talib, TA, plot 库
var task = fmz.VCtx({
start: '2019-09-19 00:00:00',
end: '2019-09-28 12:00:00',
period: '15m',
exchanges: [{"eid":"Futures_OKCoin","currency":"BTC_USD","stocks":1},{"eid":"OKEX","currency":"BTC_USDT","balance":10000,"stocks":0}]
})exchanges[0].SetContractType("quarter") // 第一个交易所对象OKEX期货(eid:Futures_OKCoin)调用设置当前合约的函数,设置为季度合约
var initQuarterAcc = exchanges[0].GetAccount() // OKEX期货交易所初始时的账户信息,记录在变量initQuarterAcc
initQuarterAcc{ Balance: 0, FrozenBalance: 0, Stocks: 1, FrozenStocks: 0 }var initSpotAcc = exchanges[1].GetAccount() // OKEX现货交易所初始时的账户信息,记录在变量initSpotAcc initSpotAcc
{ Balance: 10000, FrozenBalance: 0, Stocks: 0, FrozenStocks: 0 }var quarterTicker1 = exchanges[0].GetTicker() // 获取期货交易所行情,记录在变量quarterTicker1 quarterTicker1
{ Time: 1568851210000,
High: 10441.25002,
Low: 10441.25,
Sell: 10441.25002,
Buy: 10441.25,
Last: 10441.25001,
Volume: 1772,
OpenInterest: 0 }var spotTicker1 = exchanges[1].GetTicker() // 获取现货交易所行情,记录在变量spotTicker1 spotTicker1
{ Time: 1568851210000,
High: 10156.60000002,
Low: 10156.6,
Sell: 10156.60000002,
Buy: 10156.6,
Last: 10156.60000001,
Volume: 7.4443,
OpenInterest: 0 }quarterTicker1.Buy - spotTicker1.Sell // 期货做空,现货做多的差价
284.64999997999985
exchanges[0].SetDirection("sell") // 设置期货交易所,交易方向为做空
var quarterId1 = exchanges[0].Sell(quarterTicker1.Buy, 10) // 期货做空下单,下单量为10张合约,返回的订单ID记录在变量quarterId1
exchanges[0].GetOrder(quarterId1) // 查询期货订单ID为quarterId1的订单详情{ Id: 1,
Price: 10441.25,
Amount: 10,
DealAmount: 10,
AvgPrice: 10441.25,
Type: 1,
Offset: 0,
Status: 1,
ContractType: 'quarter' }var spotAmount = 10 * 100 / quarterTicker1.Buy // 计算10张合约等值的币数,作为现货的下单量 var spotId1 = exchanges[1].Buy(spotTicker1.Sell, spotAmount) // 现货交易所下单 exchanges[1].GetOrder(spotId1) // 查询现货订单ID为spotId1的订单详情
{ Id: 1,
Price: 10156.60000002,
Amount: 0.0957,
DealAmount: 0.0957,
AvgPrice: 10156.60000002,
Type: 0,
Offset: 0,
Status: 1,
ContractType: 'BTC_USDT_OKEX' }可以看到订单quarterId1、spotId1订单都完全成交,即对冲开仓完成。
Sleep(1000 * 60 * 60 * 24 * 7) // 持仓一段时间,等待差价变小平仓。
等待时间过后,准备平仓。获取当前的行情
quarterTicker2、spotTicker2并且打印。 期货交易所对象的交易方向设置为平空仓:exchanges[0].SetDirection("closesell")下单平仓。 打印平仓订单的详情,显示平仓订单完全成交,平仓完成。
var quarterTicker2 = exchanges[0].GetTicker() // 获取当前期货交易所的行情,记录在变量quarterTicker2 quarterTicker2
{ Time: 1569456010000,
High: 8497.20002,
Low: 8497.2,
Sell: 8497.20002,
Buy: 8497.2,
Last: 8497.20001,
Volume: 4311,
OpenInterest: 0 }var spotTicker2 = exchanges[1].GetTicker() // 获取当前现货交易所的行情,记录在变量spotTicker2 spotTicker2
{ Time: 1569456114600,
High: 8444.70000001,
Low: 8444.69999999,
Sell: 8444.70000001,
Buy: 8444.69999999,
Last: 8444.7,
Volume: 78.6273,
OpenInterest: 0 }quarterTicker2.Sell - spotTicker2.Buy // 期货空头仓位平仓,现货多头仓位平仓的差价
52.5000200100003
exchanges[0].SetDirection("closesell") // 设置期货交易所当前交易方向为平空仓
var quarterId2 = exchanges[0].Buy(quarterTicker2.Sell, 10) // 期货交易所下单平仓,并且记录下单ID,记录到变量quarterId2
exchanges[0].GetOrder(quarterId2) // 查询期货平仓订单详情{ Id: 2,
Price: 8497.20002,
Amount: 10,
DealAmount: 10,
AvgPrice: 8493.95335,
Type: 0,
Offset: 1,
Status: 1,
ContractType: 'quarter' }var spotId2 = exchanges[1].Sell(spotTicker2.Buy, spotAmount) // 现货交易所下单平仓,并且记录下单ID,记录到变量spotId2 exchanges[1].GetOrder(spotId2) // 查询现货平仓订单详情
{ Id: 2,
Price: 8444.69999999,
Amount: 0.0957,
DealAmount: 0.0957,
AvgPrice: 8444.69999999,
Type: 1,
Offset: 0,
Status: 1,
ContractType: 'BTC_USDT_OKEX' }var nowQuarterAcc = exchanges[0].GetAccount() // 获取当前期货交易所账户信息,记录在变量nowQuarterAcc nowQuarterAcc
{ Balance: 0,
FrozenBalance: 0,
Stocks: 1.021786026184,
FrozenStocks: 0 }var nowSpotAcc = exchanges[1].GetAccount() // 获取当前现货交易所账户信息,记录在变量nowSpotAcc nowSpotAcc
{ Balance: 9834.74705446,
FrozenBalance: 0,
Stocks: 0,
FrozenStocks: 0 }通过对比最初账户和当前账户,计算出此次对冲操作的收益盈亏。
var diffStocks = Math.abs(nowQuarterAcc.Stocks - initQuarterAcc.Stocks)
var diffBalance = nowSpotAcc.Balance - initSpotAcc.Balance
if (nowQuarterAcc.Stocks - initQuarterAcc.Stocks > 0) {
console.log("收益:", diffStocks * spotTicker2.Buy + diffBalance)
} else {
console.log("收益:", diffBalance - diffStocks * spotTicker2.Buy)
}收益: 18.72350977580652
下面我们看下为什么此次对冲是盈利的。我们可以看到画出的图表,期货价格是蓝色的线,现货价格是橙色的线,两个价格都是下降的,期货价格下降的比现货价格快。
var objQuarter = {
"index" : [1, 2], // 索引index 为1 即第一个时刻,开仓时刻,2为平仓时刻。
"arrPrice" : [quarterTicker1.Buy, quarterTicker2.Sell],
}
var objSpot = {
"index" : [1, 2],
"arrPrice" : [spotTicker1.Sell, spotTicker2.Buy],
}
plot([{name: 'quarter', x: objQuarter.index, y: objQuarter.arrPrice}, {name: 'spot', x: objSpot.index, y: objSpot.arrPrice}])我们再看下差价的变化情况,差价是从对冲开仓时的284(即期货做空,现货最多),到平仓时的52(期货空头持仓平仓,现货多仓平仓)。差价是从大到小。
var arrDiffPrice = [quarterTicker1.Buy - spotTicker1.Sell, quarterTicker2.Sell - spotTicker2.Buy] plot(arrDiffPrice)
我们举个例子,a1为时刻1的期货价格,b1为时刻1的现货价格。a2为时刻2的期货价格,b2为时刻2的现货价格。
只要a1-b1即时刻1的期货现货差价大于a2-b2即时刻2时的期货现货差价,就可以推出a1 - a2 > b1 - b2。 有三种情况:(期货现货持仓头寸规模相同)
1、a1 - a2大于0,b1 - b2大于0 a1 - a2为期货盈利的差价,b1 - b2为现货亏损的差价(因为现货做多,开始买入的价格比卖出平仓的价格高,所以亏钱),但是期货盈利的大于现货亏损的。所以整体是盈利。这种情况对应的就是步骤In[8]中的图表情况。
2、a1 - a2大于0,b1 - b2小于0 a1 - a2为期货盈利的差价,b1 - b2为现货盈利的差价(b1 - b2 小于0,说明b2大于b1,即开仓买入的价格低,卖出平仓的价格高,所以盈利)
3、a1 - a2小于0,b1 - b2小于0 a1 - a2为期货亏损的差价,b1 - b2为现货盈利的差价由于a1 - a2 > b1 - b2,a1 - a2的绝对值小于b1 - b2的绝对值,现货的盈利大于期货的亏损。整体为盈利。
不存在 a1 - a2小于0,b1 - b2大于0这种情况,因为已经限定了a1 - a2 > b1 - b2。同样如果a1 - a2等于0,由于a1 - a2 > b1 - b2限定,b1 - b2就一定是小于0的。所以只要是期货做空,现货做多的对冲方式,符合条件a1 - b1 > a2 - b2,的开仓平仓操作,即为盈利对冲。
例如以下模型为其中一种情况:
var a1 = 10
var b1 = 5
var a2 = 11
var b2 = 9
// a1 - b1 > a2 - b2 推出 : a1 - a2 > b1 - b2
var objA = {
"index" : [1, 2],
"arrPrice" : [a1, a2],
}
var objB = {
"index" : [1, 2],
"arrPrice" : [b1, b2],
}
plot([{name : "a", x : objA.index, y : objA.arrPrice}, {name : "b", x : objB.index, y : objB.arrPrice}])みなさん、急いで試してみてください!