Completed
Push — master ( e4fe44...6106cb )
by Eddie
01:23
created

zipline.utils.get_early_closes()   A

Complexity

Conditions 2

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 2
dl 0
loc 18
rs 9.4286
1
#
2
# Copyright 2014 Quantopian, Inc.
3
#
4
# Licensed under the Apache License, Version 2.0 (the "License");
5
# you may not use this file except in compliance with the License.
6
# You may obtain a copy of the License at
7
#
8
#     http://www.apache.org/licenses/LICENSE-2.0
9
#
10
# Unless required by applicable law or agreed to in writing, software
11
# distributed under the License is distributed on an "AS IS" BASIS,
12
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
# See the License for the specific language governing permissions and
14
# limitations under the License.
15
16
import pandas as pd
17
import pytz
18
19
from datetime import datetime
20
from dateutil import rrule
21
from zipline.utils.tradingcalendar import end, canonicalize_datetime, \
22
    get_open_and_closes
23
24
start = pd.Timestamp('1994-01-01', tz='UTC')
25
26
27
def get_non_trading_days(start, end):
28
    non_trading_rules = []
29
30
    start = canonicalize_datetime(start)
31
    end = canonicalize_datetime(end)
32
33
    weekends = rrule.rrule(
34
        rrule.YEARLY,
35
        byweekday=(rrule.SA, rrule.SU),
36
        cache=True,
37
        dtstart=start,
38
        until=end
39
    )
40
    non_trading_rules.append(weekends)
41
42
    # Universal confraternization
43
    conf_universal = rrule.rrule(
44
        rrule.MONTHLY,
45
        byyearday=1,
46
        cache=True,
47
        dtstart=start,
48
        until=end
49
    )
50
    non_trading_rules.append(conf_universal)
51
52
    # Sao Paulo city birthday
53
    aniversario_sao_paulo = rrule.rrule(
54
        rrule.MONTHLY,
55
        bymonth=1,
56
        bymonthday=25,
57
        cache=True,
58
        dtstart=start,
59
        until=end
60
    )
61
    non_trading_rules.append(aniversario_sao_paulo)
62
63
    # Carnival Monday
64
    carnaval_segunda = rrule.rrule(
65
        rrule.MONTHLY,
66
        byeaster=-48,
67
        cache=True,
68
        dtstart=start,
69
        until=end
70
    )
71
    non_trading_rules.append(carnaval_segunda)
72
73
    # Carnival Tuesday
74
    carnaval_terca = rrule.rrule(
75
        rrule.MONTHLY,
76
        byeaster=-47,
77
        cache=True,
78
        dtstart=start,
79
        until=end
80
    )
81
    non_trading_rules.append(carnaval_terca)
82
83
    # Passion of the Christ
84
    sexta_paixao = rrule.rrule(
85
        rrule.MONTHLY,
86
        byeaster=-2,
87
        cache=True,
88
        dtstart=start,
89
        until=end
90
    )
91
    non_trading_rules.append(sexta_paixao)
92
93
    # Corpus Christi
94
    corpus_christi = rrule.rrule(
95
        rrule.MONTHLY,
96
        byeaster=60,
97
        cache=True,
98
        dtstart=start,
99
        until=end
100
    )
101
    non_trading_rules.append(corpus_christi)
102
103
    tiradentes = rrule.rrule(
104
        rrule.MONTHLY,
105
        bymonth=4,
106
        bymonthday=21,
107
        cache=True,
108
        dtstart=start,
109
        until=end
110
    )
111
    non_trading_rules.append(tiradentes)
112
113
    # Labor day
114
    dia_trabalho = rrule.rrule(
115
        rrule.MONTHLY,
116
        bymonth=5,
117
        bymonthday=1,
118
        cache=True,
119
        dtstart=start,
120
        until=end
121
    )
122
    non_trading_rules.append(dia_trabalho)
123
124
    # Constitutionalist Revolution
125
    constitucionalista = rrule.rrule(
126
        rrule.MONTHLY,
127
        bymonth=7,
128
        bymonthday=9,
129
        cache=True,
130
        dtstart=datetime(1997, 1, 1, tzinfo=pytz.utc),
131
        until=end
132
    )
133
    non_trading_rules.append(constitucionalista)
134
135
    # Independency day
136
    independencia = rrule.rrule(
137
        rrule.MONTHLY,
138
        bymonth=9,
139
        bymonthday=7,
140
        cache=True,
141
        dtstart=start,
142
        until=end
143
    )
144
    non_trading_rules.append(independencia)
145
146
    # Our Lady of Aparecida
147
    aparecida = rrule.rrule(
148
        rrule.MONTHLY,
149
        bymonth=10,
150
        bymonthday=12,
151
        cache=True,
152
        dtstart=start,
153
        until=end
154
    )
155
    non_trading_rules.append(aparecida)
156
157
    # All Souls' day
158
    finados = rrule.rrule(
159
        rrule.MONTHLY,
160
        bymonth=11,
161
        bymonthday=2,
162
        cache=True,
163
        dtstart=start,
164
        until=end
165
    )
166
    non_trading_rules.append(finados)
167
168
    # Proclamation of the Republic
169
    proclamacao_republica = rrule.rrule(
170
        rrule.MONTHLY,
171
        bymonth=11,
172
        bymonthday=15,
173
        cache=True,
174
        dtstart=start,
175
        until=end
176
    )
177
    non_trading_rules.append(proclamacao_republica)
178
179
    # Day of Black Awareness
180
    consciencia_negra = rrule.rrule(
181
        rrule.MONTHLY,
182
        bymonth=11,
183
        bymonthday=20,
184
        cache=True,
185
        dtstart=datetime(2004, 1, 1, tzinfo=pytz.utc),
186
        until=end
187
    )
188
    non_trading_rules.append(consciencia_negra)
189
190
    # Christmas Eve
191
    vespera_natal = rrule.rrule(
192
        rrule.MONTHLY,
193
        bymonth=12,
194
        bymonthday=24,
195
        cache=True,
196
        dtstart=start,
197
        until=end
198
    )
199
    non_trading_rules.append(vespera_natal)
200
201
    # Christmas
202
    natal = rrule.rrule(
203
        rrule.MONTHLY,
204
        bymonth=12,
205
        bymonthday=25,
206
        cache=True,
207
        dtstart=start,
208
        until=end
209
    )
210
    non_trading_rules.append(natal)
211
212
    # New Year Eve
213
    ano_novo = rrule.rrule(
214
        rrule.MONTHLY,
215
        bymonth=12,
216
        bymonthday=31,
217
        cache=True,
218
        dtstart=start,
219
        until=end
220
    )
221
    non_trading_rules.append(ano_novo)
222
223
    # New Year Eve on saturday
224
    ano_novo_sab = rrule.rrule(
225
        rrule.MONTHLY,
226
        bymonth=12,
227
        bymonthday=30,
228
        byweekday=rrule.FR,
229
        cache=True,
230
        dtstart=start,
231
        until=end
232
    )
233
    non_trading_rules.append(ano_novo_sab)
234
235
    non_trading_ruleset = rrule.rruleset()
236
237
    for rule in non_trading_rules:
238
        non_trading_ruleset.rrule(rule)
239
240
    non_trading_days = non_trading_ruleset.between(start, end, inc=True)
241
242
    # World Cup 2014 Opening
243
    non_trading_days.append(datetime(2014, 6, 12, tzinfo=pytz.utc))
244
245
    non_trading_days.sort()
246
    return pd.DatetimeIndex(non_trading_days)
247
248
non_trading_days = get_non_trading_days(start, end)
249
trading_day = pd.tseries.offsets.CDay(holidays=non_trading_days)
250
251
252
def get_trading_days(start, end, trading_day=trading_day):
253
    return pd.date_range(start=start.date(),
254
                         end=end.date(),
255
                         freq=trading_day).tz_localize('UTC')
256
257
trading_days = get_trading_days(start, end)
258
259
260
# Ash Wednesday
261
quarta_cinzas = rrule.rrule(
262
    rrule.MONTHLY,
263
    byeaster=-46,
264
    cache=True,
265
    dtstart=start,
266
    until=end
267
)
268
269
270
def get_early_closes(start, end):
271
    # TSX closed at 1:00 PM on december 24th.
272
273
    start = canonicalize_datetime(start)
274
    end = canonicalize_datetime(end)
275
276
    early_close_rules = []
277
278
    early_close_rules.append(quarta_cinzas)
279
280
    early_close_ruleset = rrule.rruleset()
281
282
    for rule in early_close_rules:
283
        early_close_ruleset.rrule(rule)
284
    early_closes = early_close_ruleset.between(start, end, inc=True)
285
286
    early_closes.sort()
287
    return pd.DatetimeIndex(early_closes)
288
289
early_closes = get_early_closes(start, end)
290
291
292
def get_open_and_close(day, early_closes):
293
    # only "early close" event in Bovespa actually is a late start
294
    # as the market only opens at 1pm
295
    open_hour = 13 if day in quarta_cinzas else 10
296
    market_open = pd.Timestamp(
297
        datetime(
298
            year=day.year,
299
            month=day.month,
300
            day=day.day,
301
            hour=open_hour,
302
            minute=00),
303
        tz='America/Sao_Paulo').tz_convert('UTC')
304
    market_close = pd.Timestamp(
305
        datetime(
306
            year=day.year,
307
            month=day.month,
308
            day=day.day,
309
            hour=16),
310
        tz='America/Sao_Paulo').tz_convert('UTC')
311
312
    return market_open, market_close
313
314
open_and_closes = get_open_and_closes(trading_days, early_closes,
315
                                      get_open_and_close)
316