728x90
논문리뷰
- 저자 : Licheng Sun
- Licheng Sun 교수님이 발표하신 " Returns and Option Activity over the Option-Expiration Week for S&P 100 Stocks "(2013) 을 리뷰해 보겠다.
핵심내용
- The long position is opened at the start of the expiration week.
- The algorithm stays in cash during days out of the options expiration week.
논문구현
python 으로 코드구현을 해보았다
사용한 라이브러리 : custom messari, backtrader, empyrical, pandas, numpy, matplotlib
사용한 환경 : colab
핵심 포인트 : 만료하는 주에 월요일 거래, 일주일 홀딩후 판매
환경설정
from messari.messari import Messari
import backtrader as bt
import matplotlib.pyplot as plt
from pylab import rcParams
import empyrical as ep
import pandas as pd
import numpy as np
%matplotlib inline
rcParams['figure.figsize'] = 16,9
rcParams['figure.facecolor'] = '#eeeeee'
plt.title('dummy')
plt.plot([1,3,2,4])
plt.close()
messari = Messari('your api')
Data 준비
class DataCrawling():
def __init__(self, start, end, messari = messari):
self.start = start
self.end = end
self.messari = messari
def get_data(self) :
assets = 'btc'
metric = 'price'
df_btc = self.messari.get_metric_timeseries(asset_slugs=assets, asset_metric=metric, start=dt.strptime(self.start, "%Y-%m-%d"), end=dt.strptime(self.end, "%Y-%m-%d"))
df_btc.columns = df_btc.columns.get_level_values(1)
df_btc = df_btc.reset_index()
df_btc.columns = ['Time', 'Open','High','Low','Close','Volume']
df_btc.set_index('Time',inplace=True)
df_btc['openinterest'] = 0
# return bt.feeds.PandasData(dataname=df_btc)
return df_btc
data = DataCrawling('2020-01-01','2020-12-30').get_data()
만료일 설정
expire_list = []
for i,row in data.iterrows() :
if row.name.isoweekday() == 1 :
if (15<= row.name.day) and (row.name.day <= 21) :
expire_list.append(1)
elif (len(expire_list) >= 7) and (expire_list[-7] == 1) :
expire_list.append(-1)
else : expire_list.append(0)
else : expire_list.append(0)
data['Expire_data'] = expire_list
backtrader 적용
class pandasDataFeed(bt.feeds.PandasData):
lines = ('Expire_data',)
params = (
('datetime', None),
('high', 'High'),
('low', 'Low'),
('open', 'Open'),
('close', 'Close'),
('volume', None),
('Expire_data', 'Expire_data')
)
df=pandasDataFeed(dataname=data)
class Test_Strategy(bt.Strategy):
def next(self):
if not self.position:
# Not yet ... we MIGHT BUY if ...
if self.data.Expire_data == 1 :
# Keep track of the created order to avoid a 2nd order
self.order = self.buy()
else:
if self.data.Expire_data == -1 :
# Keep track of the created order to avoid a 2nd order
self.order = self.sell()
cerebro = bt.Cerebro()
cerebro.adddata(df, name = 'ok')
cerebro.addstrategy(Test_Strategy)
# strats = cerebro.optstrategy(KnnStrategy, maperiod=range(10, 11)) # [10]
cerebro.addanalyzer(bt.analyzers.PyFolio)
# Set our desired cash start
cerebro.broker.setcash(1000000)
# Add a FixedSize sizer according to the stake
cerebro.addsizer(bt.sizers.FixedSize, stake=5)
# Set the commission
cerebro.broker.setcommission(commission=0.0)
# Print out the starting conditions
print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
bt.position.Position(size=10, price=0.0)
# Run over everything
results = cerebro.run() # [15]
strat = results[0] # [16]
결과값 확인
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)) + '%'
stats
perf_stats = pd.DataFrame(stats, columns=['Backtest'])
print(perf_stats)
Reference :
더보기
'금융공학 > 논문구현' 카테고리의 다른 글
논문 리뷰 및 구현 - Does Trend Following Work on Stocks? (2005) (0) | 2022.01.19 |
---|---|
논문 리뷰 및 구현 - Testing the Significance of Calendar Effects(2003) (0) | 2022.01.03 |
논문 리뷰 및 구현 - Pairs Trading: Performance of a Relative Value Arbitrage Rule (0) | 2022.01.02 |
논문구현 을 어떤 방향으로 할것인가? (0) | 2021.12.30 |
논문 리뷰 및 구현 - Trading Cryptocurrencies Using Second OrderStochastic Dominance (0) | 2021.12.30 |