openseries 1.5.7__py3-none-any.whl → 1.7.0__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 +43 -0
- openseries/_common_model.py +237 -295
- openseries/_risk.py +9 -10
- openseries/datefixer.py +41 -36
- openseries/frame.py +120 -721
- openseries/load_plotly.py +10 -8
- openseries/portfoliotools.py +612 -0
- openseries/series.py +46 -64
- openseries/simulation.py +31 -38
- openseries/types.py +37 -24
- {openseries-1.5.7.dist-info → openseries-1.7.0.dist-info}/LICENSE.md +1 -1
- {openseries-1.5.7.dist-info → openseries-1.7.0.dist-info}/METADATA +4 -5
- openseries-1.7.0.dist-info/RECORD +16 -0
- openseries-1.5.7.dist-info/RECORD +0 -15
- {openseries-1.5.7.dist-info → openseries-1.7.0.dist-info}/WHEEL +0 -0
openseries/_common_model.py
CHANGED
@@ -9,9 +9,12 @@ from math import ceil
|
|
9
9
|
from pathlib import Path
|
10
10
|
from secrets import choice
|
11
11
|
from string import ascii_letters
|
12
|
-
from typing import
|
12
|
+
from typing import TYPE_CHECKING, Any, SupportsFloat, cast
|
13
13
|
|
14
14
|
from numpy import float64, inf, isnan, log, maximum, sqrt
|
15
|
+
|
16
|
+
if TYPE_CHECKING:
|
17
|
+
from numpy.typing import NDArray # pragma: no cover
|
15
18
|
from openpyxl.utils.dataframe import dataframe_to_rows
|
16
19
|
from openpyxl.workbook.workbook import Workbook
|
17
20
|
from openpyxl.worksheet.worksheet import Worksheet
|
@@ -28,13 +31,13 @@ from scipy.stats import ( # type: ignore[import-untyped,unused-ignore]
|
|
28
31
|
)
|
29
32
|
from typing_extensions import Self
|
30
33
|
|
31
|
-
from
|
34
|
+
from ._risk import (
|
32
35
|
_cvar_down_calc,
|
33
36
|
_var_down_calc,
|
34
37
|
)
|
35
|
-
from
|
36
|
-
from
|
37
|
-
from
|
38
|
+
from .datefixer import date_offset_foll, holiday_calendar
|
39
|
+
from .load_plotly import load_plotly_dict
|
40
|
+
from .types import (
|
38
41
|
CountriesType,
|
39
42
|
DaysInYearType,
|
40
43
|
LiteralBarPlotMode,
|
@@ -49,7 +52,6 @@ from openseries.types import (
|
|
49
52
|
|
50
53
|
|
51
54
|
class _CommonModel(BaseModel):
|
52
|
-
|
53
55
|
"""Declare _CommonModel."""
|
54
56
|
|
55
57
|
tsdf: DataFrame = DataFrame(dtype="float64")
|
@@ -62,8 +64,7 @@ class _CommonModel(BaseModel):
|
|
62
64
|
|
63
65
|
@property
|
64
66
|
def length(self: Self) -> int:
|
65
|
-
"""
|
66
|
-
Number of observations.
|
67
|
+
"""Number of observations.
|
67
68
|
|
68
69
|
Returns
|
69
70
|
-------
|
@@ -75,8 +76,7 @@ class _CommonModel(BaseModel):
|
|
75
76
|
|
76
77
|
@property
|
77
78
|
def first_idx(self: Self) -> dt.date:
|
78
|
-
"""
|
79
|
-
The first date in the timeseries.
|
79
|
+
"""The first date in the timeseries.
|
80
80
|
|
81
81
|
Returns
|
82
82
|
-------
|
@@ -88,8 +88,7 @@ class _CommonModel(BaseModel):
|
|
88
88
|
|
89
89
|
@property
|
90
90
|
def last_idx(self: Self) -> dt.date:
|
91
|
-
"""
|
92
|
-
The last date in the timeseries.
|
91
|
+
"""The last date in the timeseries.
|
93
92
|
|
94
93
|
Returns
|
95
94
|
-------
|
@@ -101,8 +100,7 @@ class _CommonModel(BaseModel):
|
|
101
100
|
|
102
101
|
@property
|
103
102
|
def span_of_days(self: Self) -> int:
|
104
|
-
"""
|
105
|
-
Number of days from the first date to the last.
|
103
|
+
"""Number of days from the first date to the last.
|
106
104
|
|
107
105
|
Returns
|
108
106
|
-------
|
@@ -114,8 +112,7 @@ class _CommonModel(BaseModel):
|
|
114
112
|
|
115
113
|
@property
|
116
114
|
def yearfrac(self: Self) -> float:
|
117
|
-
"""
|
118
|
-
Length of series expressed in years assuming all years have 365.25 days.
|
115
|
+
"""Length of series expressed in years assuming all years have 365.25 days.
|
119
116
|
|
120
117
|
Returns
|
121
118
|
-------
|
@@ -128,8 +125,7 @@ class _CommonModel(BaseModel):
|
|
128
125
|
|
129
126
|
@property
|
130
127
|
def periods_in_a_year(self: Self) -> float:
|
131
|
-
"""
|
132
|
-
The average number of observations per year.
|
128
|
+
"""The average number of observations per year.
|
133
129
|
|
134
130
|
Returns
|
135
131
|
-------
|
@@ -140,13 +136,12 @@ class _CommonModel(BaseModel):
|
|
140
136
|
return self.length / self.yearfrac
|
141
137
|
|
142
138
|
@property
|
143
|
-
def max_drawdown_cal_year(self: Self) ->
|
144
|
-
"""
|
145
|
-
https://www.investopedia.com/terms/m/maximum-drawdown-mdd.asp.
|
139
|
+
def max_drawdown_cal_year(self: Self) -> float | Series[float]:
|
140
|
+
"""https://www.investopedia.com/terms/m/maximum-drawdown-mdd.asp.
|
146
141
|
|
147
142
|
Returns
|
148
143
|
-------
|
149
|
-
|
144
|
+
float | Pandas.Series[float]
|
150
145
|
Maximum drawdown in a single calendar year.
|
151
146
|
|
152
147
|
"""
|
@@ -169,64 +164,59 @@ class _CommonModel(BaseModel):
|
|
169
164
|
)
|
170
165
|
|
171
166
|
@property
|
172
|
-
def geo_ret(self: Self) ->
|
173
|
-
"""
|
174
|
-
https://www.investopedia.com/terms/c/cagr.asp.
|
167
|
+
def geo_ret(self: Self) -> float | Series[float]:
|
168
|
+
"""https://www.investopedia.com/terms/c/cagr.asp.
|
175
169
|
|
176
170
|
Returns
|
177
171
|
-------
|
178
|
-
|
172
|
+
float | Pandas.Series[float]
|
179
173
|
Compounded Annual Growth Rate (CAGR)
|
180
174
|
|
181
175
|
"""
|
182
176
|
return self.geo_ret_func()
|
183
177
|
|
184
178
|
@property
|
185
|
-
def arithmetic_ret(self: Self) ->
|
186
|
-
"""
|
187
|
-
https://www.investopedia.com/terms/a/arithmeticmean.asp.
|
179
|
+
def arithmetic_ret(self: Self) -> float | Series[float]:
|
180
|
+
"""https://www.investopedia.com/terms/a/arithmeticmean.asp.
|
188
181
|
|
189
182
|
Returns
|
190
183
|
-------
|
191
|
-
|
184
|
+
float | Pandas.Series[float]
|
192
185
|
Annualized arithmetic mean of returns
|
193
186
|
|
194
187
|
"""
|
195
188
|
return self.arithmetic_ret_func()
|
196
189
|
|
197
190
|
@property
|
198
|
-
def value_ret(self: Self) ->
|
199
|
-
"""
|
200
|
-
Simple return.
|
191
|
+
def value_ret(self: Self) -> float | Series[float]:
|
192
|
+
"""Simple return.
|
201
193
|
|
202
194
|
Returns
|
203
195
|
-------
|
204
|
-
|
196
|
+
float | Pandas.Series[float]
|
205
197
|
Simple return
|
206
198
|
|
207
199
|
"""
|
208
200
|
return self.value_ret_func()
|
209
201
|
|
210
202
|
@property
|
211
|
-
def vol(self: Self) ->
|
212
|
-
"""
|
213
|
-
Annualized volatility.
|
203
|
+
def vol(self: Self) -> float | Series[float]:
|
204
|
+
"""Annualized volatility.
|
214
205
|
|
215
206
|
Based on Pandas .std() which is the equivalent of stdev.s([...]) in MS Excel.
|
216
207
|
https://www.investopedia.com/terms/v/volatility.asp.
|
217
208
|
|
218
209
|
Returns
|
219
210
|
-------
|
220
|
-
|
211
|
+
float | Pandas.Series[float]
|
221
212
|
Annualized volatility
|
222
213
|
|
223
214
|
"""
|
224
215
|
return self.vol_func()
|
225
216
|
|
226
217
|
@property
|
227
|
-
def downside_deviation(self: Self) ->
|
228
|
-
"""
|
229
|
-
Downside Deviation.
|
218
|
+
def downside_deviation(self: Self) -> float | Series[float]:
|
219
|
+
"""Downside Deviation.
|
230
220
|
|
231
221
|
Standard deviation of returns that are below a Minimum Accepted Return
|
232
222
|
of zero. It is used to calculate the Sortino Ratio.
|
@@ -234,7 +224,7 @@ class _CommonModel(BaseModel):
|
|
234
224
|
|
235
225
|
Returns
|
236
226
|
-------
|
237
|
-
|
227
|
+
float | Pandas.Series[float]
|
238
228
|
Downside deviation
|
239
229
|
|
240
230
|
"""
|
@@ -242,13 +232,12 @@ class _CommonModel(BaseModel):
|
|
242
232
|
return self.downside_deviation_func(min_accepted_return=min_accepted_return)
|
243
233
|
|
244
234
|
@property
|
245
|
-
def ret_vol_ratio(self: Self) ->
|
246
|
-
"""
|
247
|
-
Ratio of annualized arithmetic mean of returns and annualized volatility.
|
235
|
+
def ret_vol_ratio(self: Self) -> float | Series[float]:
|
236
|
+
"""Ratio of annualized arithmetic mean of returns and annualized volatility.
|
248
237
|
|
249
238
|
Returns
|
250
239
|
-------
|
251
|
-
|
240
|
+
float | Pandas.Series[float]
|
252
241
|
Ratio of the annualized arithmetic mean of returns and annualized
|
253
242
|
volatility.
|
254
243
|
|
@@ -257,13 +246,12 @@ class _CommonModel(BaseModel):
|
|
257
246
|
return self.ret_vol_ratio_func(riskfree_rate=riskfree_rate)
|
258
247
|
|
259
248
|
@property
|
260
|
-
def sortino_ratio(self: Self) ->
|
261
|
-
"""
|
262
|
-
https://www.investopedia.com/terms/s/sortinoratio.asp.
|
249
|
+
def sortino_ratio(self: Self) -> float | Series[float]:
|
250
|
+
"""https://www.investopedia.com/terms/s/sortinoratio.asp.
|
263
251
|
|
264
252
|
Returns
|
265
253
|
-------
|
266
|
-
|
254
|
+
float | Pandas.Series[float]
|
267
255
|
Sortino ratio calculated as the annualized arithmetic mean of returns
|
268
256
|
/ downside deviation. The ratio implies that the riskfree asset has zero
|
269
257
|
volatility, and a minimum acceptable return of zero.
|
@@ -277,13 +265,12 @@ class _CommonModel(BaseModel):
|
|
277
265
|
)
|
278
266
|
|
279
267
|
@property
|
280
|
-
def omega_ratio(self: Self) ->
|
281
|
-
"""
|
282
|
-
https://en.wikipedia.org/wiki/Omega_ratio.
|
268
|
+
def omega_ratio(self: Self) -> float | Series[float]:
|
269
|
+
"""https://en.wikipedia.org/wiki/Omega_ratio.
|
283
270
|
|
284
271
|
Returns
|
285
272
|
-------
|
286
|
-
|
273
|
+
float | Pandas.Series[float]
|
287
274
|
Omega ratio calculation
|
288
275
|
|
289
276
|
"""
|
@@ -291,41 +278,38 @@ class _CommonModel(BaseModel):
|
|
291
278
|
return self.omega_ratio_func(min_accepted_return=minimum_accepted_return)
|
292
279
|
|
293
280
|
@property
|
294
|
-
def z_score(self: Self) ->
|
295
|
-
"""
|
296
|
-
https://www.investopedia.com/terms/z/zscore.asp.
|
281
|
+
def z_score(self: Self) -> float | Series[float]:
|
282
|
+
"""https://www.investopedia.com/terms/z/zscore.asp.
|
297
283
|
|
298
284
|
Returns
|
299
285
|
-------
|
300
|
-
|
286
|
+
float | Pandas.Series[float]
|
301
287
|
Z-score as (last return - mean return) / standard deviation of returns.
|
302
288
|
|
303
289
|
"""
|
304
290
|
return self.z_score_func()
|
305
291
|
|
306
292
|
@property
|
307
|
-
def max_drawdown(self: Self) ->
|
308
|
-
"""
|
309
|
-
https://www.investopedia.com/terms/m/maximum-drawdown-mdd.asp.
|
293
|
+
def max_drawdown(self: Self) -> float | Series[float]:
|
294
|
+
"""https://www.investopedia.com/terms/m/maximum-drawdown-mdd.asp.
|
310
295
|
|
311
296
|
Returns
|
312
297
|
-------
|
313
|
-
|
298
|
+
float | Pandas.Series[float]
|
314
299
|
Maximum drawdown without any limit on date range
|
315
300
|
|
316
301
|
"""
|
317
302
|
return self.max_drawdown_func()
|
318
303
|
|
319
304
|
@property
|
320
|
-
def max_drawdown_date(self: Self) ->
|
321
|
-
"""
|
322
|
-
Date when the maximum drawdown occurred.
|
305
|
+
def max_drawdown_date(self: Self) -> dt.date | Series[dt.date]:
|
306
|
+
"""Date when the maximum drawdown occurred.
|
323
307
|
|
324
308
|
https://www.investopedia.com/terms/m/maximum-drawdown-mdd.asp.
|
325
309
|
|
326
310
|
Returns
|
327
311
|
-------
|
328
|
-
|
312
|
+
datetime.date | pandas.Series[dt.date]
|
329
313
|
Date when the maximum drawdown occurred
|
330
314
|
|
331
315
|
"""
|
@@ -343,13 +327,12 @@ class _CommonModel(BaseModel):
|
|
343
327
|
).dt.date
|
344
328
|
|
345
329
|
@property
|
346
|
-
def worst(self: Self) ->
|
347
|
-
"""
|
348
|
-
Most negative percentage change.
|
330
|
+
def worst(self: Self) -> float | Series[float]:
|
331
|
+
"""Most negative percentage change.
|
349
332
|
|
350
333
|
Returns
|
351
334
|
-------
|
352
|
-
|
335
|
+
float | Pandas.Series[float]
|
353
336
|
Most negative percentage change
|
354
337
|
|
355
338
|
"""
|
@@ -357,9 +340,8 @@ class _CommonModel(BaseModel):
|
|
357
340
|
return self.worst_func(observations=observations)
|
358
341
|
|
359
342
|
@property
|
360
|
-
def worst_month(self: Self) ->
|
361
|
-
"""
|
362
|
-
Most negative month.
|
343
|
+
def worst_month(self: Self) -> float | Series[float]:
|
344
|
+
"""Most negative month.
|
363
345
|
|
364
346
|
Returns
|
365
347
|
-------
|
@@ -383,52 +365,48 @@ class _CommonModel(BaseModel):
|
|
383
365
|
)
|
384
366
|
|
385
367
|
@property
|
386
|
-
def positive_share(self: Self) ->
|
387
|
-
"""
|
388
|
-
The share of percentage changes that are greater than zero.
|
368
|
+
def positive_share(self: Self) -> float | Series[float]:
|
369
|
+
"""The share of percentage changes that are greater than zero.
|
389
370
|
|
390
371
|
Returns
|
391
372
|
-------
|
392
|
-
|
373
|
+
float | Pandas.Series[float]
|
393
374
|
The share of percentage changes that are greater than zero
|
394
375
|
|
395
376
|
"""
|
396
377
|
return self.positive_share_func()
|
397
378
|
|
398
379
|
@property
|
399
|
-
def skew(self: Self) ->
|
400
|
-
"""
|
401
|
-
https://www.investopedia.com/terms/s/skewness.asp.
|
380
|
+
def skew(self: Self) -> float | Series[float]:
|
381
|
+
"""https://www.investopedia.com/terms/s/skewness.asp.
|
402
382
|
|
403
383
|
Returns
|
404
384
|
-------
|
405
|
-
|
385
|
+
float | Pandas.Series[float]
|
406
386
|
Skew of the return distribution
|
407
387
|
|
408
388
|
"""
|
409
389
|
return self.skew_func()
|
410
390
|
|
411
391
|
@property
|
412
|
-
def kurtosis(self: Self) ->
|
413
|
-
"""
|
414
|
-
https://www.investopedia.com/terms/k/kurtosis.asp.
|
392
|
+
def kurtosis(self: Self) -> float | Series[float]:
|
393
|
+
"""https://www.investopedia.com/terms/k/kurtosis.asp.
|
415
394
|
|
416
395
|
Returns
|
417
396
|
-------
|
418
|
-
|
397
|
+
float | Pandas.Series[float]
|
419
398
|
Kurtosis of the return distribution
|
420
399
|
|
421
400
|
"""
|
422
401
|
return self.kurtosis_func()
|
423
402
|
|
424
403
|
@property
|
425
|
-
def cvar_down(self: Self) ->
|
426
|
-
"""
|
427
|
-
https://www.investopedia.com/terms/c/conditional_value_at_risk.asp.
|
404
|
+
def cvar_down(self: Self) -> float | Series[float]:
|
405
|
+
"""https://www.investopedia.com/terms/c/conditional_value_at_risk.asp.
|
428
406
|
|
429
407
|
Returns
|
430
408
|
-------
|
431
|
-
|
409
|
+
float | Pandas.Series[float]
|
432
410
|
Downside 95% Conditional Value At Risk "CVaR"
|
433
411
|
|
434
412
|
"""
|
@@ -436,16 +414,15 @@ class _CommonModel(BaseModel):
|
|
436
414
|
return self.cvar_down_func(level=level)
|
437
415
|
|
438
416
|
@property
|
439
|
-
def var_down(self: Self) ->
|
440
|
-
"""
|
441
|
-
Downside 95% Value At Risk (VaR).
|
417
|
+
def var_down(self: Self) -> float | Series[float]:
|
418
|
+
"""Downside 95% Value At Risk (VaR).
|
442
419
|
|
443
420
|
The equivalent of percentile.inc([...], 1-level) over returns in MS Excel.
|
444
421
|
https://www.investopedia.com/terms/v/var.asp.
|
445
422
|
|
446
423
|
Returns
|
447
424
|
-------
|
448
|
-
|
425
|
+
float | Pandas.Series[float]
|
449
426
|
Downside 95% Value At Risk (VaR)
|
450
427
|
|
451
428
|
"""
|
@@ -454,15 +431,14 @@ class _CommonModel(BaseModel):
|
|
454
431
|
return self.var_down_func(level=level, interpolation=interpolation)
|
455
432
|
|
456
433
|
@property
|
457
|
-
def vol_from_var(self: Self) ->
|
458
|
-
"""
|
459
|
-
Implied annualized volatility from Downside 95% Value at Risk.
|
434
|
+
def vol_from_var(self: Self) -> float | Series[float]:
|
435
|
+
"""Implied annualized volatility from Downside 95% Value at Risk.
|
460
436
|
|
461
437
|
Assumes that returns are normally distributed.
|
462
438
|
|
463
439
|
Returns
|
464
440
|
-------
|
465
|
-
|
441
|
+
float | Pandas.Series[float]
|
466
442
|
Implied annualized volatility from the Downside 95% VaR using the
|
467
443
|
assumption that returns are normally distributed.
|
468
444
|
|
@@ -473,12 +449,11 @@ class _CommonModel(BaseModel):
|
|
473
449
|
|
474
450
|
def calc_range( # noqa: C901
|
475
451
|
self: Self,
|
476
|
-
months_offset:
|
477
|
-
from_dt:
|
478
|
-
to_dt:
|
452
|
+
months_offset: int | None = None,
|
453
|
+
from_dt: dt.date | None = None,
|
454
|
+
to_dt: dt.date | None = None,
|
479
455
|
) -> tuple[dt.date, dt.date]:
|
480
|
-
"""
|
481
|
-
Create user defined date range.
|
456
|
+
"""Create user defined date range.
|
482
457
|
|
483
458
|
Parameters
|
484
459
|
----------
|
@@ -539,8 +514,7 @@ class _CommonModel(BaseModel):
|
|
539
514
|
self: Self,
|
540
515
|
countries: CountriesType = "SE",
|
541
516
|
) -> Self:
|
542
|
-
"""
|
543
|
-
Align the index of .tsdf with local calendar business days.
|
517
|
+
"""Align the index of .tsdf with local calendar business days.
|
544
518
|
|
545
519
|
Parameters
|
546
520
|
----------
|
@@ -574,8 +548,7 @@ class _CommonModel(BaseModel):
|
|
574
548
|
return self
|
575
549
|
|
576
550
|
def value_to_log(self: Self) -> Self:
|
577
|
-
"""
|
578
|
-
Series of values converted into logarithmic weighted series.
|
551
|
+
"""Series of values converted into logarithmic weighted series.
|
579
552
|
|
580
553
|
Equivalent to LN(value[t] / value[t=0]) in Excel.
|
581
554
|
|
@@ -593,8 +566,7 @@ class _CommonModel(BaseModel):
|
|
593
566
|
return self
|
594
567
|
|
595
568
|
def value_nan_handle(self: Self, method: LiteralNanMethod = "fill") -> Self:
|
596
|
-
"""
|
597
|
-
Handle missing values in a valueseries.
|
569
|
+
"""Handle missing values in a valueseries.
|
598
570
|
|
599
571
|
Parameters
|
600
572
|
----------
|
@@ -614,8 +586,7 @@ class _CommonModel(BaseModel):
|
|
614
586
|
return self
|
615
587
|
|
616
588
|
def return_nan_handle(self: Self, method: LiteralNanMethod = "fill") -> Self:
|
617
|
-
"""
|
618
|
-
Handle missing values in a returnseries.
|
589
|
+
"""Handle missing values in a returnseries.
|
619
590
|
|
620
591
|
Parameters
|
621
592
|
----------
|
@@ -635,8 +606,7 @@ class _CommonModel(BaseModel):
|
|
635
606
|
return self
|
636
607
|
|
637
608
|
def to_drawdown_series(self: Self) -> Self:
|
638
|
-
"""
|
639
|
-
Convert timeseries into a drawdown series.
|
609
|
+
"""Convert timeseries into a drawdown series.
|
640
610
|
|
641
611
|
Returns
|
642
612
|
-------
|
@@ -654,10 +624,9 @@ class _CommonModel(BaseModel):
|
|
654
624
|
self: Self,
|
655
625
|
what_output: LiteralJsonOutput,
|
656
626
|
filename: str,
|
657
|
-
directory:
|
658
|
-
) -> list[dict[str,
|
659
|
-
"""
|
660
|
-
Dump timeseries data into a json file.
|
627
|
+
directory: DirectoryPath | None = None,
|
628
|
+
) -> list[dict[str, str | bool | ValueType | list[str] | list[float]]]:
|
629
|
+
"""Dump timeseries data into a json file.
|
661
630
|
|
662
631
|
Parameters
|
663
632
|
----------
|
@@ -671,7 +640,7 @@ class _CommonModel(BaseModel):
|
|
671
640
|
|
672
641
|
Returns
|
673
642
|
-------
|
674
|
-
list[
|
643
|
+
list[dict[str, str | bool | ValueType | list[str] | list[float]]]
|
675
644
|
A list of dictionaries with the data of the series
|
676
645
|
|
677
646
|
"""
|
@@ -718,13 +687,12 @@ class _CommonModel(BaseModel):
|
|
718
687
|
def to_xlsx(
|
719
688
|
self: Self,
|
720
689
|
filename: str,
|
721
|
-
sheet_title:
|
722
|
-
directory:
|
690
|
+
sheet_title: str | None = None,
|
691
|
+
directory: DirectoryPath | None = None,
|
723
692
|
*,
|
724
693
|
overwrite: bool = True,
|
725
694
|
) -> str:
|
726
|
-
"""
|
727
|
-
Save .tsdf DataFrame to an Excel spreadsheet file.
|
695
|
+
"""Save .tsdf DataFrame to an Excel spreadsheet file.
|
728
696
|
|
729
697
|
Parameters
|
730
698
|
----------
|
@@ -776,18 +744,17 @@ class _CommonModel(BaseModel):
|
|
776
744
|
def plot_bars(
|
777
745
|
self: Self,
|
778
746
|
mode: LiteralBarPlotMode = "group",
|
779
|
-
tick_fmt:
|
780
|
-
filename:
|
781
|
-
directory:
|
782
|
-
labels:
|
747
|
+
tick_fmt: str | None = None,
|
748
|
+
filename: str | None = None,
|
749
|
+
directory: DirectoryPath | None = None,
|
750
|
+
labels: list[str] | None = None,
|
783
751
|
output_type: LiteralPlotlyOutput = "file",
|
784
752
|
include_plotlyjs: LiteralPlotlyJSlib = "cdn",
|
785
753
|
*,
|
786
754
|
auto_open: bool = True,
|
787
755
|
add_logo: bool = True,
|
788
756
|
) -> tuple[Figure, str]:
|
789
|
-
"""
|
790
|
-
Create a Plotly Bar Figure.
|
757
|
+
"""Create a Plotly Bar Figure.
|
791
758
|
|
792
759
|
Parameters
|
793
760
|
----------
|
@@ -891,10 +858,10 @@ class _CommonModel(BaseModel):
|
|
891
858
|
def plot_series( # noqa: C901
|
892
859
|
self: Self,
|
893
860
|
mode: LiteralLinePlotMode = "lines",
|
894
|
-
tick_fmt:
|
895
|
-
filename:
|
896
|
-
directory:
|
897
|
-
labels:
|
861
|
+
tick_fmt: str | None = None,
|
862
|
+
filename: str | None = None,
|
863
|
+
directory: DirectoryPath | None = None,
|
864
|
+
labels: list[str] | None = None,
|
898
865
|
output_type: LiteralPlotlyOutput = "file",
|
899
866
|
include_plotlyjs: LiteralPlotlyJSlib = "cdn",
|
900
867
|
*,
|
@@ -902,8 +869,7 @@ class _CommonModel(BaseModel):
|
|
902
869
|
add_logo: bool = True,
|
903
870
|
show_last: bool = False,
|
904
871
|
) -> tuple[Figure, str]:
|
905
|
-
"""
|
906
|
-
Create a Plotly Scatter Figure.
|
872
|
+
"""Create a Plotly Scatter Figure.
|
907
873
|
|
908
874
|
Parameters
|
909
875
|
----------
|
@@ -1023,13 +989,12 @@ class _CommonModel(BaseModel):
|
|
1023
989
|
|
1024
990
|
def arithmetic_ret_func(
|
1025
991
|
self: Self,
|
1026
|
-
months_from_last:
|
1027
|
-
from_date:
|
1028
|
-
to_date:
|
1029
|
-
periods_in_a_year_fixed:
|
1030
|
-
) ->
|
1031
|
-
"""
|
1032
|
-
https://www.investopedia.com/terms/a/arithmeticmean.asp.
|
992
|
+
months_from_last: int | None = None,
|
993
|
+
from_date: dt.date | None = None,
|
994
|
+
to_date: dt.date | None = None,
|
995
|
+
periods_in_a_year_fixed: DaysInYearType | None = None,
|
996
|
+
) -> float | Series[float]:
|
997
|
+
"""https://www.investopedia.com/terms/a/arithmeticmean.asp.
|
1033
998
|
|
1034
999
|
Parameters
|
1035
1000
|
----------
|
@@ -1046,7 +1011,7 @@ class _CommonModel(BaseModel):
|
|
1046
1011
|
|
1047
1012
|
Returns
|
1048
1013
|
-------
|
1049
|
-
|
1014
|
+
float | Pandas.Series[float]
|
1050
1015
|
Annualized arithmetic mean of returns
|
1051
1016
|
|
1052
1017
|
"""
|
@@ -1083,13 +1048,12 @@ class _CommonModel(BaseModel):
|
|
1083
1048
|
|
1084
1049
|
def vol_func(
|
1085
1050
|
self: Self,
|
1086
|
-
months_from_last:
|
1087
|
-
from_date:
|
1088
|
-
to_date:
|
1089
|
-
periods_in_a_year_fixed:
|
1090
|
-
) ->
|
1091
|
-
"""
|
1092
|
-
Annualized volatility.
|
1051
|
+
months_from_last: int | None = None,
|
1052
|
+
from_date: dt.date | None = None,
|
1053
|
+
to_date: dt.date | None = None,
|
1054
|
+
periods_in_a_year_fixed: DaysInYearType | None = None,
|
1055
|
+
) -> float | Series[float]:
|
1056
|
+
"""Annualized volatility.
|
1093
1057
|
|
1094
1058
|
Based on Pandas .std() which is the equivalent of stdev.s([...]) in MS Excel.
|
1095
1059
|
https://www.investopedia.com/terms/v/volatility.asp.
|
@@ -1108,7 +1072,7 @@ class _CommonModel(BaseModel):
|
|
1108
1072
|
|
1109
1073
|
Returns
|
1110
1074
|
-------
|
1111
|
-
|
1075
|
+
float | Pandas.Series[float]
|
1112
1076
|
Annualized volatility
|
1113
1077
|
|
1114
1078
|
"""
|
@@ -1132,7 +1096,7 @@ class _CommonModel(BaseModel):
|
|
1132
1096
|
)
|
1133
1097
|
|
1134
1098
|
if self.tsdf.shape[1] == 1:
|
1135
|
-
return float(result.iloc[0])
|
1099
|
+
return float(cast(SupportsFloat, result.iloc[0]))
|
1136
1100
|
return Series(
|
1137
1101
|
data=result,
|
1138
1102
|
index=self.tsdf.columns,
|
@@ -1143,16 +1107,15 @@ class _CommonModel(BaseModel):
|
|
1143
1107
|
def vol_from_var_func(
|
1144
1108
|
self: Self,
|
1145
1109
|
level: float = 0.95,
|
1146
|
-
months_from_last:
|
1147
|
-
from_date:
|
1148
|
-
to_date:
|
1110
|
+
months_from_last: int | None = None,
|
1111
|
+
from_date: dt.date | None = None,
|
1112
|
+
to_date: dt.date | None = None,
|
1149
1113
|
interpolation: LiteralQuantileInterp = "lower",
|
1150
|
-
periods_in_a_year_fixed:
|
1114
|
+
periods_in_a_year_fixed: DaysInYearType | None = None,
|
1151
1115
|
*,
|
1152
1116
|
drift_adjust: bool = False,
|
1153
|
-
) ->
|
1154
|
-
"""
|
1155
|
-
Implied annualized volatility.
|
1117
|
+
) -> float | Series[float]:
|
1118
|
+
"""Implied annualized volatility.
|
1156
1119
|
|
1157
1120
|
Implied annualized volatility from the Downside VaR using the assumption
|
1158
1121
|
that returns are normally distributed.
|
@@ -1178,7 +1141,7 @@ class _CommonModel(BaseModel):
|
|
1178
1141
|
|
1179
1142
|
Returns
|
1180
1143
|
-------
|
1181
|
-
|
1144
|
+
float | Pandas.Series[float]
|
1182
1145
|
Implied annualized volatility from the Downside VaR using the
|
1183
1146
|
assumption that returns are normally distributed.
|
1184
1147
|
|
@@ -1199,16 +1162,15 @@ class _CommonModel(BaseModel):
|
|
1199
1162
|
level: float = 0.95,
|
1200
1163
|
min_leverage_local: float = 0.0,
|
1201
1164
|
max_leverage_local: float = 99999.0,
|
1202
|
-
months_from_last:
|
1203
|
-
from_date:
|
1204
|
-
to_date:
|
1165
|
+
months_from_last: int | None = None,
|
1166
|
+
from_date: dt.date | None = None,
|
1167
|
+
to_date: dt.date | None = None,
|
1205
1168
|
interpolation: LiteralQuantileInterp = "lower",
|
1206
|
-
periods_in_a_year_fixed:
|
1169
|
+
periods_in_a_year_fixed: DaysInYearType | None = None,
|
1207
1170
|
*,
|
1208
1171
|
drift_adjust: bool = False,
|
1209
|
-
) ->
|
1210
|
-
"""
|
1211
|
-
Target weight from VaR.
|
1172
|
+
) -> float | Series[float]:
|
1173
|
+
"""Target weight from VaR.
|
1212
1174
|
|
1213
1175
|
A position weight multiplier from the ratio between a VaR implied
|
1214
1176
|
volatility and a given target volatility. Multiplier = 1.0 -> target met.
|
@@ -1240,7 +1202,7 @@ class _CommonModel(BaseModel):
|
|
1240
1202
|
|
1241
1203
|
Returns
|
1242
1204
|
-------
|
1243
|
-
|
1205
|
+
float | Pandas.Series[float]
|
1244
1206
|
A position weight multiplier from the ratio between a VaR implied
|
1245
1207
|
volatility and a given target volatility. Multiplier = 1.0 -> target met
|
1246
1208
|
|
@@ -1261,19 +1223,18 @@ class _CommonModel(BaseModel):
|
|
1261
1223
|
def _var_implied_vol_and_target_func(
|
1262
1224
|
self: Self,
|
1263
1225
|
level: float,
|
1264
|
-
target_vol:
|
1226
|
+
target_vol: float | None = None,
|
1265
1227
|
min_leverage_local: float = 0.0,
|
1266
1228
|
max_leverage_local: float = 99999.0,
|
1267
|
-
months_from_last:
|
1268
|
-
from_date:
|
1269
|
-
to_date:
|
1229
|
+
months_from_last: int | None = None,
|
1230
|
+
from_date: dt.date | None = None,
|
1231
|
+
to_date: dt.date | None = None,
|
1270
1232
|
interpolation: LiteralQuantileInterp = "lower",
|
1271
|
-
periods_in_a_year_fixed:
|
1233
|
+
periods_in_a_year_fixed: DaysInYearType | None = None,
|
1272
1234
|
*,
|
1273
1235
|
drift_adjust: bool = False,
|
1274
|
-
) ->
|
1275
|
-
"""
|
1276
|
-
Volatility implied from VaR or Target Weight.
|
1236
|
+
) -> float | Series[float]:
|
1237
|
+
"""Volatility implied from VaR or Target Weight.
|
1277
1238
|
|
1278
1239
|
The function returns a position weight multiplier from the ratio between
|
1279
1240
|
a VaR implied volatility and a given target volatility if the argument
|
@@ -1284,7 +1245,7 @@ class _CommonModel(BaseModel):
|
|
1284
1245
|
----------
|
1285
1246
|
level: float
|
1286
1247
|
The sought VaR level
|
1287
|
-
target_vol:
|
1248
|
+
target_vol: float | None
|
1288
1249
|
Target Volatility
|
1289
1250
|
min_leverage_local: float, default: 0.0
|
1290
1251
|
A minimum adjustment factor
|
@@ -1307,7 +1268,7 @@ class _CommonModel(BaseModel):
|
|
1307
1268
|
|
1308
1269
|
Returns
|
1309
1270
|
-------
|
1310
|
-
|
1271
|
+
float | Pandas.Series[float]
|
1311
1272
|
Target volatility if target_vol is provided otherwise the VaR
|
1312
1273
|
implied volatility.
|
1313
1274
|
|
@@ -1361,7 +1322,7 @@ class _CommonModel(BaseModel):
|
|
1361
1322
|
label = f"Imp vol from VaR {level:.0%}"
|
1362
1323
|
|
1363
1324
|
if self.tsdf.shape[1] == 1:
|
1364
|
-
return float(result.iloc[0])
|
1325
|
+
return float(cast(SupportsFloat, result.iloc[0]))
|
1365
1326
|
return Series(
|
1366
1327
|
data=result,
|
1367
1328
|
index=self.tsdf.columns,
|
@@ -1372,12 +1333,11 @@ class _CommonModel(BaseModel):
|
|
1372
1333
|
def cvar_down_func(
|
1373
1334
|
self: Self,
|
1374
1335
|
level: float = 0.95,
|
1375
|
-
months_from_last:
|
1376
|
-
from_date:
|
1377
|
-
to_date:
|
1378
|
-
) ->
|
1379
|
-
"""
|
1380
|
-
Downside Conditional Value At Risk "CVaR".
|
1336
|
+
months_from_last: int | None = None,
|
1337
|
+
from_date: dt.date | None = None,
|
1338
|
+
to_date: dt.date | None = None,
|
1339
|
+
) -> float | Series[float]:
|
1340
|
+
"""Downside Conditional Value At Risk "CVaR".
|
1381
1341
|
|
1382
1342
|
https://www.investopedia.com/terms/c/conditional_value_at_risk.asp.
|
1383
1343
|
|
@@ -1395,7 +1355,7 @@ class _CommonModel(BaseModel):
|
|
1395
1355
|
|
1396
1356
|
Returns
|
1397
1357
|
-------
|
1398
|
-
|
1358
|
+
float | Pandas.Series[float]
|
1399
1359
|
Downside Conditional Value At Risk "CVaR"
|
1400
1360
|
|
1401
1361
|
"""
|
@@ -1434,13 +1394,12 @@ class _CommonModel(BaseModel):
|
|
1434
1394
|
def downside_deviation_func(
|
1435
1395
|
self: Self,
|
1436
1396
|
min_accepted_return: float = 0.0,
|
1437
|
-
months_from_last:
|
1438
|
-
from_date:
|
1439
|
-
to_date:
|
1440
|
-
periods_in_a_year_fixed:
|
1441
|
-
) ->
|
1442
|
-
"""
|
1443
|
-
Downside Deviation.
|
1397
|
+
months_from_last: int | None = None,
|
1398
|
+
from_date: dt.date | None = None,
|
1399
|
+
to_date: dt.date | None = None,
|
1400
|
+
periods_in_a_year_fixed: DaysInYearType | None = None,
|
1401
|
+
) -> float | Series[float]:
|
1402
|
+
"""Downside Deviation.
|
1444
1403
|
|
1445
1404
|
The standard deviation of returns that are below a Minimum Accepted
|
1446
1405
|
Return of zero. It is used to calculate the Sortino Ratio.
|
@@ -1463,7 +1422,7 @@ class _CommonModel(BaseModel):
|
|
1463
1422
|
|
1464
1423
|
Returns
|
1465
1424
|
-------
|
1466
|
-
|
1425
|
+
float | Pandas.Series[float]
|
1467
1426
|
Downside deviation
|
1468
1427
|
|
1469
1428
|
"""
|
@@ -1509,12 +1468,11 @@ class _CommonModel(BaseModel):
|
|
1509
1468
|
|
1510
1469
|
def geo_ret_func(
|
1511
1470
|
self: Self,
|
1512
|
-
months_from_last:
|
1513
|
-
from_date:
|
1514
|
-
to_date:
|
1515
|
-
) ->
|
1516
|
-
"""
|
1517
|
-
Compounded Annual Growth Rate (CAGR).
|
1471
|
+
months_from_last: int | None = None,
|
1472
|
+
from_date: dt.date | None = None,
|
1473
|
+
to_date: dt.date | None = None,
|
1474
|
+
) -> float | Series[float]:
|
1475
|
+
"""Compounded Annual Growth Rate (CAGR).
|
1518
1476
|
|
1519
1477
|
https://www.investopedia.com/terms/c/cagr.asp.
|
1520
1478
|
|
@@ -1530,7 +1488,7 @@ class _CommonModel(BaseModel):
|
|
1530
1488
|
|
1531
1489
|
Returns
|
1532
1490
|
-------
|
1533
|
-
|
1491
|
+
float | Pandas.Series[float]
|
1534
1492
|
Compounded Annual Growth Rate (CAGR)
|
1535
1493
|
|
1536
1494
|
"""
|
@@ -1563,12 +1521,11 @@ class _CommonModel(BaseModel):
|
|
1563
1521
|
|
1564
1522
|
def skew_func(
|
1565
1523
|
self: Self,
|
1566
|
-
months_from_last:
|
1567
|
-
from_date:
|
1568
|
-
to_date:
|
1569
|
-
) ->
|
1570
|
-
"""
|
1571
|
-
Skew of the return distribution.
|
1524
|
+
months_from_last: int | None = None,
|
1525
|
+
from_date: dt.date | None = None,
|
1526
|
+
to_date: dt.date | None = None,
|
1527
|
+
) -> float | Series[float]:
|
1528
|
+
"""Skew of the return distribution.
|
1572
1529
|
|
1573
1530
|
https://www.investopedia.com/terms/s/skewness.asp.
|
1574
1531
|
|
@@ -1584,7 +1541,7 @@ class _CommonModel(BaseModel):
|
|
1584
1541
|
|
1585
1542
|
Returns
|
1586
1543
|
-------
|
1587
|
-
|
1544
|
+
float | Pandas.Series[float]
|
1588
1545
|
Skew of the return distribution
|
1589
1546
|
|
1590
1547
|
"""
|
@@ -1593,7 +1550,7 @@ class _CommonModel(BaseModel):
|
|
1593
1550
|
from_dt=from_date,
|
1594
1551
|
to_dt=to_date,
|
1595
1552
|
)
|
1596
|
-
result = skew(
|
1553
|
+
result: NDArray[float64] = skew(
|
1597
1554
|
a=self.tsdf.loc[cast(int, earlier) : cast(int, later)]
|
1598
1555
|
.pct_change(fill_method=cast(str, None))
|
1599
1556
|
.to_numpy(),
|
@@ -1612,12 +1569,11 @@ class _CommonModel(BaseModel):
|
|
1612
1569
|
|
1613
1570
|
def kurtosis_func(
|
1614
1571
|
self: Self,
|
1615
|
-
months_from_last:
|
1616
|
-
from_date:
|
1617
|
-
to_date:
|
1618
|
-
) ->
|
1619
|
-
"""
|
1620
|
-
Kurtosis of the return distribution.
|
1572
|
+
months_from_last: int | None = None,
|
1573
|
+
from_date: dt.date | None = None,
|
1574
|
+
to_date: dt.date | None = None,
|
1575
|
+
) -> float | Series[float]:
|
1576
|
+
"""Kurtosis of the return distribution.
|
1621
1577
|
|
1622
1578
|
https://www.investopedia.com/terms/k/kurtosis.asp.
|
1623
1579
|
|
@@ -1633,7 +1589,7 @@ class _CommonModel(BaseModel):
|
|
1633
1589
|
|
1634
1590
|
Returns
|
1635
1591
|
-------
|
1636
|
-
|
1592
|
+
float | Pandas.Series[float]
|
1637
1593
|
Kurtosis of the return distribution
|
1638
1594
|
|
1639
1595
|
"""
|
@@ -1642,7 +1598,7 @@ class _CommonModel(BaseModel):
|
|
1642
1598
|
from_dt=from_date,
|
1643
1599
|
to_dt=to_date,
|
1644
1600
|
)
|
1645
|
-
result = kurtosis(
|
1601
|
+
result: NDArray[float64] = kurtosis(
|
1646
1602
|
self.tsdf.loc[cast(int, earlier) : cast(int, later)].pct_change(
|
1647
1603
|
fill_method=cast(str, None),
|
1648
1604
|
),
|
@@ -1662,13 +1618,12 @@ class _CommonModel(BaseModel):
|
|
1662
1618
|
|
1663
1619
|
def max_drawdown_func(
|
1664
1620
|
self: Self,
|
1665
|
-
months_from_last:
|
1666
|
-
from_date:
|
1667
|
-
to_date:
|
1621
|
+
months_from_last: int | None = None,
|
1622
|
+
from_date: dt.date | None = None,
|
1623
|
+
to_date: dt.date | None = None,
|
1668
1624
|
min_periods: int = 1,
|
1669
|
-
) ->
|
1670
|
-
"""
|
1671
|
-
Maximum drawdown without any limit on date range.
|
1625
|
+
) -> float | Series[float]:
|
1626
|
+
"""Maximum drawdown without any limit on date range.
|
1672
1627
|
|
1673
1628
|
https://www.investopedia.com/terms/m/maximum-drawdown-mdd.asp.
|
1674
1629
|
|
@@ -1686,7 +1641,7 @@ class _CommonModel(BaseModel):
|
|
1686
1641
|
|
1687
1642
|
Returns
|
1688
1643
|
-------
|
1689
|
-
|
1644
|
+
float | Pandas.Series[float]
|
1690
1645
|
Maximum drawdown without any limit on date range
|
1691
1646
|
|
1692
1647
|
"""
|
@@ -1712,12 +1667,11 @@ class _CommonModel(BaseModel):
|
|
1712
1667
|
|
1713
1668
|
def positive_share_func(
|
1714
1669
|
self: Self,
|
1715
|
-
months_from_last:
|
1716
|
-
from_date:
|
1717
|
-
to_date:
|
1718
|
-
) ->
|
1719
|
-
"""
|
1720
|
-
Calculate share of percentage changes that are greater than zero.
|
1670
|
+
months_from_last: int | None = None,
|
1671
|
+
from_date: dt.date | None = None,
|
1672
|
+
to_date: dt.date | None = None,
|
1673
|
+
) -> float | Series[float]:
|
1674
|
+
"""Calculate share of percentage changes that are greater than zero.
|
1721
1675
|
|
1722
1676
|
Parameters
|
1723
1677
|
----------
|
@@ -1731,7 +1685,7 @@ class _CommonModel(BaseModel):
|
|
1731
1685
|
|
1732
1686
|
Returns
|
1733
1687
|
-------
|
1734
|
-
|
1688
|
+
float | Pandas.Series[float]
|
1735
1689
|
Calculate share of percentage changes that are greater than zero
|
1736
1690
|
|
1737
1691
|
"""
|
@@ -1769,13 +1723,12 @@ class _CommonModel(BaseModel):
|
|
1769
1723
|
def ret_vol_ratio_func(
|
1770
1724
|
self: Self,
|
1771
1725
|
riskfree_rate: float = 0.0,
|
1772
|
-
months_from_last:
|
1773
|
-
from_date:
|
1774
|
-
to_date:
|
1775
|
-
periods_in_a_year_fixed:
|
1776
|
-
) ->
|
1777
|
-
"""
|
1778
|
-
Ratio between arithmetic mean of returns and annualized volatility.
|
1726
|
+
months_from_last: int | None = None,
|
1727
|
+
from_date: dt.date | None = None,
|
1728
|
+
to_date: dt.date | None = None,
|
1729
|
+
periods_in_a_year_fixed: DaysInYearType | None = None,
|
1730
|
+
) -> float | Series[float]:
|
1731
|
+
"""Ratio between arithmetic mean of returns and annualized volatility.
|
1779
1732
|
|
1780
1733
|
The ratio of annualized arithmetic mean of returns and annualized
|
1781
1734
|
volatility or, if riskfree return provided, Sharpe ratio calculated
|
@@ -1800,7 +1753,7 @@ class _CommonModel(BaseModel):
|
|
1800
1753
|
|
1801
1754
|
Returns
|
1802
1755
|
-------
|
1803
|
-
|
1756
|
+
float | Pandas.Series[float]
|
1804
1757
|
Ratio of the annualized arithmetic mean of returns and annualized
|
1805
1758
|
volatility or, if risk-free return provided, Sharpe ratio
|
1806
1759
|
|
@@ -1833,13 +1786,12 @@ class _CommonModel(BaseModel):
|
|
1833
1786
|
self: Self,
|
1834
1787
|
riskfree_rate: float = 0.0,
|
1835
1788
|
min_accepted_return: float = 0.0,
|
1836
|
-
months_from_last:
|
1837
|
-
from_date:
|
1838
|
-
to_date:
|
1839
|
-
periods_in_a_year_fixed:
|
1840
|
-
) ->
|
1841
|
-
"""
|
1842
|
-
Sortino Ratio.
|
1789
|
+
months_from_last: int | None = None,
|
1790
|
+
from_date: dt.date | None = None,
|
1791
|
+
to_date: dt.date | None = None,
|
1792
|
+
periods_in_a_year_fixed: DaysInYearType | None = None,
|
1793
|
+
) -> float | Series[float]:
|
1794
|
+
"""Sortino Ratio.
|
1843
1795
|
|
1844
1796
|
The Sortino ratio calculated as ( return - risk free return )
|
1845
1797
|
/ downside deviation. The ratio implies that the riskfree asset has zero
|
@@ -1866,7 +1818,7 @@ class _CommonModel(BaseModel):
|
|
1866
1818
|
|
1867
1819
|
Returns
|
1868
1820
|
-------
|
1869
|
-
|
1821
|
+
float | Pandas.Series[float]
|
1870
1822
|
Sortino ratio calculated as ( return - riskfree return ) /
|
1871
1823
|
downside deviation (std dev of returns below MAR)
|
1872
1824
|
|
@@ -1899,12 +1851,11 @@ class _CommonModel(BaseModel):
|
|
1899
1851
|
def omega_ratio_func(
|
1900
1852
|
self: Self,
|
1901
1853
|
min_accepted_return: float = 0.0,
|
1902
|
-
months_from_last:
|
1903
|
-
from_date:
|
1904
|
-
to_date:
|
1905
|
-
) ->
|
1906
|
-
"""
|
1907
|
-
Omega Ratio.
|
1854
|
+
months_from_last: int | None = None,
|
1855
|
+
from_date: dt.date | None = None,
|
1856
|
+
to_date: dt.date | None = None,
|
1857
|
+
) -> float | Series[float]:
|
1858
|
+
"""Omega Ratio.
|
1908
1859
|
|
1909
1860
|
The Omega Ratio compares returns above a certain target level
|
1910
1861
|
(often referred to as the “minimum acceptable return” or “MAR”)
|
@@ -1925,7 +1876,7 @@ class _CommonModel(BaseModel):
|
|
1925
1876
|
|
1926
1877
|
Returns
|
1927
1878
|
-------
|
1928
|
-
|
1879
|
+
float | Pandas.Series[float]
|
1929
1880
|
Omega ratio calculation
|
1930
1881
|
|
1931
1882
|
"""
|
@@ -1952,12 +1903,11 @@ class _CommonModel(BaseModel):
|
|
1952
1903
|
|
1953
1904
|
def value_ret_func(
|
1954
1905
|
self: Self,
|
1955
|
-
months_from_last:
|
1956
|
-
from_date:
|
1957
|
-
to_date:
|
1958
|
-
) ->
|
1959
|
-
"""
|
1960
|
-
Calculate simple return.
|
1906
|
+
months_from_last: int | None = None,
|
1907
|
+
from_date: dt.date | None = None,
|
1908
|
+
to_date: dt.date | None = None,
|
1909
|
+
) -> float | Series[float]:
|
1910
|
+
"""Calculate simple return.
|
1961
1911
|
|
1962
1912
|
Parameters
|
1963
1913
|
----------
|
@@ -1971,7 +1921,7 @@ class _CommonModel(BaseModel):
|
|
1971
1921
|
|
1972
1922
|
Returns
|
1973
1923
|
-------
|
1974
|
-
|
1924
|
+
float | Pandas.Series[float]
|
1975
1925
|
Calculate simple return
|
1976
1926
|
|
1977
1927
|
"""
|
@@ -2004,10 +1954,9 @@ class _CommonModel(BaseModel):
|
|
2004
1954
|
def value_ret_calendar_period(
|
2005
1955
|
self: Self,
|
2006
1956
|
year: int,
|
2007
|
-
month:
|
2008
|
-
) ->
|
2009
|
-
"""
|
2010
|
-
Calculate simple return for a specific calendar period.
|
1957
|
+
month: int | None = None,
|
1958
|
+
) -> float | Series[float]:
|
1959
|
+
"""Calculate simple return for a specific calendar period.
|
2011
1960
|
|
2012
1961
|
Parameters
|
2013
1962
|
----------
|
@@ -2018,7 +1967,7 @@ class _CommonModel(BaseModel):
|
|
2018
1967
|
|
2019
1968
|
Returns
|
2020
1969
|
-------
|
2021
|
-
|
1970
|
+
float | Pandas.Series[float]
|
2022
1971
|
Calculate simple return for a specific calendar period
|
2023
1972
|
|
2024
1973
|
"""
|
@@ -2028,7 +1977,7 @@ class _CommonModel(BaseModel):
|
|
2028
1977
|
period = "-".join([str(year), str(month).zfill(2)])
|
2029
1978
|
vrdf = self.tsdf.copy()
|
2030
1979
|
vrdf.index = DatetimeIndex(vrdf.index)
|
2031
|
-
resultdf = DataFrame(vrdf.pct_change(fill_method=
|
1980
|
+
resultdf = DataFrame(vrdf.pct_change(fill_method=None)) # type: ignore[arg-type]
|
2032
1981
|
result = resultdf.loc[period] + 1
|
2033
1982
|
cal_period = result.cumprod(axis="index").iloc[-1] - 1
|
2034
1983
|
if self.tsdf.shape[1] == 1:
|
@@ -2043,13 +1992,12 @@ class _CommonModel(BaseModel):
|
|
2043
1992
|
def var_down_func(
|
2044
1993
|
self: Self,
|
2045
1994
|
level: float = 0.95,
|
2046
|
-
months_from_last:
|
2047
|
-
from_date:
|
2048
|
-
to_date:
|
1995
|
+
months_from_last: int | None = None,
|
1996
|
+
from_date: dt.date | None = None,
|
1997
|
+
to_date: dt.date | None = None,
|
2049
1998
|
interpolation: LiteralQuantileInterp = "lower",
|
2050
|
-
) ->
|
2051
|
-
"""
|
2052
|
-
Downside Value At Risk, "VaR".
|
1999
|
+
) -> float | Series[float]:
|
2000
|
+
"""Downside Value At Risk, "VaR".
|
2053
2001
|
|
2054
2002
|
The equivalent of percentile.inc([...], 1-level) over returns in MS Excel.
|
2055
2003
|
https://www.investopedia.com/terms/v/var.asp.
|
@@ -2070,7 +2018,7 @@ class _CommonModel(BaseModel):
|
|
2070
2018
|
|
2071
2019
|
Returns
|
2072
2020
|
-------
|
2073
|
-
|
2021
|
+
float | Pandas.Series[float]
|
2074
2022
|
Downside Value At Risk
|
2075
2023
|
|
2076
2024
|
"""
|
@@ -2097,12 +2045,11 @@ class _CommonModel(BaseModel):
|
|
2097
2045
|
def worst_func(
|
2098
2046
|
self: Self,
|
2099
2047
|
observations: int = 1,
|
2100
|
-
months_from_last:
|
2101
|
-
from_date:
|
2102
|
-
to_date:
|
2103
|
-
) ->
|
2104
|
-
"""
|
2105
|
-
Most negative percentage change over a rolling number of observations.
|
2048
|
+
months_from_last: int | None = None,
|
2049
|
+
from_date: dt.date | None = None,
|
2050
|
+
to_date: dt.date | None = None,
|
2051
|
+
) -> float | Series[float]:
|
2052
|
+
"""Most negative percentage change over a rolling number of observations.
|
2106
2053
|
|
2107
2054
|
Parameters
|
2108
2055
|
----------
|
@@ -2118,7 +2065,7 @@ class _CommonModel(BaseModel):
|
|
2118
2065
|
|
2119
2066
|
Returns
|
2120
2067
|
-------
|
2121
|
-
|
2068
|
+
float | Pandas.Series[float]
|
2122
2069
|
Most negative percentage change over a rolling number of observations
|
2123
2070
|
within a chosen date range
|
2124
2071
|
|
@@ -2147,12 +2094,11 @@ class _CommonModel(BaseModel):
|
|
2147
2094
|
|
2148
2095
|
def z_score_func(
|
2149
2096
|
self: Self,
|
2150
|
-
months_from_last:
|
2151
|
-
from_date:
|
2152
|
-
to_date:
|
2153
|
-
) ->
|
2154
|
-
"""
|
2155
|
-
Z-score as (last return - mean return) / standard deviation of returns.
|
2097
|
+
months_from_last: int | None = None,
|
2098
|
+
from_date: dt.date | None = None,
|
2099
|
+
to_date: dt.date | None = None,
|
2100
|
+
) -> float | Series[float]:
|
2101
|
+
"""Z-score as (last return - mean return) / standard deviation of returns.
|
2156
2102
|
|
2157
2103
|
https://www.investopedia.com/terms/z/zscore.asp.
|
2158
2104
|
|
@@ -2168,7 +2114,7 @@ class _CommonModel(BaseModel):
|
|
2168
2114
|
|
2169
2115
|
Returns
|
2170
2116
|
-------
|
2171
|
-
|
2117
|
+
float | Pandas.Series[float]
|
2172
2118
|
Z-score as (last return - mean return) / standard deviation of returns
|
2173
2119
|
|
2174
2120
|
"""
|
@@ -2197,8 +2143,7 @@ class _CommonModel(BaseModel):
|
|
2197
2143
|
level: float = 0.95,
|
2198
2144
|
observations: int = 252,
|
2199
2145
|
) -> DataFrame:
|
2200
|
-
"""
|
2201
|
-
Calculate rolling annualized downside CVaR.
|
2146
|
+
"""Calculate rolling annualized downside CVaR.
|
2202
2147
|
|
2203
2148
|
Parameters
|
2204
2149
|
----------
|
@@ -2231,8 +2176,7 @@ class _CommonModel(BaseModel):
|
|
2231
2176
|
column: int = 0,
|
2232
2177
|
observations: int = 21,
|
2233
2178
|
) -> DataFrame:
|
2234
|
-
"""
|
2235
|
-
Calculate rolling returns.
|
2179
|
+
"""Calculate rolling returns.
|
2236
2180
|
|
2237
2181
|
Parameters
|
2238
2182
|
----------
|
@@ -2266,8 +2210,7 @@ class _CommonModel(BaseModel):
|
|
2266
2210
|
observations: int = 252,
|
2267
2211
|
interpolation: LiteralQuantileInterp = "lower",
|
2268
2212
|
) -> DataFrame:
|
2269
|
-
"""
|
2270
|
-
Calculate rolling annualized downside Value At Risk "VaR".
|
2213
|
+
"""Calculate rolling annualized downside Value At Risk "VaR".
|
2271
2214
|
|
2272
2215
|
Parameters
|
2273
2216
|
----------
|
@@ -2303,10 +2246,9 @@ class _CommonModel(BaseModel):
|
|
2303
2246
|
self: Self,
|
2304
2247
|
column: int = 0,
|
2305
2248
|
observations: int = 21,
|
2306
|
-
periods_in_a_year_fixed:
|
2249
|
+
periods_in_a_year_fixed: DaysInYearType | None = None,
|
2307
2250
|
) -> DataFrame:
|
2308
|
-
"""
|
2309
|
-
Calculate rolling annualised volatilities.
|
2251
|
+
"""Calculate rolling annualised volatilities.
|
2310
2252
|
|
2311
2253
|
Parameters
|
2312
2254
|
----------
|