작성자: admin 작성일시: 2016-07-08 18:22:47 조회수: 942 다운로드: 36
카테고리: 금융 공학 태그목록:

주식의 기술적 분석 및 백테스트

TALib 패키지

In:
import talib
In:
# list of functions
talib.get_functions()
Out:
['ATR',
 'NATR',
 'TRANGE',
 'BBANDS',
 'DEMA',
 'EMA',
 'HT_TRENDLINE',
 'KAMA',
 'MA',
 'MAMA',
 'MAVP',
 'MIDPOINT',
 'MIDPRICE',
 'SAR',
 'SAREXT',
 'SMA',
 'T3',
 'TEMA',
 'TRIMA',
 'WMA',
 'BETA',
 'CORREL',
 'LINEARREG',
 'LINEARREG_ANGLE',
 'LINEARREG_INTERCEPT',
 'LINEARREG_SLOPE',
 'STDDEV',
 'TSF',
 'VAR',
 'ADX',
 'ADXR',
 'APO',
 'AROON',
 'AROONOSC',
 'BOP',
 'CCI',
 'CMO',
 'DX',
 'MACD',
 'MACDEXT',
 'MACDFIX',
 'MFI',
 'MINUS_DI',
 'MINUS_DM',
 'MOM',
 'PLUS_DI',
 'PLUS_DM',
 'PPO',
 'ROC',
 'ROCP',
 'ROCR',
 'ROCR100',
 'RSI',
 'STOCH',
 'STOCHF',
 'STOCHRSI',
 'TRIX',
 'ULTOSC',
 'WILLR',
 'CDL2CROWS',
 'CDL3BLACKCROWS',
 'CDL3INSIDE',
 'CDL3LINESTRIKE',
 'CDL3OUTSIDE',
 'CDL3STARSINSOUTH',
 'CDL3WHITESOLDIERS',
 'CDLABANDONEDBABY',
 'CDLADVANCEBLOCK',
 'CDLBELTHOLD',
 'CDLBREAKAWAY',
 'CDLCLOSINGMARUBOZU',
 'CDLCONCEALBABYSWALL',
 'CDLCOUNTERATTACK',
 'CDLDARKCLOUDCOVER',
 'CDLDOJI',
 'CDLDOJISTAR',
 'CDLDRAGONFLYDOJI',
 'CDLENGULFING',
 'CDLEVENINGDOJISTAR',
 'CDLEVENINGSTAR',
 'CDLGAPSIDESIDEWHITE',
 'CDLGRAVESTONEDOJI',
 'CDLHAMMER',
 'CDLHANGINGMAN',
 'CDLHARAMI',
 'CDLHARAMICROSS',
 'CDLHIGHWAVE',
 'CDLHIKKAKE',
 'CDLHIKKAKEMOD',
 'CDLHOMINGPIGEON',
 'CDLIDENTICAL3CROWS',
 'CDLINNECK',
 'CDLINVERTEDHAMMER',
 'CDLKICKING',
 'CDLKICKINGBYLENGTH',
 'CDLLADDERBOTTOM',
 'CDLLONGLEGGEDDOJI',
 'CDLLONGLINE',
 'CDLMARUBOZU',
 'CDLMATCHINGLOW',
 'CDLMATHOLD',
 'CDLMORNINGDOJISTAR',
 'CDLMORNINGSTAR',
 'CDLONNECK',
 'CDLPIERCING',
 'CDLRICKSHAWMAN',
 'CDLRISEFALL3METHODS',
 'CDLSEPARATINGLINES',
 'CDLSHOOTINGSTAR',
 'CDLSHORTLINE',
 'CDLSPINNINGTOP',
 'CDLSTALLEDPATTERN',
 'CDLSTICKSANDWICH',
 'CDLTAKURI',
 'CDLTASUKIGAP',
 'CDLTHRUSTING',
 'CDLTRISTAR',
 'CDLUNIQUE3RIVER',
 'CDLUPSIDEGAP2CROWS',
 'CDLXSIDEGAP3METHODS',
 'AD',
 'ADOSC',
 'OBV',
 'ADD',
 'DIV',
 'MAX',
 'MAXINDEX',
 'MIN',
 'MININDEX',
 'MINMAX',
 'MINMAXINDEX',
 'MULT',
 'SUB',
 'SUM',
 'ACOS',
 'ASIN',
 'ATAN',
 'CEIL',
 'COS',
 'COSH',
 'EXP',
 'FLOOR',
 'LN',
 'LOG10',
 'SIN',
 'SINH',
 'SQRT',
 'TAN',
 'TANH',
 'AVGPRICE',
 'MEDPRICE',
 'TYPPRICE',
 'WCLPRICE',
 'HT_DCPERIOD',
 'HT_DCPHASE',
 'HT_PHASOR',
 'HT_SINE',
 'HT_TRENDMODE']
