Тестирование zipline с использованием не-американских (европейских) внутридневных данных

Я пытаюсь заставить zipline работать с неамериканскими внутридневными данными, которые я загрузил в панду DataFrame:

                        BARC    HSBA     LLOY     STAN
Date                                                  
2014-07-01 08:30:00  321.250  894.55  112.105  1777.25
2014-07-01 08:32:00  321.150  894.70  112.095  1777.00
2014-07-01 08:34:00  321.075  894.80  112.140  1776.50
2014-07-01 08:36:00  321.725  894.80  112.255  1777.00
2014-07-01 08:38:00  321.675  894.70  112.290  1777.00

Я следовал здесь руководству по скользящим средним, заменив "AAPL" своим собственным символьным кодом, а исторические вызовы данными "1m" вместо "1d".

Затем я делаю последний звонок, используя algo_obj.run(DataFrameSource(mydf)), где mydf это датафрейм выше.

Однако возникают все виды проблем, связанных с TradingEnvironment. Согласно исходному коду:

# This module maintains a global variable, environment, which is
# subsequently referenced directly by zipline financial
# components. To set the environment, you can set the property on
# the module directly:
#       from zipline.finance import trading
#       trading.environment = TradingEnvironment()
#
# or if you want to switch the environment for a limited context
# you can use a TradingEnvironment in a with clause:
#       lse = TradingEnvironment(bm_index="^FTSE", exchange_tz="Europe/London")
#       with lse:
# the code here will have lse as the global trading.environment
#           algo.run(start, end)

Однако использование контекста, похоже, не работает полностью. Я все еще получаю ошибки, например, утверждая, что мои временные метки находятся перед открытием рынка (и действительно, глядя на trading.environment.open_and_close времена для рынка США.

Мой вопрос: кому-нибудь удавалось использовать zipline с данными за пределами США? Не могли бы вы указать мне ресурс и в идеале пример кода о том, как это сделать?

nb Я видел, что на github есть несколько тестов, которые, похоже, связаны с торговыми календарями (tradincalendar_lse.py, tradingcalendar_tse.py и т. д.), но, похоже, они обрабатывают данные только на дневном уровне. Я должен был бы исправить:

  • время открытия / закрытия
  • справочные данные для эталона
  • и, вероятно, больше...

2 ответа

У меня все получилось после того, как я возился с учебным пособием. Пример кода ниже. Это использует DF mid, как описано в оригинальном вопросе. Несколько пунктов имеют упоминание:

  1. Торговый календарь я создаю один вручную и назначаю trading.environment, используя non_working_days в tradingcalendar_lse.py. В качестве альтернативы вы могли бы создать тот, который точно соответствует вашим данным (однако это может быть проблемой для данных вне выборки). Есть два поля, которые вам нужно определить: trading_days а также open_and_closes,

  2. sim_params Существует проблема с начальными / конечными значениями по умолчанию, потому что они не учитывают часовой пояс. Поэтому вы должны создать объект sim_params и передать параметры начала / конца с часовым поясом.

  3. Также, run() должен вызываться с аргументом overwrite_sim_params=False как calculate_first_open/close поднять ошибки отметки времени.

Я должен упомянуть, что также возможно передавать данные Panel панд с открытыми полями, максимумом, минимумом, закрытием, ценой и объемом в minor_axis. Но в этом случае первые поля являются обязательными - в противном случае возникают ошибки.

Обратите внимание, что этот код производит только ежедневную сводку производительности. Я уверен, что должен быть способ получить результат с минимальным разрешением (я думал, что это было установлено emission_rate, но, видимо, это не так). Если кто-нибудь знает, пожалуйста, прокомментируйте, и я обновлю код. Кроме того, не уверен, что вызов API для вызова "проанализировать" (т.е. при использовании %%zipline магия в IPython, как в учебнике, analyze() метод вызывается автоматически. Как мне сделать это вручную?)

import pytz
from datetime import datetime

from zipline.algorithm import TradingAlgorithm
from zipline.utils import tradingcalendar
from zipline.utils import tradingcalendar_lse
from zipline.finance.trading import TradingEnvironment
from zipline.api import order_target, record, symbol, history, add_history
from zipline.finance import trading

def initialize(context):
    # Register 2 histories that track daily prices,
    # one with a 100 window and one with a 300 day window
    add_history(10, '1m', 'price')
    add_history(30, '1m', 'price')

    context.i = 0


def handle_data(context, data):
    # Skip first 30 mins to get full windows
    context.i += 1
    if context.i < 30:
        return

    # Compute averages
    # history() has to be called with the same params
    # from above and returns a pandas dataframe.
    short_mavg = history(10, '1m', 'price').mean()
    long_mavg = history(30, '1m', 'price').mean()

    sym = symbol('BARC')

    # Trading logic
    if short_mavg[sym] > long_mavg[sym]:
        # order_target orders as many shares as needed to
        # achieve the desired number of shares.
        order_target(sym, 100)
    elif short_mavg[sym] < long_mavg[sym]:
        order_target(sym, 0)

    # Save values for later inspection
    record(BARC=data[sym].price,
           short_mavg=short_mavg[sym],
           long_mavg=long_mavg[sym])

def analyze(context,perf) : 
    perf["pnl"].plot(title="Strategy P&L")

# Create algorithm object passing in initialize and
# handle_data functions

# This is needed to handle the correct calendar. Assume that market data has the right index for tradeable days.
# Passing in env_trading_calendar=tradingcalendar_lse doesn't appear to work, as it doesn't implement open_and_closes
from zipline.utils import tradingcalendar_lse
trading.environment = TradingEnvironment(bm_symbol='^FTSE', exchange_tz='Europe/London')
#trading.environment.trading_days = mid.index.normalize().unique()
trading.environment.trading_days = pd.date_range(start=mid.index.normalize()[0],
                                                 end=mid.index.normalize()[-1],
                                                 freq=pd.tseries.offsets.CDay(holidays=tradingcalendar_lse.non_trading_days))

trading.environment.open_and_closes = pd.DataFrame(index=trading.environment.trading_days,columns=["market_open","market_close"])
trading.environment.open_and_closes.market_open = (trading.environment.open_and_closes.index + pd.to_timedelta(60*7,unit="T")).to_pydatetime()
trading.environment.open_and_closes.market_close = (trading.environment.open_and_closes.index + pd.to_timedelta(60*15+30,unit="T")).to_pydatetime()


from zipline.utils.factory import create_simulation_parameters
sim_params = create_simulation_parameters(
   start = pd.to_datetime("2014-07-01 08:30:00").tz_localize("Europe/London").tz_convert("UTC"),  #Bug in code doesn't set tz if these are not specified (finance/trading.py:SimulationParameters.calculate_first_open[close])
   end = pd.to_datetime("2014-07-24 16:30:00").tz_localize("Europe/London").tz_convert("UTC"),
   data_frequency = "minute",
   emission_rate = "minute",
   sids = ["BARC"])
algo_obj = TradingAlgorithm(initialize=initialize, 
                            handle_data=handle_data,
                            sim_params=sim_params)

# Run algorithm
perf_manual = algo_obj.run(mid,overwrite_sim_params=False) # overwrite == True calls calculate_first_open[close] (see above)

@Luciano

Можете добавить analyze(None, perf_manual)в конце вашего кода для автоматического запуска процесса анализа.

Другие вопросы по тегам