돈벌고싶다

파이썬을 이용한 페어 트레이딩과 실패 본문

코인과코딩, 그리고 인공지능

파이썬을 이용한 페어 트레이딩과 실패

coinwithpython 2022. 8. 29. 01:13
728x90
반응형

결론

결론부터 말하자면, 난 해당 코드를 이용한 전략을 사용하고 있지 않다. 하지만 코인들간의 상관관계를 분석하고 싶은 사람이 있다면, 코드를 유용하게 사용할 수 있을 듯 하여 정리한 부분을 공유한다. 해당 전략을 사용하지 않는 이유는 다음과 같다.

 

  1. pair trading을 진행할 두 종목에 대해 공적분 계수를 구할 경우 항상 오차율이 존재할 수 밖에 없으며, 이로 인한 슬리피지가 생각보다 크다. 따라서 long / short 각각에 대해 동일한 자산 분배가 쉽지 않다. 
  2. bybit 에서 거래되는 각 코인들은 거래 수량(qty) 단위가 모두 다르다. 비트코인의 경우 소수점 3자리 까지만을 허용하나, 특정 알트코인은 소수점을 허용하지 않는 등 코인마다 다르다. 문제는 허용되는 소수점 자리수 이상을 거래하려 하는 경우, API가 error를 발생시킨다는 것이다. 즉, 내가 생각했던 전략을 구현하기 위해서는 bybit 에서 거래되는 모든 코인에 대해 거래 허용 소수점 자리수를 수동으로 작성해야 했다.

 

pair trading 에 관한 심층 자료는 대가 "아마추어 퀀트" 선생님의 블로그에서 찾아 볼 수 있다.

https://blog.naver.com/chunjein/100149941007

 

7. Cointegration

페어트레이딩 (Pairs Trading) - 기초(7) Cointegration Cointegration은 시계열 분석 (Time Series)...

blog.naver.com

 


코드

1. 라이브러리 호출

import pandas as pd
from datetime import datetime
import calendar
import ccxt
import math
import time
from sklearn.preprocessing import StandardScaler
import math

 

2. 필요 함수 정의

class getCorr():
    def __init__(self):
        self.bybit = ccxt.bybit()
    
    def get_bybit_data(self, symbol, interval):
        btc_ohlcv = self.bybit.fetch_ohlcv(symbol, interval, limit=1000)
        df = pd.DataFrame(btc_ohlcv, columns=['datetime', 'open', 'high', 'low', 'close', 'volume'])
        df['datetime'] = pd.to_datetime(df['datetime'], unit='ms')
        df.set_index('datetime', inplace=True)
        return df
    
    def get_bybit_symbolList(self):
        markets = self.bybit.fetch_tickers()
        bybit_list = []
        for word in markets.keys():
            if 'USDT' in word:
                bybit_list.append(word)
        return bybit_list
    
    def get_bybit_corr_list(self, interval):
        markets = self.bybit.fetch_tickers()
        bybit_list = self.get_bybit_symbolList()
        data = [[] for n in range(len(bybit_list))]
        for usdt, n in zip(bybit_list, range(len(bybit_list))):
            data[n] = self.get_bybit_data(usdt, interval)
            time.sleep(0.2)
        df = pd.concat([d['close'] for d in data], axis=1)
        df.columns = bybit_list
        corr = df[bybit_list].corr(method = 'pearson')
        ser = corr[corr > 0.90]['BTC/USDT']
        ser = ser.dropna()
        return ser.index.tolist()

상관관계의 기준은 비트코인이다. 대부분의 코인이 비트코인의 영향을 받는 다는 점에 설정한 기준이다.

 

3. 코인 간 상관관계

%%time
gc = getCorr()
target_list = gc.get_bybit_corr_list('15m')

비트코인과 다른 코인 간 상관관계를 15분봉 데이터를 이용하여 분석하였다.

 

4. 유사한 종목 데이터 통합

data = [[] for n in range(len(target_list))]
for symbol, n in zip([target.replace('/', '') for target in target_list], range(len(target_list))):
    data[n] = gc.get_bybit_data(symbol, '15m')
    time.sleep(0.2)

df = pd.concat([d['close'] for d in data], axis=1)
df.columns = [target.replace('/', '') for target in target_list]
df

위에서 관계 수치가 높다고 판단된 종목에 대해 하나의 데이터 프레임으로 통합하였다.

 

5. 데이터 정규화

scaler = StandardScaler()
scaler.fit(df)
scaled = scaler.transform(df)
df_scaled = pd.DataFrame(data=scaled, columns=df.columns)
df_scaled

종목 간 스프레드를 계산하기 위해 데이터 정규화를 진행하였다.

 

6. 시각화

df_scaled.plot(figsize=(12, 8))

최대값, 최소값을 볼린저 밴드와 같은 기능으로도 사용 가능할 듯 하다.

 

7. pair trading 전략

# https://blog.naver.com/chunjein/100149941007
target = df_scaled.iloc[-1].sort_values().index.tolist()
long = target[0]
short = target[-1]
cointegration = df_scaled[[long, short]].cov()[long][1]/df_scaled[[long, short]].cov()[long][0]

내가 고민한 전략은 다음과 같다.

  1. 현재 정규화 값이 가장 높은 종목은 short을 한다.
  2. 현재 정규화 값이 가장 낮은 종목은 long을 한다.
  3. 두 종목의 정규값이 cross할 때 모두 청산한다.

 

728x90
반응형
Comments