In:
from pprint import pprint
pprint(talib.get_function_groups())
{'Cycle Indicators': ['HT_DCPERIOD',
                      'HT_DCPHASE',
                      'HT_PHASOR',
                      'HT_SINE',
                      'HT_TRENDMODE'],
 'Math Operators': ['ADD',
                    'DIV',
                    'MAX',
                    'MAXINDEX',
                    'MIN',
                    'MININDEX',
                    'MINMAX',
                    'MINMAXINDEX',
                    'MULT',
                    'SUB',
                    'SUM'],
 'Math Transform': ['ACOS',
                    'ASIN',
                    'ATAN',
                    'CEIL',
                    'COS',
                    'COSH',
                    'EXP',
                    'FLOOR',
                    'LN',
                    'LOG10',
                    'SIN',
                    'SINH',
                    'SQRT',
                    'TAN',
                    'TANH'],
 'Momentum Indicators': ['ADX',
                         'ADXR',
                         'APO',
                         'AROON',
                         'AROONOSC',
                         'BOP',
                         'CCI',
                         'CMO',
                         'DX',
                         'MACD',
                         'MACDEXT',
                         'MACDFIX',
                         'MFI',
                         'MINUS_DI',
                         'MINUS_DM',
                         'MOM',
                         'PLUS_DI',
                         'PLUS_DM',
                         'PPO',
                         'ROC',
                         'ROCP',
                         'ROCR',
                         'ROCR100',
                         'RSI',
                         'STOCH',
                         'STOCHF',
                         'STOCHRSI',
                         'TRIX',
                         'ULTOSC',
                         'WILLR'],
 'Overlap Studies': ['BBANDS',
                     'DEMA',
                     'EMA',
                     'HT_TRENDLINE',
                     'KAMA',
                     'MA',
                     'MAMA',
                     'MAVP',
                     'MIDPOINT',
                     'MIDPRICE',
                     'SAR',
                     'SAREXT',
                     'SMA',
                     'T3',
                     'TEMA',
                     'TRIMA',
                     'WMA'],
 'Pattern Recognition': ['CDL2CROWS',
                         'CDL3BLACKCROWS',
                         'CDL3INSIDE',
                         'CDL3LINESTRIKE',
                         'CDL3OUTSIDE',
                         'CDL3STARSINSOUTH',
                         'CDL3WHITESOLDIERS',
                         'CDLABANDONEDBABY',
                         'CDLADVANCEBLOCK',
                         'CDLBELTHOLD',
                         'CDLBREAKAWAY',
                         'CDLCLOSINGMARUBOZU',
                         'CDLCONCEALBABYSWALL',
                         'CDLCOUNTERATTACK',
                         'CDLDARKCLOUDCOVER',
                         'CDLDOJI',
                         'CDLDOJISTAR',
                         'CDLDRAGONFLYDOJI',
                         'CDLENGULFING',
                         'CDLEVENINGDOJISTAR',
                         'CDLEVENINGSTAR',
                         'CDLGAPSIDESIDEWHITE',
                         'CDLGRAVESTONEDOJI',
                         'CDLHAMMER',
                         'CDLHANGINGMAN',
                         'CDLHARAMI',
                         'CDLHARAMICROSS',
                         'CDLHIGHWAVE',
                         'CDLHIKKAKE',
                         'CDLHIKKAKEMOD',
                         'CDLHOMINGPIGEON',
                         'CDLIDENTICAL3CROWS',
                         'CDLINNECK',
                         'CDLINVERTEDHAMMER',
                         'CDLKICKING',
                         'CDLKICKINGBYLENGTH',
                         'CDLLADDERBOTTOM',
                         'CDLLONGLEGGEDDOJI',
                         'CDLLONGLINE',
                         'CDLMARUBOZU',
                         'CDLMATCHINGLOW',
                         'CDLMATHOLD',
                         'CDLMORNINGDOJISTAR',
                         'CDLMORNINGSTAR',
                         'CDLONNECK',
                         'CDLPIERCING',
                         'CDLRICKSHAWMAN',
                         'CDLRISEFALL3METHODS',
                         'CDLSEPARATINGLINES',
                         'CDLSHOOTINGSTAR',
                         'CDLSHORTLINE',
                         'CDLSPINNINGTOP',
                         'CDLSTALLEDPATTERN',
                         'CDLSTICKSANDWICH',
                         'CDLTAKURI',
                         'CDLTASUKIGAP',
                         'CDLTHRUSTING',
                         'CDLTRISTAR',
                         'CDLUNIQUE3RIVER',
                         'CDLUPSIDEGAP2CROWS',
                         'CDLXSIDEGAP3METHODS'],
 'Price Transform': ['AVGPRICE', 'MEDPRICE', 'TYPPRICE', 'WCLPRICE'],
 'Statistic Functions': ['BETA',
                         'CORREL',
                         'LINEARREG',
                         'LINEARREG_ANGLE',
                         'LINEARREG_INTERCEPT',
                         'LINEARREG_SLOPE',
                         'STDDEV',
                         'TSF',
                         'VAR'],
 'Volatility Indicators': ['ATR', 'NATR', 'TRANGE'],
 'Volume Indicators': ['AD', 'ADOSC', 'OBV']}

TALib 사용 예

In:
np.random.seed(0)
close = np.random.random(250)
In:
sma = talib.SMA(close, timeperiod=10)
plt.figure(figsize=(11,3))
plt.plot(close, "r-")
plt.plot(sma, "b-")
plt.show()
In:
upper, middle, lower = talib.BBANDS(close, timeperiod=10, nbdevup=0.5, nbdevdn=0.5)
plt.figure(figsize=(11,3))
sma = talib.SMA(close)
plt.plot(close, "r-")
plt.plot(middle, "b-")
plt.fill_between(np.arange(len(close)), lower, upper, alpha=0.5)
plt.show()

zipline 패키지

백테스트 방법

  1. TradingAlgorithm 클래스 구현
    • initialize 메서드: 알고리즘 초기화
    • handle_data 메서드: 데이터 이벤트 핸들링
  2. 백테스트용 데이터 확보
  3. TradingAlgorithm 클래스 객체의 run 메서드 호출
  4. 결과 분석
In:
import numpy as np
from talib import EMA
from zipline.api import order, record, symbol
from zipline.algorithm import TradingAlgorithm


def initialize(context):
    context.asset = symbol('AAPL')

    # To keep track of whether we invested in the stock or not
    context.invested = False


def handle_data(context, data):
    trailing_window = data.history(context.asset, 'price', 40, '1d')
    if trailing_window.isnull().values.any():
        return

    short_ema = EMA(trailing_window.values, timeperiod=20)
    long_ema = EMA(trailing_window.values, timeperiod=40)

    buy = False
    sell = False

    if (short_ema[-1] > long_ema[-1]) and not context.invested:
        order(context.asset, 100)
        context.invested = True
        buy = True
        
    elif (short_ema[-1] < long_ema[-1]) and context.invested:
        order(context.asset, -100)
        context.invested = False
        sell = True

    record(AAPL=data.current(context.asset, "price"),
           short_ema=short_ema[-1],
           long_ema=long_ema[-1],
           buy=buy,
           sell=sell)
    
    
algo = TradingAlgorithm(initialize=initialize, handle_data=handle_data)    
In:
import datetime 
import pytz
from zipline.utils.factory import load_from_yahoo

