Type/to search
3
Follow
1505
Followers
디지털 화폐 페어 거래 전략에 대한 자세한 설명
Discussions
Created 2024-07-05 16:23:42  Updated 2024-11-05 17:42:06
 3
 6566

img

디지털 화폐 페어 거래 전략에 대한 자세한 설명

소개

최근에 저는 Buu의 양적 일기를 보았는데, 거기에는 음의 상관관계를 갖는 통화를 사용하여 통화를 선택할 수 있고, 가격 차이 돌파에 따라 수익을 내기 위해 포지션을 오픈할 수 있다는 내용이 언급되어 있었습니다. 디지털 통화는 기본적으로 양의 상관관계가 있고, 소수의 통화만이 음의 상관관계를 가지고 있습니다. 종종 MEME 코인의 독립적인 시장 조건과 같이 시장 추세를 전혀 따르지 않는 특별한 시장 조건이 있습니다. 필터링 이러한 통화들은 돌파구가 생긴 후에도 오랫동안 가격이 유지되며, 이 방법은 특정 시장 조건 하에서 수익을 낼 수 있습니다. 그러나 양적 거래 분야에서 가장 흔한 방법은 페어 거래에 양의 상관관계를 사용하는 것입니다. 이 글에서는 이 전략을 간략하게 소개합니다.

암호화폐 페어 트레이딩은 통계적 차익거래를 기반으로 한 트레이딩 전략으로, 상관관계가 높은 두 개의 암호화폐 영구 계약을 동시에 매수 및 매도하여 가격 편차를 이용해 수익을 올리는 것을 목표로 합니다. 이 글에서는 전략의 원칙, 수익 메커니즘, 통화 선별 방법, 잠재적 위험 및 이를 개선하는 방법을 소개하고 몇 가지 실용적인 Python 코드 예제를 제공합니다.

전략 원칙

페어 트레이딩 전략은 두 암호화폐의 가격 간의 과거 상관관계에 의존합니다. 두 통화가 강력한 상관관계를 가지고 있으면, 두 통화의 가격은 대략적으로 동기화되어 움직입니다. 특정 순간에 두 가격의 비율에 큰 차이가 생긴다면 이는 일시적인 이상 현상으로 볼 수 있으며, 가격은 정상 수준으로 돌아가는 경향이 있습니다. 디지털 통화 시장은 매우 상호 연결되어 있습니다. 주요 디지털 통화(예: 비트코인)가 상당한 변동을 겪을 때 일반적으로 다른 디지털 통화 간의 연쇄 반응을 유발합니다. 일부 통화는 매우 확실한 긍정적 상관관계를 보일 수 있으며, 같은 투자 기관, 같은 시장 조성자, 같은 트랙에 속하기 때문에 그 상관관계가 지속될 수도 있습니다. 일부 통화는 음의 상관관계를 가지고 있지만, 음의 상관관계를 가진 통화는 그 수가 적고, 모두 전체 시장 추세에 영향을 받기 때문에 일관된 시장 추세를 보이는 경우가 많습니다.

동전 A와 동전 B의 가격 상관관계가 높다고 가정해보자. 특정 시점에서 A/B 가격 비율의 평균값은 1입니다. 특정 시점에서 A/B 가격 비율이 증가에서 0.001 이상, 즉 1.001 이상 벗어나면 다음과 같은 방식으로 거래할 수 있습니다. B에 롱 포지션을 열고 A에 숏 포지션을 엽니다. . 반대로, A/B 가격 비율이 0.999보다 낮은 경우: A에 롱 포지션을, B에 숏 포지션을 엽니다.

수익성의 핵심은 가격이 변동하여 정상화될 때 발생하는 가격 차이의 이익에 있습니다. 가격 편차는 보통 단기적으로 지속되므로, 트레이더는 가격이 평균으로 회귀하면 포지션을 정리하고 그 차이에서 수익을 낼 수 있습니다.

데이터 준비

해당 라이브러리를 가져옵니다

이러한 코드는 직접 사용할 수도 있지만, Anancoda를 다운로드하여 Jupyer Notebook에서 디버깅하는 것이 가장 좋습니다. 일반적으로 사용되는 데이터 분석을 위한 패키지를 직접 포함합니다.

python
import requests from datetime import date,datetime import time import pandas as pd import numpy as np import matplotlib.pyplot as plt import requests, zipfile, io %matplotlib inline

거래 중인 모든 거래 쌍을 가져옵니다.

python
Info = requests.get('https://fapi.binance.com/fapi/v1/exchangeInfo') b_symbols = [s['symbol'] for s in Info.json()['symbols'] if s['contractType'] == 'PERPETUAL' and s['status'] == 'TRADING' and s['quoteAsset'] == 'USDT'] b_symbols = list(filter(lambda x: x[-4:] == 'USDT', [s.split('_')[0] for s in b_symbols])) b_symbols = [x[:-4] for x in b_symbols] print(b_symbols) # 获取所有的正在交易的交易对

K-line 함수 다운로드

GetKlines 함수의 주요 기능은 Binance 거래소에서 지정된 거래 쌍의 무기한 계약에 대한 과거 K-라인 데이터를 얻고 이 데이터를 Pandas DataFrame에 저장하는 것입니다. K-라인 데이터에는 시가, 최고가, 최저가, 종가, 거래량 및 기타 정보가 포함됩니다. 이번에는 주로 종가 데이터를 활용했습니다.

python
def GetKlines(symbol='BTCUSDT',start='2020-8-10',end='2024-7-01',period='1h',base='fapi',v = 'v1'): Klines = [] start_time = int(time.mktime(datetime.strptime(start, "%Y-%m-%d").timetuple()))*1000 + 8*60*60*1000 end_time = min(int(time.mktime(datetime.strptime(end, "%Y-%m-%d").timetuple()))*1000 + 8*60*60*1000,time.time()*1000) intervel_map = {'m':60*1000,'h':60*60*1000,'d':24*60*60*1000} while start_time < end_time: time.sleep(0.3) mid_time = start_time+1000*int(period[:-1])*intervel_map[period[-1]] url = 'https://'+base+'.binance.com/'+base+'/'+v+'/klines?symbol=%s&interval=%s&startTime=%s&endTime=%s&limit=1000'%(symbol,period,start_time,mid_time) res = requests.get(url) res_list = res.json() if type(res_list) == list and len(res_list) > 0: start_time = res_list[-1][0]+int(period[:-1])*intervel_map[period[-1]] Klines += res_list if type(res_list) == list and len(res_list) == 0: start_time = start_time+1000*int(period[:-1])*intervel_map[period[-1]] if mid_time >= end_time: break df = pd.DataFrame(Klines,columns=['time','open','high','low','close','amount','end_time','volume','count','buy_amount','buy_volume','null']).astype('float') df.index = pd.to_datetime(df.time,unit='ms') return df

데이터 다운로드

데이터 양이 비교적 많습니다. 더 빠르게 다운로드하기 위해 지난 3개월 동안의 시간별 K-line 데이터만 얻었습니다. df_close에는 모든 통화에 대한 종가 데이터가 포함되어 있습니다.

python
start_date = '2024-04-01' end_date = '2024-07-05' period = '1h' df_dict = {} for symbol in b_symbols: print(symbol) if symbol in df_dict.keys(): continue df_s = GetKlines(symbol=symbol+'USDT',start=start_date,end=end_date,period=period) if not df_s.empty: df_dict[symbol] = df_s df_close = pd.DataFrame(index=pd.date_range(start=start_date, end=end_date, freq=period),columns=df_dict.keys()) for symbol in symbols: df_close[symbol] = df_dict[symbol].close df_close = df_close.dropna(how='all')

백테스팅 엔진

다음 백테스트에 대한 Exchange 객체를 정의합니다.

python
class Exchange: def __init__(self, trade_symbols, fee=0.0002, initial_balance=10000): self.initial_balance = initial_balance #初始的资产 self.fee = fee self.trade_symbols = trade_symbols self.account = {'USDT':{'realised_profit':0, 'unrealised_profit':0, 'total':initial_balance, 'fee':0, 'leverage':0, 'hold':0, 'long':0, 'short':0}} for symbol in trade_symbols: self.account[symbol] = {'amount':0, 'hold_price':0, 'value':0, 'price':0, 'realised_profit':0,'unrealised_profit':0,'fee':0} def Trade(self, symbol, direction, price, amount): cover_amount = 0 if direction*self.account[symbol]['amount'] >=0 else min(abs(self.account[symbol]['amount']), amount) open_amount = amount - cover_amount self.account['USDT']['realised_profit'] -= price*amount*self.fee #扣除手续费 self.account['USDT']['fee'] += price*amount*self.fee self.account[symbol]['fee'] += price*amount*self.fee if cover_amount > 0: #先平仓 self.account['USDT']['realised_profit'] += -direction*(price - self.account[symbol]['hold_price'])*cover_amount #利润 self.account[symbol]['realised_profit'] += -direction*(price - self.account[symbol]['hold_price'])*cover_amount self.account[symbol]['amount'] -= -direction*cover_amount 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[symbol]['hold_price'] = total_cost/total_amount self.account[symbol]['amount'] += direction*open_amount def Buy(self, symbol, price, amount): self.Trade(symbol, 1, price, amount) def Sell(self, symbol, price, amount): self.Trade(symbol, -1, price, amount) def Update(self, close_price): #对资产进行更新 self.account['USDT']['unrealised_profit'] = 0 self.account['USDT']['hold'] = 0 self.account['USDT']['long'] = 0 self.account['USDT']['short'] = 0 for symbol in self.trade_symbols: if not np.isnan(close_price[symbol]): 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'] = self.account[symbol]['amount']*close_price[symbol] if self.account[symbol]['amount'] > 0: self.account['USDT']['long'] += self.account[symbol]['value'] if self.account[symbol]['amount'] < 0: self.account['USDT']['short'] += self.account[symbol]['value'] self.account['USDT']['hold'] += abs(self.account[symbol]['value']) 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']['hold']/self.account['USDT']['total'],3)

통화 필터링을 위한 상관관계 분석

상관관계 계산은 두 변수 간의 선형 관계를 측정하는 데 사용되는 통계학적 방법입니다. 가장 일반적으로 사용되는 상관관계 계산 방법은 피어슨 상관 계수입니다. 상관관계 계산의 원칙, 공식, 구현 방법은 아래와 같습니다. 피어슨 상관 계수는 두 변수 간의 선형 관계를 측정하는 데 사용되며 값 범위는 -1과 1 사이입니다.

  • 1 두 변수가 항상 동시에 변하는 완벽한 양의 상관관계를 나타냅니다. 한 변수가 증가하면, 다른 변수도 비례해서 증가합니다. 1에 가까울수록 상관관계가 강해집니다.
  • -1 두 변수가 항상 반대 방향으로 변하는 완벽한 음의 상관관계를 나타냅니다. -1에 가까울수록 음의 상관관계가 강하다는 것을 의미합니다.
  • 0 선형 상관관계가 없음을 나타내며, 두 변수 사이에 직선 관계가 없습니다.

피어슨 상관계수는 공분산과 표준편차를 계산하여 두 변수 간의 상관관계를 결정합니다. 공식은 다음과 같습니다.

[ \rho_{X,Y} = \frac{\text{cov}(X,Y)}{\sigma_X \sigma_Y} ]

안에:

  • ( \rho_{X,Y} ) 변수입니다( X ) 그리고 ( Y ) 피어슨 상관계수.
  • ( \text{cov}(X,Y) ) 예 ( X ) 그리고 ( Y ) .의 공분산.
  • ( \sigma_X ) 그리고 ( \sigma_Y ) 그들은( X ) 그리고 ( Y ) .의 표준편차.

물론, 계산 방법에 대해 너무 걱정할 필요는 없습니다. 단 한 줄의 Python 코드로 모든 통화의 상관관계를 계산할 수 있습니다. 그림은 상관관계 히트 맵을 보여줍니다. 빨간색은 양의 상관관계를 나타내고, 파란색은 음의 상관관계를 나타내며, 색상이 진할수록 상관관계가 강합니다. 넓은 영역이 진한 빨간색으로 표시되어 있어 디지털 화폐의 양의 상관관계가 매우 강함을 알 수 있습니다.

img

python
import seaborn as sns corr = df_close.corr() plt.figure(figsize=(20, 20)) sns.heatmap(corr, annot=False, cmap='coolwarm', vmin=-1, vmax=1) plt.title('Correlation Heatmap of Cryptocurrency Closing Prices', fontsize=20);

상관관계를 바탕으로 가장 관련성이 높은 상위 20개의 통화 쌍이 선택됩니다. 결과는 다음과 같습니다. 상관관계는 모두 0.99 이상으로 매우 강합니다.

MANA SAND 0.996562 ICX ZIL 0.996000 STORJ FLOW 0.994193 FLOW SXP 0.993861 STORJ SXP 0.993822 IOTA ZIL 0.993204 SAND 0.993095 KAVA SAND 0.992303 ZIL SXP 0.992285 SAND 0.992103 DYDX ZIL 0.992053 DENT REEF 0.991789 RDNT MANTA 0.991690 STMX STORJ 0.991222 BIGTIME ACE 0.990987 RDNT HOOK 0.990718 IOST GAS 0.990643 ZIL HOOK 0.990576 MATIC FLOW 0.990564 MANTA HOOK 0.990563

해당 코드는 다음과 같습니다.

python
corr_pairs = corr.unstack() # 移除自身相关性(即对角线上的值) corr_pairs = corr_pairs[corr_pairs != 1] sorted_corr_pairs = corr_pairs.sort_values(kind="quicksort") # 提取最相关和最不相关的前20个币种对 most_correlated = sorted_corr_pairs.tail(40)[::-2] print("最相关的前20个币种对:") print(most_correlated)

백테스팅 검증

구체적인 백테스트 코드는 다음과 같습니다. 데모 전략은 두 가지 암호화폐(IOTA와 ZIL)의 가격 비율을 관찰하고 이 비율의 변화에 ​​따라 거래하는 데 중점을 둡니다. 구체적인 단계는 다음과 같습니다.

  1. 초기화

    • 거래 쌍을 정의합니다(pair_a = 'IOTA', pair_b = 'ZIL').
    • 교환 객체 생성e초기 잔액은 10,000달러이고 거래 수수료는 0.02%입니다.
    • 초기 평균 가격 비율 계산avg
    • 초기 거래 가치 설정value = 1000
  2. 반복적으로 가격 데이터 처리

    • 각 시간 지점의 가격 데이터를 탐색합니다.df_close
    • 현재 가격 비율의 평균으로부터의 편차를 계산합니다.diff
    • 편차를 기준으로 목표 거래 가치를 계산합니다.aim_value0.01의 편차마다 하나의 값을 교환합니다. 그리고 현재 계좌 포지션과 가격 상황에 따라 매수 및 매도 작업을 결정합니다.
    • 편차가 너무 큰 경우 매도를 실행하세요.pair_a 그리고 구매하다pair_b 작동하다.
    • 편차가 너무 작으면 매수를 실행하세요.pair_a 그리고 판매하다pair_b 작동하다.
  3. 조정된 평균

    • 업데이트된 평균 가격 비율avg최신 가격 비율을 반영하기 위해.
  4. 계정 및 기록 업데이트

    • 거래소 계좌의 포지션 및 잔액 정보를 업데이트합니다.
    • 각 단계의 계정 상태(총 자산, 보유 자산, 거래 수수료, 롱 포지션 및 숏 포지션)를 기록합니다.res_list
  5. 결과 출력

    • 할 것이다 res_list 데이터 프레임으로 변환res추가 분석 및 프레젠테이션을 위해.
python
pair_a = 'IOTA' pair_b = "ZIL" e = Exchange([pair_a,pair_b], fee=0.0002, initial_balance=10000) #Exchange定义放在评论区 res_list = [] index_list = [] avg = df_close[pair_a][0] / df_close[pair_b][0] value = 1000 for idx, row in df_close.iterrows(): diff = (row[pair_a] / row[pair_b] - avg)/avg aim_value = -value * diff / 0.01 if -aim_value + e.account[pair_a]['amount']*row[pair_a] > 0.5*value: e.Sell(pair_a,row[pair_a],(-aim_value + e.account[pair_a]['amount']*row[pair_a])/row[pair_a]) e.Buy(pair_b,row[pair_b],(-aim_value - e.account[pair_b]['amount']*row[pair_b])/row[pair_b]) if -aim_value + e.account[pair_a]['amount']*row[pair_a] < -0.5*value: e.Buy(pair_a, row[pair_a],(aim_value - e.account[pair_a]['amount']*row[pair_a])/row[pair_a]) e.Sell(pair_b, row[pair_b],(aim_value + e.account[pair_b]['amount']*row[pair_b])/row[pair_b]) avg = 0.99*avg + 0.01*row[pair_a] / row[pair_b] index_list.append(idx) e.Update(row) res_list.append([e.account['USDT']['total'],e.account['USDT']['hold'], e.account['USDT']['fee'],e.account['USDT']['long'],e.account['USDT']['short']]) res = pd.DataFrame(data=res_list, columns=['total','hold', 'fee', 'long', 'short'],index = index_list) res['total'].plot(grid=True);

총 4개의 통화 그룹에 대해 백테스트를 실시하였고, 그 결과는 비교적 이상적이었습니다. 현재의 상관관계 계산은 미래의 데이터를 사용하므로 그다지 정확하지 않습니다. 이 글에서는 또한 데이터를 두 부분으로 나눕니다. 앞부분은 계산된 상관관계를 나타내고, 뒷부분은 백테스트된 거래를 나타냅니다. 결과는 약간 떨어졌지만 여전히 꽤 좋았습니다. 검증은 사용자에게 맡겨집니다.

img

잠재적 위험 및 개선 방법

페어 트레이딩 전략은 이론상으로는 수익성이 있을 수 있지만, 실제로 운영되는 데는 여전히 몇 가지 위험이 있습니다. 즉, 시간이 지남에 따라 통화 간 상관관계가 변하여 전략이 실패할 수 있으며, 극단적인 시장 상황에서는 가격 편차가 커져 큰 손실이 발생할 수 있습니다. 특정 통화의 유동성이 낮아 거래 실행이 어려워지거나 비용이 증가할 수 있으며, 빈번한 거래로 인해 발생하는 수수료로 인해 수익이 잠식될 수 있습니다.

위험을 줄이고 전략의 안정성을 높이기 위해 다음과 같은 개선 조치를 고려할 수 있습니다. 정기적으로 통화 간 상관관계를 다시 계산하고 거래 쌍을 적절한 시기에 조정합니다. 손절매 지점과 이익실현 지점을 설정하여 단일 거래의 최대 손실을 통제합니다. 위험을 분산하기 위해 다양한 코인 쌍을 거래하세요.

결론적으로

디지털 통화 쌍 거래 전략은 통화 가격 간의 상관관계를 활용하고, 가격이 변동할 때 차익거래를 수행하여 수익을 창출합니다. 이 전략은 이론적으로 실현 가능성이 높습니다. 이 전략을 기반으로 한 간단한 실시간 전략 소스 코드는 나중에 공개될 예정입니다. 더 궁금한 점이 있거나 추가 논의가 필요하면 언제든지 문의하세요.

Comment
All comments (2)

    这个值得研究,码源呢?

    2 years ago

    张总加班 - -! 哈哈哈

    2 years ago
  • 1
iPhone Download
Forums
PINE Language
© 2015 - ∞ INVENTOR PTE LTD (SG)