O termo
No painel da plataforma FMZ Quant, clique em
Aqui eu carrego o arquivo de análise diretamente:
Este documento de análise é uma análise do processo de abertura e fechamento de uma posição de cobertura spot de futuros durante o backtesting.quarter
A troca à vista é uma transacção moeda-moeda OKX, e o par de negociação éBTC_USDT
Para analisar o processo de operação do hedging spot de futuros, você pode ver o seguinte arquivo de ambiente de pesquisa específico, escrito em duas versões: uma versão em Python, uma versão em JavaScript.
Análise sobre o princípio da cobertura spot de futuros.ipynb Em [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
Em [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
Fora[2]:
(
Em [3]:
initSpotAcc = exchanges[1].GetAccount() # The initial account information of the OKX Spot Exchange is recorded in the variable initSpotAcc
initSpotAcc
Fora[3]:
(
Em [4]:
quarterTicker1 = exchanges[0].GetTicker() # Get the futures exchange ticker, recorded in the variable quarterTicker1
quarterTicker1
Fora[4]:
Hora: 1568851210000,
Em [5]:
spotTicker1 = exchanges[1].GetTicker() # Get the spot exchange ticker, recorded in the variable spotTicker1
spotTicker1
Fora[5]:
Tempo: 1568851210000,
Em [6]:
quarterTicker1.Buy - spotTicker1.Sell # The price difference between going short on futures and going long on spot.
Fora[6]: 284,64999997999985
Em [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.
Fora[7]:
- Sim, senhor.
Em [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
Fora[8]:
- Sim, senhor.
Podem ver-se que as ordens trimestraisId1 e spotId1 estão totalmente preenchidas, ou seja, a cobertura das posições abertas está concluída.
Em [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.
Após o tempo de espera, preparar para fechar a posição.quarterTicker2
, spotTicker2
e imprimi-los.
A direção da transação do objeto de troca de futuros é definida para fechar a posição curta:exchanges[0].SetDirection("closesell")
colocar uma ordem para fechar a posição.
Imprimir os pormenores da ordem de encerramento da posição, indicando que a ordem de encerramento foi concluída, a posição de encerramento terminada.
Em [10]:
quarterTicker2 = exchanges[0].GetTicker() # Get the current futures exchange ticker, recorded in the variable quarterTicker2
quarterTicker2
Fora[10]:
Hora: 1569456010000,
Em [11]:
spotTicker2 = exchanges[1].GetTicker() # Get the current ticker of the spot exchange, recorded in the variable spotTicker2
spotTicker2
Fora[11]:
- Está bem.
Em [12]:
quarterTicker2.Sell - spotTicker2.Buy # The price difference between closing a short futures position and closing a long spot position.
Fora[12]: 52.5000200100003
Em [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
Fora[13]:
- O que é que se passa?
Em [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
Fora [1]:
- O que é que se passa?
Em [15]:
nowQuarterAcc = exchanges[0].GetAccount() # Get the current futures exchange account information, recorded in the variable nowQuarterAcc.
nowQuarterAcc
Fora [1]:
{
Em [16]:
nowSpotAcc = exchanges[1].GetAccount() # Get the current spot exchange account information, recorded in the variable nowSpotAcc.
nowSpotAcc
Fora [1]:
(Balanço: 9834.74705446,
Comparando a conta inicial com a conta corrente, é calculado o lucro e a perda da operação de cobertura.
Em [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)
Fora [1]: Lucros: 18,72350977580652
Agora vamos ver por que a cobertura é rentável. Podemos ver o gráfico desenhado. O preço de futuros é uma linha azul e o preço spot é uma linha laranja. Ambos os preços estão diminuindo. O preço de futuros está diminuindo mais rápido que o preço spot.
Em [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()
Fora [1]:
A diferença de preço varia de 284 no momento da posição de abertura de cobertura (isto é, futuros vão curto e spot vai longo) para 52 no momento da posição de fechamento (positivos futuros curtos fechados, posição longa fechada no local).
Em [19]:
xDiff = [1, 2]
yDiff = [quarterTicker1.Buy - spotTicker1.Sell, quarterTicker2.Sell - spotTicker2.Buy]
plt.plot(xDiff, yDiff, linewidth=5)
plt.show()
Fora [1]:
Por exemplo, a1 é o preço de futuros no momento 1, e b1 é o preço ao instante no momento 1. A2 é o preço de futuros no momento 2, e b2 é o preço ao instante no momento 2.Desde que a diferença de preço spot dos futuros no momento 1 (a1-b1) seja maior do que a diferença de preço spot dos futuros no momento 2 (a2-b2), pode ser introduzida a1 - a2>b1 - b2. Existem três situações: (a quantidade de posições futuras e de posições spot é a mesma)
a1 - a2 é maior que 0, b1 - b2 é maior que 0 a1 - a2 refere-se à diferença de preço dos lucros futuros, e b1 - b2 refere-se à diferença de preço das perdas spot (porque o spot foi longo, o preço de começar a comprar é maior do que o preço de venda para fechar a posição, então o dinheiro é perdido), mas os lucros futuros são maiores do que as perdas spot. Então é lucrativo como um todo. Esta situação corresponde ao gráfico na etapa In [8].
a1 - a2 é maior que 0, b1 - b2 é menor que 0 a1 - a2 é a diferença de preço dos lucros futuros, e b1 - b2 é a diferença de preço dos lucros spot (b1 - b2 é menor que 0, indicando que b2 é maior que b1, ou seja, o preço de abertura e compra da posição é baixo, e o preço de venda e fechamento é alto, por isso é rentável).
a1 - a2 inferior a 0, b1 - b2 inferior a 0 a1 - a2 é a diferença de preço das perdas de futuros, e b1 - b2 é a diferença de preço dos lucros pontuais. Como a1 - a2 > b1 - b2, o valor absoluto de a1 - a2 é menor que o valor absoluto de b1 - b2, e os lucros pontuais são maiores do que as perdas de futuros. É lucrativo como um todo.
Não há caso em que a1 - a2 é menor que 0 e b1 - b2 é maior que 0, porque a1 - a2 > b1 - b2 foi definido. Da mesma forma, se a1 - a2 é igual a 0, uma vez que a1 - a2 > b1 - b2 é definido, b1 - b2 deve ser menor que 0. Portanto, desde que o método de cobertura de futuros curtos e spot longos atenda às condições a1 - b1 > a2 - b2, as operações de abertura e fechamento de posição são cobertura de lucro.
Por exemplo, o modelo seguinte é um dos casos:
Em [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()
Fora [1]:
O ambiente de pesquisa suporta não só Python, mas também JavaScript Eu também dou um exemplo de ambiente de pesquisa JavaScript:
Análise do princípio da cobertura spot de futuros (JavaScript).ipynb Em [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}]
})
Em [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
Fora[2]: { Saldo: 0, FrozenBalance: 0, Stocks: 1, FrozenStocks: 0 }
Em [3]:
var initSpotAcc = exchanges[1].GetAccount() // The initial account information of the OKX Spot Exchange is recorded in the variable initSpotAcc.
initSpotAcc
Fora[3]: { Saldo: 10 000, FrozenBalance: 0, Stocks: 0, FrozenStocks: 0 }
Em [4]:
var quarterTicker1 = exchanges[0].GetTicker() // Get the futures exchange ticker, recorded in the variable quarterTicker1.
quarterTicker1
Fora[4]: Hora: 1568851210000, Alto: 10441.25002, Baixo: 10441,25. Venda: 10441.25002, Compra: 10441.25, Último: 10441.25001, Volume: 1772, Interesse aberto: 0 }
Em [5]:
var spotTicker1 = exchanges[1].GetTicker() // Get the spot exchange ticker, recorded in the variable spotTicker1.
spotTicker1
Fora[5]: Hora: 1568851210000, Alto: 10156.60000002, Baixo: 10156,6. Vender: 10156.60000002, Compra: 10156,6, Último: 10156.60000001, Volume: 7.4443, Interesse aberto: 0 }
Em [6]:
quarterTicker1.Buy - spotTicker1.Sell // The price difference between going short on futures and going long on spot.
Fora[6]: 284,64999997999985 Em [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.
Fora[7]:
{Id: 1,
Preço: 10441.25,
Montante: 10
O valor do negócio: 10,
Preço médio: 10441,25.
Tipo: 1,
Deslocamento: 0,
Situação:
Tipo de contrato:
Em [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.
Fora[8]:
{Id: 1,
Preço: 10156.60000002,
Montante: 0,0957,
O valor do acordo é de 0,0957.
Preço médio: 10156.60000002,
Tipo: 0,
Deslocamento: 0,
Situação:
Tipo de contrato:
Como pode ver, as ordens quarterId1 e spotId1 estão totalmente preenchidas, ou seja, a cobertura das posições de abertura está concluída.
Em [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.
Após o tempo de espera, preparar para fechar a posição.quarterTicker2
, spotTicker2
e imprimi-los.
A direção da transação do objeto de troca de futuros é definida para fechar a posição curta:exchanges[0].SetDirection("closesell")
colocar uma ordem para fechar a posição.
Imprimir os pormenores da ordem de encerramento da posição, indicando que a ordem de encerramento foi concluída, a posição de encerramento terminada.
Em [10]:
var quarterTicker2 = exchanges[0].GetTicker() // Get the current futures exchange ticker, recorded in the variable quarterTicker2.
quarterTicker2
Fora[10]: Hora: 1569456010000, Alto: 8497.20002, Baixo: 8497.2, Venda: 8497.20002, Compra: 8497.2, Último: 8497.20001, Volume: 4311, Interesse aberto: 0 }
Em [11]:
var spotTicker2 = exchanges[1].GetTicker() // Get the current ticker of the spot exchange, recorded in the variable spotTicker2.
spotTicker2
Fora[11]: (Hora: 1569456114600) Alto: 8444.70000001, Baixo: 8444.69999999, Venda: 8444.70000001, Compra: 8444.69999999, Último: 8444,7, Volume: 78.6273, Interesse aberto: 0 }
Em [12]:
quarterTicker2.Sell - spotTicker2.Buy // The price difference between closing short position of futures and closing long position of spot.
Fora[12]: 52.5000200100003
Em [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.
Fora[13]:
- O que é?
Preço: 8497.20002,
Montante: 10
O valor do negócio: 10,
Preço médio: 8493,95335,
Tipo: 0,
Deslocamento: 1,
Situação:
Tipo de contrato:
Em [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.
Fora [1]:
- O que é?
Preço: 8444,69999999,
Montante: 0,0957,
O valor da transacção é de 0,0957.
Preço médio: 8444,69999999,
Tipo: 1,
Deslocamento: 0,
Situação: 1,
Tipo de contrato:
Em [15]:
var nowQuarterAcc = exchanges[0].GetAccount() // Get the current futures exchange account information, recorded in the variable nowQuarterAcc.
nowQuarterAcc
Fora [1]: { Saldo: 0, FrigoríficoBalance: 0, Reservas: 1.021786026184, FrozenStocks:
Em [16]:
var nowSpotAcc = exchanges[1].GetAccount() // Get the current spot exchange account information, recorded in the variable nowSpotAcc.
nowSpotAcc
Fora [1]: Saldo: 9834.74705446, FrigoríficoBalance: 0, Reservas: 0, FrozenStocks: Comparando a conta inicial com a conta corrente, é calculado o lucro e a perda da operação de cobertura.
Em [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)
}
Fora [1]: Lucros: 18,72350977580652
Agora vamos ver por que a cobertura é rentável. Podemos ver o gráfico desenhado. O preço de futuros é uma linha azul e o preço spot é uma linha laranja. Ambos os preços estão diminuindo. O preço de futuros está diminuindo mais rápido que o preço spot.
Em [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}])
Fora [1]: A diferença de preço varia de 284 no momento da cobertura de posições de abertura (ou seja, os futuros ficaram curtos e o local ficou longo) para 52 no momento do fechamento (fechamento de posição curta de futuros e fechamento de posição longa de local).
Em [19]:
var arrDiffPrice = [quarterTicker1.Buy - spotTicker1.Sell, quarterTicker2.Sell - spotTicker2.Buy]
plot(arrDiffPrice)
Fora [1]:Por exemplo, a1 é o preço de futuros no momento 1, e b1 é o preço ao instante no momento 1. A2 é o preço de futuros no momento 2, e b2 é o preço ao instante no momento 2.Desde que a diferença de preço spot dos futuros no momento 1 (a1-b1) seja maior do que a diferença de preço spot dos futuros no momento 2 (a2-b2), pode ser introduzida a1 - a2>b1 - b2. Existem três situações: (a quantidade de posições futuras e de posições spot é a mesma)
a1 - a2 é maior que 0, b1 - b2 é maior que 0 a1 - a2 refere-se à diferença de preço dos lucros futuros, e b1 - b2 refere-se à diferença de preço das perdas spot (porque o spot foi longo, o preço de começar a comprar é maior do que o preço de venda para fechar a posição, então o dinheiro é perdido), mas os lucros futuros são maiores do que as perdas spot. Então é lucrativo como um todo. Esta situação corresponde ao gráfico na etapa In [8].
a1 - a2 é maior que 0, b1 - b2 é menor que 0 a1 - a2 é a diferença de preço dos lucros futuros, e b1 - b2 é a diferença de preço dos lucros spot (b1 - b2 é menor que 0, indicando que b2 é maior que b1, ou seja, o preço de abertura e compra da posição é baixo, e o preço de venda e fechamento é alto, por isso é rentável).
a1 - a2 inferior a 0, b1 - b2 inferior a 0 a1 - a2 é a diferença de preço das perdas de futuros, e b1 - b2 é a diferença de preço dos lucros pontuais. Como a1 - a2 > b1 - b2, o valor absoluto de a1 - a2 é menor que o valor absoluto de b1 - b2, e os lucros pontuais são maiores do que as perdas de futuros. É lucrativo como um todo.
Não há caso em que a1 - a2 é menor que 0 e b1 - b2 é maior que 0, porque a1 - a2 > b1 - b2 foi definido. Da mesma forma, se a1 - a2 é igual a 0, uma vez que a1 - a2 > b1 - b2 é definido, b1 - b2 deve ser menor que 0. Portanto, desde que o método de cobertura de futuros curtos e spot longos atenda às condições a1 - b1 > a2 - b2, as operações de abertura e fechamento de posição são cobertura de lucro.
Por exemplo, o modelo seguinte é um dos casos:
Em [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}])
Fora [1]:
Experimentem, rapazes!