냥냥펀치데스
BAO_BAO
냥냥펀치데스
  • 분류 전체보기
    • AI 공부
      • AI 끄적
      • ML 끄적
      • DL 끄적
      • 데이터 끄적
      • RL 끄적
      • GAN 끄적
    • 끄적이기
      • etc
      • 독서
    • 컴퓨터 공부
      • 운영체제
      • ADsP 공부
      • 파이썬 공부
      • etc
    • 코딩공부
      • 문제 풀이
    • 금융공학
      • BackTrader 공부
      • etc
      • 논문구현
      • 퀀트 투자 공부
      • 전략 연습
    • 블록체인
      • ICO 분석
      • etc

인기 글

최근 글

전체 방문자
오늘
어제

티스토리

hELLO · Designed By 정상우.
냥냥펀치데스

BAO_BAO

논문 리뷰 및 구현 - Pairs Trading: Performance of a Relative Value Arbitrage Rule
금융공학/논문구현

논문 리뷰 및 구현 - Pairs Trading: Performance of a Relative Value Arbitrage Rule

2022. 1. 2. 18:32
728x90

논문

글쓴이

더보기

Evan Gatev

Simon Fraser University

William N. Goetzmann

Yale School of Management - International Center for Finance; National Bureau of Economic Research (NBER)

K. Geert Rouwenhorst

Yale School of Management - International Center for Finance

소개

논문은 1962년부터 2002년 기간의 일간 데이터를 이용하여 "Pair Trading"이라는 월가의 투자 전략을 테스트하고 결과를 정리합니다.

핵심이론

  • Enter a long position on the spread if it is below -1 STD.
  • Enter a short position on the spread if it is above 1 STD.
  •  

프로세스

  1. 데이터 (binance,bitmart,huobi,gateio,bittrex)
  2. indicator 정립
  3. Strategy 정립
  4. 데이터 -> indicator -> Strategy -> broker 연결

Bactrader 목표

  • custom indicator 만들기
  • broker 다루어 보기

논문구현

python 으로 코드구현을 해보았다

사용한 라이브러리 : ccxt backtrader, empyrical, pandas, numpy, matplotlib

사용한 환경 : colab

설정

import datetime
from datetime import datetime as dt
import pandas as pd
import numpy as np
import ccxt
import backtrader as bt
import empyrical as ep
import matplotlib.pyplot as plt
from pylab import rcParams
%matplotlib inline
rcParams['figure.figsize'] = 16,9
rcParams['figure.facecolor'] = '#eeeeee'
plt.title('dummy')
plt.plot([1,3,2,4])
plt.close()

데이터 불러오기 (binance BTC/USDT, binance ETH/USDT)

def get_data(place,coin) :
    start_date = int(datetime.datetime(2020, 1, 1, 0, 0).timestamp() * 1000)

    if place == 'binance' :
      binance = ccxt.binance()
      ohlcvs = binance.fetch_ohlcv(coin, timeframe='1d', since=start_date, limit = 365)
    if place == 'okex' :
      okex = ccxt.okex()
      ohlcvs = okex.fetch_ohlcv(coin, timeframe='1d', since=start_date , limit = 365)
    if place == 'upbit' :
      upbit = ccxt.upbit()
      ohlcvs = upbit.fetch_ohlcv(coin, timeframe='1d', since=start_date , limit = 365)
    if place == 'ftx' :
      ftx = ccxt.ftx()
      ohlcvs = ftx.fetch_ohlcv(coin, timeframe='1d', since=start_date , limit = 365)
    if place == 'huobi' :
      huobi = ccxt.huobi()
      ohlcvs = huobi.fetch_ohlcv(coin, timeframe='1d', since=start_date , limit = 365)
    if place == 'bitmart' :
      bitmart = ccxt.bitmart()
      ohlcvs = bitmart.fetch_ohlcv(coin, timeframe='1d', since=start_date , limit = 365)
    if place == 'gateio' :
      gateio = ccxt.gateio()
      ohlcvs = gateio.fetch_ohlcv(coin, timeframe='1d', since=start_date , limit = 365)
    if place == 'bitrue' :
      bitrue = ccxt.bitrue()
      ohlcvs = bitrue.fetch_ohlcv(coin, timeframe='1d', since=start_date , limit = 365)
    if place == 'bittrex' :
      bittrex = ccxt.bittrex()
      ohlcvs = bittrex.fetch_ohlcv(coin, timeframe='1d', since=start_date , limit = 365)
    for idx, ohlcv in enumerate(ohlcvs):
        ohlcvs[idx] = [dt.fromtimestamp(ohlcv[0]/1000).strftime('%Y-%m-%d %H:%M:%S'), ohlcv[1], ohlcv[2], ohlcv[3], ohlcv[4],ohlcv[5]]

    df = pd.DataFrame(ohlcvs)
    df.columns = ['Time', 'Open','High','Low','Close','Volume']
    df['Time'] = pd.to_datetime(df['Time'], format='%Y-%m-%d %H:%M:%S', errors='raise')
    df.set_index('Time',inplace=True)

    return df

indicator 설정

class Pair(bt.indicators.PeriodN):
    params = {'period': 10}  # even if defined, we can redefine the default value
    lines = ('zscore',)  # our output line

    def __init__(self):
        self.transform = bt.ind.OLS_TransformationN(self.data0, self.data1,
                                                   period=self.p.period)
        self.lines.zscore = self.transform.zscore

Strategy 설정

class Test_Strategy(bt.Strategy):
    params = dict(
        threshold=1,
    )
    def __init__(self):
        self.lines.zscore = Pair(self.data0,self.data1)
        self.threshold = self.p.threshold

    def next(self):
        # if not self.position:

          if (self.lines.zscore[0] < abs(self.threshold)) :
            self.order = self.buy()

        # else:
          if (self.lines.zscore[0] > self.threshold) :
            self.order = self.sell()

실행

binance_btc = get_data('binance','BTC/USDT')
binance_eth = get_data('binance','ETH/USDT')
data0=bt.feeds.PandasData(dataname=binance_btc)
data1=bt.feeds.PandasData(dataname=binance_eth)

data0=bt.feeds.PandasData(dataname=binance_btc)
data1=bt.feeds.PandasData(dataname=binance_eth)

cerebro = bt.Cerebro()
cerebro.adddata(data0)
cerebro.adddata(data1)
cerebro.addstrategy(Test_Strategy)
cerebro.addanalyzer(bt.analyzers.PyFolio)
cerebro.broker.setcash(1000000)
cerebro.addsizer(bt.sizers.FixedSize, stake=5)
print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
# Run over everything
results = cerebro.run()  # [15]
# Print out the final result
print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())

Analyze

strat = results[0]
pyfoliozer = strat.analyzers.getbyname('pyfolio')
returns, positions, transactions, gross_lev = pyfoliozer.get_pf_items()

SIMPLE_STAT_FUNCS = [
    ep.annual_return,
    ep.cum_returns_final,
    ep.annual_volatility,
    ep.sharpe_ratio,
    ep.calmar_ratio,
    ep.stability_of_timeseries,
    ep.max_drawdown,
    ep.omega_ratio,
    ep.sortino_ratio,
    ep.tail_ratio,
]

STAT_FUNC_NAMES = {
    'annual_return': 'Annual return',
    'cum_returns_final': 'Cumulative returns',
    'annual_volatility': 'Annual volatility',
    'sharpe_ratio': 'Sharpe ratio',
    'calmar_ratio': 'Calmar ratio',
    'stability_of_timeseries': 'Stability',
    'max_drawdown': 'Max drawdown',
    'omega_ratio': 'Omega ratio',
    'sortino_ratio': 'Sortino ratio',
    'skew': 'Skew',
    'kurtosis': 'Kurtosis',
    'tail_ratio': 'Tail ratio',
    'common_sense_ratio': 'Common sense ratio',
    'value_at_risk': 'Daily value at risk',
    'alpha': 'Alpha',
    'beta': 'Beta',
}

