Introducing FMZ Quant data science research environment
Tags: fmzquant, cryptocurrency, trading, data
Published: 2024-06-11 07:51:35

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:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vail8abwy077oxnvsprk.png)

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 OKX and the contract is quarterly contract; The spots side exchange is OKX 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 the principle of futures-cash hedging.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":"OKX","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 OKX 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 OKX 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]:
Revenue: 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]:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ugvez9vzm10vxpt0m0i7.png)

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]:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3xp18u2hmvo7bxerewvt.png)

**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]:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iyryoeaqhx5scicywymz.png)
 
## 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:
 
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 OKX 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 OKX 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 has passed, prepare to close the position. Get the current market price quarterTicker2and spotTicker2print it.
The trading direction of the futures exchange object is set to close short position: exchanges[0].SetDirection("closesell")place an order to close the position.
Print the details of the closing order, showing that the closing order is fully filled and the closing is completed.

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

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]:
Revenue: 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]:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cbm2wy354rifueyjo5it.png)

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]:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6sh6cbnwofpiogxx4sam.png)

**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]:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wtj94fxgngo9o8ghqjd9.png)

From: https://blog.mathquant.com/2023/03/17/introducing-fmz-quant-data-science-research-environment.html