Как использовать собственный календарь в пользовательском пакете zipline?
У меня есть следующий код в моем файле viacsv.py, который предназначен для загрузки пользовательского пакета:
#
# Ingest stock csv files to create a zipline data bundle
import os
import numpy as np
import pandas as pd
import datetime
boDebug=True # Set True to get trace messages
from zipline.utils.cli import maybe_show_progress
def viacsv(symbols,start=None,end=None):
# strict this in memory so that we can reiterate over it.
# (Because it could be a generator and they live only once)
tuSymbols = tuple(symbols)
if boDebug:
print "entering viacsv. tuSymbols=",tuSymbols
# Define our custom ingest function
def ingest(environ,
asset_db_writer,
minute_bar_writer, # unused
daily_bar_writer,
adjustment_writer,
calendar,
cache,
show_progress,
output_dir,
# pass these as defaults to make them 'nonlocal' in py2
start=start,
end=end):
if boDebug:
print "entering ingest and creating blank dfMetadata"
dfMetadata = pd.DataFrame(np.empty(len(tuSymbols), dtype=[
('start_date', 'datetime64[ns]'),
('end_date', 'datetime64[ns]'),
('auto_close_date', 'datetime64[ns]'),
('symbol', 'object'),
]))
if boDebug:
print "dfMetadata",type(dfMetadata)
print dfMetadata.describe
print
# We need to feed something that is iterable - like a list or a generator -
# that is a tuple with an integer for sid and a DataFrame for the data to
# daily_bar_writer
liData=[]
iSid=0
for S in tuSymbols:
IFIL="~/notebooks/csv/"+S+".csv"
if boDebug:
print "S=",S,"IFIL=",IFIL
dfData=pd.read_csv(IFIL,index_col='Date',parse_dates=True).sort_index()
if boDebug:
print "read_csv dfData",type(dfData),"length",len(dfData)
print
dfData.rename(
columns={
'Open': 'open',
'High': 'high',
'Low': 'low',
'Close': 'close',
'Volume': 'volume',
'Adj Close': 'price',
},
inplace=True,
)
dfData['volume']=dfData['volume']/1000
liData.append((iSid,dfData))
# the start date is the date of the first trade and
start_date = dfData.index[0]
if boDebug:
print "start_date",type(start_date),start_date
# the end date is the date of the last trade
end_date = dfData.index[-1]
if boDebug:
print "end_date",type(end_date),end_date
# The auto_close date is the day after the last trade.
ac_date = end_date + pd.Timedelta(days=1)
if boDebug:
print "ac_date",type(ac_date),ac_date
# Update our meta data
dfMetadata.iloc[iSid] = start_date, end_date, ac_date, S
iSid += 1
if boDebug:
print "liData",type(liData),"length",len(liData)
print liData
print
print "Now calling daily_bar_writer"
daily_bar_writer.write(liData, show_progress=False)
# Hardcode the exchange to "YAHOO" for all assets and (elsewhere)
# register "YAHOO" to resolve to the NYSE calendar, because these are
# all equities and thus can use the NYSE calendar.
dfMetadata['exchange'] = "YAHOO"
if boDebug:
print "returned from daily_bar_writer"
print "calling asset_db_writer"
print "dfMetadata",type(dfMetadata)
print dfMetadata
print
# Not sure why symbol_map is needed
symbol_map = pd.Series(dfMetadata.symbol.index, dfMetadata.symbol)
if boDebug:
print "symbol_map",type(symbol_map)
print symbol_map
print
asset_db_writer.write(equities=dfMetadata)
if boDebug:
print "returned from asset_db_writer"
print "calling adjustment_writer"
adjustment_writer.write()
if boDebug:
print "returned from adjustment_writer"
print "now leaving ingest function"
if boDebug:
print "about to return ingest function"
return ingest
Моя проблема в том, что данные, которые я передаю, - это не данные по США, а данные по австралийским акциям. Таким образом, он придерживается австралийских праздников, а не праздников США. Кажется, почему-то код ниже по умолчанию использует торговый календарь США и говорит мне, что я не могу передавать данные в течение дней, когда рынки США должны быть закрыты, и наоборот. Как я могу настроить приведенный выше код, чтобы взять в пользовательском календаре? Чтобы принять пакет, я запускаю следующую команду на своем терминале:
zipline ingest -b CBA.csv
мысли?
1 ответ
Вам нужно определить свой собственный календарь в zipline / utils / calendars: просто создайте копию одного из существующих файлов (скажем, exchange_calendar_nyse.py) и отредактируйте его с необходимыми выходными. Допустим, вы называете этот файл my_own_calendar.py и класс MyOwnCalendar.
Обратите внимание, что есть еще 2 (или 3) шага, которые необходимо предпринять:
1) Зарегистрируйте свой календарь в zipline / util / calendars / calendar_utils.py: вы можете сделать это, добавив запись в _default_calendar_factories и, если вам нужен псевдоним, _default_calendar_aliases. Например, чтобы отобразить my_own_calendar.py в "OWN" и с псевдонимом "MY_CALENDAR":
_default_calendar_factories = {
'NYSE': NYSEExchangeCalendar,
'CME': CMEExchangeCalendar,
...
'OWN': MyOwnCalendar
}
_default_calendar_aliases = {
'NASDAQ': 'NYSE',
...
'MY_CALENDAR': 'OWN'
}
2) вам нужно отредактировать .zipline / extension.py (вы найдете.zipline в вашем домашнем каталоге - чтобы увидеть свой дом под Windows, откройте оболочку dos и введите echo %USERPROFILE%
# List the tickers of the market you defined
tickers_of_interest = {'TICKER1', 'TICKER2', ...}
register('my_market', viacsv(tickers_of_interest), calendar_name="OWN")
с этими шагами вы сможете получить пакет, просто набрав zipline ingest -b my_market.
3) У меня лично была проблема с тем, что мне нужно было еще больше контролировать торговый календарь, учитывая, что суперкласс TradingCalendar предполагает, что суббота / воскресенье не являются торговыми днями, и это не так для каждого класса рынка / актива. Неправильное определение календаря приведет к исключению во время приема. Например, чтобы иметь календарь для рынка, который торгует 7/7 24/24, я взломал календарь следующим образом:
from datetime import time
from pytz import timezone
from pandas import date_range
from .trading_calendar import TradingCalendar, HolidayCalendar
from zipline.utils.memoize import lazyval
from pandas.tseries.offsets import CustomBusinessDay
class MyOwnCalendar(TradingCalendar):
"""
Round the clock calendar: 7/7, 24/24
"""
@property
def name(self):
return "OWN"
@property
def tz(self):
return timezone("Europe/London")
@property
def open_time(self):
return time(0)
@property
def close_time(self):
return time(23, 59)
@property
def regular_holidays(self):
return []
@property
def special_opens(self):
return []
def sessions_in_range(self, start_session, last_session):
return date_range(start_session, last_session)
@lazyval
def day(self):
return CustomBusinessDay(holidays=self.adhoc_holidays,
calendar=self.regular_holidays,weekmask="Mon Tue Wed Thu Fri Sat Sun")