stats = pd.Series()
for i,stat_func in enumerate(SIMPLE_STAT_FUNCS):
    stats[STAT_FUNC_NAMES[stat_func.__name__]] = stat_func(returns)
    stats.iloc[i] = str(np.round(stats.iloc[i]  * 100,3)) + '%'

perf_stats = pd.DataFrame(stats, columns=['Backtest'])

Result

Reference

더보기

https://papers.ssrn.com/sol3/papers.cfm?abstract_id=141615 

 

Pairs Trading: Performance of a Relative Value Arbitrage Rule

47 Pages Posted: 28 Dec 1998 Last revised: 24 Jan 2008 Abstract We test a Wall Street investment strategy, pairs trading, with daily data over 1962-2002. Stocks are matched into pairs with minimum distance between normalized historical prices. A simple tra

papers.ssrn.com

https://quantpedia.com/strategies/pairs-trading-with-stocks/

 

Pairs Trading with Stocks - QuantPedia

We’ve already analyzed tens of thousands of financial research papers and identified more than 600 attractive trading systems together with hundreds of related academic papers. Browse Strategies Unlocked Screener & 200+ Advanced Charts600+ uncommon tradi

quantpedia.com

https://www.quantconnect.com/tutorials/strategy-library/pairs-trading-with-stocks

 

QuantConnect Tutorials

Learn to use QuantConnect with guided tutorials

www.quantconnect.com

 

https://towardsdatascience.com/pairs-trading-with-cryptocurrencies-e79b4a00b015

 

Pairs Trading with Cryptocurrencies

The article describes a brief introduction to pairs trading including concept, basic math, strategy algorithm, trading robot development…

towardsdatascience.com

https://medium.com/@dinodecastro/pair-trading-with-cryptocurrencies-part-2-a820ca121400

 

Pair-trading With Cryptocurrencies Part 2

How To Implement A Pair-trading Strategy Using Python

medium.com

https://github.com/lamres/pairs_trading_cryptocurrencies_strategy_catalyst

 

GitHub - lamres/pairs_trading_cryptocurrencies_strategy_catalyst: Pairs trading strategy example based on Catalyst

Pairs trading strategy example based on Catalyst. Contribute to lamres/pairs_trading_cryptocurrencies_strategy_catalyst development by creating an account on GitHub.

github.com

https://github.com/mementum/backtrader/blob/master/contrib/samples/pair-trading/pair-trading.py

 

GitHub - mementum/backtrader: Python Backtesting library for trading strategies

Python Backtesting library for trading strategies. Contribute to mementum/backtrader development by creating an account on GitHub.

github.com

 

 

저작자표시 (새창열림)

'금융공학 > 논문구현' 카테고리의 다른 글

논문 리뷰 및 구현 - Does Trend Following Work on Stocks? (2005)  (0) 2022.01.19
논문 리뷰 및 구현 - Testing the Significance of Calendar Effects(2003)  (0) 2022.01.03
논문구현 을 어떤 방향으로 할것인가?  (0) 2021.12.30
논문 리뷰 및 구현 - Option-Expiration Week Effect  (0) 2021.12.30
논문 리뷰 및 구현 - Trading Cryptocurrencies Using Second OrderStochastic Dominance  (0) 2021.12.30
    '금융공학/논문구현' 카테고리의 다른 글
    • 논문 리뷰 및 구현 - Does Trend Following Work on Stocks? (2005)
    • 논문 리뷰 및 구현 - Testing the Significance of Calendar Effects(2003)
    • 논문구현 을 어떤 방향으로 할것인가?
    • 논문 리뷰 및 구현 - Option-Expiration Week Effect
    냥냥펀치데스
    냥냥펀치데스
    데이터 를 공부하는 무지몽매한 자입니다

    티스토리툴바