최근, 바이낸스 선물은 두 번째
바이낸스 챔피언십을 위해 준비된 전략은 배달 계약의 나비 헤지입니다. 이 기사는 전략의 연구 보고서입니다. 주의: 전략은 참고용입니다. 이 기반에 최적화를 위해 자신의 아이디어를 제시 할 수 있습니다. 또한 공유 할 수 있습니다. 보고서는 FMZ 웹 사이트의 연구 환경에서 직접 사용할 수 있습니다 (다운로드하려면 오른쪽 상단에 클릭하고
헤딩은 안정적인 가격 차이를 찾아야 한다. 가격 차이가 너무 커지면 가격 차이를 단축한다. 가격 차이가 너무 작을 때 가격 차이를 길게 한다. 가격 차이가 포지션을 닫기 위해 돌아왔을 때 가격 차이를 벌인다. 선물과 스팟이 헤딩을 한다면, 배달되지 않은 선물의 가격이 스팟 가격보다 훨씬 높을 때 선물 계약을 단축하고 스팟 가격을 길게 하여 가격 차이를 단축할 수 있다. 또한 서로 다른 배달 시간, 선물과 스팟 헤딩을 가진 계약의 시간 간 헤딩도 있다. 선물과 스팟과 크로스 퓨처스는 치열한 경쟁을 가진 일반적인 전략이다. 시장이 없을 때 가격 차이가 상대적으로 안정적이다. 장기 시장이 될 수 있지만 기회는 거의 없으며 수동 운영도 필요하다. 모두 안정적인 가격 차이를 추구하기 때문에, 거래가 가능한 세 가지 계약이 있기 때문에, 이 또한 배추 거래에 대한 헤딩이라고도 불린다.
바이낸스 화폐 표준 계약은 BTC와 ETH와 같이 세 개의 계약을 동시에 가지고 있으며, 즉, 현재 분기 BTCUSD_ PERP, BTCUSD_200925의 영구, BTCUSD_ 201225의 다음 분기. 영구 계약은 스팟으로 사용할 수 있습니다. 일반적으로 두 계약을 헤지하기 위해 세 가지 가격 차이점이 있습니다. 현재 분기 영구, 다음 분기 영구, 다음 분기 현재 분기. 나비 중재는 세 개의 계약을 필요로합니다. 차이점은 (다음 분기 - 현재 분기) - (현재 분기 - 영구), 즉 차이 = 다음 분기 + 영구 - 2 * 현재 분기 가격. 차이점을 길게하려면 다음 분기 및 영구 계약에 대한 긴 포지션 계약을 열고 현재 분기에 대한 두 개의 계약을 단축해야합니다.
저는 8월 14일부터 9월 14일까지 바이낸스의 5분 K-라인 데이터를 탐색했는데, 바로 읽을 수 있습니다. (시간차로 인해 표시된 시간차는 8시간입니다.)
[4]:
# Libraries to be imported
import pandas as pd
import requests
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import time
%matplotlib inline
[12]에서:
#Read the data, you can also upload the data to the FMZ forum, which can be referenced in the "Analyze" directly
df = pd.read_csv('https://www.fmz.com/upload/asset/1420b2081ecd122522d.csv',index_col = 0)
df.index = pd.to_datetime(df.index)
df.tail(3)
아웃[12]:
먼저, 비트코인 계약 사이의 가격 차이를 살펴보자. 8월 17일, 비트코인의 가격은 500u로 급격히 상승했다. 일반적으로, 배달된 계약은 현금 가격에 비해 프리미엄에 있었고, 현금 가격이 상승했다. 미래에 대한 기대는 더 낙관적일 것이다. 배달되지 않은 계약과 영구 계약 사이의 가격 차이는 커질 것이다. 예를 들어, 다음 분기와 영구 계약 사이의 가격 차이는 700u이 될 것이다. 9월 비트코인 가격 하락과 함께, 사람들의 기대는 빠르게 악화 될 것이다, 다음 분기와 영구 계약 사이의 가격 차이는 약 150u로 떨어졌고, 현재 분기와 영구 계약 사이의 가격 차이는 거의 없었다. 다음 분기와 영구 계약 사이의 헤지징이 수행된다면, 큰 장기 가격의 반환만 수행될 수 있을 것이다. 만약 400-600 오그스트 사이의 차이는 현재 상태로 수행하기로 결정되었다면, 분명히 잠겨 있다.
[18]에서:
#Perpetual price
df['BTCUSD_PERP'].dropna().plot(figsize=(15,6),grid=True);
아웃[18]:
[15]에서:
# Price difference of next quarter - perpetual
(df['BTCUSD_201225']-df['BTCUSD_PERP']).dropna().plot(figsize=(15,6),grid=True);
외출[15]:
[16]에서:
# Price difference of current quarter - perpetual
(df['BTCUSD_200925']-df['BTCUSD_PERP']).dropna().plot(figsize=(15,6),grid=True);
외출[16]:
[17]에서:
# Price difference of next quarter - current quarter
(df['BTCUSD_201225']-df['BTCUSD_200925']).dropna().plot(figsize=(15,6),grid=True);
아웃[17]:
따라서 가격 차이는 지금 어떻게 변하고 있습니까? 아래 그림에서 볼 수 있듯이 최근 가격 차이는 오랫동안 100-200u에서 안정되어 있습니다. 9 월 초에 급격한 하락도 큰 영향을 미치지 않고 반복적 인 중재에 많은 공간을 제공합니다. 현재, 가격 차이가 100u로 떨어지면 수동으로 긴 거리로 가는 것이 좋습니다.
현금 가격이 변동할 때, 두 개의 만료되지 않은 계약은 동시에 미래에 대한 기대를 반영합니다. 가격 차이 감소 과정은 이러한 변동을 상당 부분 상쇄 할 수 있으며 성능은 상대적으로 안정적입니다. ETH의 나비 중재 스프레드는 유사한 성능을 가지고 있습니다.
[19]에서:
#(next quarter - current quarter)-(current quarter - perpetual)
(df['BTCUSD_201225']-df['BTCUSD_200925']-(df['BTCUSD_200925']-df['BTCUSD_PERP'])).dropna().plot(figsize=(15,6),grid=True);
아웃[19]:
[22]에서:
#The price difference of ETH
(df['ETHUSD_201225']+df['ETHUSD_PERP']-2*df['ETHUSD_200925']).dropna().plot(figsize=(15,6),grid=True);
외출[22]:
시간을 절약하기 위해 (단 게으름), 백테스트는 여전히 마지막 바이낸스 챔피언십 전략의 USDT 표준 엔진을 사용합니다. 약간의 오류가있을 수 있지만 문제를 설명 할 수도 있습니다. 백테스트 엔진은이 보고서의 끝에 배치됩니다. 코드를 실행 할 때 기사 끝을 보아야합니다. 통화 표준 전략은 USDT를 벌고 싶다면 헤지를 고려 할 수 있으며 복잡하지 않습니다.
가격차이의 중간선은 EMA에 의해 추적되며, 포지션은 격자로 제어됩니다. 즉, 차이가 열릴 때마다 (예를 들어 30), N 주식을 단축하고 반대로합니다. 가격차이의 중간선은 100u이고, 가격차이는 90일 때, 3 주식을 단축하고, 가격차이는 60이됩니다. 격자의 크기는 주요 매개 변수입니다.
다음은 BTC 및 ETH 백테스팅의 특정 코드 및 결과입니다. 성능은 기대에 부합합니다. ETH와 LINK가 더 큰 변동성을 가지고 있으며 가격 차이가 더 안정적이기 때문에 성능이 좋습니다. 여기서 서비스 요금이 0.02%, 바이낸스의 기본 VIP0 사용자 서비스 요금이 0.04%입니다. 서비스 요금은 매우 중요하며 다음 장에서 분석 할 것입니다.
[39]에서:
trade_symbols = ['BTCUSD_201225', 'BTCUSD_200925', 'BTCUSD_PERP']
account = []
diff = df['BTCUSD_201225']+df['BTCUSD_PERP']-2*df['BTCUSD_200925']
diff_mean = diff.ewm(alpha=0.001).mean()
e = Exchange(trade_symbols,initial_balance=10000,taker_fee=0.0002)
for row in df[trade_symbols].dropna().iterrows():
date = row[0]
prices = row[1]
e.Update(date, trade_symbols, prices)
account.append([e.account['USDT']['margin'],e.account['USDT']['realised_profit']+e.account['USDT']['unrealised_profit']])
aim_amount = -round((diff[date] - diff_mean[date])/30,1)
now_amount = e.account['BTCUSD_PERP']['amount']
if aim_amount - now_amount < -1:
trade_amount = now_amount - aim_amount
e.Buy('BTCUSD_200925',prices['BTCUSD_200925'],2*trade_amount)
e.Sell('BTCUSD_201225',prices['BTCUSD_201225'],trade_amount)
e.Sell('BTCUSD_PERP',prices['BTCUSD_PERP'],trade_amount)
if aim_amount - now_amount > 1:
trade_amount = aim_amount - now_amount
e.Sell('BTCUSD_200925',prices['BTCUSD_200925'],2*trade_amount)
e.Buy('BTCUSD_201225',prices['BTCUSD_201225'],trade_amount)
e.Buy('BTCUSD_PERP',prices['BTCUSD_PERP'],trade_amount)
e.df = pd.DataFrame(index=df[trade_symbols].dropna().index,columns=['margin','profit'],data=account)
e.df['profit'].plot(figsize=(15,6),grid=True);
아웃[39]:
[59]에서:
symbol = 'ETH'
trade_symbols = [symbol+'USD_201225', symbol+'USD_200925', symbol+'USD_PERP']
fee = 0.0002
account = []
diff = df[trade_symbols[0]]+df[trade_symbols[2]]-2*df[trade_symbols[1]]
diff_mean = diff.ewm(alpha=0.001).mean()
e = Exchange(trade_symbols,initial_balance=10000,taker_fee=fee)
for row in df[trade_symbols].dropna().iloc[30:].iterrows():
date = row[0]
prices = row[1]
e.Update(date, trade_symbols, prices)
account.append([e.account['USDT']['margin'],e.account['USDT']['realised_profit']+e.account['USDT']['unrealised_profit']])
aim_amount = -round((diff[date] - diff_mean[date])/(15*prices[trade_symbols[2]]*fee),1)
now_amount = e.account[trade_symbols[2]]['amount']
if aim_amount - now_amount < -1:
trade_amount = 1
e.Buy(trade_symbols[1],prices[trade_symbols[1]],2*trade_amount)
e.Sell(trade_symbols[0],prices[trade_symbols[0]],trade_amount)
e.Sell(trade_symbols[2],prices[trade_symbols[2]],trade_amount)
if aim_amount - now_amount > 1:
trade_amount = 1
e.Sell(trade_symbols[1],prices[trade_symbols[1]],2*trade_amount)
e.Buy(trade_symbols[0],prices[trade_symbols[0]],trade_amount)
e.Buy(trade_symbols[2],prices[trade_symbols[2]],trade_amount)
e.df = pd.DataFrame(index=df[trade_symbols].dropna().iloc[30:].index,columns=['margin','profit'],data=account)
e.df['profit'].plot(figsize=(15,6),grid=True);
아웃[59]:
[60]에서:
symbol = 'LINK'
trade_symbols = [symbol+'USD_201225', symbol+'USD_200925', symbol+'USD_PERP']
fee = 0.0002
account = []
diff = df[trade_symbols[0]]+df[trade_symbols[2]]-2*df[trade_symbols[1]]
diff_mean = diff.ewm(alpha=0.001).mean()
e = Exchange(trade_symbols,initial_balance=10000,taker_fee=fee)
for row in df[trade_symbols].dropna().iloc[30:].iterrows():
date = row[0]
prices = row[1]
e.Update(date, trade_symbols, prices)
account.append([e.account['USDT']['margin'],e.account['USDT']['realised_profit']+e.account['USDT']['unrealised_profit']])
aim_amount = -round((diff[date] - diff_mean[date])/(15*prices[trade_symbols[2]]*fee),1)
now_amount = e.account[trade_symbols[2]]['amount']
if aim_amount - now_amount < -1:
trade_amount = 1
e.Buy(trade_symbols[1],prices[trade_symbols[1]],2*trade_amount)
e.Sell(trade_symbols[0],prices[trade_symbols[0]],trade_amount)
e.Sell(trade_symbols[2],prices[trade_symbols[2]],trade_amount)
if aim_amount - now_amount > 1:
trade_amount = 1
e.Sell(trade_symbols[1],prices[trade_symbols[1]],2*trade_amount)
e.Buy(trade_symbols[0],prices[trade_symbols[0]],trade_amount)
e.Buy(trade_symbols[2],prices[trade_symbols[2]],trade_amount)
e.df = pd.DataFrame(index=df[trade_symbols].dropna().iloc[30:].index,columns=['margin','profit'],data=account)
e.df['profit'].plot(figsize=(15,6),grid=True);
외출[60]:
3개의 계약이 동시에 운영되어야 하기 때문에, 오픈 후 포지션을 닫기 위해 8개의 서비스 요금이 필요하기 때문에, 서비스 요금은 전략에 큰 영향을 미친다. 0.01%의 서비스 요금이 있다면, 가격 차이 그리드 사이의 격차는 더욱 줄어들 수 있다. BTC
만약 수수료가 0.03%라면 BTC 백테스트 결과는 다음과 같습니다.
ETH의 백테스트 결과:
신규 등록 사용자에 대한 vip0의 수급률은 0.0004이며, 초청된 첫 달에 10%가 감소하고, 30%가 반환되며, BNB 소비에 10%가 감소됩니다. 따라서 최종 처리 수수료는 0.0002268입니다. 또한 바이낸스 배달 계약의 최근 큰 거래 금액에 대한 직접 보상도 있습니다. 또한, 청구서의 일부를 배치하고 청구서의 일부를 취할 수 있으며, 최종 종합 비율은 0.02로 감소 할 수 있습니다. 또한, FMZ 관계자는 바이낸스와 서비스 요금 할인 문제를 논의하고 있습니다. 기대할 수 있습니다.
중재의 목적은 안정적인 가격 차이를 찾는 것입니다. 가격 차이의 가격 차이는 더 안정적입니다. 따라서 나비 중재는 크로스 기간과 미래 스팟보다 훨씬 덜 위험하며 수동으로 작동 할 수도 있습니다. 이 전략은 소개로만 사용됩니다. 실제 봇에 글을 쓸 때 많은 문제가 고려되어야합니다. 모든 사람들이 소통하는 것을 환영합니다.
[23]에서:
class Exchange:
def __init__(self, trade_symbols, leverage=20, maker_fee=0.0002,taker_fee=0.0004,log='',initial_balance=10000):
self.initial_balance = initial_balance #Initial assets
self.taker_fee = taker_fee
self.maker_fee = maker_fee
self.leverage = leverage
self.trade_symbols = trade_symbols
self.date = ''
self.log = log
self.df = pd.DataFrame()
self.account = {'USDT':{'realised_profit':0, 'margin':0, 'unrealised_profit':0,
'total':initial_balance, 'leverage':0, 'fee':0,'maker_fee':0,'taker_fee':0}}
for symbol in trade_symbols:
self.account[symbol] = {'amount':0, 'hold_price':0, 'value':0, 'price':0, 'realised_profit':0,
'margin':0, 'unrealised_profit':0,'fee':0}
def Trade(self, symbol, direction, price, amount, msg='', maker=True):
if (self.date and symbol == self.log) or self.log == 'all':
print('%-26s%-15s%-5s%-10.8s%-8.6s %s'%(str(self.date)[:24], symbol, 'buy' if direction == 1 else 'sell', price, amount, msg))
cover_amount = 0 if direction*self.account[symbol]['amount'] >=0 else min(abs(self.account[symbol]['amount']), amount)
open_amount = amount - cover_amount
if maker:
self.account['USDT']['realised_profit'] -= price*amount*self.maker_fee #Deduct service charge
self.account['USDT']['maker_fee'] += price*amount*self.maker_fee
self.account['USDT']['fee'] += price*amount*self.maker_fee
self.account[symbol]['fee'] += price*amount*self.maker_fee
else:
self.account['USDT']['realised_profit'] -= price*amount*self.taker_fee #Deduct service charge
self.account['USDT']['taker_fee'] += price*amount*self.taker_fee
self.account['USDT']['fee'] += price*amount*self.taker_fee
self.account[symbol]['fee'] += price*amount*self.taker_fee
if cover_amount > 0: #Close the position first
self.account['USDT']['realised_profit'] += -direction*(price - self.account[symbol]['hold_price'])*cover_amount #Profit
self.account['USDT']['margin'] -= cover_amount*self.account[symbol]['hold_price']/self.leverage #Release margin
self.account[symbol]['realised_profit'] += -direction*(price - self.account[symbol]['hold_price'])*cover_amount
self.account[symbol]['amount'] -= -direction*cover_amount
self.account[symbol]['margin'] -= cover_amount*self.account[symbol]['hold_price']/self.leverage
self.account[symbol]['hold_price'] = 0 if self.account[symbol]['amount'] == 0 else self.account[symbol]['hold_price']
if open_amount > 0:
total_cost = self.account[symbol]['hold_price']*direction*self.account[symbol]['amount'] + price*open_amount
total_amount = direction*self.account[symbol]['amount']+open_amount
self.account['USDT']['margin'] += open_amount*price/self.leverage
self.account[symbol]['hold_price'] = total_cost/total_amount
self.account[symbol]['amount'] += direction*open_amount
self.account[symbol]['margin'] += open_amount*price/self.leverage
self.account[symbol]['unrealised_profit'] = (price - self.account[symbol]['hold_price'])*self.account[symbol]['amount']
self.account[symbol]['price'] = price
self.account[symbol]['value'] = abs(self.account[symbol]['amount'])*price
def Buy(self, symbol, price, amount, msg='', maker=False):
self.Trade(symbol, 1, price, amount, msg, maker)
def Sell(self, symbol, price, amount, msg='', maker=False):
self.Trade(symbol, -1, price, amount, msg,maker)
def Update(self, date, symbols, close_price): #Update the assets
self.date = date
self.close = close_price
self.account['USDT']['unrealised_profit'] = 0
for symbol in symbols:
self.account[symbol]['unrealised_profit'] = (close_price[symbol] - self.account[symbol]['hold_price'])*self.account[symbol]['amount']
self.account[symbol]['price'] = close_price[symbol]
self.account[symbol]['value'] = abs(self.account[symbol]['amount'])*close_price[symbol]
self.account['USDT']['unrealised_profit'] += self.account[symbol]['unrealised_profit']
self.account['USDT']['total'] = round(self.account['USDT']['realised_profit'] + self.initial_balance + self.account['USDT']['unrealised_profit'],6)
self.account['USDT']['leverage'] = round(self.account['USDT']['margin']*self.leverage/self.account['USDT']['total'],4)
[ ]에서: