파이썬 3.5 zipline 패키지를 이용한 백테스킹

조회수 1165회

안녕하세요 https://wikidocs.net/book/110에서 제공하는 내용을 바탕으로 공부 중인 사람입니다.

여기서 14. Pandas와 zipline을 이용한 백테스킹(revision)

2) 이동평균선 전략 백테스트

1) Zipline을 이용한 이동평균선 전략테스트

의 코드가 실행이 안되는 문제가 있습니다.

제공되어 있는 코드는 아래와 같습니다.

import pandas_datareader.data as web
import datetime
import matplotlib.pyplot as plt
from zipline.api import order_target, record, symbol
from zipline.algorithm import TradingAlgorithm

start = datetime.datetime(2010, 1, 1)
end = datetime.datetime(2016, 3, 29)
data = web.DataReader("AAPL", "yahoo", start, end)

#plt.plot(data.index, data['Adj Close'])
#plt.show()

data = data[['Adj Close']]
data.columns = ['AAPL']
data = data.tz_localize('UTC')

#print(data.head())

def initialize(context):
    context.i = 0
    context.sym = symbol('AAPL')

def handle_data(context, data):
    context.i += 1
    if context.i < 20:
        return

    ma5 = data.history(context.sym, 'price', 5, '1d').mean()
    ma20 = data.history(context.sym, 'price', 20, '1d').mean()

    if ma5 > ma20:
        order_target(context.sym, 1)
    else:
        order_target(context.sym, -1)

    record(AAPL=data.current(context.sym, "price"), ma5=ma5, ma20=ma20)

algo = TradingAlgorithm(initialize=initialize, handle_data=handle_data)
result = algo.run(data)

오류내용은 아래와 같습니다.

Traceback (most recent call last):
  File "c:/Users/parkk/PycharmProjects/untitled/ex04.py", line 39, in <module>
    algo = TradingAlgorithm(initialize=initialize, handle_data=handle_data)
  File "C:\Anaconda3\envs\py35\lib\site-packages\zipline\algorithm.py", line 279, in __init__
    self.trading_environment = TradingEnvironment()
  File "C:\Anaconda3\envs\py35\lib\site-packages\zipline\finance\trading.py", line 103, in __init__
    self.bm_symbol,
  File "C:\Anaconda3\envs\py35\lib\site-packages\zipline\data\loader.py", line 149, in load_market_data
    environ,
  File "C:\Anaconda3\envs\py35\lib\site-packages\zipline\data\loader.py", line 216, in ensure_benchmark_data
    data = get_benchmark_returns(symbol)
  File "C:\Anaconda3\envs\py35\lib\site-packages\zipline\data\benchmarks.py", line 35, in get_benchmark_returns
    df = pd.DataFrame(data)
NameError: name 'data' is not defined

느낌상 data의 형식이나, 갯구가 맞지 않을까 라는 생각이 듭니다.

비전공자로서 공부하는 입자이여서,이해도가 낮은 부분에 대해 이해해주시면 감사하겠습니다.

해결할 수 있도록 도와주시면 감사하겠습니다.

  • (•́ ✖ •̀)
    알 수 없는 사용자

4 답변

  • 제 환경(mint 19.3(ubuntu 18.04)) 에서 동작을 확인했습니다만...저도 여러번 시도하니 같은 오류 메세지가 발생했습니다.

    디버깅이 필요할 것 같습니다.

    오류의 원인은 하기 라인의 결과가 없기 때문에 오류가 발생할겁니다.

    즉 requests 모듈을 이용해서 문자열 데이터를 받아오고 그것을 json 으로 변환하는 것인데 문자열이 없거나 json 이 아니어서 오류가 발생하는 겁니다.

    r = requests.get('https://cloud.iexapis.com/stable/stock/{}/chart/5y?token={}'.format(symbol, IEX_KEY))
    

    r의 값을 확인해보면 될겁니다.

    파이썬은 pdb 라는 디버깅 모듈을 내장하고 있습니다. benchmarks.py 파일을 아래와 같이 수정해줍니다,

    • benchmarks.py
    r= requests.get(
        'https://cloud.iexapis.com/stable/stock/{}/chart/5y?token={}'.format(symbol, IEX_KEY)
    )
    import pdb; pdb.set_trace() # 해당라인 추가
    data = r.json()
    

    다시 실행해보면 아래와 같이 프롬프트가 보이면서 프로그램이 멈춤상태가 됩니다.

    > /home/allinux/workspace/lang/python/py35_zipline/lib/python3.5/site-packages/zipline/data/benchmarks.py(37)get_benchmark_returns()
    -> data = r.json()
    (Pdb)
    

    여기서 아래와 같이 r의 내용을 확인해보세요.(p r.content)

    저는 사용할 수 있는 횟수 제한을 초과했다는 메세지를 받았네요. 결과 메세지는 일반 문자열이지 json 포맷이 아닙니다.

    (Pdb) p r.content
    b'You have exceeded your allotted message quota. Please enable pay-as-you-go to regain access'
    

    c 명령으로 계속 진행합니다. 질문자와 같은 오류 메세지를 받았네요.

    당연합니다. 기대한 json 이 아니니까요.

    (Pdb) c
    Traceback (most recent call last):
      File "a.py", line 39, in <module>
        algo = TradingAlgorithm(initialize=initialize, handle_data=handle_data)
      File "/home/allinux/workspace/lang/python/py35_zipline/lib/python3.5/site-packages/zipline/algorithm.py", line 279, in __init__
        self.trading_environment = TradingEnvironment()
      File "/home/allinux/workspace/lang/python/py35_zipline/lib/python3.5/site-packages/zipline/finance/trading.py", line 103, in __init__
        self.bm_symbol,
      File "/home/allinux/workspace/lang/python/py35_zipline/lib/python3.5/site-packages/zipline/data/loader.py", line 149, in load_market_data
        environ,
      File "/home/allinux/workspace/lang/python/py35_zipline/lib/python3.5/site-packages/zipline/data/loader.py", line 216, in ensure_benchmark_data
        data = get_benchmark_returns(symbol)
      File "/home/allinux/workspace/lang/python/py35_zipline/lib/python3.5/site-packages/zipline/data/benchmarks.py", line 37, in get_benchmark_returns
        data = r.json()
      File "/home/allinux/workspace/lang/python/py35_zipline/lib/python3.5/site-packages/requests/models.py", line 897, in json
        return complexjson.loads(self.text, **kwargs)
      File "/usr/local/lib/python3.5/json/__init__.py", line 319, in loads
        return _default_decoder.decode(s)
      File "/usr/local/lib/python3.5/json/decoder.py", line 339, in decode
        obj, end = self.raw_decode(s, idx=_w(s, 0).end())
      File "/usr/local/lib/python3.5/json/decoder.py", line 357, in raw_decode
        raise JSONDecodeError("Expecting value", s, err.value) from None
    json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
    

    제한은 아래 링크를 확인하세요.

    https://iexcloud.io/docs/api/#request-limits

    • 말씀하신대로 하다가, 저도 코인이 없다는 메시지가 나오네요. 코인이 떨어지면 현금으로 충전해야 가능 한건가요? 그리고 여기까지 해결해나갈 수 있도록 도와주셔서 정말 감사합니다. 알 수 없는 사용자 2020.2.9 15:09
    • 코인이 다 떨어지면, zipline 패키지는 더 이상 사용이 안되는 건가요? 알 수 없는 사용자 2020.2.9 15:10
    • 더 많은 데이터를 조회하려며 유료 라이센스를 구매해야 하는가 봅니다. https://iexcloud.io/pricing/ 정영훈 2020.2.9 15:58
  • 질문상의 오류는 data 변수가 없다는 메세지입니다. 뭔가 다른 실수를 한 듯 싶고 테스트 해보니 다른 문제가 있습니다.

    주식정보를 아래의 사이트에서 얻어옵니다. 문제는 key 를 명시적으로 넣어야 이용할 수 있도록 변경된 모양입니다. 그런데 기존 라이브러리에는 처리가 안되어 있습니다.

    cloud.iexapis.com

    조치방법이 비전공자라고 하시니 어려울 수 있습니다.

    • https://iexcloud.io/ 가입하고 key 를 얻습니다.
    • site-packages/zipline/data/benchmarks.py 코드를 아래와 같이 수정합니다.

    • 기존코드

    r = requests.get(
        'https://api.iextrading.com/1.0/stock/{}/chart/5y'.format(symbol)
    )
    
    
    • 변경된 코드
    IEX_KEY = 'iex 가입후 얻은 키를 입력'
    r = requests.get(
        'https://cloud.iexapis.com/stable/stock/{}/chart/5y?token={}'.format(symbol, IEX_KEY)
    )
    
    • 자세한 설명 진심으로 감사합니다. 하지만, 다시 오류가 발생해서 답변으로 오류에 대한 내용을 정리했습니다. 부탁드립니다 ㅠㅠ 알 수 없는 사용자 2020.2.2 21:23
  • 자세한 설명과 쉽게 이해하도록 도와주신 설명에 진심으로 감사합니다.

    알려주신 방법을 그대로 해봤지만,

    algo = TradingAlgorithm(initialize=initialize, handle_data=handle_data)
    부분에서 오류가 발생합니다.

    KEY를 변경한 디렉토리는

    C:\Anaconda3\envs\py35\Lib\site-packages\zipline\data

    입니다. zipline 패키지를 사용하기 위해 아나콘다3 가상환경으로 파이썬을 설치했습니다.

    수정한 코드 내용은 아래와 같습니다.

    # limitations under the License.
    import pandas as pd
    import requests
    
    
    def get_benchmark_returns(symbol):
        """
        Get a Series of benchmark returns from IEX associated with `symbol`.
        Default is `SPY`.
    
        Parameters
        ----------
        symbol : str
            Benchmark symbol for which we're getting the returns.
    
        The data is provided by IEX (https://iextrading.com/), and we can
        get up to 5 years worth of data.
        """
        IEX_KEY = 'pk_e363662b70ce4aa484f3548b6619f0b4 '
        r = requests.get('https://cloud.iexapis.com/stable/stock/{}/chart/5y?token={}'.format(symbol, IEX_KEY))
    
        df = pd.DataFrame(data)
    
        df.index = pd.DatetimeIndex(df['date'])
        df = df['close']
    
        return df.sort_index().tz_localize('UTC').pct_change(1).iloc[1:]
    

    key는 알려주신 사이트에서 회원가입 후 얻게 된 키로 입력했습니다.

    그리고, 오류가 발생하는 부분의 내용은 아래와 같습니다.

    algo = TradingAlgorithm(initialize=initialize, handle_data=handle_data)
    ---------------------------------------------------------------------------
    NameError                                 Traceback (most recent call last)
    <ipython-input-14-f3ede435492a> in <module>()
    ----> 1 algo = TradingAlgorithm(initialize=initialize, handle_data=handle_data)
    
    C:\Anaconda3\envs\py35\lib\site-packages\zipline\algorithm.py in __init__(self, *args, **kwargs)
        277 
        278         if self.trading_environment is None:
    --> 279             self.trading_environment = TradingEnvironment()
        280 
        281         # Update the TradingEnvironment with the provided asset metadata
    
    C:\Anaconda3\envs\py35\lib\site-packages\zipline\finance\trading.py in __init__(self, load, bm_symbol, exchange_tz, trading_calendar, trading_day, trading_days, asset_db_path, future_chain_predicates, environ)
        101             trading_day,
        102             trading_days,
    --> 103             self.bm_symbol,
        104         )
        105 
    
    C:\Anaconda3\envs\py35\lib\site-packages\zipline\data\loader.py in load_market_data(trading_day, trading_days, bm_symbol, environ)
        147         # date so that we can compute returns for the first date.
        148         trading_day,
    --> 149         environ,
        150     )
        151     tc = ensure_treasury_data(
    
    C:\Anaconda3\envs\py35\lib\site-packages\zipline\data\loader.py in ensure_benchmark_data(symbol, first_date, last_date, now, trading_day, environ)
        214 
        215     try:
    --> 216         data = get_benchmark_returns(symbol)
        217         data.to_csv(get_data_filepath(filename, environ))
        218     except (OSError, IOError, HTTPError):
    
    C:\Anaconda3\envs\py35\lib\site-packages\zipline\data\benchmarks.py in get_benchmark_returns(symbol)
         33     r = requests.get('https://cloud.iexapis.com/stable/stock/{}/chart/5y?token={}'.format(symbol, IEX_KEY))
         34 
    ---> 35     df = pd.DataFrame(data)
         36 
         37     df.index = pd.DatetimeIndex(df['date'])
    
    NameError: name 'data' is not defined
    

    혹시 도움이 될까하여 qtconsole로 실행 해보았습니다.
    제가 놓이고 있는 부분이나 잘못된 부분에 대해 알려주시면 정말 감사하겠습니다.

    • (•́ ✖ •̀)
      알 수 없는 사용자
    • benchmarks.py 파일이 잘못되어 있네요. 35 라인 이전에 즉 34 라인에 data = r.json() 가 있어야 합니다. 삭제가 된 듯 싶고 당연히 data 가 없다고 에러가 나는 겁니다. 정영훈 2020.2.2 22:57
    • 죄송합니다 말씀하신 대로 했지만, 해결이 안되었습니다 ㅜㅜ 오류 내용은 아래 답변으로 달았습니다 도와주신다면 정말 감사하겠습니다. 알 수 없는 사용자 2020.2.4 21:30
  • 말씀하신대로 추가를 했지만, 이상하게도 작동이 되지 않네요 ㅠㅠ
    오류 내용은 아래와 같습니다.(qtconsole 입니다.)

    algo = TradingAlgorithm(initialize=initialize, handle_data=handle_data)
    ---------------------------------------------------------------------------
    JSONDecodeError                           Traceback (most recent call last)
    <ipython-input-16-f3ede435492a> in <module>()
    ----> 1 algo = TradingAlgorithm(initialize=initialize, handle_data=handle_data)
    
    C:\Anaconda3\envs\py35\lib\site-packages\zipline\algorithm.py in __init__(self, *args, **kwargs)
        277 
        278         if self.trading_environment is None:
    --> 279             self.trading_environment = TradingEnvironment()
        280 
        281         # Update the TradingEnvironment with the provided asset metadata
    
    C:\Anaconda3\envs\py35\lib\site-packages\zipline\finance\trading.py in __init__(self, load, bm_symbol, exchange_tz, trading_calendar, trading_day, trading_days, asset_db_path, future_chain_predicates, environ)
        101             trading_day,
        102             trading_days,
    --> 103             self.bm_symbol,
        104         )
        105 
    
    C:\Anaconda3\envs\py35\lib\site-packages\zipline\data\loader.py in load_market_data(trading_day, trading_days, bm_symbol, environ)
        147         # date so that we can compute returns for the first date.
        148         trading_day,
    --> 149         environ,
        150     )
        151     tc = ensure_treasury_data(
    
    C:\Anaconda3\envs\py35\lib\site-packages\zipline\data\loader.py in ensure_benchmark_data(symbol, first_date, last_date, now, trading_day, environ)
        214 
        215     try:
    --> 216         data = get_benchmark_returns(symbol)
        217         data.to_csv(get_data_filepath(filename, environ))
        218     except (OSError, IOError, HTTPError):
    
    C:\Anaconda3\envs\py35\lib\site-packages\zipline\data\benchmarks.py in get_benchmark_returns(symbol)
         33     r = requests.get('https://cloud.iexapis.com/stable/stock/{}/chart/5y?token={}'.format(symbol, IEX_KEY))
         34 
    ---> 35     data = r.json()
         36     df = pd.DataFrame(data)
         37 
    
    C:\Anaconda3\envs\py35\lib\site-packages\requests\models.py in json(self, **kwargs)
        890                     # used.
        891                     pass
    --> 892         return complexjson.loads(self.text, **kwargs)
        893 
        894     @property
    
    C:\Anaconda3\envs\py35\lib\json\__init__.py in loads(s, encoding, cls, object_hook, parse_float, parse_int, parse_constant, object_pairs_hook, **kw)
        317             parse_int is None and parse_float is None and
        318             parse_constant is None and object_pairs_hook is None and not kw):
    --> 319         return _default_decoder.decode(s)
        320     if cls is None:
        321         cls = JSONDecoder
    
    C:\Anaconda3\envs\py35\lib\json\decoder.py in decode(self, s, _w)
        337 
        338         """
    --> 339         obj, end = self.raw_decode(s, idx=_w(s, 0).end())
        340         end = _w(s, end).end()
        341         if end != len(s):
    
    C:\Anaconda3\envs\py35\lib\json\decoder.py in raw_decode(self, s, idx)
        355             obj, end = self.scan_once(s, idx)
        356         except StopIteration as err:
    --> 357             raise JSONDecodeError("Expecting value", s, err.value) from None
        358         return obj, end
    
    JSONDecodeError: Expecting value: line 1 column 1 (char 0)
    

    형식을 변환도중에 오류 발생인가 싶은데, 정확한 문제가 무엇일까요??
    죄송합니다. 깔끔하게 해결을 해야하는데 쉽지가 않네요 ㅠㅠ

    • (•́ ✖ •̀)
      알 수 없는 사용자

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)