El término
En el panel de control de la plataforma FMZ Quant, haga clic en
Aquí subo el archivo de análisis directamente:
Este documento de análisis es un análisis del proceso de apertura y cierre de una posición de cobertura de spot de futuros durante el backtesting.quarter
El intercambio al contado es una transacción moneda-moneda OKX, y el par de negociación esBTC_USDT
Para analizar el proceso de operación de la cobertura de futuros-spot, puede ver el siguiente archivo de entorno de investigación específico, escrito en dos versiones: una versión en lenguaje Python, una versión en lenguaje JavaScript.
Análisis sobre el principio de cobertura de futuros al contado.ipynb En [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
En [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
Fuera de juego[2]:
(Bilancio: 0,0,
En [3]:
initSpotAcc = exchanges[1].GetAccount() # The initial account information of the OKX Spot Exchange is recorded in the variable initSpotAcc
initSpotAcc
Fuera[3]:
(Bilancio: 10000,0
En [4]:
quarterTicker1 = exchanges[0].GetTicker() # Get the futures exchange ticker, recorded in the variable quarterTicker1
quarterTicker1
Fuera[4]:
¿Qué es lo que está pasando?
En [5]:
spotTicker1 = exchanges[1].GetTicker() # Get the spot exchange ticker, recorded in the variable spotTicker1
spotTicker1
Fuera[5]:
¿Qué es lo que está pasando?
En [6]:
quarterTicker1.Buy - spotTicker1.Sell # The price difference between going short on futures and going long on spot.
Fuera de juego[6]: 284.64999997999985
En [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.
Fuera[7]:
- ¿Qué es eso?
En [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
Fuera[8]:
- ¿Qué es eso?
Puede observarse que las órdenes quarterId1 y spotId1 están completamente cumplidas, es decir, se ha completado la cobertura de las posiciones abiertas.
En [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.
Después del tiempo de espera, prepárate para cerrar la posición.quarterTicker2
, spotTicker2
y imprimirlos.
La dirección de la transacción del objeto de intercambio de futuros está configurada para cerrar la posición corta:exchanges[0].SetDirection("closesell")
Poner una orden para cerrar la posición.
Imprimir los detalles de la orden de cierre de la posición, indicando que la orden de cierre se ha completado, la posición de cierre terminada.
En el [10]:
quarterTicker2 = exchanges[0].GetTicker() # Get the current futures exchange ticker, recorded in the variable quarterTicker2
quarterTicker2
Fuera [10]:
¿Qué es lo que está pasando?
En [11]:
spotTicker2 = exchanges[1].GetTicker() # Get the current ticker of the spot exchange, recorded in the variable spotTicker2
spotTicker2
Fuera [11]:
¿Qué es lo que está pasando?
En [12]:
quarterTicker2.Sell - spotTicker2.Buy # The price difference between closing a short futures position and closing a long spot position.
Fuera [12]: 52 500 200 100 003
En [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
Fuera[13]:
- ¿Qué es eso?
En [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
Fuera [1]:
- ¿Qué es eso?
En [15]:
nowQuarterAcc = exchanges[0].GetAccount() # Get the current futures exchange account information, recorded in the variable nowQuarterAcc.
nowQuarterAcc
Fuera [1]:
{
En [16]:
nowSpotAcc = exchanges[1].GetAccount() # Get the current spot exchange account information, recorded in the variable nowSpotAcc.
nowSpotAcc
Fuera [1]:
El saldo es de 9834.74705446.
Al comparar la cuenta inicial con la cuenta corriente, se calcula el beneficio y la pérdida de la operación de cobertura.
En [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)
Fuera [1]: Las ganancias: 18,72350977580652
Ahora vamos a ver por qué la cobertura es rentable. Podemos ver el gráfico dibujado. El precio de los futuros es una línea azul y el precio al contado es una línea naranja. Ambos precios están disminuyendo. El precio de los futuros está disminuyendo más rápido que el precio al contado.
En el [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()
Fuera [1]:
La diferencia de precio varía de 284 en el momento de la cobertura de la posición de apertura (es decir, los futuros van a corto, y el spot va a largo) a 52 en el momento del cierre de la posición (los futuros posiciones cortas cerradas, posición larga al contado cerrada).
En [19]:
xDiff = [1, 2]
yDiff = [quarterTicker1.Buy - spotTicker1.Sell, quarterTicker2.Sell - spotTicker2.Buy]
plt.plot(xDiff, yDiff, linewidth=5)
plt.show()
Fuera [1]:
Por ejemplo, a1 es el precio de los futuros en el momento 1, y b1 es el precio al contado en el momento 1. A2 es el precio de los futuros en el momento 2, y b2 es el precio al contado en el momento 2.Siempre que la diferencia de precio spot de los futuros en el momento 1 (a1-b1) sea mayor que la diferencia de precio spot de los futuros en el momento 2 (a2-b2), se puede introducir a1 - a2>b1 - b2. Existen tres situaciones: (la cantidad de futuros y de posiciones al contado es la misma)
a1 - a2 es mayor que 0, b1 - b2 es mayor que 0 a1 - a2 se refiere a la diferencia de precio de las ganancias de futuros, y b1 - b2 se refiere a la diferencia de precio de las pérdidas al contado (porque el spot fue largo, el precio de comenzar a comprar es mayor que el precio de venta para cerrar la posición, por lo que se pierde el dinero), pero las ganancias de futuros son mayores que las pérdidas al contado. Por lo tanto, es rentable en su conjunto.
a1 - a2 es mayor que 0, b1 - b2 es menor que 0 a1 - a2 es la diferencia de precio de las ganancias de futuros, y b1 - b2 es la diferencia de precio de las ganancias al contado (b1 - b2 es menor que 0, lo que indica que b2 es mayor que b1, es decir, el precio de apertura y compra de la posición es bajo, y el precio de venta y cierre es alto, por lo que es rentable).
a1 - a2 menos de 0, b1 - b2 menos de 0 a1 - a2 es la diferencia de precio de las pérdidas de futuros, y b1 - b2 es la diferencia de precio de las ganancias al contado. Dado que a1 - a2 > b1 - b2, el valor absoluto de a1 - a2 es menor que el valor absoluto de b1 - b2, y las ganancias al contado son mayores que las pérdidas de futuros. Es rentable en su conjunto.
No hay ningún caso en el que a1 - a2 sea menor que 0 y b1 - b2 sea mayor que 0, porque a1 - a2 > b1 - b2 ha sido definido. De manera similar, si a1 - a2 es igual a 0, ya que a1 - a2 > b1 - b2 está definido, b1 - b2 debe ser menor que 0. Por lo tanto, siempre que el método de cobertura de futuros cortos y spot largos cumpla con las condiciones a1 - b1 > a2 - b2, las operaciones de apertura y cierre de posiciones son cobertura de ganancias.
Por ejemplo, el siguiente modelo es uno de los casos:
En [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()
Fuera [1]:
El entorno de investigación admite no sólo Python, sino también JavaScript También doy un ejemplo de entorno de investigación JavaScript:
Análisis del principio de cobertura de futuros al contado (JavaScript).ipynb En [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}]
})
En [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
Fuera de juego[2]: { Saldo: 0, congeladoBalance: 0, existencias: 1, congeladas existencias: 0 }
En [3]:
var initSpotAcc = exchanges[1].GetAccount() // The initial account information of the OKX Spot Exchange is recorded in the variable initSpotAcc.
initSpotAcc
Fuera[3]: { Saldo: 10000, congeladoBalance: 0, existencias: 0, congeladas existencias: 0 }
En [4]:
var quarterTicker1 = exchanges[0].GetTicker() // Get the futures exchange ticker, recorded in the variable quarterTicker1.
quarterTicker1
Fuera[4]: - ¿Qué es eso? Alto: 10441.25002, Bajo: 10441.25, Se vende: 10441.25002, Comprar: 10441.25, el precio es de $1. El último: 10441.25001, Volumen: 1772, El interés abierto:
En [5]:
var spotTicker1 = exchanges[1].GetTicker() // Get the spot exchange ticker, recorded in the variable spotTicker1.
spotTicker1
Fuera[5]: ¿Por qué no lo haces? Alto: 10156.60000002 Bajo: 10156.6. Vender: 10156.60000002, Comprar: 10156.6, ¿Qué es eso? Último: 10156.60000001, Volumen: 7.4443, El interés abierto:
En [6]:
quarterTicker1.Buy - spotTicker1.Sell // The price difference between going short on futures and going long on spot.
Fuera[6]: 284,64999997999985 y otras cantidades En [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.
Fuera[7]:
El número de identificación: 1,
Precio: 10441.25,
Cantidad: 10
Contrato: 10
Precio promedio: 10441.25,
Tipo: 1,
Desviación: 0,
El estado: 1,
Tipo de contrato:
En [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.
Fuera[8]:
El número de identificación: 1,
Precio: 10156.60000002,
Importe: 0,0957,
Contrato de cantidad: 0.0957,
Precio promedio: 10156.60000002,
Tipo: 0,
Desviación: 0,
El estado: 1,
Tipo de contrato:
Se puede ver que las órdenes quarterId1 y spotId1 están completamente cumplidas, es decir, se ha completado la cobertura de las posiciones de apertura.
En [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.
Después del tiempo de espera, prepárate para cerrar la posición.quarterTicker2
, spotTicker2
y imprimirlos.
La dirección de la transacción del objeto de intercambio de futuros está configurada para cerrar la posición corta:exchanges[0].SetDirection("closesell")
Poner una orden para cerrar la posición.
Imprimir los detalles de la orden de cierre de la posición, indicando que la orden de cierre se ha completado, la posición de cierre terminada.
En el [10]:
var quarterTicker2 = exchanges[0].GetTicker() // Get the current futures exchange ticker, recorded in the variable quarterTicker2.
quarterTicker2
Fuera[10]: Es hora de 1569456010000. Alto: 8497.20002, es muy alto. Bajo: 8497.2, Vender: 8497.20002, el precio de venta es el siguiente: Comprar: 8497.2, El último: 8497.20001, Volumen: 4311 y número de ejemplares. El interés abierto:
En [11]:
var spotTicker2 = exchanges[1].GetTicker() // Get the current ticker of the spot exchange, recorded in the variable spotTicker2.
spotTicker2
Fuera [11]: ¿Qué es lo que está sucediendo? Alto: 8444.70000001. Bajo: 8444.69999999, Vender: 8444.70000001, Comprar: 8444.69999999, Último: 8444.7, Volumen: 78.6273 y número de páginas. El interés abierto:
En [12]:
quarterTicker2.Sell - spotTicker2.Buy // The price difference between closing short position of futures and closing long position of spot.
Fuera [12]: 52 500 200 100 003
En [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.
Fuera[13]:
- ¿Qué es eso?
Precio: 8497.20002,
Cantidad: 10
Contrato: 10
Precio promedio: 8493.95335,
Tipo: 0,
Desembolso: 1,
El estado: 1,
Tipo de contrato:
En [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.
Fuera [1]:
- ¿Por qué no?
Precio: 8444.69999999,
Importe: 0,0957,
Contrato de cantidad: 0.0957,
Precio promedio: 8444.69999999,
Tipo: uno.
Desviación: 0,
El estado: 1,
Tipo de contrato:
En [15]:
var nowQuarterAcc = exchanges[0].GetAccount() // Get the current futures exchange account information, recorded in the variable nowQuarterAcc.
nowQuarterAcc
Fuera [1]: { Saldo: 0, FríoBalance: 0, Las existencias: 1.021786026184, ¿ Qué es eso?
En [16]:
var nowSpotAcc = exchanges[1].GetAccount() // Get the current spot exchange account information, recorded in the variable nowSpotAcc.
nowSpotAcc
Fuera [1]: { Saldo: 9834.74705446, El saldo congelado: 0, Las existencias: 0, ¿ Qué es eso? Al comparar la cuenta inicial con la cuenta corriente, se calcula el beneficio y la pérdida de la operación de cobertura.
En [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)
}
Fuera [1]: Las ganancias: 18,72350977580652
Ahora vamos a ver por qué la cobertura es rentable. Podemos ver el gráfico dibujado. El precio de los futuros es una línea azul y el precio al contado es una línea naranja. Ambos precios están disminuyendo. El precio de los futuros está disminuyendo más rápido que el precio al contado.
En el [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}])
Fuera [1]: La diferencia de precio varía de 284 en el momento de cubrir las posiciones de apertura (es decir, los futuros fueron cortos y el spot fue largo) a 52 en el momento del cierre (cierre de la posición corta de futuros y cierre de la posición larga del spot).
En [19]:
var arrDiffPrice = [quarterTicker1.Buy - spotTicker1.Sell, quarterTicker2.Sell - spotTicker2.Buy]
plot(arrDiffPrice)
Fuera [1]:Por ejemplo, a1 es el precio de los futuros en el momento 1, y b1 es el precio al contado en el momento 1. A2 es el precio de los futuros en el momento 2, y b2 es el precio al contado en el momento 2.Siempre que la diferencia de precio spot de los futuros en el momento 1 (a1-b1) sea mayor que la diferencia de precio spot de los futuros en el momento 2 (a2-b2), se puede introducir a1 - a2>b1 - b2. Existen tres situaciones: (la cantidad de futuros y de posiciones al contado es la misma)
a1 - a2 es mayor que 0, b1 - b2 es mayor que 0 a1 - a2 se refiere a la diferencia de precio de las ganancias de futuros, y b1 - b2 se refiere a la diferencia de precio de las pérdidas al contado (porque el spot fue largo, el precio de comenzar a comprar es mayor que el precio de venta para cerrar la posición, por lo que se pierde el dinero), pero las ganancias de futuros son mayores que las pérdidas al contado. Por lo tanto, es rentable en su conjunto.
a1 - a2 es mayor que 0, b1 - b2 es menor que 0 a1 - a2 es la diferencia de precio de las ganancias de futuros, y b1 - b2 es la diferencia de precio de las ganancias al contado (b1 - b2 es menor que 0, lo que indica que b2 es mayor que b1, es decir, el precio de apertura y compra de la posición es bajo, y el precio de venta y cierre es alto, por lo que es rentable).
a1 - a2 menos de 0, b1 - b2 menos de 0 a1 - a2 es la diferencia de precio de las pérdidas de futuros, y b1 - b2 es la diferencia de precio de las ganancias al contado. Dado que a1 - a2 > b1 - b2, el valor absoluto de a1 - a2 es menor que el valor absoluto de b1 - b2, y las ganancias al contado son mayores que las pérdidas de futuros. Es rentable en su conjunto.
No hay ningún caso en el que a1 - a2 sea menor que 0 y b1 - b2 sea mayor que 0, porque a1 - a2 > b1 - b2 ha sido definido. De manera similar, si a1 - a2 es igual a 0, ya que a1 - a2 > b1 - b2 está definido, b1 - b2 debe ser menor que 0. Por lo tanto, siempre que el método de cobertura de futuros cortos y spot largos cumpla con las condiciones a1 - b1 > a2 - b2, las operaciones de apertura y cierre de posiciones son cobertura de ganancias.
Por ejemplo, el siguiente modelo es uno de los casos:
En [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}])
Fuera [1]:
¡Pruébalo, muchachos!