-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathtests.py
203 lines (145 loc) · 5.75 KB
/
tests.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
import unittest
from abc import ABCMeta, abstractmethod
from random import randint
from data import A, MeanReturns
from entities.portfolio import Portfolio
from generator import generateGaussianScenarios, generateStudentTScenarios
from markowitz import Markowitz
from scenarios_based.models import CVaR, GMD, MAD, Minimax, SemiMAD, VaR
class TestCaseWrapper(object):
"""
All the base plot_test cases are defined inside this class, because we do not want them to be read as tests
themselves (because they should be overriden).
"""
class ModelBaseTestCase(unittest.TestCase):
"""
Base plot_test case for all the portfolio models (Markowitz + Scenarios-based).
"""
__metaclass__ = ABCMeta
@abstractmethod
def Model(self):
"""Returns the class of the Model tested (should be overridden)."""
return None
def createModel(self, *args, **kwargs):
"""
Will be overriden by the scenarios-based portfolio models (which requires scenarios / probas).
:rtype: entities.PortfolioOptimizer
"""
return self.Model(*args, **kwargs)
def test_init(self):
self.assertIsInstance(self.createModel(), self.Model)
def test_get_portfolios(self):
self.assertIsInstance(self.createModel().optimize().getPortfolio(), Portfolio)
def test_Wmin(self):
Wmin = 0.1
m = self.createModel(Wmin=Wmin)
self.assertIsInstance(
m.optimize().objval,
float
)
for a in A:
if m._X[a].x > 0.5:
self.assertGreaterEqual(m._W[a].x, Wmin - 1e-7)
def test_Wmax(self):
Wmax = 0.1
m = self.createModel(Wmax=Wmax)
self.assertIsInstance(m.optimize().objval, float)
for a in A:
self.assertLessEqual(m._W[a].x, Wmax)
def test_Nmax(self):
Nmax = 3
m = self.createModel(Nmax=Nmax)
self.assertIsInstance(m.optimize().objval, float)
nbAssets = 0
for a in A:
if m._W[a].x > 1e-7:
nbAssets += 1
self.assertLessEqual(nbAssets, Nmax)
class ScenariosBasedModelBaseTestCase(ModelBaseTestCase):
__metaclass__ = ABCMeta
def setUp(self):
self.seed = 5
self.scenarios, self.probas = generateGaussianScenarios(100, seed=self.seed)
def createModel(self, *args, **kwargs):
"""
:rtype: linear.models.model.ScenariosBasedPortfolioModel
"""
return self.Model(self.scenarios, self.probas, *args, **kwargs)
def test_reconfigure(self):
"""
Checks that reconfiguring the model with new scenarios/probas gives the same output as creating a new Model.
"""
s, p = self.scenarios, self.probas
s2, p2 = generateGaussianScenarios(len(p), seed=self.seed + 1 if self.seed is not None else None)
self.assertEqual(
self.Model(s, p).update().reconfigure(s2, p2).optimize().objval,
self.Model(s2, p2).optimize().objval
)
class GeneratorBaseTestCase(unittest.TestCase):
"""
This class should be overriden by all the plot_test cases of generators. Tests the scenarios generators over the
basics functions.
"""
__metaclass__ = ABCMeta
@abstractmethod
def generator(self):
"""Should be overriden. Returns the scenarios generator."""
raise NotImplementedError
def test_shape(self):
N = randint(1000, 100000)
scenarios, probas = self.generator(N)
self.assertEqual(scenarios.shape, (N, len(A)))
self.assertEqual(probas.shape, (N,))
def test_mean(self):
N = 1000000
s, p = self.generator(N)
self.assertAlmostEqual((s.mean(axis=0) * 252 - MeanReturns).mean(), 0, delta=0.1)
class TestMAD(TestCaseWrapper.ScenariosBasedModelBaseTestCase):
@property
def Model(self):
return MAD
class TestSemiMAD(TestCaseWrapper.ScenariosBasedModelBaseTestCase):
@property
def Model(self):
return SemiMAD
class TestGMD(TestCaseWrapper.ScenariosBasedModelBaseTestCase):
@property
def Model(self):
return GMD
class TestMinimax(TestCaseWrapper.ScenariosBasedModelBaseTestCase):
@property
def Model(self):
return Minimax
class TestVaR(TestCaseWrapper.ScenariosBasedModelBaseTestCase):
@property
def Model(self):
return VaR
class TestCVaR(TestCaseWrapper.ScenariosBasedModelBaseTestCase):
@property
def Model(self):
return CVaR
class TestMarkowitz(TestCaseWrapper.ModelBaseTestCase):
@property
def Model(self):
return Markowitz
class TestMADAndSemiMAD(unittest.TestCase):
def test_same_output(self):
"""Checks that the MAD and the SemiMAD give the same output portfolio and half of the objective value."""
s, p = generateGaussianScenarios()
m = MAD(s, p).optimize()
m2 = SemiMAD(s, p).optimize()
self.assertAlmostEqual((m.getPortfolio() - m2.getPortfolio()).max(), 0, places=4)
self.assertAlmostEqual(m.objval, 2 * m2.objval)
class GaussianGeneratorTestCase(TestCaseWrapper.GeneratorBaseTestCase):
@property
def generator(self):
return generateGaussianScenarios
class StudentGeneratorTestCase(TestCaseWrapper.GeneratorBaseTestCase):
@property
def generator(self):
return generateStudentTScenarios
class Test(unittest.TestCase):
def test_coucou(self):
self.assertEqual(3, 3)
if __name__ == '__main__':
unittest.main()