quantopian / zipline

Zipline, a Pythonic Algorithmic Trading Library
https://www.zipline.io
Apache License 2.0
17.34k stars 4.68k forks source link

Make tradingcalendar specific to the TradingEnvironment #257

Closed mtrovo closed 8 years ago

mtrovo commented 10 years ago

I'm trying to run some backtests against Brazilian stocks and I'm running through some problems related to the calendar used by zipline by default. Some of the trading days don't match between the Brazilian trading calendar and the american one and I'm not seeing any easy way to override the calendar without changing the tradingcalendar imports on the zipline internal files (e.g finance/performance/tracker.py).

I'm already overriding the default benchmark using the TradingEnvironment object and it's working fine, my idea is to make the tradingcalendar an attribute of the TradingEnvironment object set at initialization and when not given defaults to the US tradingcalendar that comes by default.

ehebert commented 10 years ago

@mtrovo, I agree that internal modules should refer to TradingEnvironment. The default TradingEnvironment does have members of trading_days, early_closes, open_and_closes, and should be used by internal modules. However, I am not seeing where tradingcalendar is being imported in places that are not the trading module or unit tests. What commit-ish and line number are you seeing it on?

The process for creating non-US Equity calendars does need to be made clearer, and less bug prone. When you get a chance would you mind sharing your Brazil TradingEnvironment implementation?

mtrovo commented 10 years ago

@ehebert my problem is with the TradingEnvironment class itself, on the next_open_and_close method it gets the next_trading_day from the input benchmark provided but the call to get_open_and_close executes a call to the trading calendar open_and_closes variable, which return NaN for days that exist on the benchmark data but are not trading days on the calendar.

I'm creating and using my TradingEnvironment with the following code:

    bvsp=trading.TradingEnvironment(bm_symbol="^BVSP", exchange_tz="America/Sao_Paulo")
    with bvsp:
      # load stock data and do all the processing here

I made a dirt quick fix for this bug by calling tradingcalendar.get_open_and_close instead as you can see on the following diff.

diff --git i/zipline/finance/trading.py w/zipline/finance/trading.py
index 98a0fce..30ae4ac 100644
--- i/zipline/finance/trading.py
+++ w/zipline/finance/trading.py
@@ -179,7 +179,7 @@ class TradingEnvironment(object):
                 "Attempt to backtest beyond available history. \
 Last successful date: %s" % self.last_trading_day)

-        return self.get_open_and_close(next_open)
+        return tradingcalendar.get_open_and_close(next_open, tradingcalendar.ea

     def get_open_and_close(self, day):
         todays_minutes = self.open_and_closes.ix[day.date()]
lines 114-136/136 (END)
ehebert commented 10 years ago

Ah, I see. (Disculpe!)

It looks like your fix will prevent you from crashing, but you might runt into some odd behavior because you would be still using the early closes from the US calendar. (Unless you've done something like monkey patched the early_closes variable in the tradingcalendar module.)

I think the root problem here, as you have identified, is that the tradingcalendar does not match the benchmark data.

As part of your process of supporting the Brazil stock exchange, have you also defined a tradingcalendar_suffixforbrazil.py? (There are a few examples in zipline/utils of non-U.S. equities.)

Though even with your own tradingcalendar, I think you are hitting the exact paint point, and instead of using the tradingcalendar module, we should investigate passing it as a parameter to the TradingEnvironment init, so that it will be easier to use the early_closes etc.

On Thu, Jan 9, 2014 at 12:06 PM, Moises Trovo notifications@github.comwrote:

@ehebert https://github.com/ehebert my problem is with the TradingEnvironment class itself, on the next_open_and_close method it gets the next_trading_day from the input benchmark provided but the call to get_open_and_close executes a call to the trading calendar open_and_closes variable, which return NaN for days that exist on the benchmark data but are not trading days on the calendar.

I'm creating and using my TradingEnvironment with the following code:

bvsp=trading.TradingEnvironment(bm_symbol="^BVSP", exchange_tz="America/Sao_Paulo")
with bvsp:
  # load stock data and do all the processing here

I made a dirt quick fix for this bug by calling tradingcalendar.get_open_and_close instead as you can see on the following diff.

diff --git i/zipline/finance/trading.py w/zipline/finance/trading.pyindex 98a0fce..30ae4ac 100644--- i/zipline/finance/trading.py+++ w/zipline/finance/trading.py@@ -179,7 +179,7 @@ class TradingEnvironment(object): "Attempt to backtest beyond available history. \ Last successful date: %s" % self.last_trading_day)

  •  return self.get_open_and_close(next_open)+        return tradingcalendar.get_open_and_close(next_open, tradingcalendar.ea

    def get_open_and_close(self, day): todays_minutes = self.open_and_closes.ix[day.date()] lines 114-136/136 (END)

— Reply to this email directly or view it on GitHubhttps://github.com/quantopian/zipline/issues/257#issuecomment-31953800 .

llllllllll commented 8 years ago

@ehebert I think we now have support for passing in calendars, correct?

ehebert commented 8 years ago

@llllllllll correct https://github.com/quantopian/zipline/blob/master/zipline/finance/trading.py#L72

llllllllll commented 8 years ago

kk, can we close this?

ehebert commented 8 years ago

I believe so.

jpspfaria commented 8 years ago

Nice, i will test this for BM&FBovespa!