FMZ 퀀트 플랫폼의 대시보드에서
여기서 분석 파일을 직접 업로드합니다.
이 분석 문서는 백테스팅 동안 선물 스팟 헤지 포지션의 개장 및 폐쇄 과정을 분석합니다. 선물 거래소는 OKX 선물이며 계약은quarter
거래상 거래는 OKX 통화-화폐 거래이며 거래 쌍은BTC_USDT
. 선물 스팟 헤지의 운영 프로세스를 분석하려면 다음의 특정 연구 환경 파일을 볼 수 있습니다. 두 가지 버전으로 작성되었습니다. 파이썬 언어 버전, 자바스크립트 언어 버전.
선물 포트 헤지링 원칙에 대한 분석.ipynb [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
[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
외출[2]:
{
[3]에서:
initSpotAcc = exchanges[1].GetAccount() # The initial account information of the OKX Spot Exchange is recorded in the variable initSpotAcc
initSpotAcc
아웃[3]:
{
[4]:
quarterTicker1 = exchanges[0].GetTicker() # Get the futures exchange ticker, recorded in the variable quarterTicker1
quarterTicker1
아웃[4]:
시간: 1568851210000,
[5]에서:
spotTicker1 = exchanges[1].GetTicker() # Get the spot exchange ticker, recorded in the variable spotTicker1
spotTicker1
외출[5]:
시간: 1568851210000,
[6]에서:
quarterTicker1.Buy - spotTicker1.Sell # The price difference between going short on futures and going long on spot.
외출[6]: 284.6499999799999985
[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.
아웃[7]:
1번
[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
아웃[8]:
1개
가격: 10156.60000002,
금액: 0.0957
거래 금액: 0.0957,
평균 가격은 10156.60000002입니다.
분기 ID1 및 스팟 ID1 명령이 완전히 채워졌다는 것을 볼 수 있습니다. 즉, 개방된 포지션의 헤딩이 완료되었습니다.
[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.
대기 시간이 지나면, 포지션을 닫기 위해 준비.quarterTicker2
, spotTicker2
그리고 그들을 인쇄합니다.
선물 거래 대상의 거래 방향은 짧은 지위를 닫기 위해 설정됩니다.exchanges[0].SetDirection("closesell")
포지션을 닫는 명령을 내립니다.
클로저 포지션 오더의 세부 정보를 인쇄하여 클로저 오더가 완료되었다고 표시합니다.
[10]에서:
quarterTicker2 = exchanges[0].GetTicker() # Get the current futures exchange ticker, recorded in the variable quarterTicker2
quarterTicker2
아웃[10]:
시간: 1569456010000,
[11]에서:
spotTicker2 = exchanges[1].GetTicker() # Get the current ticker of the spot exchange, recorded in the variable spotTicker2
spotTicker2
아웃[11]:
시간: 1569456114600
[12]에서:
quarterTicker2.Sell - spotTicker2.Buy # The price difference between closing a short futures position and closing a long spot position.
아웃[12]: 52.5000200100003
[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
아웃[13]:
2명
[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
아웃[14]:
2명
가격: 8444.69999999,
금액: 0.0957
거래 금액: 0.0957
평균 가격: 8444.69999999,
[15]에서:
nowQuarterAcc = exchanges[0].GetAccount() # Get the current futures exchange account information, recorded in the variable nowQuarterAcc.
nowQuarterAcc
외출[15]:
{
[16]에서:
nowSpotAcc = exchanges[1].GetAccount() # Get the current spot exchange account information, recorded in the variable nowSpotAcc.
nowSpotAcc
외출[16]:
초기계산과 courant계산을 비교함으로써 헤지업의 이익과 손실이 계산됩니다.
[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)
아웃[17]: 이익: 18.72350977580652
이제 왜 헤딩이 수익성이 있는지 봅시다. 그래프를 그려보겠습니다. 선물 가격은 파란색 선이고 스포트 가격은 오렌지 선입니다. 두 가격 모두 감소하고 있습니다. 선물 가격은 스포트 가격보다 빠르게 감소하고 있습니다.
[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()
아웃[18]:
가격 차이의 변화를 살펴보자. 가격 차이는 헤지 개설 지점 (즉, 선물은 짧고 스팟은 길다) 의 284에서 포지션 종료 시점 (퓨처 짧은 지점 폐쇄, 스팟 긴 지점 폐쇄) 의 52까지 다양합니다. 가격 차이는 크기에서 작습니다.
[19]에서:
xDiff = [1, 2]
yDiff = [quarterTicker1.Buy - spotTicker1.Sell, quarterTicker2.Sell - spotTicker2.Buy]
plt.plot(xDiff, yDiff, linewidth=5)
plt.show()
아웃[19]:
예를 들어, a1은 시간 1의 선물 가격이고, b1은 시간 1의 스팟 가격이다. A2는 시간 2의 선물 가격이고, b2는 시간 2의 스팟 가격이다.시점 1 (a1-b1) 의 선물 현장 가격 차이는 시점 2 (a2-b2) 의 선물 현장 가격 차이보다 크면 a1 - a2>b1 - b2를 도입할 수 있습니다. 세 가지 상황이 있습니다. (미래상과 현금상의 양은 동일합니다.)
a1 - a2는 0보다 크다 b1 - b2는 0보다 크다 a1 - a2는 선물 수익의 가격 차이, 그리고 b1 - b2는 스팟 손실의 가격 차이 (스팟이 길어졌기 때문에 구매 시작 가격은 포지션을 닫는 판매 가격보다 높으므로 돈이 손실됩니다) 를 나타냅니다. 그러나 선물 수익은 스팟 손실보다 크습니다. 따라서 전체적으로 수익성이 있습니다. 이 상황은 단계 [8]의 차트에 해당합니다.
a1 - a2는 0보다 크다 b1 - b2는 0보다 작다 a1 - a2는 선물 수익의 가격 차이이고, b1 - b2는 스팟 수익의 가격 차이입니다 (b1 - b2는 0보다 작으며, b2가 b1보다 크다는 것을 나타냅니다. 즉, 포지션 개설 및 구매 가격은 낮고, 판매 및 폐쇄 가격은 높으므로 수익성이 있습니다.)
a1 - a2 0 보다 작다 b1 - b2 0 보다 작다 a1 - a2는 선물 손실의 가격 차이이고, b1 - b2는 즉석 이익의 가격 차이입니다. a1 - a2 > b1 - b2이기 때문에, a1 - a2의 절대 값은 b1 - b2의 절대 값보다 작고, 즉석 이익은 선물 손실보다 크습니다. 전체적으로 수익성이 있습니다.
a1 - a2가 0보다 작고 b1 - b2가 0보다 크다는 경우는 없습니다. 왜냐하면 a1 - a2 > b1 - b2가 정의되었기 때문입니다. 마찬가지로, a1 - a2가 0과 같다면, a1 - a2 > b1 - b2가 정의되기 때문에, b1 - b2는 0보다 작아야합니다. 따라서, 짧은 선물과 긴 스팟의 헤지 방식이 a1 - b1 > a2 - b2의 조건을 충족하는 한, 개장 및 폐쇄 포지션 작업은 수익 헤지입니다.
예를 들어, 다음 모델은 다음과 같은 경우 중 하나입니다.
[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()
외출[20]:
연구 환경은 파이썬뿐만 아니라 자바스크립트도 지원합니다. 자바스크립트 연구 환경의 예를 들어보겠습니다.
선물 포트 헤지링 원칙 분석 (JavaScript).ipynb [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}]
})
[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
외출[2]: { 재고: 0, 냉동재고: 0}
[3]에서:
var initSpotAcc = exchanges[1].GetAccount() // The initial account information of the OKX Spot Exchange is recorded in the variable initSpotAcc.
initSpotAcc
아웃[3]: { 재고: 10,000, FrozenBalance: 0, 재고: 0, FrozenStocks: 0 }
[4]:
var quarterTicker1 = exchanges[0].GetTicker() // Get the futures exchange ticker, recorded in the variable quarterTicker1.
quarterTicker1
아웃[4]: 시간: 1568851210000, 높은: 10441.25002, 낮은: 10441.25, 판매: 10441.25002, 구매: 10441.25, 마지막: 10441.25001 부: 1772, 오픈인터레스: 0 }
[5]에서:
var spotTicker1 = exchanges[1].GetTicker() // Get the spot exchange ticker, recorded in the variable spotTicker1.
spotTicker1
외출[5]: 시간: 1568851210000, 높은: 10156.60000002, 낮은: 10156.6, 판매: 10156.60000002, 구매: 10156.6, 마지막: 10156.60000001, 부문: 7.4443 오픈인터레스: 0 }
[6]에서:
quarterTicker1.Buy - spotTicker1.Sell // The price difference between going short on futures and going long on spot.
아웃[6]: 284.6499999799999985 [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.
아웃[7]:
{ id: 1,
가격은: 10441.25,
양: 10개
거래 금액: 10,
평균 가격: 10441.25,
종류: 1,
오프셋: 0
상태: 1,
계약 유형:
[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.
아웃[8]:
{ id: 1,
가격: 10156.60000002,
금액: 0.0957
거래 금액: 0.0957
평균 가격: 10156.60000002,
타입: 0
오프셋: 0
상태: 1,
계약 유형:
quarterId1과 spotId1의 명령이 완전히 채워졌다는 것을 볼 수 있습니다. 즉, 개설 포지션의 헤딩이 완료되었습니다.
[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.
대기 시간이 지나면, 포지션을 닫기 위해 준비.quarterTicker2
, spotTicker2
그리고 그들을 인쇄합니다.
선물 거래 대상의 거래 방향은 짧은 지위를 닫기 위해 설정됩니다.exchanges[0].SetDirection("closesell")
포지션을 닫는 명령을 내립니다.
클로저 포지션 오더의 세부 정보를 인쇄하여 클로저 오더가 완료되었다고 표시합니다.
[10]에서:
var quarterTicker2 = exchanges[0].GetTicker() // Get the current futures exchange ticker, recorded in the variable quarterTicker2.
quarterTicker2
아웃[10]: 시간: 1569456010000, 높은: 8497.20002, 낮은: 8497.2, 판매: 8497.20002, 구매: 8497.2, 마지막: 8497.20001 부문: 4311, 오픈인터레스: 0 }
[11]에서:
var spotTicker2 = exchanges[1].GetTicker() // Get the current ticker of the spot exchange, recorded in the variable spotTicker2.
spotTicker2
아웃[11]: { 시간: 1569456114600, 높은: 8444.70000001, 낮은: 8444.69999999, 판매: 8444.70000001, 구매: 8444.69999999, 마지막: 8444.7 78.6273 부지 오픈인터레스: 0 }
[12]에서:
quarterTicker2.Sell - spotTicker2.Buy // The price difference between closing short position of futures and closing long position of spot.
아웃[12]: 52.5000200100003
[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.
아웃[13]:
{ id: 2,
가격: 8497.20002,
양: 10개
거래 금액: 10,
평균 가격: 8493.95335,
타입: 0
오프셋: 1,
상태: 1,
계약 유형:
[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.
아웃[14]:
{ id: 2,
가격은: 8444.69999999,
금액: 0.0957
거래 금액: 0.0957,
평균 가격: 8444.69999999,
종류: 1,
오프셋: 0
상태: 1,
계약 타입:
[15]에서:
var nowQuarterAcc = exchanges[0].GetAccount() // Get the current futures exchange account information, recorded in the variable nowQuarterAcc.
nowQuarterAcc
외출[15]: { 잔액: 0, 얼어붙은 밸런스: 0 물자: 1.021786026184 FrozenStocks: 0
[16]에서:
var nowSpotAcc = exchanges[1].GetAccount() // Get the current spot exchange account information, recorded in the variable nowSpotAcc.
nowSpotAcc
외출[16]: { 잔액: 9834.74705446, 얼어붙은 밸런스: 0 양: 0, FrozenStocks: 0 초기계산과 courant계산을 비교함으로써 헤지업의 이익과 손실이 계산됩니다.
[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)
}
아웃[17]: 이익: 18.72350977580652
이제 왜 헤딩이 수익성이 있는지 봅시다. 그래프를 그려보겠습니다. 선물 가격은 파란색 선이고 스포트 가격은 오렌지 선입니다. 두 가격 모두 감소하고 있습니다. 선물 가격은 스포트 가격보다 빠르게 감소하고 있습니다.
[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}])
아웃[18]: 가격 차이의 변화를 살펴보자. 가격 차이는 헤지 오픈 포지션 (즉, 선물은 짧고 스팟은 길게) 의 284에서 폐쇄 (예약의 짧은 포지션 폐쇄 및 스팟의 긴 포지션 폐쇄) 의 52까지 다양합니다. 가격 차이는 크기에서 작습니다.
[19]에서:
var arrDiffPrice = [quarterTicker1.Buy - spotTicker1.Sell, quarterTicker2.Sell - spotTicker2.Buy]
plot(arrDiffPrice)
아웃[19]:예를 들어, a1은 시간 1의 선물 가격이고, b1은 시간 1의 스팟 가격이다. A2는 시간 2의 선물 가격이고, b2는 시간 2의 스팟 가격이다.시점 1 (a1-b1) 의 선물 현장 가격 차이는 시점 2 (a2-b2) 의 선물 현장 가격 차이보다 크면 a1 - a2>b1 - b2를 도입할 수 있습니다. 세 가지 상황이 있습니다. (미래상과 현금상의 양은 동일합니다.)
a1 - a2는 0보다 크다 b1 - b2는 0보다 크다 a1 - a2는 선물 수익의 가격 차이, 그리고 b1 - b2는 스팟 손실의 가격 차이 (스팟이 길어졌기 때문에 구매 시작 가격은 포지션을 닫는 판매 가격보다 높으므로 돈이 손실됩니다) 를 나타냅니다. 그러나 선물 수익은 스팟 손실보다 크습니다. 따라서 전체적으로 수익성이 있습니다. 이 상황은 단계 [8]의 차트에 해당합니다.
a1 - a2는 0보다 크다 b1 - b2는 0보다 작다 a1 - a2는 선물 수익의 가격 차이이고, b1 - b2는 스팟 수익의 가격 차이입니다 (b1 - b2는 0보다 작으며, b2가 b1보다 크다는 것을 나타냅니다. 즉, 포지션 개설 및 구매 가격은 낮고, 판매 및 폐쇄 가격은 높으므로 수익성이 있습니다.)
a1 - a2 0 보다 작다 b1 - b2 0 보다 작다 a1 - a2는 선물 손실의 가격 차이이고, b1 - b2는 즉석 이익의 가격 차이입니다. a1 - a2 > b1 - b2이기 때문에, a1 - a2의 절대 값은 b1 - b2의 절대 값보다 작고, 즉석 이익은 선물 손실보다 크습니다. 전체적으로 수익성이 있습니다.
a1 - a2가 0보다 작고 b1 - b2가 0보다 크다는 경우는 없습니다. 왜냐하면 a1 - a2 > b1 - b2가 정의되었기 때문입니다. 마찬가지로, a1 - a2가 0과 같다면, a1 - a2 > b1 - b2가 정의되기 때문에, b1 - b2는 0보다 작아야합니다. 따라서, 짧은 선물과 긴 스팟의 헤지 방식이 a1 - b1 > a2 - b2의 조건을 충족하는 한, 개장 및 폐쇄 포지션 작업은 수익 헤지입니다.
예를 들어, 다음 모델은 다음과 같은 경우 중 하나입니다.
[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}])
외출[20]:
시도해 보세요!