Completed
Push — master ( a28236...71395d )
by
unknown
01:27
created

tests.risk.TestRisk.test_trading_days_06()   A

Complexity

Conditions 3

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 3
dl 0
loc 7
rs 9.4286
1
#
2
# Copyright 2013 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 unittest
17
import datetime
18
import calendar
19
import numpy as np
20
import pytz
21
22
from itertools import chain
23
from six import itervalues
24
25
import zipline.finance.risk as risk
26
from zipline.utils import factory
27
28
from zipline.finance.trading import SimulationParameters, TradingEnvironment
29
30
from . import answer_key
31
from . answer_key import AnswerKey
32
33
ANSWER_KEY = AnswerKey()
34
35
RETURNS = ANSWER_KEY.RETURNS
36
37
38
class TestRisk(unittest.TestCase):
39
40
    @classmethod
41
    def setUpClass(cls):
42
        cls.env = TradingEnvironment()
43
44
    @classmethod
45
    def tearDownClass(cls):
46
        del cls.env
47
48
    def setUp(self):
49
50
        start_date = datetime.datetime(
51
            year=2006,
52
            month=1,
53
            day=1,
54
            hour=0,
55
            minute=0,
56
            tzinfo=pytz.utc)
57
        end_date = datetime.datetime(
58
            year=2006, month=12, day=31, tzinfo=pytz.utc)
59
60
        self.sim_params = SimulationParameters(
61
            period_start=start_date,
62
            period_end=end_date,
63
            env=self.env,
64
        )
65
66
        self.algo_returns_06 = factory.create_returns_from_list(
67
            RETURNS,
68
            self.sim_params
69
        )
70
71
        self.benchmark_returns_06 = \
72
            answer_key.RETURNS_DATA['Benchmark Returns']
73
74
        self.metrics_06 = risk.RiskReport(
75
            self.algo_returns_06,
76
            self.sim_params,
77
            benchmark_returns=self.benchmark_returns_06,
78
            env=self.env,
79
        )
80
81
        start_08 = datetime.datetime(
82
            year=2008,
83
            month=1,
84
            day=1,
85
            hour=0,
86
            minute=0,
87
            tzinfo=pytz.utc)
88
89
        end_08 = datetime.datetime(
90
            year=2008,
91
            month=12,
92
            day=31,
93
            tzinfo=pytz.utc
94
        )
95
        self.sim_params08 = SimulationParameters(
96
            period_start=start_08,
97
            period_end=end_08,
98
            env=self.env,
99
        )
100
101
    def tearDown(self):
102
        return
103
104
    def test_factory(self):
105
        returns = [0.1] * 100
106
        r_objects = factory.create_returns_from_list(returns, self.sim_params)
107
        self.assertTrue(r_objects.index[-1] <=
108
                        datetime.datetime(
109
                            year=2006, month=12, day=31, tzinfo=pytz.utc))
110
111
    def test_drawdown(self):
112
        returns = factory.create_returns_from_list(
113
            [1.0, -0.5, 0.8, .17, 1.0, -0.1, -0.45], self.sim_params)
114
        # 200, 100, 180, 210.6, 421.2, 379.8, 208.494
115
        metrics = risk.RiskMetricsPeriod(
116
            returns.index[0],
117
            returns.index[-1],
118
            returns,
119
            env=self.env,
120
            benchmark_returns=self.env.benchmark_returns,
121
            )
122
        self.assertEqual(metrics.max_drawdown, 0.505)
123
124
    def test_benchmark_returns_06(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
125
126
        np.testing.assert_almost_equal(
127
            [x.benchmark_period_returns
128
             for x in self.metrics_06.month_periods],
129
            ANSWER_KEY.BENCHMARK_PERIOD_RETURNS['Monthly'])
130
        np.testing.assert_almost_equal(
131
            [x.benchmark_period_returns
132
             for x in self.metrics_06.three_month_periods],
133
            ANSWER_KEY.BENCHMARK_PERIOD_RETURNS['3-Month'])
134
        np.testing.assert_almost_equal(
135
            [x.benchmark_period_returns
136
             for x in self.metrics_06.six_month_periods],
137
            ANSWER_KEY.BENCHMARK_PERIOD_RETURNS['6-month'])
138
        np.testing.assert_almost_equal(
139
            [x.benchmark_period_returns
140
             for x in self.metrics_06.year_periods],
141
            ANSWER_KEY.BENCHMARK_PERIOD_RETURNS['year'])
142
143
    def test_trading_days_06(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
144
        returns = factory.create_returns_from_range(self.sim_params)
145
        metrics = risk.RiskReport(returns, self.sim_params, env=self.env)
146
        self.assertEqual([x.num_trading_days for x in metrics.year_periods],
147
                         [251])
148
        self.assertEqual([x.num_trading_days for x in metrics.month_periods],
149
                         [20, 19, 23, 19, 22, 22, 20, 23, 20, 22, 21, 20])
150
151
    def test_benchmark_volatility_06(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
152
153
        np.testing.assert_almost_equal(
154
            [x.benchmark_volatility
155
             for x in self.metrics_06.month_periods],
156
            ANSWER_KEY.BENCHMARK_PERIOD_VOLATILITY['Monthly'])
157
        np.testing.assert_almost_equal(
158
            [x.benchmark_volatility
159
             for x in self.metrics_06.three_month_periods],
160
            ANSWER_KEY.BENCHMARK_PERIOD_VOLATILITY['3-Month'])
161
        np.testing.assert_almost_equal(
162
            [x.benchmark_volatility
163
             for x in self.metrics_06.six_month_periods],
164
            ANSWER_KEY.BENCHMARK_PERIOD_VOLATILITY['6-month'])
165
        np.testing.assert_almost_equal(
166
            [x.benchmark_volatility
167
             for x in self.metrics_06.year_periods],
168
            ANSWER_KEY.BENCHMARK_PERIOD_VOLATILITY['year'])
169
170
    def test_algorithm_returns_06(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
171
        np.testing.assert_almost_equal(
172
            [x.algorithm_period_returns
173
             for x in self.metrics_06.month_periods],
174
            ANSWER_KEY.ALGORITHM_PERIOD_RETURNS['Monthly'])
175
        np.testing.assert_almost_equal(
176
            [x.algorithm_period_returns
177
             for x in self.metrics_06.three_month_periods],
178
            ANSWER_KEY.ALGORITHM_PERIOD_RETURNS['3-Month'])
179
        np.testing.assert_almost_equal(
180
            [x.algorithm_period_returns
181
             for x in self.metrics_06.six_month_periods],
182
            ANSWER_KEY.ALGORITHM_PERIOD_RETURNS['6-month'])
183
        np.testing.assert_almost_equal(
184
            [x.algorithm_period_returns
185
             for x in self.metrics_06.year_periods],
186
            ANSWER_KEY.ALGORITHM_PERIOD_RETURNS['year'])
187
188
    def test_algorithm_volatility_06(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
189
        np.testing.assert_almost_equal(
190
            [x.algorithm_volatility
191
             for x in self.metrics_06.month_periods],
192
            ANSWER_KEY.ALGORITHM_PERIOD_VOLATILITY['Monthly'])
193
        np.testing.assert_almost_equal(
194
            [x.algorithm_volatility
195
             for x in self.metrics_06.three_month_periods],
196
            ANSWER_KEY.ALGORITHM_PERIOD_VOLATILITY['3-Month'])
197
        np.testing.assert_almost_equal(
198
            [x.algorithm_volatility
199
             for x in self.metrics_06.six_month_periods],
200
            ANSWER_KEY.ALGORITHM_PERIOD_VOLATILITY['6-month'])
201
        np.testing.assert_almost_equal(
202
            [x.algorithm_volatility
203
             for x in self.metrics_06.year_periods],
204
            ANSWER_KEY.ALGORITHM_PERIOD_VOLATILITY['year'])
205
206
    def test_algorithm_sharpe_06(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
207
        np.testing.assert_almost_equal(
208
            [x.sharpe for x in self.metrics_06.month_periods],
209
            ANSWER_KEY.ALGORITHM_PERIOD_SHARPE['Monthly'])
210
        np.testing.assert_almost_equal(
211
            [x.sharpe for x in self.metrics_06.three_month_periods],
212
            ANSWER_KEY.ALGORITHM_PERIOD_SHARPE['3-Month'])
213
        np.testing.assert_almost_equal(
214
            [x.sharpe for x in self.metrics_06.six_month_periods],
215
            ANSWER_KEY.ALGORITHM_PERIOD_SHARPE['6-month'])
216
        np.testing.assert_almost_equal(
217
            [x.sharpe for x in self.metrics_06.year_periods],
218
            ANSWER_KEY.ALGORITHM_PERIOD_SHARPE['year'])
219
220
    def test_algorithm_downside_risk_06(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
221
        np.testing.assert_almost_equal(
222
            [x.downside_risk for x in self.metrics_06.month_periods],
223
            ANSWER_KEY.ALGORITHM_PERIOD_DOWNSIDE_RISK['Monthly'],
224
            decimal=4)
225
        np.testing.assert_almost_equal(
226
            [x.downside_risk for x in self.metrics_06.three_month_periods],
227
            ANSWER_KEY.ALGORITHM_PERIOD_DOWNSIDE_RISK['3-Month'],
228
            decimal=4)
229
        np.testing.assert_almost_equal(
230
            [x.downside_risk for x in self.metrics_06.six_month_periods],
231
            ANSWER_KEY.ALGORITHM_PERIOD_DOWNSIDE_RISK['6-month'],
232
            decimal=4)
233
        np.testing.assert_almost_equal(
234
            [x.downside_risk for x in self.metrics_06.year_periods],
235
            ANSWER_KEY.ALGORITHM_PERIOD_DOWNSIDE_RISK['year'],
236
            decimal=4)
237
238
    def test_algorithm_sortino_06(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
239
        np.testing.assert_almost_equal(
240
            [x.sortino for x in self.metrics_06.month_periods],
241
            ANSWER_KEY.ALGORITHM_PERIOD_SORTINO['Monthly'],
242
            decimal=3)
243
244
        np.testing.assert_almost_equal(
245
            [x.sortino for x in self.metrics_06.three_month_periods],
246
            ANSWER_KEY.ALGORITHM_PERIOD_SORTINO['3-Month'],
247
            decimal=3)
248
249
        np.testing.assert_almost_equal(
250
            [x.sortino for x in self.metrics_06.six_month_periods],
251
            ANSWER_KEY.ALGORITHM_PERIOD_SORTINO['6-month'],
252
            decimal=3)
253
254
        np.testing.assert_almost_equal(
255
            [x.sortino for x in self.metrics_06.year_periods],
256
            ANSWER_KEY.ALGORITHM_PERIOD_SORTINO['year'],
257
            decimal=3)
258
259
    def test_algorithm_information_06(self):
260
        self.assertEqual([round(x.information, 3)
261
                          for x in self.metrics_06.month_periods],
262
                         [0.131,
263
                          -0.11,
264
                          -0.067,
265
                          0.136,
266
                          0.301,
267
                          -0.387,
268
                          0.107,
269
                          -0.032,
270
                          -0.058,
271
                          0.069,
272
                          0.095,
273
                          -0.123])
274
        self.assertEqual([round(x.information, 3)
275
                          for x in self.metrics_06.three_month_periods],
276
                         [-0.013,
277
                          -0.009,
278
                          0.111,
279
                          -0.014,
280
                          -0.017,
281
                          -0.108,
282
                          0.011,
283
                          -0.004,
284
                          0.032,
285
                          0.011])
286
        self.assertEqual([round(x.information, 3)
287
                          for x in self.metrics_06.six_month_periods],
288
                         [-0.013,
289
                          -0.014,
290
                          -0.003,
291
                          -0.002,
292
                          -0.011,
293
                          -0.041,
294
                          0.011])
295
        self.assertEqual([round(x.information, 3)
296
                          for x in self.metrics_06.year_periods],
297
                         [-0.001])
298
299
    def test_algorithm_beta_06(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
300
        np.testing.assert_almost_equal(
301
            [x.beta for x in self.metrics_06.month_periods],
302
            ANSWER_KEY.ALGORITHM_PERIOD_BETA['Monthly'])
303
        np.testing.assert_almost_equal(
304
            [x.beta for x in self.metrics_06.three_month_periods],
305
            ANSWER_KEY.ALGORITHM_PERIOD_BETA['3-Month'])
306
        np.testing.assert_almost_equal(
307
            [x.beta for x in self.metrics_06.six_month_periods],
308
            ANSWER_KEY.ALGORITHM_PERIOD_BETA['6-month'])
309
        np.testing.assert_almost_equal(
310
            [x.beta for x in self.metrics_06.year_periods],
311
            ANSWER_KEY.ALGORITHM_PERIOD_BETA['year'])
312
313
    def test_algorithm_alpha_06(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
314
        np.testing.assert_almost_equal(
315
            [x.alpha for x in self.metrics_06.month_periods],
316
            ANSWER_KEY.ALGORITHM_PERIOD_ALPHA['Monthly'])
317
        np.testing.assert_almost_equal(
318
            [x.alpha for x in self.metrics_06.three_month_periods],
319
            ANSWER_KEY.ALGORITHM_PERIOD_ALPHA['3-Month'])
320
        np.testing.assert_almost_equal(
321
            [x.alpha for x in self.metrics_06.six_month_periods],
322
            ANSWER_KEY.ALGORITHM_PERIOD_ALPHA['6-month'])
323
        np.testing.assert_almost_equal(
324
            [x.alpha for x in self.metrics_06.year_periods],
325
            ANSWER_KEY.ALGORITHM_PERIOD_ALPHA['year'])
326
327
    # FIXME: Covariance is not matching excel precisely enough to run the test.
328
    # Month 4 seems to be the problem. Variance is disabled
329
    # just to avoid distraction - it is much closer than covariance
330
    # and can probably pass with 6 significant digits instead of 7.
331
    # re-enable variance, alpha, and beta tests once this is resolved
332
    def test_algorithm_covariance_06(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
333
        np.testing.assert_almost_equal(
334
            [x.algorithm_covariance for x in self.metrics_06.month_periods],
335
            ANSWER_KEY.ALGORITHM_PERIOD_COVARIANCE['Monthly'])
336
        np.testing.assert_almost_equal(
337
            [x.algorithm_covariance
338
             for x in self.metrics_06.three_month_periods],
339
            ANSWER_KEY.ALGORITHM_PERIOD_COVARIANCE['3-Month'])
340
        np.testing.assert_almost_equal(
341
            [x.algorithm_covariance
342
             for x in self.metrics_06.six_month_periods],
343
            ANSWER_KEY.ALGORITHM_PERIOD_COVARIANCE['6-month'])
344
        np.testing.assert_almost_equal(
345
            [x.algorithm_covariance
346
             for x in self.metrics_06.year_periods],
347
            ANSWER_KEY.ALGORITHM_PERIOD_COVARIANCE['year'])
348
349
    def test_benchmark_variance_06(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
350
        np.testing.assert_almost_equal(
351
            [x.benchmark_variance
352
             for x in self.metrics_06.month_periods],
353
            ANSWER_KEY.ALGORITHM_PERIOD_BENCHMARK_VARIANCE['Monthly'])
354
        np.testing.assert_almost_equal(
355
            [x.benchmark_variance
356
             for x in self.metrics_06.three_month_periods],
357
            ANSWER_KEY.ALGORITHM_PERIOD_BENCHMARK_VARIANCE['3-Month'])
358
        np.testing.assert_almost_equal(
359
            [x.benchmark_variance
360
             for x in self.metrics_06.six_month_periods],
361
            ANSWER_KEY.ALGORITHM_PERIOD_BENCHMARK_VARIANCE['6-month'])
362
        np.testing.assert_almost_equal(
363
            [x.benchmark_variance
364
             for x in self.metrics_06.year_periods],
365
            ANSWER_KEY.ALGORITHM_PERIOD_BENCHMARK_VARIANCE['year'])
366
367
    def test_benchmark_returns_08(self):
368
        returns = factory.create_returns_from_range(self.sim_params08)
369
        metrics = risk.RiskReport(returns, self.sim_params08, env=self.env)
370
371
        self.assertEqual([round(x.benchmark_period_returns, 3)
372
                          for x in metrics.month_periods],
373
                         [-0.061,
374
                          -0.035,
375
                          -0.006,
376
                          0.048,
377
                          0.011,
378
                          -0.086,
379
                          -0.01,
380
                          0.012,
381
                          -0.091,
382
                          -0.169,
383
                          -0.075,
384
                          0.008])
385
386
        self.assertEqual([round(x.benchmark_period_returns, 3)
387
                          for x in metrics.three_month_periods],
388
                         [-0.099,
389
                          0.005,
390
                          0.052,
391
                          -0.032,
392
                          -0.085,
393
                          -0.084,
394
                          -0.089,
395
                          -0.236,
396
                          -0.301,
397
                          -0.226])
398
399
        self.assertEqual([round(x.benchmark_period_returns, 3)
400
                          for x in metrics.six_month_periods],
401
                         [-0.128,
402
                          -0.081,
403
                          -0.036,
404
                          -0.118,
405
                          -0.301,
406
                          -0.36,
407
                          -0.294])
408
409
        self.assertEqual([round(x.benchmark_period_returns, 3)
410
                          for x in metrics.year_periods],
411
                         [-0.385])
412
413
    def test_trading_days_08(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
414
        returns = factory.create_returns_from_range(self.sim_params08)
415
        metrics = risk.RiskReport(returns, self.sim_params08, env=self.env)
416
        self.assertEqual([x.num_trading_days for x in metrics.year_periods],
417
                         [253])
418
419
        self.assertEqual([x.num_trading_days for x in metrics.month_periods],
420
                         [21, 20, 20, 22, 21, 21, 22, 21, 21, 23, 19, 22])
421
422
    def test_benchmark_volatility_08(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
423
        returns = factory.create_returns_from_range(self.sim_params08)
424
        metrics = risk.RiskReport(returns, self.sim_params08, env=self.env)
425
426
        self.assertEqual([round(x.benchmark_volatility, 3)
427
                          for x in metrics.month_periods],
428
                         [0.07,
429
                          0.058,
430
                          0.082,
431
                          0.054,
432
                          0.041,
433
                          0.057,
434
                          0.068,
435
                          0.06,
436
                          0.157,
437
                          0.244,
438
                          0.195,
439
                          0.145])
440
441
        self.assertEqual([round(x.benchmark_volatility, 3)
442
                          for x in metrics.three_month_periods],
443
                         [0.12,
444
                          0.113,
445
                          0.105,
446
                          0.09,
447
                          0.098,
448
                          0.107,
449
                          0.179,
450
                          0.293,
451
                          0.344,
452
                          0.34])
453
454
        self.assertEqual([round(x.benchmark_volatility, 3)
455
                          for x in metrics.six_month_periods],
456
                         [0.15,
457
                          0.149,
458
                          0.15,
459
                          0.2,
460
                          0.308,
461
                          0.36,
462
                          0.383])
463
        # TODO: ugly, but I can't get the rounded float to match.
464
        # maybe we need a different test that checks the
465
        # difference between the numbers
466
        self.assertEqual([round(x.benchmark_volatility, 3)
467
                          for x in metrics.year_periods],
468
                         [0.411])
469
470
    def test_treasury_returns_06(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
471
        returns = factory.create_returns_from_range(self.sim_params)
472
        metrics = risk.RiskReport(returns, self.sim_params, env=self.env)
473
        self.assertEqual([round(x.treasury_period_return, 4)
474
                          for x in metrics.month_periods],
475
                         [0.0037,
476
                          0.0034,
477
                          0.0039,
478
                          0.0038,
479
                          0.0040,
480
                          0.0037,
481
                          0.0043,
482
                          0.0043,
483
                          0.0038,
484
                          0.0044,
485
                          0.0043,
486
                          0.004])
487
488
        self.assertEqual([round(x.treasury_period_return, 4)
489
                          for x in metrics.three_month_periods],
490
                         [0.0114,
491
                          0.0116,
492
                          0.0122,
493
                          0.0125,
494
                          0.0129,
495
                          0.0127,
496
                          0.0123,
497
                          0.0128,
498
                          0.0125,
499
                          0.0127])
500
        self.assertEqual([round(x.treasury_period_return, 4)
501
                          for x in metrics.six_month_periods],
502
                         [0.0260,
503
                          0.0257,
504
                          0.0258,
505
                          0.0252,
506
                          0.0259,
507
                          0.0256,
508
                          0.0257])
509
510
        self.assertEqual([round(x.treasury_period_return, 4)
511
                          for x in metrics.year_periods],
512
                         [0.0500])
513
514
    def test_benchmarkrange(self):
515
        self.check_year_range(
516
            datetime.datetime(
517
                year=2008, month=1, day=1, tzinfo=pytz.utc),
518
            2)
519
520
    def test_partial_month(self):
521
522
        start = datetime.datetime(
523
            year=1991,
524
            month=1,
525
            day=1,
526
            hour=0,
527
            minute=0,
528
            tzinfo=pytz.utc)
529
530
        # 1992 and 1996 were leap years
531
        total_days = 365 * 5 + 2
532
        end = start + datetime.timedelta(days=total_days)
533
        sim_params90s = SimulationParameters(
534
            period_start=start,
535
            period_end=end,
536
            env=self.env,
537
        )
538
539
        returns = factory.create_returns_from_range(sim_params90s)
540
        returns = returns[:-10]  # truncate the returns series to end mid-month
541
        metrics = risk.RiskReport(returns, sim_params90s, env=self.env)
542
        total_months = 60
543
        self.check_metrics(metrics, total_months, start)
544
545
    def check_year_range(self, start_date, years):
546
        sim_params = SimulationParameters(
547
            period_start=start_date,
548
            period_end=start_date.replace(year=(start_date.year + years)),
549
            env=self.env,
550
        )
551
        returns = factory.create_returns_from_range(sim_params)
552
        metrics = risk.RiskReport(returns, self.sim_params, env=self.env)
553
        total_months = years * 12
554
        self.check_metrics(metrics, total_months, start_date)
555
556
    def check_metrics(self, metrics, total_months, start_date):
557
        """
558
        confirm that the right number of riskmetrics were calculated for each
559
        window length.
560
        """
561
        self.assert_range_length(
562
            metrics.month_periods,
563
            total_months,
564
            1,
565
            start_date
566
        )
567
568
        self.assert_range_length(
569
            metrics.three_month_periods,
570
            total_months,
571
            3,
572
            start_date
573
        )
574
575
        self.assert_range_length(
576
            metrics.six_month_periods,
577
            total_months,
578
            6,
579
            start_date
580
        )
581
582
        self.assert_range_length(
583
            metrics.year_periods,
584
            total_months,
585
            12,
586
            start_date
587
        )
588
589
    def assert_last_day(self, period_end):
590
        # 30 days has september, april, june and november
591
        if period_end.month in [9, 4, 6, 11]:
592
            self.assertEqual(period_end.day, 30)
593
        # all the rest have 31, except for february
594
        elif(period_end.month != 2):
595
            self.assertEqual(period_end.day, 31)
596
        else:
597
            if calendar.isleap(period_end.year):
598
                self.assertEqual(period_end.day, 29)
599
            else:
600
                self.assertEqual(period_end.day, 28)
601
602
    def assert_month(self, start_month, actual_end_month):
603
        if start_month == 1:
604
            expected_end_month = 12
605
        else:
606
            expected_end_month = start_month - 1
607
608
        self.assertEqual(expected_end_month, actual_end_month)
609
610
    def assert_range_length(self, col, total_months,
611
                            period_length, start_date):
612
        if(period_length > total_months):
613
            self.assertEqual(len(col), 0)
614
        else:
615
            self.assertEqual(
616
                len(col),
617
                total_months - (period_length - 1),
618
                "mismatch for total months - \
619
                expected:{total_months}/actual:{actual}, \
620
                period:{period_length}, start:{start_date}, \
621
                calculated end:{end}".format(total_months=total_months,
622
                                             period_length=period_length,
623
                                             start_date=start_date,
624
                                             end=col[-1].end_date,
625
                                             actual=len(col))
626
            )
627
            self.assert_month(start_date.month, col[-1].end_date.month)
628
            self.assert_last_day(col[-1].end_date)
629
630
    def test_sparse_benchmark(self):
631
        benchmark_returns = self.benchmark_returns_06.copy()
632
        # Set every other day to nan.
633
        benchmark_returns.iloc[::2] = np.nan
634
635
        report = risk.RiskReport(
636
            self.algo_returns_06,
637
            self.sim_params,
638
            benchmark_returns=benchmark_returns,
639
            env=self.env,
640
        )
641
        for risk_period in chain.from_iterable(itervalues(report.to_dict())):
642
            self.assertIsNone(risk_period['beta'])
643