start = datetime.datetime(2013, 1, 1, tzinfo=pytz.utc)
end = datetime.datetime(2015, 12, 31, tzinfo=pytz.utc)
data = load_from_yahoo(stocks=['AAPL'], indexes={}, start=start, end=end)
In:
%time results = algo.run(data)
CPU times: user 2.97 s, sys: 10 ms, total: 2.98 s
Wall time: 2.98 s
In:
results.describe().T
Out:
count mean std min 25% 50% 75% max
AAPL 756.0 91.727977 23.304820 52.111852 70.946907 95.572789 112.279082 129.880553
algo_volatility 756.0 0.010242 0.004167 0.000000 0.009665 0.010780 0.013869 0.014843
algorithm_period_return 756.0 0.016400 0.016568 -0.006961 0.000000 0.014524 0.033993 0.045075
alpha 756.0 -0.020135 0.008000 -0.041907 -0.025932 -0.018765 -0.013841 -0.005793
benchmark_period_return 756.0 0.317319 0.134576 0.021708 0.192722 0.351885 0.439670 0.494065
benchmark_volatility 756.0 0.114952 0.012146 0.000000 0.111104 0.113927 0.115355 0.308564
beta 756.0 0.018719 0.014553 -0.005675 0.005961 0.015010 0.033034 0.042977
capital_used 756.0 4.069460 1583.777224 -12654.957900 0.000000 0.000000 0.000000 12530.406100
ending_cash 756.0 96363.179792 4691.836117 91204.565600 92409.451900 93380.451200 100235.297400 103859.523500
ending_exposure 756.0 5276.783787 4895.852912 0.000000 0.000000 6612.796800 9576.393650 12988.055300
ending_value 756.0 5276.783787 4895.852912 0.000000 0.000000 6612.796800 9576.393650 12988.055300
excess_return 756.0 -0.007038 0.017995 -0.034251 -0.023553 -0.011591 0.012667 0.024475
gross_leverage 756.0 0.051702 0.047633 0.000000 0.000000 0.066132 0.093899 0.124654
information 697.0 -55.481518 777.763080 -20550.700273 NaN NaN NaN -7.295255
long_ema 756.0 90.468828 23.319521 57.242575 69.446575 93.527037 112.118000 126.049750
long_exposure 756.0 5276.783787 4895.852912 0.000000 0.000000 6612.796800 9576.393650 12988.055300
long_value 756.0 5276.783787 4895.852912 0.000000 0.000000 6612.796800 9576.393650 12988.055300
longs_count 756.0 0.568783 0.495574 0.000000 0.000000 1.000000 1.000000 1.000000
max_drawdown 756.0 0.008250 0.003525 0.000000 0.007772 0.007772 0.011499 0.013816
max_leverage 756.0 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
net_leverage 756.0 0.051702 0.047633 0.000000 0.000000 0.066132 0.093899 0.124654
pnl 756.0 4.069460 95.011158 -421.972100 -12.940625 0.000000 17.678675 464.622200
portfolio_value 756.0 101639.963580 1656.844439 99303.918200 100000.000000 101452.355600 103399.302750 104507.517500
returns 756.0 0.000041 0.000927 -0.004121 -0.000130 0.000000 0.000175 0.004501
sharpe 697.0 -3.302259 34.620227 -914.515958 NaN NaN NaN 0.057572
short_ema 756.0 91.108935 23.279094 55.608291 70.553582 95.524788 111.595019 126.987418
short_exposure 756.0 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
short_value 756.0 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
shorts_count 756.0 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
sortino 756.0 -1.458391 1.110156 -4.501724 -2.405280 -1.122388 -0.647516 0.071656
starting_cash 756.0 96359.110333 4687.337651 91204.565600 92409.451900 93380.451200 100235.297400 103859.523500
starting_exposure 756.0 5276.783787 4895.852912 0.000000 0.000000 6612.796800 9576.393650 12988.055300
starting_value 756.0 5276.783787 4895.852912 0.000000 0.000000 6612.796800 9576.393650 12988.055300
trading_days 756.0 378.500000 218.382692 1.000000 189.750000 378.500000 567.250000 756.000000
treasury_period_return 756.0 0.023438 0.003248 0.016600 0.020875 0.023200 0.026225 0.030400
In:
results[["AAPL", "portfolio_value", "algorithm_period_return", "benchmark_period_return"]].tail()
Out:
AAPL portfolio_value algorithm_period_return benchmark_period_return
2015-12-24 18:00:00 106.796739 103076.5114 0.030765 0.445102
2015-12-28 21:00:00 105.600553 103076.5114 0.030765 0.441954
2015-12-29 21:00:00 107.498633 103076.5114 0.030765 0.457281
2015-12-30 21:00:00 106.094845 103076.5114 0.030765 0.446764
2015-12-31 21:00:00 104.058365 103076.5114 0.030765 0.433147
In:
import matplotlib.pyplot as plt

fig = plt.figure(figsize=(12,15))

ax1 = fig.add_subplot(211)
ax1.set_ylabel('Price (USD)')

ax2 = fig.add_subplot(212)
results.portfolio_value.plot(ax=ax2)
ax2.set_ylabel('Portfolio value (USD)')

results[['AAPL', 'short_ema', 'long_ema']].plot(ax=ax1)
results[results.buy.fillna(False)].AAPL.plot(ls="", marker="^", c="g", markersize=10, alpha=0.9, ax=ax1)
results[results.sell.fillna(False)].AAPL.plot(ls="", marker="v", c="r", markersize=10, alpha=0.9, ax=ax1)
plt.show()

질문/덧글

아직 질문이나 덧글이 없습니다. 첫번째 글을 남겨주세요!