Le terme "hedging" est un concept très basique dans le domaine du trading quantitatif et du trading de programme. Dans le trading quantitatif de la monnaie numérique, les stratégies de couverture souvent utilisées sont: la couverture à spot à terme, la couverture à travers la période et la couverture au spot, qui sont essentiellement des transactions pour les différences de prix. Peut-être que lorsqu'il s'agit du concept, du principe et des détails de la couverture, de nombreux étudiants qui viennent d'entrer dans le domaine du trading quantitatif ne sont toujours pas très clairs. Peu importe.
Dans le tableau de bord de la plateforme FMZ Quant, cliquez sur
Ici je télécharge le fichier d'analyse directement:
Ce document d'analyse est une analyse du processus d'ouverture et de clôture d'une position de couverture à spot à terme pendant le backtesting.quarter
Le marché au comptant est une transaction OKX monnaie-monnaie, et la paire de négociation estBTC_USDT
. Pour analyser le processus de fonctionnement de la couverture des contrats à terme, vous pouvez voir le fichier d'environnement de recherche spécifique suivant, écrit en deux versions: une version Python, une version JavaScript.
Analyse du principe de la couverture au comptant.ipynb Dans [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 backtesting environment
import matplotlib.pyplot as plt
import numpy as np
# Import the plot library matplotlib and library numpy
Dans [2]:
exchanges[0].SetContractType("quarter") # The first exchange object OKX Futures (eid: Futures_OKCoin) calls the function to set the current contract as a quarterly contract
initQuarterAcc = exchanges[0].GetAccount() # The initial account information of OKX Futures Exchange is recorded in the variable initQuarterAcc
initQuarterAcc
Extrait [2]: Le taux de change de la valeur de l'actif de la banque est le taux de change de l'actif de la banque.
Dans [3]:
initSpotAcc = exchanges[1].GetAccount() # The initial account information of the OKX Spot Exchange is recorded in the variable initSpotAcc
initSpotAcc
À l'extérieur [3]: Le taux de change de la valeur de l'actif de l'entreprise est supérieur au taux de change de la valeur de l'actif de la société.
Dans [4]:
quarterTicker1 = exchanges[0].GetTicker() # Get the futures exchange ticker, recorded in the variable quarterTicker1
quarterTicker1
Extrait [4]:
Je suis désolée.
Dans [5]:
spotTicker1 = exchanges[1].GetTicker() # Get the spot exchange ticker, recorded in the variable spotTicker1
spotTicker1
Extrait [5]:
Je suis désolée.
Dans [6]:
quarterTicker1.Buy - spotTicker1.Sell # The price difference between going short on futures and going long on spot.
Extrait [6]: 284,64999997999985 Pour les produits de base
Dans [7]:
exchanges[0].SetDirection("sell") # Set up a futures exchange and trade in the direction of going short
quarterId1 = exchanges[0].Sell(quarterTicker1.Buy, 10) # Futures go short to place orders. The order quantity is 10 contracts. The returned order ID is recorded in the variable quarterId1.
exchanges[0].GetOrder(quarterId1) # Check the details of the order with futures order ID quarterId1.
À l'extérieur[7]:
Je ne sais pas.
Dans [8]:
spotAmount = 10 * 100 / quarterTicker1.Buy # Calculate the currency equivalent of 10 contracts as the order quantity of the spot.
spotId1 = exchanges[1].Buy(spotTicker1.Sell, spotAmount) # Place orders on the spot exchange
exchanges[1].GetOrder(spotId1) # Check the order details of the spot order ID of spotId1
À l'extérieur[8]:
Je ne sais pas.
Vous pouvez voir que les ordres trimestriels Id1 et les ordres spotId1 sont entièrement remplis, c'est-à-dire que la couverture des positions ouvertes est terminée.
Dans [9]:
Sleep(1000 * 60 * 60 * 24 * 7) # Hold the position for a while and wait for the price difference to become smaller to close the position.
Après le temps d'attente, préparez-vous à fermer la position.quarterTicker2
, spotTicker2
et les imprimer.
La direction de transaction de l'objet d'échange de contrats à terme est réglée pour fermer la position courte:exchanges[0].SetDirection("closesell")
placer un ordre de clôture de la position.
Imprimer les détails de l'ordre de clôture de position, indiquant que l'ordre de clôture a été exécuté, la position de clôture terminée.
Dans [10]:
quarterTicker2 = exchanges[0].GetTicker() # Get the current futures exchange ticker, recorded in the variable quarterTicker2
quarterTicker2
À l'extérieur [10]:
Je suis désolée.
Dans [11]:
spotTicker2 = exchanges[1].GetTicker() # Get the current ticker of the spot exchange, recorded in the variable spotTicker2
spotTicker2
Extrait [11]:
Je suis désolée.
Dans [12]:
quarterTicker2.Sell - spotTicker2.Buy # The price difference between closing a short futures position and closing a long spot position.
À l'extérieur [12]: 52 000 000 200 100 003
Dans [13]:
exchanges[0].SetDirection("closesell") # Set the current trading direction of the futures exchange to close short positions.
quarterId2 = exchanges[0].Buy(quarterTicker2.Sell, 10) # The futures exchange places an order to close a position and records the order ID to the variable quarterId2.
exchanges[0].GetOrder(quarterId2) # Check futures close out order details
À l'extérieur[13]:
Je ne sais pas.
Dans [14]:
spotId2 = exchanges[1].Sell(spotTicker2.Buy, spotAmount) # The spot exchange places an order to close a position and records the order ID, which is recorded to the variable spotId2.
exchanges[1].GetOrder(spotId2) # Check spot close out order details
Extrait [1]:
Je ne sais pas.
Dans [15]:
nowQuarterAcc = exchanges[0].GetAccount() # Get the current futures exchange account information, recorded in the variable nowQuarterAcc.
nowQuarterAcc
Extrait [1]:
{
Dans [16]:
nowSpotAcc = exchanges[1].GetAccount() # Get the current spot exchange account information, recorded in the variable nowSpotAcc.
nowSpotAcc
Extrait [1]:
Le solde est de 9834,74705446.
En comparant le compte initial avec le compte courant, le résultat de l'opération de couverture est calculé.
Dans [17]:
diffStocks = abs(nowQuarterAcc.Stocks - initQuarterAcc.Stocks)
diffBalance = nowSpotAcc.Balance - initSpotAcc.Balance
if nowQuarterAcc.Stocks - initQuarterAcc.Stocks > 0 :
print("profits:", diffStocks * spotTicker2.Buy + diffBalance)
else :
print("profits:", diffBalance - diffStocks * spotTicker2.Buy)
Extrait [1]: Les bénéfices: 18,72350977580652
Maintenant voyons pourquoi la couverture est rentable. Nous pouvons voir le graphique dessiné. Le prix des contrats à terme est une ligne bleue et le prix au comptant est une ligne orange. Les deux prix diminuent. Le prix des contrats à terme diminue plus vite que le prix au comptant.
Dans [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()
À l'extérieur [1]:
La différence de prix varie de 284 au moment de la couverture de la position d'ouverture (c'est-à-dire que les contrats à terme vont court et le spot va long) à 52 au moment de la fermeture de la position (position à terme courte fermée, position longue fermée).
Dans [19]:
xDiff = [1, 2]
yDiff = [quarterTicker1.Buy - spotTicker1.Sell, quarterTicker2.Sell - spotTicker2.Buy]
plt.plot(xDiff, yDiff, linewidth=5)
plt.show()
Extrait [1]:
Par exemple, a1 est le prix des contrats à terme au moment 1, et b1 est le prix au comptant au moment 1. A2 est le prix des contrats à terme au moment 2, et b2 est le prix au comptant au moment 2.Tant que l'écart de prix au comptant des contrats à terme au moment 1 (a1-b1) est supérieur à l'écart de prix au comptant des contrats à terme au moment 2 (a2-b2), a1 - a2>b1 - b2 peut être introduit. Il y a trois situations: (la quantité de futures et de positions au comptant est la même)
a1 - a2 est supérieur à 0, b1 - b2 est supérieur à 0 a1 - a2 se réfère à la différence de prix des profits futures, et b1 - b2 se réfère à la différence de prix des pertes au comptant (parce que le spot est allé long, le prix de début d'achat est plus élevé que le prix de vente pour fermer la position, donc l'argent est perdu), mais les profits à terme sont plus importants que les pertes au comptant.
a1 - a2 est supérieur à 0, b1 - b2 est inférieur à 0 a1 - a2 est la différence de prix des bénéfices à terme, et b1 - b2 est la différence de prix des bénéfices au comptant (b1 - b2 est inférieur à 0, ce qui indique que b2 est supérieur à b1, c'est-à-dire que le prix d'ouverture et d'achat de la position est faible, et le prix de vente et de clôture est élevé, il est donc rentable).
a1 - a2 inférieur à 0, b1 - b2 inférieur à 0 a1 - a2 est la différence de prix des pertes futures, et b1 - b2 est la différence de prix des profits au comptant. Puisque a1 - a2 > b1 - b2, la valeur absolue de a1 - a2 est inférieure à la valeur absolue de b1 - b2, et les profits au comptant sont plus importants que les pertes futures.
Il n'y a pas de cas où a1 - a2 est inférieur à 0 et b1 - b2 est supérieur à 0, car a1 - a2 > b1 - b2 a été défini. De même, si a1 - a2 est égal à 0, puisque a1 - a2 > b1 - b2 est défini, b1 - b2 doit être inférieur à 0. Par conséquent, tant que la méthode de couverture des contrats à terme courts et des contrats à terme longs répond aux conditions a1 - b1 > a2 - b2, les opérations d'ouverture et de clôture de position sont des opérations de couverture des bénéfices.
Par exemple, le modèle suivant est l'un des cas:
Dans [20]:
a1 = 10
b1 = 5
a2 = 11
b2 = 9
# a1 - b1 > a2 - b2 launches: 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()
Extrait [1]:
L'environnement de recherche prend en charge non seulement Python, mais aussi JavaScript Je donne aussi un exemple d'environnement de recherche JavaScript:
Analyse du principe de la couverture des contrats à terme au comptant (JavaScript).ipynb Dans [1]:
// Import the required package, click "Save settings" on the FMZ's "Strategy editing page" to get the string configuration and convert it to an object.
var fmz = require("fmz") // Import the talib, TA, and plot libraries automatically 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":"OKX","currency":"BTC_USDT","balance":10000,"stocks":0}]
})
Dans [2]:
exchanges[0].SetContractType("quarter") // The first exchange object OKX Futures (eid: Futures_OKCoin) calls the function to set the current contract as a quarterly contract.
var initQuarterAcc = exchanges[0].GetAccount() // The initial account information of OKX Futures Exchange is recorded in the variable initQuarterAcc.
initQuarterAcc
À l'extérieur [2]: { Solde: 0, geléBalance: 0, stocks: 1, gelé stocks: 0 }
Dans [3]:
var initSpotAcc = exchanges[1].GetAccount() // The initial account information of the OKX Spot Exchange is recorded in the variable initSpotAcc.
initSpotAcc
Extrait [3]: { Solde: 10 000, FrozenBalance: 0, Stocks: 0, FrozenStocks: 0 }
Dans [4]:
var quarterTicker1 = exchanges[0].GetTicker() // Get the futures exchange ticker, recorded in the variable quarterTicker1.
quarterTicker1
Extrait [4]: { heure: 1568851210000, Elle est élevée: 10441,25002. Faible: 10441,25 Vendre: 10441.25002, Acheter: 10441.25, Dernière: 10441.25001, Volume: 1772 (en anglais seulement) Je ne peux pas vous aider.
Dans [5]:
var spotTicker1 = exchanges[1].GetTicker() // Get the spot exchange ticker, recorded in the variable spotTicker1.
spotTicker1
Extrait [5]: Je vous en prie. Le niveau élevé: 10156.60000002. Faible: 10156,6 Vendre: 10156.60000002, Achetez: 10156,6, Dernière: 10156.60000001, Volume: 7.4443 et le numéro de série: 7.4443 Je ne suis pas intéressé.
Dans [6]:
quarterTicker1.Buy - spotTicker1.Sell // The price difference between going short on futures and going long on spot.
Extrait [6]: 284,64999997999985 Pour les produits de base Dans [7]:
exchanges[0].SetDirection("sell") // Set up a futures exchange and trade in the direction of going short
var quarterId1 = exchanges[0].Sell(quarterTicker1.Buy, 10) // Go short futures to place orders. The order quantity is 10 contracts. The returned order ID is recorded in the variable quarterId1.
exchanges[0].GetOrder(quarterId1) // Check the details of the order with futures order ID quarterId1.
À l'extérieur[7]:
{ Id: 1,
Le prix: 10441,25.
Nombre: 10
Le montant de l'offre: 10,
Le prix moyen: 10441,25.
Type: 1,
Décalage: 0,
Le statut: 1,
Type de contrat:
Dans [8]:
var spotAmount = 10 * 100 / quarterTicker1.Buy // Calculate the currency equivalent of 10 contracts as the order quantity of the spot.
var spotId1 = exchanges[1].Buy(spotTicker1.Sell, spotAmount) // Place orders on the spot exchange.
exchanges[1].GetOrder(spotId1) // Check the order details of the spot order ID of spotId1.
À l'extérieur[8]:
{ Id: 1,
Prix: 10156.60000002,
Montant: 0,0957,
Le montant de la transaction est de 0,0957.
Le prix moyen est de 10156,60000002.
Type: 0,
Décalage: 0,
Le statut: 1,
Le type de contrat:
Vous pouvez voir que les ordres quarterId1 et spotId1 sont entièrement exécutés, c'est-à-dire que la couverture des positions d'ouverture est terminée.
Dans [9]:
Sleep(1000 * 60 * 60 * 24 * 7) // Hold the position for a while and wait for the price difference to become smaller to close the position.
Après le temps d'attente, préparez-vous à fermer la position.quarterTicker2
, spotTicker2
et les imprimer.
La direction de transaction de l'objet d'échange de contrats à terme est réglée pour fermer la position courte:exchanges[0].SetDirection("closesell")
placer un ordre de clôture de la position.
Imprimer les détails de l'ordre de clôture de position, indiquant que l'ordre de clôture a été exécuté, la position de clôture terminée.
Dans [10]:
var quarterTicker2 = exchanges[0].GetTicker() // Get the current futures exchange ticker, recorded in the variable quarterTicker2.
quarterTicker2
À l'extérieur [10]: { heure: 1569456010000, Elle est élevée: 8497.20002. Faible: 8497,2 Vendre: 8497.20002, Acheter: 8497,2 Dernière: 8497.20001, Volume: 4311 Je ne peux pas vous aider.
Dans [11]:
var spotTicker2 = exchanges[1].GetTicker() // Get the current ticker of the spot exchange, recorded in the variable spotTicker2.
spotTicker2
À l'extérieur [11]: { heure: 1569456114600, Elle est élevée: 8444.70000001. Le plus bas: 8444,69999999, Vendre: 8444.70000001, Achetez: 8444.69999999, Dernière: 8444,7 Volume: 78,6273 et le numéro de série: Je ne peux pas vous aider.
Dans [12]:
quarterTicker2.Sell - spotTicker2.Buy // The price difference between closing short position of futures and closing long position of spot.
À l'extérieur [12]: 52 000 000 200 100 003
Dans [13]:
exchanges[0].SetDirection("closesell") // Set the current trading direction of the futures exchange to close short positions.
var quarterId2 = exchanges[0].Buy(quarterTicker2.Sell, 10) // The futures exchange places an order to close the position, and records the order ID to the variable quarterId2.
exchanges[0].GetOrder(quarterId2) // Check futures closing position order details.
À l'extérieur[13]:
{ Id: 2,
Le prix: 8497.20002,
Nombre: 10
Le montant de l'offre: 10,
Le prix moyen: 8493,95335,
Type: 0,
Décalage: 1,
Le statut: 1,
Type de contrat:
Dans [14]:
var spotId2 = exchanges[1].Sell(spotTicker2.Buy, spotAmount) // The spot exchange places an order to close the position, and records the order ID to the variable spotId2.
exchanges[1].GetOrder(spotId2) // Check spot closing position order details.
Extrait [1]:
{ Id: 2,
Le prix est de 8444,69999999.
Montant: 0,0957,
Le montant de la transaction est de 0,0957.
Prix moyen: 8444,69999999,
Type: 1,
Décalage: 0,
Le statut: 1,
Le type de contrat:
Dans [15]:
var nowQuarterAcc = exchanges[0].GetAccount() // Get the current futures exchange account information, recorded in the variable nowQuarterAcc.
nowQuarterAcc
Extrait [1]: { Solde: 0, Le solde est de 0, Les stocks sont de 1,021786026184. Je ne sais pas.
Dans [16]:
var nowSpotAcc = exchanges[1].GetAccount() // Get the current spot exchange account information, recorded in the variable nowSpotAcc.
nowSpotAcc
Extrait [1]: { Solde: 9834.74705446, Le solde est de 0, Les stocks: 0, Je ne sais pas. En comparant le compte initial avec le compte courant, le résultat de l'opération de couverture est calculé.
Dans [17]:
var diffStocks = Math.abs(nowQuarterAcc.Stocks - initQuarterAcc.Stocks)
var diffBalance = nowSpotAcc.Balance - initSpotAcc.Balance
if (nowQuarterAcc.Stocks - initQuarterAcc.Stocks > 0) {
console.log("profits:", diffStocks * spotTicker2.Buy + diffBalance)
} else {
console.log("profits:", diffBalance - diffStocks * spotTicker2.Buy)
}
Extrait [1]: Les bénéfices: 18,72350977580652
Maintenant voyons pourquoi la couverture est rentable. Nous pouvons voir le graphique dessiné. Le prix des contrats à terme est une ligne bleue et le prix au comptant est une ligne orange. Les deux prix diminuent. Le prix des contrats à terme diminue plus vite que le prix au comptant.
Dans [18]:
var objQuarter = {
"index" : [1, 2], // The index is 1, that is, the first time, the opening time, and 2 is the closing 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}])
À l'extérieur [1]: La différence de prix varie de 284 au moment de la couverture des positions d'ouverture (c'est-à-dire que les contrats à terme sont allés court et que le spot est allé long) à 52 au moment de la clôture (close short position des contrats à terme et close long position du spot).
Dans [19]:
var arrDiffPrice = [quarterTicker1.Buy - spotTicker1.Sell, quarterTicker2.Sell - spotTicker2.Buy]
plot(arrDiffPrice)
Extrait [1]:Par exemple, a1 est le prix des contrats à terme au moment 1, et b1 est le prix au comptant au moment 1. A2 est le prix des contrats à terme au moment 2, et b2 est le prix au comptant au moment 2.Tant que l'écart de prix au comptant des contrats à terme au moment 1 (a1-b1) est supérieur à l'écart de prix au comptant des contrats à terme au moment 2 (a2-b2), a1 - a2>b1 - b2 peut être introduit. Il y a trois situations: (la quantité de futures et de positions au comptant est la même)
a1 - a2 est supérieur à 0, b1 - b2 est supérieur à 0 a1 - a2 se réfère à la différence de prix des profits futures, et b1 - b2 se réfère à la différence de prix des pertes au comptant (parce que le spot est allé long, le prix de début d'achat est plus élevé que le prix de vente pour fermer la position, donc l'argent est perdu), mais les profits à terme sont plus importants que les pertes au comptant.
a1 - a2 est supérieur à 0, b1 - b2 est inférieur à 0 a1 - a2 est la différence de prix des bénéfices à terme, et b1 - b2 est la différence de prix des bénéfices au comptant (b1 - b2 est inférieur à 0, ce qui indique que b2 est supérieur à b1, c'est-à-dire que le prix d'ouverture et d'achat de la position est faible, et le prix de vente et de clôture est élevé, il est donc rentable).
a1 - a2 inférieur à 0, b1 - b2 inférieur à 0 a1 - a2 est la différence de prix des pertes futures, et b1 - b2 est la différence de prix des profits au comptant. Puisque a1 - a2 > b1 - b2, la valeur absolue de a1 - a2 est inférieure à la valeur absolue de b1 - b2, et les profits au comptant sont plus importants que les pertes futures.
Il n'y a pas de cas où a1 - a2 est inférieur à 0 et b1 - b2 est supérieur à 0, car a1 - a2 > b1 - b2 a été défini. De même, si a1 - a2 est égal à 0, puisque a1 - a2 > b1 - b2 est défini, b1 - b2 doit être inférieur à 0. Par conséquent, tant que la méthode de couverture des contrats à terme courts et des contrats à terme longs répond aux conditions a1 - b1 > a2 - b2, les opérations d'ouverture et de clôture de position sont des opérations de couverture des bénéfices.
Par exemple, le modèle suivant est l'un des cas:
Dans [20]:
var a1 = 10
var b1 = 5
var a2 = 11
var b2 = 9
// a1 - b1 > a2 - b2 launches: 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}])
Extrait [1]:
Essayez ça, les gars!