openseries 1.2.2__py3-none-any.whl → 1.2.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- openseries/__init__.py +1 -0
- openseries/common_model.py +265 -171
- openseries/datefixer.py +94 -111
- openseries/frame.py +252 -160
- openseries/load_plotly.py +11 -21
- openseries/risk.py +45 -23
- openseries/series.py +135 -110
- openseries/simulation.py +157 -109
- openseries/types.py +88 -21
- {openseries-1.2.2.dist-info → openseries-1.2.4.dist-info}/METADATA +11 -12
- openseries-1.2.4.dist-info/RECORD +15 -0
- {openseries-1.2.2.dist-info → openseries-1.2.4.dist-info}/WHEEL +1 -1
- openseries-1.2.2.dist-info/RECORD +0 -15
- {openseries-1.2.2.dist-info → openseries-1.2.4.dist-info}/LICENSE.md +0 -0
openseries/simulation.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
"""
|
2
|
-
Defining the ReturnSimulation class
|
3
|
-
stochastic processes, and defining ModelParameters used by it.
|
2
|
+
Defining the ReturnSimulation class and ModelParameters used by it.
|
4
3
|
|
5
4
|
Source:
|
6
5
|
http://www.turingfinance.com/random-walks-down-wall-street-stochastic-processes-in-python/
|
@@ -14,20 +13,26 @@ Processes that can be simulated in this module are:
|
|
14
13
|
- Cox Ingersoll Ross
|
15
14
|
- Ornstein Uhlenbeck
|
16
15
|
"""
|
16
|
+
from __future__ import annotations
|
17
|
+
|
17
18
|
import datetime as dt
|
18
|
-
from math import log
|
19
|
-
from
|
19
|
+
from math import log
|
20
|
+
from math import pow as mathpow
|
21
|
+
from typing import Optional, TypeVar, cast
|
22
|
+
|
20
23
|
from numpy import (
|
21
24
|
add,
|
22
25
|
array,
|
23
26
|
exp,
|
24
27
|
float64,
|
25
28
|
insert,
|
26
|
-
random as nprandom,
|
27
29
|
sqrt,
|
28
30
|
)
|
31
|
+
from numpy import (
|
32
|
+
random as nprandom,
|
33
|
+
)
|
29
34
|
from numpy.typing import NDArray
|
30
|
-
from pandas import
|
35
|
+
from pandas import DataFrame, concat
|
31
36
|
from pydantic import BaseModel, ConfigDict
|
32
37
|
|
33
38
|
from openseries.datefixer import generate_calender_date_range
|
@@ -36,16 +41,18 @@ from openseries.types import (
|
|
36
41
|
DaysInYearType,
|
37
42
|
SimCountType,
|
38
43
|
TradingDaysType,
|
39
|
-
VolatilityType,
|
40
44
|
ValueType,
|
45
|
+
VolatilityType,
|
41
46
|
)
|
42
47
|
|
43
48
|
TypeModelParameters = TypeVar("TypeModelParameters", bound="ModelParameters")
|
44
49
|
TypeReturnSimulation = TypeVar("TypeReturnSimulation", bound="ReturnSimulation")
|
45
50
|
|
46
51
|
|
47
|
-
class ReturnSimulation(BaseModel):
|
48
|
-
|
52
|
+
class ReturnSimulation(BaseModel): # type: ignore[misc]
|
53
|
+
|
54
|
+
"""
|
55
|
+
Object of the class ReturnSimulation.
|
49
56
|
|
50
57
|
Parameters
|
51
58
|
----------
|
@@ -75,6 +82,8 @@ class ReturnSimulation(BaseModel):
|
|
75
82
|
@property
|
76
83
|
def results(self: TypeReturnSimulation) -> DataFrame:
|
77
84
|
"""
|
85
|
+
Simulation data.
|
86
|
+
|
78
87
|
Returns
|
79
88
|
-------
|
80
89
|
pandas.DataFrame
|
@@ -85,12 +94,13 @@ class ReturnSimulation(BaseModel):
|
|
85
94
|
@property
|
86
95
|
def realized_mean_return(self: TypeReturnSimulation) -> float:
|
87
96
|
"""
|
97
|
+
Annualized arithmetic mean of returns.
|
98
|
+
|
88
99
|
Returns
|
89
100
|
-------
|
90
101
|
float
|
91
102
|
Annualized arithmetic mean of returns
|
92
103
|
"""
|
93
|
-
|
94
104
|
return cast(
|
95
105
|
float,
|
96
106
|
(self.results.pct_change().mean() * self.trading_days_in_year).iloc[0],
|
@@ -99,12 +109,13 @@ class ReturnSimulation(BaseModel):
|
|
99
109
|
@property
|
100
110
|
def realized_vol(self: TypeReturnSimulation) -> float:
|
101
111
|
"""
|
112
|
+
Annualized volatility.
|
113
|
+
|
102
114
|
Returns
|
103
115
|
-------
|
104
116
|
float
|
105
117
|
Annualized volatility
|
106
118
|
"""
|
107
|
-
|
108
119
|
return cast(
|
109
120
|
float,
|
110
121
|
(self.results.pct_change().std() * sqrt(self.trading_days_in_year)).iloc[
|
@@ -114,11 +125,14 @@ class ReturnSimulation(BaseModel):
|
|
114
125
|
|
115
126
|
@classmethod
|
116
127
|
def convert_to_prices(
|
117
|
-
cls:
|
128
|
+
cls: type[TypeReturnSimulation],
|
118
129
|
param: TypeModelParameters,
|
119
130
|
log_returns: NDArray[float64],
|
120
131
|
) -> NDArray[float64]:
|
121
|
-
"""
|
132
|
+
"""
|
133
|
+
Price series.
|
134
|
+
|
135
|
+
Converts a sequence of log returns into normal returns (exponentiation)
|
122
136
|
and then computes a price sequence given a starting price, param.all_s0.
|
123
137
|
|
124
138
|
Parameters
|
@@ -133,7 +147,6 @@ class ReturnSimulation(BaseModel):
|
|
133
147
|
numpy.NDArray[float64]
|
134
148
|
Price series
|
135
149
|
"""
|
136
|
-
|
137
150
|
returns = exp(log_returns)
|
138
151
|
# A sequence of prices starting with param.all_s0
|
139
152
|
price_sequence: list[float] = [param.all_s0]
|
@@ -144,13 +157,16 @@ class ReturnSimulation(BaseModel):
|
|
144
157
|
|
145
158
|
@classmethod
|
146
159
|
def brownian_motion_log_returns(
|
147
|
-
cls:
|
160
|
+
cls: type[TypeReturnSimulation],
|
148
161
|
param: TypeModelParameters,
|
149
162
|
seed: Optional[int] = None,
|
150
163
|
) -> NDArray[float64]:
|
151
|
-
"""
|
164
|
+
"""
|
165
|
+
Brownian Motion log returns.
|
166
|
+
|
167
|
+
Method returns a Wiener process. The Wiener process is also called
|
152
168
|
Brownian motion. For more information about the Wiener process check out
|
153
|
-
the Wikipedia page: http://en.wikipedia.org/wiki/Wiener_process
|
169
|
+
the Wikipedia page: http://en.wikipedia.org/wiki/Wiener_process.
|
154
170
|
|
155
171
|
Parameters
|
156
172
|
----------
|
@@ -164,22 +180,22 @@ class ReturnSimulation(BaseModel):
|
|
164
180
|
numpy.NDArray[float64]
|
165
181
|
Brownian Motion log returns
|
166
182
|
"""
|
167
|
-
|
168
183
|
if seed is not None:
|
169
184
|
nprandom.seed(seed)
|
170
185
|
|
171
186
|
sqrt_delta_sigma = sqrt(param.all_delta) * param.all_sigma
|
172
187
|
return array(
|
173
|
-
nprandom.normal(loc=0, scale=sqrt_delta_sigma, size=param.all_time)
|
188
|
+
nprandom.normal(loc=0, scale=sqrt_delta_sigma, size=param.all_time),
|
174
189
|
)
|
175
190
|
|
176
191
|
@classmethod
|
177
192
|
def brownian_motion_levels(
|
178
|
-
cls:
|
193
|
+
cls: type[TypeReturnSimulation],
|
179
194
|
param: TypeModelParameters,
|
180
195
|
seed: Optional[int] = None,
|
181
196
|
) -> NDArray[float64]:
|
182
|
-
"""
|
197
|
+
"""
|
198
|
+
Delivers a price sequence whose returns evolve as to a brownian motion.
|
183
199
|
|
184
200
|
Parameters
|
185
201
|
----------
|
@@ -193,21 +209,24 @@ class ReturnSimulation(BaseModel):
|
|
193
209
|
numpy.NDArray[float64]
|
194
210
|
Price sequence which follows a brownian motion
|
195
211
|
"""
|
196
|
-
|
197
212
|
return cls.convert_to_prices(
|
198
|
-
param,
|
213
|
+
param,
|
214
|
+
cls.brownian_motion_log_returns(param, seed=seed),
|
199
215
|
)
|
200
216
|
|
201
217
|
@classmethod
|
202
218
|
def geometric_brownian_motion_log_returns(
|
203
|
-
cls:
|
219
|
+
cls: type[TypeReturnSimulation],
|
204
220
|
param: TypeModelParameters,
|
205
221
|
seed: Optional[int] = None,
|
206
222
|
) -> NDArray[float64]:
|
207
|
-
"""
|
223
|
+
"""
|
224
|
+
Log returns of a Geometric Brownian Motion process.
|
225
|
+
|
226
|
+
Method constructs a sequence of log returns which, when
|
208
227
|
exponentiated, produce a random Geometric Brownian Motion (GBM).
|
209
228
|
GBM is the stochastic process underlying the Black Scholes
|
210
|
-
options pricing formula
|
229
|
+
options pricing formula.
|
211
230
|
|
212
231
|
Parameters
|
213
232
|
----------
|
@@ -221,7 +240,6 @@ class ReturnSimulation(BaseModel):
|
|
221
240
|
numpy.NDArray[float64]
|
222
241
|
Log returns of a Geometric Brownian Motion process
|
223
242
|
"""
|
224
|
-
|
225
243
|
wiener_process = array(cls.brownian_motion_log_returns(param, seed=seed))
|
226
244
|
sigma_pow_mu_delta = (
|
227
245
|
param.gbm_mu - 0.5 * mathpow(param.all_sigma, 2.0)
|
@@ -230,11 +248,12 @@ class ReturnSimulation(BaseModel):
|
|
230
248
|
|
231
249
|
@classmethod
|
232
250
|
def geometric_brownian_motion_levels(
|
233
|
-
cls:
|
251
|
+
cls: type[TypeReturnSimulation],
|
234
252
|
param: TypeModelParameters,
|
235
253
|
seed: Optional[int] = None,
|
236
254
|
) -> NDArray[float64]:
|
237
|
-
"""
|
255
|
+
"""
|
256
|
+
Prices for an asset which evolves according to a geometric brownian motion.
|
238
257
|
|
239
258
|
Parameters
|
240
259
|
----------
|
@@ -248,20 +267,23 @@ class ReturnSimulation(BaseModel):
|
|
248
267
|
numpy.NDArray[float64]
|
249
268
|
Price levels for the asset
|
250
269
|
"""
|
251
|
-
|
252
270
|
return cls.convert_to_prices(
|
253
|
-
param,
|
271
|
+
param,
|
272
|
+
cls.geometric_brownian_motion_log_returns(param, seed=seed),
|
254
273
|
)
|
255
274
|
|
256
275
|
@classmethod
|
257
276
|
def jump_diffusion_process(
|
258
|
-
cls:
|
277
|
+
cls: type[TypeReturnSimulation],
|
259
278
|
param: TypeModelParameters,
|
260
279
|
seed: Optional[int] = None,
|
261
280
|
) -> NDArray[float64]:
|
262
|
-
"""
|
281
|
+
"""
|
282
|
+
Jump sizes for each point in time (mostly zeroes if jumps are infrequent).
|
283
|
+
|
284
|
+
Method produces a sequence of Jump Sizes which represent a jump
|
263
285
|
diffusion process. These jumps are combined with a geometric brownian
|
264
|
-
motion (log returns) to produce the Merton model
|
286
|
+
motion (log returns) to produce the Merton model.
|
265
287
|
|
266
288
|
Parameters
|
267
289
|
----------
|
@@ -275,7 +297,6 @@ class ReturnSimulation(BaseModel):
|
|
275
297
|
numpy.NDArray[float64]
|
276
298
|
Jump sizes for each point in time (mostly zeroes if jumps are infrequent)
|
277
299
|
"""
|
278
|
-
|
279
300
|
if seed is not None:
|
280
301
|
nprandom.seed(seed)
|
281
302
|
s_n = 0.0
|
@@ -299,13 +320,16 @@ class ReturnSimulation(BaseModel):
|
|
299
320
|
|
300
321
|
@classmethod
|
301
322
|
def geometric_brownian_motion_jump_diffusion_log_returns(
|
302
|
-
cls:
|
323
|
+
cls: type[TypeReturnSimulation],
|
303
324
|
param: TypeModelParameters,
|
304
325
|
seed: Optional[int] = None,
|
305
326
|
) -> NDArray[float64]:
|
306
|
-
"""
|
327
|
+
"""
|
328
|
+
Geometric Brownian Motion process with jumps in it.
|
329
|
+
|
330
|
+
Method constructs combines a geometric brownian motion process
|
307
331
|
(log returns) with a jump diffusion process (log returns) to produce a
|
308
|
-
sequence of gbm jump returns
|
332
|
+
sequence of gbm jump returns.
|
309
333
|
|
310
334
|
Parameters
|
311
335
|
----------
|
@@ -319,21 +343,24 @@ class ReturnSimulation(BaseModel):
|
|
319
343
|
numpy.NDArray[float64]
|
320
344
|
Geometric Brownian Motion process with jumps in it
|
321
345
|
"""
|
322
|
-
|
323
346
|
jump_diffusion = cls.jump_diffusion_process(param, seed=seed)
|
324
347
|
geometric_brownian_motion = cls.geometric_brownian_motion_log_returns(
|
325
|
-
param,
|
348
|
+
param,
|
349
|
+
seed=seed,
|
326
350
|
)
|
327
351
|
return add(jump_diffusion, geometric_brownian_motion)
|
328
352
|
|
329
353
|
@classmethod
|
330
354
|
def geometric_brownian_motion_jump_diffusion_levels(
|
331
|
-
cls:
|
355
|
+
cls: type[TypeReturnSimulation],
|
332
356
|
param: TypeModelParameters,
|
333
357
|
seed: Optional[int] = None,
|
334
358
|
) -> NDArray[float64]:
|
335
|
-
"""
|
336
|
-
|
359
|
+
"""
|
360
|
+
Geometric Brownian Motion generated prices.
|
361
|
+
|
362
|
+
Converts returns generated with a Geometric Brownian Motion process
|
363
|
+
with jumps into prices.
|
337
364
|
|
338
365
|
Parameters
|
339
366
|
----------
|
@@ -347,7 +374,6 @@ class ReturnSimulation(BaseModel):
|
|
347
374
|
numpy.NDArray[float64]
|
348
375
|
Geometric Brownian Motion generated prices
|
349
376
|
"""
|
350
|
-
|
351
377
|
return cls.convert_to_prices(
|
352
378
|
param,
|
353
379
|
cls.geometric_brownian_motion_jump_diffusion_log_returns(param, seed=seed),
|
@@ -355,14 +381,17 @@ class ReturnSimulation(BaseModel):
|
|
355
381
|
|
356
382
|
@classmethod
|
357
383
|
def heston_construct_correlated_path(
|
358
|
-
cls:
|
384
|
+
cls: type[TypeReturnSimulation],
|
359
385
|
param: TypeModelParameters,
|
360
386
|
brownian_motion_one: NDArray[float64],
|
361
387
|
seed: Optional[int] = None,
|
362
388
|
) -> tuple[NDArray[float64], NDArray[float64]]:
|
363
|
-
"""
|
389
|
+
"""
|
390
|
+
Generate correlated Brownian Motion path.
|
391
|
+
|
392
|
+
Method is a simplified version of the Cholesky decomposition method for
|
364
393
|
just two assets. It does not make use of matrix algebra and is therefore quite
|
365
|
-
easy to implement
|
394
|
+
easy to implement.
|
366
395
|
|
367
396
|
Parameters
|
368
397
|
----------
|
@@ -378,33 +407,36 @@ class ReturnSimulation(BaseModel):
|
|
378
407
|
tuple[NDArray[float64], NDArray[float64]]
|
379
408
|
A correlated Brownian Motion path
|
380
409
|
"""
|
381
|
-
|
382
410
|
if seed is not None:
|
383
411
|
nprandom.seed(seed)
|
384
|
-
|
412
|
+
|
385
413
|
sqrt_delta = sqrt(param.all_delta)
|
386
|
-
|
414
|
+
|
387
415
|
brownian_motion_two = []
|
388
416
|
for npath in range(param.all_time - 1):
|
389
417
|
term_one = param.cir_rho * brownian_motion_one[npath]
|
390
418
|
term_two = sqrt(1 - mathpow(param.cir_rho, 2.0)) * nprandom.normal(
|
391
|
-
0,
|
419
|
+
0,
|
420
|
+
sqrt_delta,
|
392
421
|
)
|
393
422
|
brownian_motion_two.append(term_one + term_two)
|
394
423
|
return array(brownian_motion_one), array(brownian_motion_two)
|
395
424
|
|
396
425
|
@classmethod
|
397
426
|
def cox_ingersoll_ross_heston(
|
398
|
-
cls:
|
427
|
+
cls: type[TypeReturnSimulation],
|
399
428
|
param: TypeModelParameters,
|
400
429
|
seed: Optional[int] = None,
|
401
430
|
) -> tuple[NDArray[float64], NDArray[float64]]:
|
402
|
-
"""
|
431
|
+
"""
|
432
|
+
Generate interest rate levels for the CIR process.
|
433
|
+
|
434
|
+
Method returns the rate levels of a mean-reverting Cox Ingersoll Ross
|
403
435
|
process. It is used to model interest rates as well as stochastic
|
404
436
|
volatility in the Heston model. Because the returns between the underlying
|
405
437
|
and the stochastic volatility should be correlated we pass a correlated
|
406
438
|
Brownian motion process into the method from which the interest rate levels
|
407
|
-
are constructed. The other correlated process is used in the Heston model
|
439
|
+
are constructed. The other correlated process is used in the Heston model.
|
408
440
|
|
409
441
|
Parameters
|
410
442
|
----------
|
@@ -418,14 +450,15 @@ class ReturnSimulation(BaseModel):
|
|
418
450
|
tuple[NDArray[float64], NDArray[float64]]
|
419
451
|
The interest rate levels for the CIR process
|
420
452
|
"""
|
421
|
-
|
422
453
|
if seed is not None:
|
423
454
|
nprandom.seed(seed)
|
424
455
|
|
425
|
-
# We don't multiply by sigma here because we do that in heston
|
426
456
|
sqrt_delta_sigma = sqrt(param.all_delta) * param.all_sigma
|
457
|
+
|
427
458
|
brownian_motion_volatility = nprandom.normal(
|
428
|
-
loc=0,
|
459
|
+
loc=0,
|
460
|
+
scale=sqrt_delta_sigma,
|
461
|
+
size=param.all_time,
|
429
462
|
)
|
430
463
|
meanrev_vol, avg_vol, start_vol = (
|
431
464
|
param.heston_a,
|
@@ -444,18 +477,21 @@ class ReturnSimulation(BaseModel):
|
|
444
477
|
|
445
478
|
@classmethod
|
446
479
|
def heston_model_levels(
|
447
|
-
cls:
|
480
|
+
cls: type[TypeReturnSimulation],
|
448
481
|
param: TypeModelParameters,
|
449
482
|
seed: Optional[int] = None,
|
450
483
|
) -> tuple[NDArray[float64], NDArray[float64]]:
|
451
|
-
"""
|
484
|
+
"""
|
485
|
+
Generate prices for an asset following a Heston process.
|
486
|
+
|
487
|
+
The Heston model is the geometric brownian motion model with stochastic
|
452
488
|
volatility. This stochastic volatility is given by the Cox Ingersoll Ross
|
453
489
|
process. Step one on this method is to construct two correlated
|
454
490
|
GBM processes. One is used for the underlying asset prices and the other
|
455
491
|
is used for the stochastic volatility levels
|
456
492
|
Get two correlated brownian motion sequences for the volatility parameter
|
457
493
|
and the underlying asset brownian_motion_market,
|
458
|
-
brownian_motion_vol = get_correlated_paths_simple(param)
|
494
|
+
brownian_motion_vol = get_correlated_paths_simple(param).
|
459
495
|
|
460
496
|
Parameters
|
461
497
|
----------
|
@@ -469,10 +505,11 @@ class ReturnSimulation(BaseModel):
|
|
469
505
|
tuple[NDArray[float64], NDArray[float64]]
|
470
506
|
The prices for an asset following a Heston process
|
471
507
|
"""
|
472
|
-
|
473
508
|
brownian, cir_process = cls.cox_ingersoll_ross_heston(param, seed=seed)
|
474
509
|
brownian, brownian_motion_market = cls.heston_construct_correlated_path(
|
475
|
-
param,
|
510
|
+
param,
|
511
|
+
brownian,
|
512
|
+
seed=seed,
|
476
513
|
)
|
477
514
|
|
478
515
|
heston_market_price_levels: list[float] = [param.all_s0]
|
@@ -486,22 +523,25 @@ class ReturnSimulation(BaseModel):
|
|
486
523
|
* brownian_motion_market[hpath - 1]
|
487
524
|
)
|
488
525
|
heston_market_price_levels.append(
|
489
|
-
heston_market_price_levels[hpath - 1] + drift + vol
|
526
|
+
heston_market_price_levels[hpath - 1] + drift + vol,
|
490
527
|
)
|
491
528
|
return array(heston_market_price_levels), array(cir_process)
|
492
529
|
|
493
530
|
@classmethod
|
494
531
|
def cox_ingersoll_ross_levels(
|
495
|
-
cls:
|
532
|
+
cls: type[TypeReturnSimulation],
|
496
533
|
param: TypeModelParameters,
|
497
534
|
seed: Optional[int] = None,
|
498
535
|
) -> NDArray[float64]:
|
499
|
-
"""
|
536
|
+
"""
|
537
|
+
Generate interest rate levels for the CIR process.
|
538
|
+
|
539
|
+
Method returns the rate levels of a mean-reverting Cox Ingersoll Ross (CIR)
|
500
540
|
process. It is used to model interest rates as well as stochastic
|
501
541
|
volatility in the Heston model. Because the returns between the underlying
|
502
542
|
and the stochastic volatility should be correlated we pass a correlated
|
503
543
|
Brownian motion process into the method from which the interest rate levels
|
504
|
-
are constructed. The other correlated process is used in the Heston model
|
544
|
+
are constructed. The other correlated process is used in the Heston model.
|
505
545
|
|
506
546
|
Parameters
|
507
547
|
----------
|
@@ -515,7 +555,6 @@ class ReturnSimulation(BaseModel):
|
|
515
555
|
numpy.NDArray[float64]
|
516
556
|
The interest rate levels for the CIR process
|
517
557
|
"""
|
518
|
-
|
519
558
|
brownian_motion = cls.brownian_motion_log_returns(param, seed=seed)
|
520
559
|
|
521
560
|
levels: list[float] = [param.all_r0]
|
@@ -527,12 +566,12 @@ class ReturnSimulation(BaseModel):
|
|
527
566
|
|
528
567
|
@classmethod
|
529
568
|
def ornstein_uhlenbeck_levels(
|
530
|
-
cls:
|
569
|
+
cls: type[TypeReturnSimulation],
|
531
570
|
param: TypeModelParameters,
|
532
571
|
seed: Optional[int] = None,
|
533
572
|
) -> NDArray[float64]:
|
534
|
-
"""
|
535
|
-
Ornstein Uhlenbeck process
|
573
|
+
"""
|
574
|
+
Generate rate levels of a mean-reverting Ornstein Uhlenbeck process.
|
536
575
|
|
537
576
|
Parameters
|
538
577
|
----------
|
@@ -546,7 +585,6 @@ class ReturnSimulation(BaseModel):
|
|
546
585
|
numpy.NDArray[float64]
|
547
586
|
The interest rate levels for the Ornstein Uhlenbeck process
|
548
587
|
"""
|
549
|
-
|
550
588
|
ou_levels: list[float] = [param.all_r0]
|
551
589
|
brownian_motion_returns = cls.brownian_motion_log_returns(param, seed=seed)
|
552
590
|
for hpath in range(1, param.all_time):
|
@@ -557,7 +595,7 @@ class ReturnSimulation(BaseModel):
|
|
557
595
|
|
558
596
|
@classmethod
|
559
597
|
def from_normal(
|
560
|
-
cls:
|
598
|
+
cls: type[TypeReturnSimulation],
|
561
599
|
number_of_sims: SimCountType,
|
562
600
|
mean_annual_return: float,
|
563
601
|
mean_annual_vol: VolatilityType,
|
@@ -565,7 +603,8 @@ class ReturnSimulation(BaseModel):
|
|
565
603
|
trading_days_in_year: DaysInYearType = 252,
|
566
604
|
seed: Optional[int] = 71,
|
567
605
|
) -> TypeReturnSimulation:
|
568
|
-
"""
|
606
|
+
"""
|
607
|
+
Simulate normally distributed prices.
|
569
608
|
|
570
609
|
Parameters
|
571
610
|
----------
|
@@ -586,9 +625,8 @@ class ReturnSimulation(BaseModel):
|
|
586
625
|
Returns
|
587
626
|
-------
|
588
627
|
ReturnSimulation
|
589
|
-
|
628
|
+
Normally distributed prices
|
590
629
|
"""
|
591
|
-
|
592
630
|
if seed:
|
593
631
|
nprandom.seed(seed)
|
594
632
|
daily_returns = nprandom.normal(
|
@@ -607,7 +645,7 @@ class ReturnSimulation(BaseModel):
|
|
607
645
|
|
608
646
|
@classmethod
|
609
647
|
def from_lognormal(
|
610
|
-
cls:
|
648
|
+
cls: type[TypeReturnSimulation],
|
611
649
|
number_of_sims: SimCountType,
|
612
650
|
mean_annual_return: float,
|
613
651
|
mean_annual_vol: VolatilityType,
|
@@ -615,7 +653,8 @@ class ReturnSimulation(BaseModel):
|
|
615
653
|
trading_days_in_year: DaysInYearType = 252,
|
616
654
|
seed: Optional[int] = 71,
|
617
655
|
) -> TypeReturnSimulation:
|
618
|
-
"""
|
656
|
+
"""
|
657
|
+
Lognormal distribution simulation.
|
619
658
|
|
620
659
|
Parameters
|
621
660
|
----------
|
@@ -638,7 +677,6 @@ class ReturnSimulation(BaseModel):
|
|
638
677
|
ReturnSimulation
|
639
678
|
Lognormal distribution simulation
|
640
679
|
"""
|
641
|
-
|
642
680
|
if seed:
|
643
681
|
nprandom.seed(seed)
|
644
682
|
daily_returns = (
|
@@ -660,7 +698,7 @@ class ReturnSimulation(BaseModel):
|
|
660
698
|
|
661
699
|
@classmethod
|
662
700
|
def from_gbm(
|
663
|
-
cls:
|
701
|
+
cls: type[TypeReturnSimulation],
|
664
702
|
number_of_sims: SimCountType,
|
665
703
|
mean_annual_return: float,
|
666
704
|
mean_annual_vol: VolatilityType,
|
@@ -668,8 +706,11 @@ class ReturnSimulation(BaseModel):
|
|
668
706
|
trading_days_in_year: DaysInYearType = 252,
|
669
707
|
seed: Optional[int] = 71,
|
670
708
|
) -> TypeReturnSimulation:
|
671
|
-
"""
|
672
|
-
|
709
|
+
"""
|
710
|
+
Geometric Brownian Motion simulation.
|
711
|
+
|
712
|
+
Method constructs a sequence of log returns which, when
|
713
|
+
exponentiated, produce a random Geometric Brownian Motion (GBM).
|
673
714
|
|
674
715
|
Parameters
|
675
716
|
----------
|
@@ -690,9 +731,8 @@ class ReturnSimulation(BaseModel):
|
|
690
731
|
Returns
|
691
732
|
-------
|
692
733
|
ReturnSimulation
|
693
|
-
|
734
|
+
Geometric Brownian Motion simulation
|
694
735
|
"""
|
695
|
-
|
696
736
|
if seed:
|
697
737
|
nprandom.seed(seed)
|
698
738
|
|
@@ -706,7 +746,7 @@ class ReturnSimulation(BaseModel):
|
|
706
746
|
daily_returns = []
|
707
747
|
for _ in range(number_of_sims):
|
708
748
|
daily_returns.append(
|
709
|
-
cls.geometric_brownian_motion_log_returns(param=model_params)
|
749
|
+
cls.geometric_brownian_motion_log_returns(param=model_params),
|
710
750
|
)
|
711
751
|
return cls(
|
712
752
|
number_of_sims=number_of_sims,
|
@@ -719,7 +759,7 @@ class ReturnSimulation(BaseModel):
|
|
719
759
|
|
720
760
|
@classmethod
|
721
761
|
def from_heston(
|
722
|
-
cls:
|
762
|
+
cls: type[TypeReturnSimulation],
|
723
763
|
number_of_sims: SimCountType,
|
724
764
|
trading_days: TradingDaysType,
|
725
765
|
mean_annual_return: float,
|
@@ -729,8 +769,11 @@ class ReturnSimulation(BaseModel):
|
|
729
769
|
trading_days_in_year: DaysInYearType = 252,
|
730
770
|
seed: Optional[int] = 71,
|
731
771
|
) -> TypeReturnSimulation:
|
732
|
-
"""
|
733
|
-
|
772
|
+
"""
|
773
|
+
Heston model simulation.
|
774
|
+
|
775
|
+
Heston model is the geometric brownian motion model
|
776
|
+
with stochastic volatility.
|
734
777
|
|
735
778
|
Parameters
|
736
779
|
----------
|
@@ -757,7 +800,6 @@ class ReturnSimulation(BaseModel):
|
|
757
800
|
ReturnSimulation
|
758
801
|
Heston model simulation
|
759
802
|
"""
|
760
|
-
|
761
803
|
if seed:
|
762
804
|
nprandom.seed(seed)
|
763
805
|
|
@@ -788,7 +830,7 @@ class ReturnSimulation(BaseModel):
|
|
788
830
|
|
789
831
|
@classmethod
|
790
832
|
def from_heston_vol(
|
791
|
-
cls:
|
833
|
+
cls: type[TypeReturnSimulation],
|
792
834
|
number_of_sims: SimCountType,
|
793
835
|
trading_days: TradingDaysType,
|
794
836
|
mean_annual_return: float,
|
@@ -798,7 +840,8 @@ class ReturnSimulation(BaseModel):
|
|
798
840
|
trading_days_in_year: DaysInYearType = 252,
|
799
841
|
seed: Optional[int] = 71,
|
800
842
|
) -> TypeReturnSimulation:
|
801
|
-
"""
|
843
|
+
"""
|
844
|
+
Heston Vol model simulation.
|
802
845
|
|
803
846
|
Parameters
|
804
847
|
----------
|
@@ -825,7 +868,6 @@ class ReturnSimulation(BaseModel):
|
|
825
868
|
ReturnSimulation
|
826
869
|
Heston Vol model simulation
|
827
870
|
"""
|
828
|
-
|
829
871
|
if seed:
|
830
872
|
nprandom.seed(seed)
|
831
873
|
|
@@ -856,7 +898,7 @@ class ReturnSimulation(BaseModel):
|
|
856
898
|
|
857
899
|
@classmethod
|
858
900
|
def from_merton_jump_gbm(
|
859
|
-
cls:
|
901
|
+
cls: type[TypeReturnSimulation],
|
860
902
|
number_of_sims: SimCountType,
|
861
903
|
trading_days: TradingDaysType,
|
862
904
|
mean_annual_return: float,
|
@@ -867,7 +909,8 @@ class ReturnSimulation(BaseModel):
|
|
867
909
|
trading_days_in_year: DaysInYearType = 252,
|
868
910
|
seed: Optional[int] = 71,
|
869
911
|
) -> TypeReturnSimulation:
|
870
|
-
"""
|
912
|
+
"""
|
913
|
+
Merton Jump-Diffusion model simulation.
|
871
914
|
|
872
915
|
Parameters
|
873
916
|
----------
|
@@ -896,7 +939,6 @@ class ReturnSimulation(BaseModel):
|
|
896
939
|
ReturnSimulation
|
897
940
|
Merton Jump-Diffusion model simulation
|
898
941
|
"""
|
899
|
-
|
900
942
|
if seed:
|
901
943
|
nprandom.seed(seed)
|
902
944
|
|
@@ -932,18 +974,19 @@ class ReturnSimulation(BaseModel):
|
|
932
974
|
end: Optional[dt.date] = None,
|
933
975
|
countries: CountriesType = "SE",
|
934
976
|
) -> DataFrame:
|
935
|
-
"""
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
977
|
+
"""
|
978
|
+
Create pandas.DataFrame from simulation(s).
|
979
|
+
|
980
|
+
Parameters
|
981
|
+
----------
|
982
|
+
name: str
|
983
|
+
Name label of the serie(s)
|
984
|
+
start: datetime.date, optional
|
985
|
+
Date when the simulation starts
|
986
|
+
end: datetime.date, optional
|
987
|
+
Date when the simulation ends
|
988
|
+
countries: CountriesType, default: "SE"
|
989
|
+
(List of) country code(s) according to ISO 3166-1 alpha-2
|
947
990
|
|
948
991
|
Returns
|
949
992
|
-------
|
@@ -951,7 +994,10 @@ class ReturnSimulation(BaseModel):
|
|
951
994
|
Object based on the simulation(s)
|
952
995
|
"""
|
953
996
|
d_range = generate_calender_date_range(
|
954
|
-
trading_days=self.trading_days,
|
997
|
+
trading_days=self.trading_days,
|
998
|
+
start=start,
|
999
|
+
end=end,
|
1000
|
+
countries=countries,
|
955
1001
|
)
|
956
1002
|
|
957
1003
|
if self.number_of_sims == 1:
|
@@ -968,8 +1014,10 @@ class ReturnSimulation(BaseModel):
|
|
968
1014
|
return fdf
|
969
1015
|
|
970
1016
|
|
971
|
-
class ModelParameters(BaseModel):
|
972
|
-
|
1017
|
+
class ModelParameters(BaseModel): # type: ignore[misc]
|
1018
|
+
|
1019
|
+
"""
|
1020
|
+
Object of the class ModelParameters.
|
973
1021
|
|
974
1022
|
Parameters
|
975
1023
|
----------
|