The term “hedging” in quantitative trading and programmatic trading is a very basic concept. In cryptocurrency quantitative trading, the typical hedging strategies are: Spots-Futures hedging, intertemporal hedging and individual spot hedging.

Most of hedging tradings are based on the price difference of two trading varieties. The concept, principle and details of hedging trading may not very clear to traders who have just entered the field of quantitative trading. That's ok, Let's use the “Data science research environment” tool provided by the FMZ Quant platform to master these knowledge.

On FMZ Quant website Dashboard page, click on "Research" to jump to the page of this tool:

Here I uploaded this analysis file directly:

This analysis file is an analysis of the process of the opening and closing positions in a Spots-Futures hedging trading. The futures side exchange is OKEX and the contract is quarterly contract; The spots side exchange is OKEX spots trading. The transaction pair is BTC_USDT, The following specific analysis environment file, contains two version of it, both Python and JavaScript.

# Research Environment Python Language File

Analysis of futures and spot hedging principles.ipynbDownload

In [1]:

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}] ''') # Create a backtest environment import matplotlib.pyplot as plt import numpy as np # Imported drawing library matplotlib and numpy library

In [2]:

exchanges[0].SetContractType("quarter") # The first exchange object OKEX futures (eid: Futures_OKCoin) calls the function that sets the current contract, set to the quarterly contract initQuarterAcc = exchanges[0].GetAccount() # Account information at the OKEX Futures Exchange, recorded in the variable initQuarterAcc initQuarterAcc

Out[2]:

{'Balance': 0.0, 'FrozenBalance': 0.0, 'Stocks': 1.0, 'FrozenStocks': 0.0}

In [3]:

initSpotAcc = exchanges[1].GetAccount() # Account information at the OKEX spot exchange, recorded in the variable initSpotAcc initSpotAcc

Out[3]:

{'Balance': 10000.0, 'FrozenBalance': 0.0, 'Stocks': 0.0, 'FrozenStocks': 0.0}

In [4]:

quarterTicker1 = exchanges[0].GetTicker() # Get the futures exchange market quotes, recorded in the variable quarterTicker1 quarterTicker1

Out[4]:

{'Time': 1568851210000, 'High': 10441.25002, 'Low': 10441.25, 'Sell': 10441.25002, 'Buy': 10441.25, 'Last': 10441.25001, 'Volume': 1772.0, 'OpenInterest': 0.0}

In [5]:

spotTicker1 = exchanges[1].GetTicker() # Get the spot exchange market quotes, recorded in the variable spotTicker1 spotTicker1

Out[5]:

{'Time': 1568851210000, 'High': 10156.60000002, 'Low': 10156.6, 'Sell': 10156.60000002, 'Buy': 10156.6, 'Last': 10156.60000001, 'Volume': 7.4443, 'OpenInterest': 0.0}

In [6]:

quarterTicker1.Buy - spotTicker1.Sell # The price difference between Short selling futures and Buying long spots

Out[6]:

284.64999997999985

In [7]:

exchanges[0].SetDirection("sell") # Set up the futures exchange, the trading direction is short quarterId1 = exchanges[0].Sell(quarterTicker1.Buy, 10) # The futures are short-selled, the order quantity is 10 contracts, and the returned order ID is recorded in the variable quarterId1. exchanges[0].GetOrder(quarterId1) # Query the order details of the futures order ID is quarterId1

Out[7]:

{'Id': 1, 'Price': 10441.25, 'Amount': 10.0, 'DealAmount': 10.0, 'AvgPrice': 10441.25, 'Type': 1, 'Offset': 0, 'Status': 1, 'ContractType': b'quarter'}

In [8]:

spotAmount = 10 * 100 / quarterTicker1.Buy # Calculate the number of cryptocurrency equivalent to 10 contracts, as the spots amount of the order placed spotId1 = exchanges[1].Buy(spotTicker1.Sell, spotAmount) # Spot exchange placing order exchanges[1].GetOrder(spotId1) # Query the order details of the spot order ID as spotId1

Out[8]:

{'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'}

It can be seen that the orders of the order quarterId1 and the spotId1 are all completely filled, that is, the opening position of the hedge is completed.

In [9]:

Sleep(1000 * 60 * 60 * 24 * 7) # Hold the position for a while, wait for the difference to become smaller and close the position.

After the waiting time has elapsed, prepare to close the position. Get the current quotes `quarterTicker2`

, `spotTicker2`

and print. The trading direction of the futures exchange object is set to close short positions: `exchanges[0].SetDirection("closesell")`

to close the position. Print the details of the closing positions, showing that the closing position is completely done.

In [10]:

quarterTicker2 = exchanges[0].GetTicker() # Get the current market quotes of the futures exchange, recorded in the variable quarterTicker2 quarterTicker2

Out[10]:

{'Time': 1569456010000, 'High': 8497.20002, 'Low': 8497.2, 'Sell': 8497.20002, 'Buy': 8497.2, 'Last': 8497.20001, 'Volume': 4311.0, 'OpenInterest': 0.0}

In [11]:

spotTicker2 = exchanges[1].GetTicker() # Get the current spot exchange market quotes, recorded in the variable spotTicker2 spotTicker2

Out[11]:

{'Time': 1569456114600, 'High': 8444.70000001, 'Low': 8444.69999999, 'Sell': 8444.70000001, 'Buy': 8444.69999999, 'Last': 8444.7, 'Volume': 78.6273, 'OpenInterest': 0.0}

In [12]:

quarterTicker2.Sell - spotTicker2.Buy # The price difference of closing position between Short position of futures and the Long position of spot

Out[12]:

52.5000200100003

In [13]:

exchanges[0].SetDirection("closesell") # Set the current trading direction of the futures exchange to close short position quarterId2 = exchanges[0].Buy(quarterTicker2.Sell, 10) # The futures exchange closing positions, and records the order ID, recorded to the variable quarterId2 exchanges[0].GetOrder(quarterId2) # Query futures closing position orders detail

Out[13]:

{'Id': 2, 'Price': 8497.20002, 'Amount': 10.0, 'DealAmount': 10.0, 'AvgPrice': 8493.95335, 'Type': 0, 'Offset': 1, 'Status': 1, 'ContractType': b'quarter'}

In [14]:

spotId2 = exchanges[1].Sell(spotTicker2.Buy, spotAmount) # The spot exchange place order to closing positions, and records the order ID, recorded to the variable spotId2 exchanges[1].GetOrder(spotId2) # Query spots closing order details

Out[14]:

{'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'}

In [15]:

nowQuarterAcc = exchanges[0].GetAccount() # Get current futures exchange account information, recorded in the variable nowQuarterAcc nowQuarterAcc

Out[15]:

{'Balance': 0.0, 'FrozenBalance': 0.0, 'Stocks': 1.021786026184, 'FrozenStocks': 0.0}

In [16]:

nowSpotAcc = exchanges[1].GetAccount() # Get current spot exchange account information, recorded in the variable nowSpotAcc nowSpotAcc

Out[16]:

{'Balance': 9834.74705446, 'FrozenBalance': 0.0, 'Stocks': 0.0, 'FrozenStocks': 0.0}

Calculate the profit and loss of this hedging operation by comparing the initial account with the current account.

In [17]:

diffStocks = abs(nowQuarterAcc.Stocks - initQuarterAcc.Stocks) diffBalance = nowSpotAcc.Balance - initSpotAcc.Balance if nowQuarterAcc.Stocks - initQuarterAcc.Stocks > 0 : print("profit：", diffStocks * spotTicker2.Buy + diffBalance) else : print("profit：", diffBalance - diffStocks * spotTicker2.Buy)

Out[17]:

收益： 18.72350977580652

Below we look at why the hedge is profitable. We can see the chart drawn, the futures price is the blue line, the spot price is the orange line, both prices are falling, and the futures price is falling faster than the spot price.

In [18]:

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()

Out[18]:

Let us look at the changes in the price difference. The difference is 284 when the hedge is opened (that is, shorting the futures, longing the spot), reaching 52 when the position is closed (the futures short positions are closed, and the spot long positions are closed). The difference is from big to small.

In [19]:

xDiff = [1, 2] yDiff = [quarterTicker1.Buy - spotTicker1.Sell, quarterTicker2.Sell - spotTicker2.Buy] plt.plot(xDiff, yDiff, linewidth=5) plt.show()

Out[19]:

## Let me give an example, a1 is the futures price of time 1, and b1 is the spot price of time 1. A2 is the futures price at time 2, and b2 is the spot price at time 2.

As long as a1-b1, that is, the futures-spot price difference of time 1 is greater than the futures-spot price difference of a2-b2 of time 2, a1 - a2 > b1 - b2 can be introduced. There are three cases: (the futures-spot holding position are the same size)

- a1 - a2 is greater than 0, b1 - b2 is greater than 0, a1 - a2 is the difference in futures profit, b1 - b2 is the difference in spot loss (because the spot is long position, the price of opening position is higher than the price of closing position, therefore, the position loses money), but the futures profit is greater than the spot loss. So the overall trading operation is profitable. This case corresponds to the chart in step
`In[8]`

. - a1 - a2 is greater than 0, b1 - b2 is less than 0, a1 - a2 is the difference of futures profit, b1 - b2 is the difference of spot profit (b1 - b2 is less than 0, indicating that b2 is greater than b1, that is, the price of opening the position is low, the price of selling the position is high, so the position make profit)
- a1 - a2 is less than 0, b1 - b2 is less than 0, a1 - a2 is the difference of futures losses, b1 - b2 is the difference of spot profit due to a1 - a2 > b1 - b2, the absolute value of a1 - a2 is less than b1 - b2 Absolute value, the profit of the spot is greater than the loss of the futures. So the overall trading operation is profitable.

There is no case where a1 - a2 is less than 0 and b1 - b2 is greater than 0, because a1 - a2 > b1 - b2 have been defined. Similarly, if a1 - a2 is equal to 0, since a1 - a2 > b1 - b2 is defined, b1 - b2 must be less than 0. Therefore, as long as the futures are short position and the spot are long position in a long-term hedging method, which meets the conditions a1 - b1 > a2 - b2, the opening and closing position operation is the profit hedging.

For example, the following model is one of the cases:

In [20]:

a1 = 10 b1 = 5 a2 = 11 b2 = 9 if a1 - b1 > a2 - b2: print(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()

Out[20]:

True

In [ ]:

# Research Environment JavaScript Language File

Research environment not only supports Python, but also supports JavaScript

Below I also give an example of a JavaScript research environment:

JS版.ipynbDownload

In [1]:

// Import the required package, click "Save Backtest Settings" on the FMZ Quant "Strategy Editing Page" to get the string configuration and convert it to an object. var fmz = require("fmz") // Automatically import talib, TA, plot library after import 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}] })

In [2]:

exchanges[0].SetContractType("quarter") // The first exchange object OKEX futures (eid: Futures_OKCoin) calls the function that sets the current contract, set to the quarterly contract var initQuarterAcc = exchanges[0].GetAccount() // Account information at the OKEX Futures Exchange, recorded in the variable initQuarterAcc initQuarterAcc

Out[2]:

{ Balance: 0, FrozenBalance: 0, Stocks: 1, FrozenStocks: 0 }

In [3]:

var initSpotAcc = exchanges[1].GetAccount() // Account information at the OKEX spot exchange, recorded in the variable initSpotAcc initSpotAcc

Out[3]:

{ Balance: 10000, FrozenBalance: 0, Stocks: 0, FrozenStocks: 0 }

In [4]:

var quarterTicker1 = exchanges[0].GetTicker() // Get the futures exchange market quotes, recorded in the variable quarterTicker1 quarterTicker1

Out[4]:

{ Time: 1568851210000, High: 10441.25002, Low: 10441.25, Sell: 10441.25002, Buy: 10441.25, Last: 10441.25001, Volume: 1772, OpenInterest: 0 }

In [5]:

var spotTicker1 = exchanges[1].GetTicker() // Get the spot exchange market quotes, recorded in the variable spotTicker1 spotTicker1

Out[5]:

{ Time: 1568851210000, High: 10156.60000002, Low: 10156.6, Sell: 10156.60000002, Buy: 10156.6, Last: 10156.60000001, Volume: 7.4443, OpenInterest: 0 }

In [6]:

quarterTicker1.Buy - spotTicker1.Sell // the price difference between Short selling futures and long buying spot

Out[6]:

284.64999997999985

In [7]:

exchanges[0].SetDirection("sell") // Set up the futures exchange, the trading direction is shorting var quarterId1 = exchanges[0].Sell(quarterTicker1.Buy, 10) // The futures are short-selled, the order quantity is 10 contracts, and the returned order ID is recorded in the variable quarterId1. exchanges[0].GetOrder(quarterId1) // Query the order details of the futures order ID is quarterId1

Out[7]:

{ Id: 1, Price: 10441.25, Amount: 10, DealAmount: 10, AvgPrice: 10441.25, Type: 1, Offset: 0, Status: 1, ContractType: 'quarter' }

In [8]:

var spotAmount = 10 * 100 / quarterTicker1.Buy // Calculate the number of cryptocurrency equivalent to 10 contracts, as the amount of the order placed var spotId1 = exchanges[1].Buy(spotTicker1.Sell, spotAmount) // Spot exchange placing order exchanges[1].GetOrder(spotId1) // Query the order details of the spot order ID as spotId1

Out[8]:

{ Id: 1, Price: 10156.60000002, Amount: 0.0957, DealAmount: 0.0957, AvgPrice: 10156.60000002, Type: 0, Offset: 0, Status: 1, ContractType: 'BTC_USDT_OKEX' }

It can be seen that the orders of the order quarterId1 and the spotId1 are all completely filled, that is, the opening of the hedge is completed.

In [9]:

Sleep(1000 * 60 * 60 * 24 * 7) // Hold the position for a while, wait for the difference to become smaller and close the position.

After the waiting time, prepare to close the position. Get the current quotation quarterTicker2, spotTicker2 and print it.

Set the direction of the futures exchange object to close the short position: exchanges[0].SetDirection("closesell") to place the order to close the position.

The details of the closed order are printed, showing that the closed order is fully filled and the position is closed.

In [10]:

var quarterTicker2 = exchanges[0].GetTicker() // Get the current market quote of the futures exchange, recorded in the variable quarterTicker2 quarterTicker2

Out[10]:

{ Time: 1569456010000, High: 8497.20002, Low: 8497.2, Sell: 8497.20002, Buy: 8497.2, Last: 8497.20001, Volume: 4311, OpenInterest: 0 }

In [11]:

var spotTicker2 = exchanges[1].GetTicker() // Get the current spot exchange market quotes, recorded in the variable spotTicker2 spotTicker2

Out[11]:

{ Time: 1569456114600, High: 8444.70000001, Low: 8444.69999999, Sell: 8444.70000001, Buy: 8444.69999999, Last: 8444.7, Volume: 78.6273, OpenInterest: 0 }

In [12]:

quarterTicker2.Sell - spotTicker2.Buy // the price difference between the short position of futures and the long position of spot

Out[12]:

52.5000200100003

In [13]:

exchanges[0].SetDirection("closesell") // Set the current trading direction of the futures exchange to close short position var quarterId2 = exchanges[0].Buy(quarterTicker2.Sell, 10) // The futures exchange place orders to close position, and records the order ID, recorded to the variable quarterId2 exchanges[0].GetOrder(quarterId2) // Query futures closing position order details

Out[13]:

{ Id: 2, Price: 8497.20002, Amount: 10, DealAmount: 10, AvgPrice: 8493.95335, Type: 0, Offset: 1, Status: 1, ContractType: 'quarter' }

In [14]:

var spotId2 = exchanges[1].Sell(spotTicker2.Buy, spotAmount) // The spot exchange place orders to close position, and records the order ID, recorded to the variable spotId2 exchanges[1].GetOrder(spotId2) // Query spot closing position order details

Out[14]:

{ Id: 2, Price: 8444.69999999, Amount: 0.0957, DealAmount: 0.0957, AvgPrice: 8444.69999999, Type: 1, Offset: 0, Status: 1, ContractType: 'BTC_USDT_OKEX' }

In [15]:

var nowQuarterAcc = exchanges[0].GetAccount() // Get current futures exchange account information, recorded in the variable nowQuarterAcc nowQuarterAcc

Out[15]:

{ Balance: 0, FrozenBalance: 0, Stocks: 1.021786026184, FrozenStocks: 0 }

In [16]:

var nowSpotAcc = exchanges[1].GetAccount() // Get current spot exchange account information, recorded in the variable nowSpotAcc nowSpotAcc

Out[16]:

{ Balance: 9834.74705446, FrozenBalance: 0, Stocks: 0, FrozenStocks: 0 }

Calculate the profit and loss of this hedging operation by comparing the initial account with the current account.

In [17]:

var diffStocks = Math.abs(nowQuarterAcc.Stocks - initQuarterAcc.Stocks) var diffBalance = nowSpotAcc.Balance - initSpotAcc.Balance if (nowQuarterAcc.Stocks - initQuarterAcc.Stocks > 0) { console.log("profit：", diffStocks * spotTicker2.Buy + diffBalance) } else { console.log("profit：", diffBalance - diffStocks * spotTicker2.Buy) }

Out[17]:

收益： 18.72350977580652

Below we look at why the hedge is profitable. We can see the chart drawn, the futures price is the blue line, the spot price is the orange line, both prices are falling, and the futures price is falling faster than the spot price.

In [18]:

var objQuarter = { "index" : [1, 2], // The index 1 for the first moment, the opening position time, and 2 for the closing position time. "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}])

Out[18]:

Let us look at the changes in the price difference. The difference is 284 when the hedge is opened (that is, shorting the futures, longing the spot), reaching 52 when the position is closed (the futures short positions are closed, and the spot long positions are closed). The difference is from big to small.

In [19]:

var arrDiffPrice = [quarterTicker1.Buy - spotTicker1.Sell, quarterTicker2.Sell - spotTicker2.Buy] plot(arrDiffPrice)

Out[19]:

## Let me give an example, a1 is the futures price of time 1, and b1 is the spot price of time 1. A2 is the futures price at time 2, and b2 is the spot price at time 2.

As long as a1-b1, that is, the futures-spot price difference of time 1 is greater than the futures-spot price difference of a2-b2 of time 2, a1 - a2 > b1 - b2 can be introduced. There are three cases: (the futures-spot holding position are the same size)

- a1 - a2 is greater than 0, b1 - b2 is greater than 0, a1 - a2 is the difference in futures profit, b1 - b2 is the difference in spot loss (because the spot is long position, the price of opening position is higher than the price of closing position, therefore, the position loses money), but the futures profit is greater than the spot loss. So the overall trading operation is profitable. This case corresponds to the chart in step
`In[8]`

. - a1 - a2 is greater than 0, b1 - b2 is less than 0, a1 - a2 is the difference of futures profit, b1 - b2 is the difference of spot profit (b1 - b2 is less than 0, indicating that b2 is greater than b1, that is, the price of opening the position is low, the price of selling the position is high, so the position make profit)
- a1 - a2 is less than 0, b1 - b2 is less than 0, a1 - a2 is the difference of futures losses, b1 - b2 is the difference of spot profit due to a1 - a2 > b1 - b2, the absolute value of a1 - a2 is less than b1 - b2 Absolute value, the profit of the spot is greater than the loss of the futures. So the overall trading operation is profitable.

There is no case where a1 - a2 is less than 0 and b1 - b2 is greater than 0, because a1 - a2 > b1 - b2 have been defined. Similarly, if a1 - a2 is equal to 0, since a1 - a2 > b1 - b2 is defined, b1 - b2 must be less than 0. Therefore, as long as the futures are short position and the spot are long position in a long-term hedging method, which meets the conditions a1 - b1 > a2 - b2, the opening and closing position operation is the profit hedging.

For example, the following model is one of the cases:

In [20]:

var a1 = 10 var b1 = 5 var a2 = 11 var b2 = 9 // a1 - b1 > a2 - b2 get ： 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}])

Out[20]: