openseries 1.6.0__py3-none-any.whl → 1.7.1__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 +0 -2
- openseries/_common_model.py +261 -324
- openseries/_risk.py +9 -10
- openseries/datefixer.py +42 -63
- openseries/frame.py +125 -161
- openseries/load_plotly.py +8 -8
- openseries/portfoliotools.py +39 -35
- openseries/series.py +65 -93
- openseries/simulation.py +39 -50
- openseries/types.py +17 -24
- {openseries-1.6.0.dist-info → openseries-1.7.1.dist-info}/LICENSE.md +1 -1
- {openseries-1.6.0.dist-info → openseries-1.7.1.dist-info}/METADATA +4 -5
- openseries-1.7.1.dist-info/RECORD +16 -0
- openseries-1.6.0.dist-info/RECORD +0 -16
- {openseries-1.6.0.dist-info → openseries-1.7.1.dist-info}/WHEEL +0 -0
openseries/_common_model.py
CHANGED
@@ -9,10 +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
|
-
|
15
|
+
|
16
|
+
if TYPE_CHECKING:
|
17
|
+
from numpy.typing import NDArray # pragma: no cover
|
16
18
|
from openpyxl.utils.dataframe import dataframe_to_rows
|
17
19
|
from openpyxl.workbook.workbook import Workbook
|
18
20
|
from openpyxl.worksheet.worksheet import Worksheet
|
@@ -29,13 +31,13 @@ from scipy.stats import ( # type: ignore[import-untyped,unused-ignore]
|
|
29
31
|
)
|
30
32
|
from typing_extensions import Self
|
31
33
|
|
32
|
-
from
|
34
|
+
from ._risk import (
|
33
35
|
_cvar_down_calc,
|
34
36
|
_var_down_calc,
|
35
37
|
)
|
36
|
-
from
|
37
|
-
from
|
38
|
-
from
|
38
|
+
from .datefixer import date_offset_foll, holiday_calendar
|
39
|
+
from .load_plotly import load_plotly_dict
|
40
|
+
from .types import (
|
39
41
|
CountriesType,
|
40
42
|
DaysInYearType,
|
41
43
|
LiteralBarPlotMode,
|
@@ -50,7 +52,6 @@ from openseries.types import (
|
|
50
52
|
|
51
53
|
|
52
54
|
class _CommonModel(BaseModel):
|
53
|
-
|
54
55
|
"""Declare _CommonModel."""
|
55
56
|
|
56
57
|
tsdf: DataFrame = DataFrame(dtype="float64")
|
@@ -63,8 +64,7 @@ class _CommonModel(BaseModel):
|
|
63
64
|
|
64
65
|
@property
|
65
66
|
def length(self: Self) -> int:
|
66
|
-
"""
|
67
|
-
Number of observations.
|
67
|
+
"""Number of observations.
|
68
68
|
|
69
69
|
Returns
|
70
70
|
-------
|
@@ -76,8 +76,7 @@ class _CommonModel(BaseModel):
|
|
76
76
|
|
77
77
|
@property
|
78
78
|
def first_idx(self: Self) -> dt.date:
|
79
|
-
"""
|
80
|
-
The first date in the timeseries.
|
79
|
+
"""The first date in the timeseries.
|
81
80
|
|
82
81
|
Returns
|
83
82
|
-------
|
@@ -89,8 +88,7 @@ class _CommonModel(BaseModel):
|
|
89
88
|
|
90
89
|
@property
|
91
90
|
def last_idx(self: Self) -> dt.date:
|
92
|
-
"""
|
93
|
-
The last date in the timeseries.
|
91
|
+
"""The last date in the timeseries.
|
94
92
|
|
95
93
|
Returns
|
96
94
|
-------
|
@@ -102,8 +100,7 @@ class _CommonModel(BaseModel):
|
|
102
100
|
|
103
101
|
@property
|
104
102
|
def span_of_days(self: Self) -> int:
|
105
|
-
"""
|
106
|
-
Number of days from the first date to the last.
|
103
|
+
"""Number of days from the first date to the last.
|
107
104
|
|
108
105
|
Returns
|
109
106
|
-------
|
@@ -115,8 +112,7 @@ class _CommonModel(BaseModel):
|
|
115
112
|
|
116
113
|
@property
|
117
114
|
def yearfrac(self: Self) -> float:
|
118
|
-
"""
|
119
|
-
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.
|
120
116
|
|
121
117
|
Returns
|
122
118
|
-------
|
@@ -129,8 +125,7 @@ class _CommonModel(BaseModel):
|
|
129
125
|
|
130
126
|
@property
|
131
127
|
def periods_in_a_year(self: Self) -> float:
|
132
|
-
"""
|
133
|
-
The average number of observations per year.
|
128
|
+
"""The average number of observations per year.
|
134
129
|
|
135
130
|
Returns
|
136
131
|
-------
|
@@ -141,13 +136,12 @@ class _CommonModel(BaseModel):
|
|
141
136
|
return self.length / self.yearfrac
|
142
137
|
|
143
138
|
@property
|
144
|
-
def max_drawdown_cal_year(self: Self) ->
|
145
|
-
"""
|
146
|
-
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.
|
147
141
|
|
148
142
|
Returns
|
149
143
|
-------
|
150
|
-
|
144
|
+
float | Pandas.Series[float]
|
151
145
|
Maximum drawdown in a single calendar year.
|
152
146
|
|
153
147
|
"""
|
@@ -170,64 +164,59 @@ class _CommonModel(BaseModel):
|
|
170
164
|
)
|
171
165
|
|
172
166
|
@property
|
173
|
-
def geo_ret(self: Self) ->
|
174
|
-
"""
|
175
|
-
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.
|
176
169
|
|
177
170
|
Returns
|
178
171
|
-------
|
179
|
-
|
172
|
+
float | Pandas.Series[float]
|
180
173
|
Compounded Annual Growth Rate (CAGR)
|
181
174
|
|
182
175
|
"""
|
183
176
|
return self.geo_ret_func()
|
184
177
|
|
185
178
|
@property
|
186
|
-
def arithmetic_ret(self: Self) ->
|
187
|
-
"""
|
188
|
-
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.
|
189
181
|
|
190
182
|
Returns
|
191
183
|
-------
|
192
|
-
|
184
|
+
float | Pandas.Series[float]
|
193
185
|
Annualized arithmetic mean of returns
|
194
186
|
|
195
187
|
"""
|
196
188
|
return self.arithmetic_ret_func()
|
197
189
|
|
198
190
|
@property
|
199
|
-
def value_ret(self: Self) ->
|
200
|
-
"""
|
201
|
-
Simple return.
|
191
|
+
def value_ret(self: Self) -> float | Series[float]:
|
192
|
+
"""Simple return.
|
202
193
|
|
203
194
|
Returns
|
204
195
|
-------
|
205
|
-
|
196
|
+
float | Pandas.Series[float]
|
206
197
|
Simple return
|
207
198
|
|
208
199
|
"""
|
209
200
|
return self.value_ret_func()
|
210
201
|
|
211
202
|
@property
|
212
|
-
def vol(self: Self) ->
|
213
|
-
"""
|
214
|
-
Annualized volatility.
|
203
|
+
def vol(self: Self) -> float | Series[float]:
|
204
|
+
"""Annualized volatility.
|
215
205
|
|
216
206
|
Based on Pandas .std() which is the equivalent of stdev.s([...]) in MS Excel.
|
217
207
|
https://www.investopedia.com/terms/v/volatility.asp.
|
218
208
|
|
219
209
|
Returns
|
220
210
|
-------
|
221
|
-
|
211
|
+
float | Pandas.Series[float]
|
222
212
|
Annualized volatility
|
223
213
|
|
224
214
|
"""
|
225
215
|
return self.vol_func()
|
226
216
|
|
227
217
|
@property
|
228
|
-
def downside_deviation(self: Self) ->
|
229
|
-
"""
|
230
|
-
Downside Deviation.
|
218
|
+
def downside_deviation(self: Self) -> float | Series[float]:
|
219
|
+
"""Downside Deviation.
|
231
220
|
|
232
221
|
Standard deviation of returns that are below a Minimum Accepted Return
|
233
222
|
of zero. It is used to calculate the Sortino Ratio.
|
@@ -235,7 +224,7 @@ class _CommonModel(BaseModel):
|
|
235
224
|
|
236
225
|
Returns
|
237
226
|
-------
|
238
|
-
|
227
|
+
float | Pandas.Series[float]
|
239
228
|
Downside deviation
|
240
229
|
|
241
230
|
"""
|
@@ -243,13 +232,12 @@ class _CommonModel(BaseModel):
|
|
243
232
|
return self.downside_deviation_func(min_accepted_return=min_accepted_return)
|
244
233
|
|
245
234
|
@property
|
246
|
-
def ret_vol_ratio(self: Self) ->
|
247
|
-
"""
|
248
|
-
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.
|
249
237
|
|
250
238
|
Returns
|
251
239
|
-------
|
252
|
-
|
240
|
+
float | Pandas.Series[float]
|
253
241
|
Ratio of the annualized arithmetic mean of returns and annualized
|
254
242
|
volatility.
|
255
243
|
|
@@ -258,13 +246,12 @@ class _CommonModel(BaseModel):
|
|
258
246
|
return self.ret_vol_ratio_func(riskfree_rate=riskfree_rate)
|
259
247
|
|
260
248
|
@property
|
261
|
-
def sortino_ratio(self: Self) ->
|
262
|
-
"""
|
263
|
-
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.
|
264
251
|
|
265
252
|
Returns
|
266
253
|
-------
|
267
|
-
|
254
|
+
float | Pandas.Series[float]
|
268
255
|
Sortino ratio calculated as the annualized arithmetic mean of returns
|
269
256
|
/ downside deviation. The ratio implies that the riskfree asset has zero
|
270
257
|
volatility, and a minimum acceptable return of zero.
|
@@ -278,13 +265,12 @@ class _CommonModel(BaseModel):
|
|
278
265
|
)
|
279
266
|
|
280
267
|
@property
|
281
|
-
def omega_ratio(self: Self) ->
|
282
|
-
"""
|
283
|
-
https://en.wikipedia.org/wiki/Omega_ratio.
|
268
|
+
def omega_ratio(self: Self) -> float | Series[float]:
|
269
|
+
"""https://en.wikipedia.org/wiki/Omega_ratio.
|
284
270
|
|
285
271
|
Returns
|
286
272
|
-------
|
287
|
-
|
273
|
+
float | Pandas.Series[float]
|
288
274
|
Omega ratio calculation
|
289
275
|
|
290
276
|
"""
|
@@ -292,41 +278,38 @@ class _CommonModel(BaseModel):
|
|
292
278
|
return self.omega_ratio_func(min_accepted_return=minimum_accepted_return)
|
293
279
|
|
294
280
|
@property
|
295
|
-
def z_score(self: Self) ->
|
296
|
-
"""
|
297
|
-
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.
|
298
283
|
|
299
284
|
Returns
|
300
285
|
-------
|
301
|
-
|
286
|
+
float | Pandas.Series[float]
|
302
287
|
Z-score as (last return - mean return) / standard deviation of returns.
|
303
288
|
|
304
289
|
"""
|
305
290
|
return self.z_score_func()
|
306
291
|
|
307
292
|
@property
|
308
|
-
def max_drawdown(self: Self) ->
|
309
|
-
"""
|
310
|
-
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.
|
311
295
|
|
312
296
|
Returns
|
313
297
|
-------
|
314
|
-
|
298
|
+
float | Pandas.Series[float]
|
315
299
|
Maximum drawdown without any limit on date range
|
316
300
|
|
317
301
|
"""
|
318
302
|
return self.max_drawdown_func()
|
319
303
|
|
320
304
|
@property
|
321
|
-
def max_drawdown_date(self: Self) ->
|
322
|
-
"""
|
323
|
-
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.
|
324
307
|
|
325
308
|
https://www.investopedia.com/terms/m/maximum-drawdown-mdd.asp.
|
326
309
|
|
327
310
|
Returns
|
328
311
|
-------
|
329
|
-
|
312
|
+
datetime.date | pandas.Series[dt.date]
|
330
313
|
Date when the maximum drawdown occurred
|
331
314
|
|
332
315
|
"""
|
@@ -344,13 +327,12 @@ class _CommonModel(BaseModel):
|
|
344
327
|
).dt.date
|
345
328
|
|
346
329
|
@property
|
347
|
-
def worst(self: Self) ->
|
348
|
-
"""
|
349
|
-
Most negative percentage change.
|
330
|
+
def worst(self: Self) -> float | Series[float]:
|
331
|
+
"""Most negative percentage change.
|
350
332
|
|
351
333
|
Returns
|
352
334
|
-------
|
353
|
-
|
335
|
+
float | Pandas.Series[float]
|
354
336
|
Most negative percentage change
|
355
337
|
|
356
338
|
"""
|
@@ -358,9 +340,8 @@ class _CommonModel(BaseModel):
|
|
358
340
|
return self.worst_func(observations=observations)
|
359
341
|
|
360
342
|
@property
|
361
|
-
def worst_month(self: Self) ->
|
362
|
-
"""
|
363
|
-
Most negative month.
|
343
|
+
def worst_month(self: Self) -> float | Series[float]:
|
344
|
+
"""Most negative month.
|
364
345
|
|
365
346
|
Returns
|
366
347
|
-------
|
@@ -384,52 +365,48 @@ class _CommonModel(BaseModel):
|
|
384
365
|
)
|
385
366
|
|
386
367
|
@property
|
387
|
-
def positive_share(self: Self) ->
|
388
|
-
"""
|
389
|
-
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.
|
390
370
|
|
391
371
|
Returns
|
392
372
|
-------
|
393
|
-
|
373
|
+
float | Pandas.Series[float]
|
394
374
|
The share of percentage changes that are greater than zero
|
395
375
|
|
396
376
|
"""
|
397
377
|
return self.positive_share_func()
|
398
378
|
|
399
379
|
@property
|
400
|
-
def skew(self: Self) ->
|
401
|
-
"""
|
402
|
-
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.
|
403
382
|
|
404
383
|
Returns
|
405
384
|
-------
|
406
|
-
|
385
|
+
float | Pandas.Series[float]
|
407
386
|
Skew of the return distribution
|
408
387
|
|
409
388
|
"""
|
410
389
|
return self.skew_func()
|
411
390
|
|
412
391
|
@property
|
413
|
-
def kurtosis(self: Self) ->
|
414
|
-
"""
|
415
|
-
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.
|
416
394
|
|
417
395
|
Returns
|
418
396
|
-------
|
419
|
-
|
397
|
+
float | Pandas.Series[float]
|
420
398
|
Kurtosis of the return distribution
|
421
399
|
|
422
400
|
"""
|
423
401
|
return self.kurtosis_func()
|
424
402
|
|
425
403
|
@property
|
426
|
-
def cvar_down(self: Self) ->
|
427
|
-
"""
|
428
|
-
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.
|
429
406
|
|
430
407
|
Returns
|
431
408
|
-------
|
432
|
-
|
409
|
+
float | Pandas.Series[float]
|
433
410
|
Downside 95% Conditional Value At Risk "CVaR"
|
434
411
|
|
435
412
|
"""
|
@@ -437,16 +414,15 @@ class _CommonModel(BaseModel):
|
|
437
414
|
return self.cvar_down_func(level=level)
|
438
415
|
|
439
416
|
@property
|
440
|
-
def var_down(self: Self) ->
|
441
|
-
"""
|
442
|
-
Downside 95% Value At Risk (VaR).
|
417
|
+
def var_down(self: Self) -> float | Series[float]:
|
418
|
+
"""Downside 95% Value At Risk (VaR).
|
443
419
|
|
444
420
|
The equivalent of percentile.inc([...], 1-level) over returns in MS Excel.
|
445
421
|
https://www.investopedia.com/terms/v/var.asp.
|
446
422
|
|
447
423
|
Returns
|
448
424
|
-------
|
449
|
-
|
425
|
+
float | Pandas.Series[float]
|
450
426
|
Downside 95% Value At Risk (VaR)
|
451
427
|
|
452
428
|
"""
|
@@ -455,15 +431,14 @@ class _CommonModel(BaseModel):
|
|
455
431
|
return self.var_down_func(level=level, interpolation=interpolation)
|
456
432
|
|
457
433
|
@property
|
458
|
-
def vol_from_var(self: Self) ->
|
459
|
-
"""
|
460
|
-
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.
|
461
436
|
|
462
437
|
Assumes that returns are normally distributed.
|
463
438
|
|
464
439
|
Returns
|
465
440
|
-------
|
466
|
-
|
441
|
+
float | Pandas.Series[float]
|
467
442
|
Implied annualized volatility from the Downside 95% VaR using the
|
468
443
|
assumption that returns are normally distributed.
|
469
444
|
|
@@ -472,14 +447,13 @@ class _CommonModel(BaseModel):
|
|
472
447
|
interpolation: LiteralQuantileInterp = "lower"
|
473
448
|
return self.vol_from_var_func(level=level, interpolation=interpolation)
|
474
449
|
|
475
|
-
def calc_range(
|
450
|
+
def calc_range(
|
476
451
|
self: Self,
|
477
|
-
months_offset:
|
478
|
-
from_dt:
|
479
|
-
to_dt:
|
452
|
+
months_offset: int | None = None,
|
453
|
+
from_dt: dt.date | None = None,
|
454
|
+
to_dt: dt.date | None = None,
|
480
455
|
) -> tuple[dt.date, dt.date]:
|
481
|
-
"""
|
482
|
-
Create user defined date range.
|
456
|
+
"""Create user defined date range.
|
483
457
|
|
484
458
|
Parameters
|
485
459
|
----------
|
@@ -497,42 +471,38 @@ class _CommonModel(BaseModel):
|
|
497
471
|
Start and end date of the chosen date range
|
498
472
|
|
499
473
|
"""
|
500
|
-
earlier, later = self.
|
501
|
-
if
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
474
|
+
earlier, later = self.first_idx, self.last_idx
|
475
|
+
if months_offset is not None:
|
476
|
+
earlier = date_offset_foll(
|
477
|
+
raw_date=self.last_idx,
|
478
|
+
months_offset=-months_offset,
|
479
|
+
adjust=False,
|
480
|
+
following=True,
|
481
|
+
)
|
482
|
+
if earlier < self.first_idx:
|
483
|
+
msg = (
|
484
|
+
"Argument months_offset implies start"
|
485
|
+
"date before first date in series."
|
508
486
|
)
|
509
|
-
|
510
|
-
msg
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
if from_dt < self.tsdf.index[0]:
|
487
|
+
raise ValueError(
|
488
|
+
msg,
|
489
|
+
)
|
490
|
+
later = self.last_idx
|
491
|
+
else:
|
492
|
+
if from_dt is not None:
|
493
|
+
if from_dt < self.first_idx:
|
517
494
|
msg = "Given from_dt date < series start"
|
518
495
|
raise ValueError(msg)
|
519
|
-
earlier
|
520
|
-
|
521
|
-
if to_dt > self.
|
496
|
+
earlier = from_dt
|
497
|
+
if to_dt is not None:
|
498
|
+
if to_dt > self.last_idx:
|
522
499
|
msg = "Given to_dt date > series end"
|
523
500
|
raise ValueError(msg)
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
msg,
|
530
|
-
)
|
531
|
-
earlier, later = from_dt, to_dt
|
532
|
-
while earlier not in self.tsdf.index.tolist():
|
533
|
-
earlier -= dt.timedelta(days=1)
|
534
|
-
while later not in self.tsdf.index.tolist():
|
535
|
-
later += dt.timedelta(days=1)
|
501
|
+
later = to_dt
|
502
|
+
while earlier not in self.tsdf.index:
|
503
|
+
earlier -= dt.timedelta(days=1)
|
504
|
+
while later not in self.tsdf.index:
|
505
|
+
later += dt.timedelta(days=1)
|
536
506
|
|
537
507
|
return earlier, later
|
538
508
|
|
@@ -540,8 +510,7 @@ class _CommonModel(BaseModel):
|
|
540
510
|
self: Self,
|
541
511
|
countries: CountriesType = "SE",
|
542
512
|
) -> Self:
|
543
|
-
"""
|
544
|
-
Align the index of .tsdf with local calendar business days.
|
513
|
+
"""Align the index of .tsdf with local calendar business days.
|
545
514
|
|
546
515
|
Parameters
|
547
516
|
----------
|
@@ -575,8 +544,7 @@ class _CommonModel(BaseModel):
|
|
575
544
|
return self
|
576
545
|
|
577
546
|
def value_to_log(self: Self) -> Self:
|
578
|
-
"""
|
579
|
-
Series of values converted into logarithmic weighted series.
|
547
|
+
"""Series of values converted into logarithmic weighted series.
|
580
548
|
|
581
549
|
Equivalent to LN(value[t] / value[t=0]) in Excel.
|
582
550
|
|
@@ -594,8 +562,7 @@ class _CommonModel(BaseModel):
|
|
594
562
|
return self
|
595
563
|
|
596
564
|
def value_nan_handle(self: Self, method: LiteralNanMethod = "fill") -> Self:
|
597
|
-
"""
|
598
|
-
Handle missing values in a valueseries.
|
565
|
+
"""Handle missing values in a valueseries.
|
599
566
|
|
600
567
|
Parameters
|
601
568
|
----------
|
@@ -615,8 +582,7 @@ class _CommonModel(BaseModel):
|
|
615
582
|
return self
|
616
583
|
|
617
584
|
def return_nan_handle(self: Self, method: LiteralNanMethod = "fill") -> Self:
|
618
|
-
"""
|
619
|
-
Handle missing values in a returnseries.
|
585
|
+
"""Handle missing values in a returnseries.
|
620
586
|
|
621
587
|
Parameters
|
622
588
|
----------
|
@@ -636,8 +602,7 @@ class _CommonModel(BaseModel):
|
|
636
602
|
return self
|
637
603
|
|
638
604
|
def to_drawdown_series(self: Self) -> Self:
|
639
|
-
"""
|
640
|
-
Convert timeseries into a drawdown series.
|
605
|
+
"""Convert timeseries into a drawdown series.
|
641
606
|
|
642
607
|
Returns
|
643
608
|
-------
|
@@ -655,10 +620,9 @@ class _CommonModel(BaseModel):
|
|
655
620
|
self: Self,
|
656
621
|
what_output: LiteralJsonOutput,
|
657
622
|
filename: str,
|
658
|
-
directory:
|
659
|
-
) -> list[dict[str,
|
660
|
-
"""
|
661
|
-
Dump timeseries data into a json file.
|
623
|
+
directory: DirectoryPath | None = None,
|
624
|
+
) -> list[dict[str, str | bool | ValueType | list[str] | list[float]]]:
|
625
|
+
"""Dump timeseries data into a json file.
|
662
626
|
|
663
627
|
Parameters
|
664
628
|
----------
|
@@ -672,7 +636,7 @@ class _CommonModel(BaseModel):
|
|
672
636
|
|
673
637
|
Returns
|
674
638
|
-------
|
675
|
-
list[
|
639
|
+
list[dict[str, str | bool | ValueType | list[str] | list[float]]]
|
676
640
|
A list of dictionaries with the data of the series
|
677
641
|
|
678
642
|
"""
|
@@ -719,13 +683,12 @@ class _CommonModel(BaseModel):
|
|
719
683
|
def to_xlsx(
|
720
684
|
self: Self,
|
721
685
|
filename: str,
|
722
|
-
sheet_title:
|
723
|
-
directory:
|
686
|
+
sheet_title: str | None = None,
|
687
|
+
directory: DirectoryPath | None = None,
|
724
688
|
*,
|
725
689
|
overwrite: bool = True,
|
726
690
|
) -> str:
|
727
|
-
"""
|
728
|
-
Save .tsdf DataFrame to an Excel spreadsheet file.
|
691
|
+
"""Save .tsdf DataFrame to an Excel spreadsheet file.
|
729
692
|
|
730
693
|
Parameters
|
731
694
|
----------
|
@@ -777,18 +740,17 @@ class _CommonModel(BaseModel):
|
|
777
740
|
def plot_bars(
|
778
741
|
self: Self,
|
779
742
|
mode: LiteralBarPlotMode = "group",
|
780
|
-
tick_fmt:
|
781
|
-
filename:
|
782
|
-
directory:
|
783
|
-
labels:
|
743
|
+
tick_fmt: str | None = None,
|
744
|
+
filename: str | None = None,
|
745
|
+
directory: DirectoryPath | None = None,
|
746
|
+
labels: list[str] | None = None,
|
784
747
|
output_type: LiteralPlotlyOutput = "file",
|
785
748
|
include_plotlyjs: LiteralPlotlyJSlib = "cdn",
|
786
749
|
*,
|
787
750
|
auto_open: bool = True,
|
788
751
|
add_logo: bool = True,
|
789
752
|
) -> tuple[Figure, str]:
|
790
|
-
"""
|
791
|
-
Create a Plotly Bar Figure.
|
753
|
+
"""Create a Plotly Bar Figure.
|
792
754
|
|
793
755
|
Parameters
|
794
756
|
----------
|
@@ -892,10 +854,10 @@ class _CommonModel(BaseModel):
|
|
892
854
|
def plot_series( # noqa: C901
|
893
855
|
self: Self,
|
894
856
|
mode: LiteralLinePlotMode = "lines",
|
895
|
-
tick_fmt:
|
896
|
-
filename:
|
897
|
-
directory:
|
898
|
-
labels:
|
857
|
+
tick_fmt: str | None = None,
|
858
|
+
filename: str | None = None,
|
859
|
+
directory: DirectoryPath | None = None,
|
860
|
+
labels: list[str] | None = None,
|
899
861
|
output_type: LiteralPlotlyOutput = "file",
|
900
862
|
include_plotlyjs: LiteralPlotlyJSlib = "cdn",
|
901
863
|
*,
|
@@ -903,8 +865,7 @@ class _CommonModel(BaseModel):
|
|
903
865
|
add_logo: bool = True,
|
904
866
|
show_last: bool = False,
|
905
867
|
) -> tuple[Figure, str]:
|
906
|
-
"""
|
907
|
-
Create a Plotly Scatter Figure.
|
868
|
+
"""Create a Plotly Scatter Figure.
|
908
869
|
|
909
870
|
Parameters
|
910
871
|
----------
|
@@ -1024,13 +985,12 @@ class _CommonModel(BaseModel):
|
|
1024
985
|
|
1025
986
|
def arithmetic_ret_func(
|
1026
987
|
self: Self,
|
1027
|
-
months_from_last:
|
1028
|
-
from_date:
|
1029
|
-
to_date:
|
1030
|
-
periods_in_a_year_fixed:
|
1031
|
-
) ->
|
1032
|
-
"""
|
1033
|
-
https://www.investopedia.com/terms/a/arithmeticmean.asp.
|
988
|
+
months_from_last: int | None = None,
|
989
|
+
from_date: dt.date | None = None,
|
990
|
+
to_date: dt.date | None = None,
|
991
|
+
periods_in_a_year_fixed: DaysInYearType | None = None,
|
992
|
+
) -> float | Series[float]:
|
993
|
+
"""https://www.investopedia.com/terms/a/arithmeticmean.asp.
|
1034
994
|
|
1035
995
|
Parameters
|
1036
996
|
----------
|
@@ -1047,7 +1007,7 @@ class _CommonModel(BaseModel):
|
|
1047
1007
|
|
1048
1008
|
Returns
|
1049
1009
|
-------
|
1050
|
-
|
1010
|
+
float | Pandas.Series[float]
|
1051
1011
|
Annualized arithmetic mean of returns
|
1052
1012
|
|
1053
1013
|
"""
|
@@ -1084,13 +1044,12 @@ class _CommonModel(BaseModel):
|
|
1084
1044
|
|
1085
1045
|
def vol_func(
|
1086
1046
|
self: Self,
|
1087
|
-
months_from_last:
|
1088
|
-
from_date:
|
1089
|
-
to_date:
|
1090
|
-
periods_in_a_year_fixed:
|
1091
|
-
) ->
|
1092
|
-
"""
|
1093
|
-
Annualized volatility.
|
1047
|
+
months_from_last: int | None = None,
|
1048
|
+
from_date: dt.date | None = None,
|
1049
|
+
to_date: dt.date | None = None,
|
1050
|
+
periods_in_a_year_fixed: DaysInYearType | None = None,
|
1051
|
+
) -> float | Series[float]:
|
1052
|
+
"""Annualized volatility.
|
1094
1053
|
|
1095
1054
|
Based on Pandas .std() which is the equivalent of stdev.s([...]) in MS Excel.
|
1096
1055
|
https://www.investopedia.com/terms/v/volatility.asp.
|
@@ -1109,7 +1068,7 @@ class _CommonModel(BaseModel):
|
|
1109
1068
|
|
1110
1069
|
Returns
|
1111
1070
|
-------
|
1112
|
-
|
1071
|
+
float | Pandas.Series[float]
|
1113
1072
|
Annualized volatility
|
1114
1073
|
|
1115
1074
|
"""
|
@@ -1144,16 +1103,15 @@ class _CommonModel(BaseModel):
|
|
1144
1103
|
def vol_from_var_func(
|
1145
1104
|
self: Self,
|
1146
1105
|
level: float = 0.95,
|
1147
|
-
months_from_last:
|
1148
|
-
from_date:
|
1149
|
-
to_date:
|
1106
|
+
months_from_last: int | None = None,
|
1107
|
+
from_date: dt.date | None = None,
|
1108
|
+
to_date: dt.date | None = None,
|
1150
1109
|
interpolation: LiteralQuantileInterp = "lower",
|
1151
|
-
periods_in_a_year_fixed:
|
1110
|
+
periods_in_a_year_fixed: DaysInYearType | None = None,
|
1152
1111
|
*,
|
1153
1112
|
drift_adjust: bool = False,
|
1154
|
-
) ->
|
1155
|
-
"""
|
1156
|
-
Implied annualized volatility.
|
1113
|
+
) -> float | Series[float]:
|
1114
|
+
"""Implied annualized volatility.
|
1157
1115
|
|
1158
1116
|
Implied annualized volatility from the Downside VaR using the assumption
|
1159
1117
|
that returns are normally distributed.
|
@@ -1179,7 +1137,7 @@ class _CommonModel(BaseModel):
|
|
1179
1137
|
|
1180
1138
|
Returns
|
1181
1139
|
-------
|
1182
|
-
|
1140
|
+
float | Pandas.Series[float]
|
1183
1141
|
Implied annualized volatility from the Downside VaR using the
|
1184
1142
|
assumption that returns are normally distributed.
|
1185
1143
|
|
@@ -1200,16 +1158,15 @@ class _CommonModel(BaseModel):
|
|
1200
1158
|
level: float = 0.95,
|
1201
1159
|
min_leverage_local: float = 0.0,
|
1202
1160
|
max_leverage_local: float = 99999.0,
|
1203
|
-
months_from_last:
|
1204
|
-
from_date:
|
1205
|
-
to_date:
|
1161
|
+
months_from_last: int | None = None,
|
1162
|
+
from_date: dt.date | None = None,
|
1163
|
+
to_date: dt.date | None = None,
|
1206
1164
|
interpolation: LiteralQuantileInterp = "lower",
|
1207
|
-
periods_in_a_year_fixed:
|
1165
|
+
periods_in_a_year_fixed: DaysInYearType | None = None,
|
1208
1166
|
*,
|
1209
1167
|
drift_adjust: bool = False,
|
1210
|
-
) ->
|
1211
|
-
"""
|
1212
|
-
Target weight from VaR.
|
1168
|
+
) -> float | Series[float]:
|
1169
|
+
"""Target weight from VaR.
|
1213
1170
|
|
1214
1171
|
A position weight multiplier from the ratio between a VaR implied
|
1215
1172
|
volatility and a given target volatility. Multiplier = 1.0 -> target met.
|
@@ -1241,7 +1198,7 @@ class _CommonModel(BaseModel):
|
|
1241
1198
|
|
1242
1199
|
Returns
|
1243
1200
|
-------
|
1244
|
-
|
1201
|
+
float | Pandas.Series[float]
|
1245
1202
|
A position weight multiplier from the ratio between a VaR implied
|
1246
1203
|
volatility and a given target volatility. Multiplier = 1.0 -> target met
|
1247
1204
|
|
@@ -1262,19 +1219,18 @@ class _CommonModel(BaseModel):
|
|
1262
1219
|
def _var_implied_vol_and_target_func(
|
1263
1220
|
self: Self,
|
1264
1221
|
level: float,
|
1265
|
-
target_vol:
|
1222
|
+
target_vol: float | None = None,
|
1266
1223
|
min_leverage_local: float = 0.0,
|
1267
1224
|
max_leverage_local: float = 99999.0,
|
1268
|
-
months_from_last:
|
1269
|
-
from_date:
|
1270
|
-
to_date:
|
1225
|
+
months_from_last: int | None = None,
|
1226
|
+
from_date: dt.date | None = None,
|
1227
|
+
to_date: dt.date | None = None,
|
1271
1228
|
interpolation: LiteralQuantileInterp = "lower",
|
1272
|
-
periods_in_a_year_fixed:
|
1229
|
+
periods_in_a_year_fixed: DaysInYearType | None = None,
|
1273
1230
|
*,
|
1274
1231
|
drift_adjust: bool = False,
|
1275
|
-
) ->
|
1276
|
-
"""
|
1277
|
-
Volatility implied from VaR or Target Weight.
|
1232
|
+
) -> float | Series[float]:
|
1233
|
+
"""Volatility implied from VaR or Target Weight.
|
1278
1234
|
|
1279
1235
|
The function returns a position weight multiplier from the ratio between
|
1280
1236
|
a VaR implied volatility and a given target volatility if the argument
|
@@ -1285,7 +1241,7 @@ class _CommonModel(BaseModel):
|
|
1285
1241
|
----------
|
1286
1242
|
level: float
|
1287
1243
|
The sought VaR level
|
1288
|
-
target_vol:
|
1244
|
+
target_vol: float | None
|
1289
1245
|
Target Volatility
|
1290
1246
|
min_leverage_local: float, default: 0.0
|
1291
1247
|
A minimum adjustment factor
|
@@ -1308,7 +1264,7 @@ class _CommonModel(BaseModel):
|
|
1308
1264
|
|
1309
1265
|
Returns
|
1310
1266
|
-------
|
1311
|
-
|
1267
|
+
float | Pandas.Series[float]
|
1312
1268
|
Target volatility if target_vol is provided otherwise the VaR
|
1313
1269
|
implied volatility.
|
1314
1270
|
|
@@ -1373,12 +1329,11 @@ class _CommonModel(BaseModel):
|
|
1373
1329
|
def cvar_down_func(
|
1374
1330
|
self: Self,
|
1375
1331
|
level: float = 0.95,
|
1376
|
-
months_from_last:
|
1377
|
-
from_date:
|
1378
|
-
to_date:
|
1379
|
-
) ->
|
1380
|
-
"""
|
1381
|
-
Downside Conditional Value At Risk "CVaR".
|
1332
|
+
months_from_last: int | None = None,
|
1333
|
+
from_date: dt.date | None = None,
|
1334
|
+
to_date: dt.date | None = None,
|
1335
|
+
) -> float | Series[float]:
|
1336
|
+
"""Downside Conditional Value At Risk "CVaR".
|
1382
1337
|
|
1383
1338
|
https://www.investopedia.com/terms/c/conditional_value_at_risk.asp.
|
1384
1339
|
|
@@ -1396,7 +1351,7 @@ class _CommonModel(BaseModel):
|
|
1396
1351
|
|
1397
1352
|
Returns
|
1398
1353
|
-------
|
1399
|
-
|
1354
|
+
float | Pandas.Series[float]
|
1400
1355
|
Downside Conditional Value At Risk "CVaR"
|
1401
1356
|
|
1402
1357
|
"""
|
@@ -1435,13 +1390,12 @@ class _CommonModel(BaseModel):
|
|
1435
1390
|
def downside_deviation_func(
|
1436
1391
|
self: Self,
|
1437
1392
|
min_accepted_return: float = 0.0,
|
1438
|
-
months_from_last:
|
1439
|
-
from_date:
|
1440
|
-
to_date:
|
1441
|
-
periods_in_a_year_fixed:
|
1442
|
-
) ->
|
1443
|
-
"""
|
1444
|
-
Downside Deviation.
|
1393
|
+
months_from_last: int | None = None,
|
1394
|
+
from_date: dt.date | None = None,
|
1395
|
+
to_date: dt.date | None = None,
|
1396
|
+
periods_in_a_year_fixed: DaysInYearType | None = None,
|
1397
|
+
) -> float | Series[float]:
|
1398
|
+
"""Downside Deviation.
|
1445
1399
|
|
1446
1400
|
The standard deviation of returns that are below a Minimum Accepted
|
1447
1401
|
Return of zero. It is used to calculate the Sortino Ratio.
|
@@ -1464,7 +1418,7 @@ class _CommonModel(BaseModel):
|
|
1464
1418
|
|
1465
1419
|
Returns
|
1466
1420
|
-------
|
1467
|
-
|
1421
|
+
float | Pandas.Series[float]
|
1468
1422
|
Downside deviation
|
1469
1423
|
|
1470
1424
|
"""
|
@@ -1510,12 +1464,11 @@ class _CommonModel(BaseModel):
|
|
1510
1464
|
|
1511
1465
|
def geo_ret_func(
|
1512
1466
|
self: Self,
|
1513
|
-
months_from_last:
|
1514
|
-
from_date:
|
1515
|
-
to_date:
|
1516
|
-
) ->
|
1517
|
-
"""
|
1518
|
-
Compounded Annual Growth Rate (CAGR).
|
1467
|
+
months_from_last: int | None = None,
|
1468
|
+
from_date: dt.date | None = None,
|
1469
|
+
to_date: dt.date | None = None,
|
1470
|
+
) -> float | Series[float]:
|
1471
|
+
"""Compounded Annual Growth Rate (CAGR).
|
1519
1472
|
|
1520
1473
|
https://www.investopedia.com/terms/c/cagr.asp.
|
1521
1474
|
|
@@ -1531,7 +1484,7 @@ class _CommonModel(BaseModel):
|
|
1531
1484
|
|
1532
1485
|
Returns
|
1533
1486
|
-------
|
1534
|
-
|
1487
|
+
float | Pandas.Series[float]
|
1535
1488
|
Compounded Annual Growth Rate (CAGR)
|
1536
1489
|
|
1537
1490
|
"""
|
@@ -1564,12 +1517,11 @@ class _CommonModel(BaseModel):
|
|
1564
1517
|
|
1565
1518
|
def skew_func(
|
1566
1519
|
self: Self,
|
1567
|
-
months_from_last:
|
1568
|
-
from_date:
|
1569
|
-
to_date:
|
1570
|
-
) ->
|
1571
|
-
"""
|
1572
|
-
Skew of the return distribution.
|
1520
|
+
months_from_last: int | None = None,
|
1521
|
+
from_date: dt.date | None = None,
|
1522
|
+
to_date: dt.date | None = None,
|
1523
|
+
) -> float | Series[float]:
|
1524
|
+
"""Skew of the return distribution.
|
1573
1525
|
|
1574
1526
|
https://www.investopedia.com/terms/s/skewness.asp.
|
1575
1527
|
|
@@ -1585,7 +1537,7 @@ class _CommonModel(BaseModel):
|
|
1585
1537
|
|
1586
1538
|
Returns
|
1587
1539
|
-------
|
1588
|
-
|
1540
|
+
float | Pandas.Series[float]
|
1589
1541
|
Skew of the return distribution
|
1590
1542
|
|
1591
1543
|
"""
|
@@ -1613,12 +1565,11 @@ class _CommonModel(BaseModel):
|
|
1613
1565
|
|
1614
1566
|
def kurtosis_func(
|
1615
1567
|
self: Self,
|
1616
|
-
months_from_last:
|
1617
|
-
from_date:
|
1618
|
-
to_date:
|
1619
|
-
) ->
|
1620
|
-
"""
|
1621
|
-
Kurtosis of the return distribution.
|
1568
|
+
months_from_last: int | None = None,
|
1569
|
+
from_date: dt.date | None = None,
|
1570
|
+
to_date: dt.date | None = None,
|
1571
|
+
) -> float | Series[float]:
|
1572
|
+
"""Kurtosis of the return distribution.
|
1622
1573
|
|
1623
1574
|
https://www.investopedia.com/terms/k/kurtosis.asp.
|
1624
1575
|
|
@@ -1634,7 +1585,7 @@ class _CommonModel(BaseModel):
|
|
1634
1585
|
|
1635
1586
|
Returns
|
1636
1587
|
-------
|
1637
|
-
|
1588
|
+
float | Pandas.Series[float]
|
1638
1589
|
Kurtosis of the return distribution
|
1639
1590
|
|
1640
1591
|
"""
|
@@ -1663,13 +1614,12 @@ class _CommonModel(BaseModel):
|
|
1663
1614
|
|
1664
1615
|
def max_drawdown_func(
|
1665
1616
|
self: Self,
|
1666
|
-
months_from_last:
|
1667
|
-
from_date:
|
1668
|
-
to_date:
|
1617
|
+
months_from_last: int | None = None,
|
1618
|
+
from_date: dt.date | None = None,
|
1619
|
+
to_date: dt.date | None = None,
|
1669
1620
|
min_periods: int = 1,
|
1670
|
-
) ->
|
1671
|
-
"""
|
1672
|
-
Maximum drawdown without any limit on date range.
|
1621
|
+
) -> float | Series[float]:
|
1622
|
+
"""Maximum drawdown without any limit on date range.
|
1673
1623
|
|
1674
1624
|
https://www.investopedia.com/terms/m/maximum-drawdown-mdd.asp.
|
1675
1625
|
|
@@ -1687,7 +1637,7 @@ class _CommonModel(BaseModel):
|
|
1687
1637
|
|
1688
1638
|
Returns
|
1689
1639
|
-------
|
1690
|
-
|
1640
|
+
float | Pandas.Series[float]
|
1691
1641
|
Maximum drawdown without any limit on date range
|
1692
1642
|
|
1693
1643
|
"""
|
@@ -1713,12 +1663,11 @@ class _CommonModel(BaseModel):
|
|
1713
1663
|
|
1714
1664
|
def positive_share_func(
|
1715
1665
|
self: Self,
|
1716
|
-
months_from_last:
|
1717
|
-
from_date:
|
1718
|
-
to_date:
|
1719
|
-
) ->
|
1720
|
-
"""
|
1721
|
-
Calculate share of percentage changes that are greater than zero.
|
1666
|
+
months_from_last: int | None = None,
|
1667
|
+
from_date: dt.date | None = None,
|
1668
|
+
to_date: dt.date | None = None,
|
1669
|
+
) -> float | Series[float]:
|
1670
|
+
"""Calculate share of percentage changes that are greater than zero.
|
1722
1671
|
|
1723
1672
|
Parameters
|
1724
1673
|
----------
|
@@ -1732,7 +1681,7 @@ class _CommonModel(BaseModel):
|
|
1732
1681
|
|
1733
1682
|
Returns
|
1734
1683
|
-------
|
1735
|
-
|
1684
|
+
float | Pandas.Series[float]
|
1736
1685
|
Calculate share of percentage changes that are greater than zero
|
1737
1686
|
|
1738
1687
|
"""
|
@@ -1770,13 +1719,12 @@ class _CommonModel(BaseModel):
|
|
1770
1719
|
def ret_vol_ratio_func(
|
1771
1720
|
self: Self,
|
1772
1721
|
riskfree_rate: float = 0.0,
|
1773
|
-
months_from_last:
|
1774
|
-
from_date:
|
1775
|
-
to_date:
|
1776
|
-
periods_in_a_year_fixed:
|
1777
|
-
) ->
|
1778
|
-
"""
|
1779
|
-
Ratio between arithmetic mean of returns and annualized volatility.
|
1722
|
+
months_from_last: int | None = None,
|
1723
|
+
from_date: dt.date | None = None,
|
1724
|
+
to_date: dt.date | None = None,
|
1725
|
+
periods_in_a_year_fixed: DaysInYearType | None = None,
|
1726
|
+
) -> float | Series[float]:
|
1727
|
+
"""Ratio between arithmetic mean of returns and annualized volatility.
|
1780
1728
|
|
1781
1729
|
The ratio of annualized arithmetic mean of returns and annualized
|
1782
1730
|
volatility or, if riskfree return provided, Sharpe ratio calculated
|
@@ -1801,7 +1749,7 @@ class _CommonModel(BaseModel):
|
|
1801
1749
|
|
1802
1750
|
Returns
|
1803
1751
|
-------
|
1804
|
-
|
1752
|
+
float | Pandas.Series[float]
|
1805
1753
|
Ratio of the annualized arithmetic mean of returns and annualized
|
1806
1754
|
volatility or, if risk-free return provided, Sharpe ratio
|
1807
1755
|
|
@@ -1834,13 +1782,12 @@ class _CommonModel(BaseModel):
|
|
1834
1782
|
self: Self,
|
1835
1783
|
riskfree_rate: float = 0.0,
|
1836
1784
|
min_accepted_return: float = 0.0,
|
1837
|
-
months_from_last:
|
1838
|
-
from_date:
|
1839
|
-
to_date:
|
1840
|
-
periods_in_a_year_fixed:
|
1841
|
-
) ->
|
1842
|
-
"""
|
1843
|
-
Sortino Ratio.
|
1785
|
+
months_from_last: int | None = None,
|
1786
|
+
from_date: dt.date | None = None,
|
1787
|
+
to_date: dt.date | None = None,
|
1788
|
+
periods_in_a_year_fixed: DaysInYearType | None = None,
|
1789
|
+
) -> float | Series[float]:
|
1790
|
+
"""Sortino Ratio.
|
1844
1791
|
|
1845
1792
|
The Sortino ratio calculated as ( return - risk free return )
|
1846
1793
|
/ downside deviation. The ratio implies that the riskfree asset has zero
|
@@ -1867,7 +1814,7 @@ class _CommonModel(BaseModel):
|
|
1867
1814
|
|
1868
1815
|
Returns
|
1869
1816
|
-------
|
1870
|
-
|
1817
|
+
float | Pandas.Series[float]
|
1871
1818
|
Sortino ratio calculated as ( return - riskfree return ) /
|
1872
1819
|
downside deviation (std dev of returns below MAR)
|
1873
1820
|
|
@@ -1900,12 +1847,11 @@ class _CommonModel(BaseModel):
|
|
1900
1847
|
def omega_ratio_func(
|
1901
1848
|
self: Self,
|
1902
1849
|
min_accepted_return: float = 0.0,
|
1903
|
-
months_from_last:
|
1904
|
-
from_date:
|
1905
|
-
to_date:
|
1906
|
-
) ->
|
1907
|
-
"""
|
1908
|
-
Omega Ratio.
|
1850
|
+
months_from_last: int | None = None,
|
1851
|
+
from_date: dt.date | None = None,
|
1852
|
+
to_date: dt.date | None = None,
|
1853
|
+
) -> float | Series[float]:
|
1854
|
+
"""Omega Ratio.
|
1909
1855
|
|
1910
1856
|
The Omega Ratio compares returns above a certain target level
|
1911
1857
|
(often referred to as the “minimum acceptable return” or “MAR”)
|
@@ -1926,7 +1872,7 @@ class _CommonModel(BaseModel):
|
|
1926
1872
|
|
1927
1873
|
Returns
|
1928
1874
|
-------
|
1929
|
-
|
1875
|
+
float | Pandas.Series[float]
|
1930
1876
|
Omega ratio calculation
|
1931
1877
|
|
1932
1878
|
"""
|
@@ -1953,12 +1899,11 @@ class _CommonModel(BaseModel):
|
|
1953
1899
|
|
1954
1900
|
def value_ret_func(
|
1955
1901
|
self: Self,
|
1956
|
-
months_from_last:
|
1957
|
-
from_date:
|
1958
|
-
to_date:
|
1959
|
-
) ->
|
1960
|
-
"""
|
1961
|
-
Calculate simple return.
|
1902
|
+
months_from_last: int | None = None,
|
1903
|
+
from_date: dt.date | None = None,
|
1904
|
+
to_date: dt.date | None = None,
|
1905
|
+
) -> float | Series[float]:
|
1906
|
+
"""Calculate simple return.
|
1962
1907
|
|
1963
1908
|
Parameters
|
1964
1909
|
----------
|
@@ -1972,7 +1917,7 @@ class _CommonModel(BaseModel):
|
|
1972
1917
|
|
1973
1918
|
Returns
|
1974
1919
|
-------
|
1975
|
-
|
1920
|
+
float | Pandas.Series[float]
|
1976
1921
|
Calculate simple return
|
1977
1922
|
|
1978
1923
|
"""
|
@@ -2005,10 +1950,9 @@ class _CommonModel(BaseModel):
|
|
2005
1950
|
def value_ret_calendar_period(
|
2006
1951
|
self: Self,
|
2007
1952
|
year: int,
|
2008
|
-
month:
|
2009
|
-
) ->
|
2010
|
-
"""
|
2011
|
-
Calculate simple return for a specific calendar period.
|
1953
|
+
month: int | None = None,
|
1954
|
+
) -> float | Series[float]:
|
1955
|
+
"""Calculate simple return for a specific calendar period.
|
2012
1956
|
|
2013
1957
|
Parameters
|
2014
1958
|
----------
|
@@ -2019,7 +1963,7 @@ class _CommonModel(BaseModel):
|
|
2019
1963
|
|
2020
1964
|
Returns
|
2021
1965
|
-------
|
2022
|
-
|
1966
|
+
float | Pandas.Series[float]
|
2023
1967
|
Calculate simple return for a specific calendar period
|
2024
1968
|
|
2025
1969
|
"""
|
@@ -2029,7 +1973,7 @@ class _CommonModel(BaseModel):
|
|
2029
1973
|
period = "-".join([str(year), str(month).zfill(2)])
|
2030
1974
|
vrdf = self.tsdf.copy()
|
2031
1975
|
vrdf.index = DatetimeIndex(vrdf.index)
|
2032
|
-
resultdf = DataFrame(vrdf.pct_change(fill_method=
|
1976
|
+
resultdf = DataFrame(vrdf.pct_change(fill_method=None)) # type: ignore[arg-type]
|
2033
1977
|
result = resultdf.loc[period] + 1
|
2034
1978
|
cal_period = result.cumprod(axis="index").iloc[-1] - 1
|
2035
1979
|
if self.tsdf.shape[1] == 1:
|
@@ -2044,13 +1988,12 @@ class _CommonModel(BaseModel):
|
|
2044
1988
|
def var_down_func(
|
2045
1989
|
self: Self,
|
2046
1990
|
level: float = 0.95,
|
2047
|
-
months_from_last:
|
2048
|
-
from_date:
|
2049
|
-
to_date:
|
1991
|
+
months_from_last: int | None = None,
|
1992
|
+
from_date: dt.date | None = None,
|
1993
|
+
to_date: dt.date | None = None,
|
2050
1994
|
interpolation: LiteralQuantileInterp = "lower",
|
2051
|
-
) ->
|
2052
|
-
"""
|
2053
|
-
Downside Value At Risk, "VaR".
|
1995
|
+
) -> float | Series[float]:
|
1996
|
+
"""Downside Value At Risk, "VaR".
|
2054
1997
|
|
2055
1998
|
The equivalent of percentile.inc([...], 1-level) over returns in MS Excel.
|
2056
1999
|
https://www.investopedia.com/terms/v/var.asp.
|
@@ -2071,7 +2014,7 @@ class _CommonModel(BaseModel):
|
|
2071
2014
|
|
2072
2015
|
Returns
|
2073
2016
|
-------
|
2074
|
-
|
2017
|
+
float | Pandas.Series[float]
|
2075
2018
|
Downside Value At Risk
|
2076
2019
|
|
2077
2020
|
"""
|
@@ -2098,12 +2041,11 @@ class _CommonModel(BaseModel):
|
|
2098
2041
|
def worst_func(
|
2099
2042
|
self: Self,
|
2100
2043
|
observations: int = 1,
|
2101
|
-
months_from_last:
|
2102
|
-
from_date:
|
2103
|
-
to_date:
|
2104
|
-
) ->
|
2105
|
-
"""
|
2106
|
-
Most negative percentage change over a rolling number of observations.
|
2044
|
+
months_from_last: int | None = None,
|
2045
|
+
from_date: dt.date | None = None,
|
2046
|
+
to_date: dt.date | None = None,
|
2047
|
+
) -> float | Series[float]:
|
2048
|
+
"""Most negative percentage change over a rolling number of observations.
|
2107
2049
|
|
2108
2050
|
Parameters
|
2109
2051
|
----------
|
@@ -2119,7 +2061,7 @@ class _CommonModel(BaseModel):
|
|
2119
2061
|
|
2120
2062
|
Returns
|
2121
2063
|
-------
|
2122
|
-
|
2064
|
+
float | Pandas.Series[float]
|
2123
2065
|
Most negative percentage change over a rolling number of observations
|
2124
2066
|
within a chosen date range
|
2125
2067
|
|
@@ -2148,12 +2090,11 @@ class _CommonModel(BaseModel):
|
|
2148
2090
|
|
2149
2091
|
def z_score_func(
|
2150
2092
|
self: Self,
|
2151
|
-
months_from_last:
|
2152
|
-
from_date:
|
2153
|
-
to_date:
|
2154
|
-
) ->
|
2155
|
-
"""
|
2156
|
-
Z-score as (last return - mean return) / standard deviation of returns.
|
2093
|
+
months_from_last: int | None = None,
|
2094
|
+
from_date: dt.date | None = None,
|
2095
|
+
to_date: dt.date | None = None,
|
2096
|
+
) -> float | Series[float]:
|
2097
|
+
"""Z-score as (last return - mean return) / standard deviation of returns.
|
2157
2098
|
|
2158
2099
|
https://www.investopedia.com/terms/z/zscore.asp.
|
2159
2100
|
|
@@ -2169,7 +2110,7 @@ class _CommonModel(BaseModel):
|
|
2169
2110
|
|
2170
2111
|
Returns
|
2171
2112
|
-------
|
2172
|
-
|
2113
|
+
float | Pandas.Series[float]
|
2173
2114
|
Z-score as (last return - mean return) / standard deviation of returns
|
2174
2115
|
|
2175
2116
|
"""
|
@@ -2198,8 +2139,7 @@ class _CommonModel(BaseModel):
|
|
2198
2139
|
level: float = 0.95,
|
2199
2140
|
observations: int = 252,
|
2200
2141
|
) -> DataFrame:
|
2201
|
-
"""
|
2202
|
-
Calculate rolling annualized downside CVaR.
|
2142
|
+
"""Calculate rolling annualized downside CVaR.
|
2203
2143
|
|
2204
2144
|
Parameters
|
2205
2145
|
----------
|
@@ -2232,8 +2172,7 @@ class _CommonModel(BaseModel):
|
|
2232
2172
|
column: int = 0,
|
2233
2173
|
observations: int = 21,
|
2234
2174
|
) -> DataFrame:
|
2235
|
-
"""
|
2236
|
-
Calculate rolling returns.
|
2175
|
+
"""Calculate rolling returns.
|
2237
2176
|
|
2238
2177
|
Parameters
|
2239
2178
|
----------
|
@@ -2267,8 +2206,7 @@ class _CommonModel(BaseModel):
|
|
2267
2206
|
observations: int = 252,
|
2268
2207
|
interpolation: LiteralQuantileInterp = "lower",
|
2269
2208
|
) -> DataFrame:
|
2270
|
-
"""
|
2271
|
-
Calculate rolling annualized downside Value At Risk "VaR".
|
2209
|
+
"""Calculate rolling annualized downside Value At Risk "VaR".
|
2272
2210
|
|
2273
2211
|
Parameters
|
2274
2212
|
----------
|
@@ -2304,10 +2242,9 @@ class _CommonModel(BaseModel):
|
|
2304
2242
|
self: Self,
|
2305
2243
|
column: int = 0,
|
2306
2244
|
observations: int = 21,
|
2307
|
-
periods_in_a_year_fixed:
|
2245
|
+
periods_in_a_year_fixed: DaysInYearType | None = None,
|
2308
2246
|
) -> DataFrame:
|
2309
|
-
"""
|
2310
|
-
Calculate rolling annualised volatilities.
|
2247
|
+
"""Calculate rolling annualised volatilities.
|
2311
2248
|
|
2312
2249
|
Parameters
|
2313
2250
|
----------
|