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.
@@ -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 Any, Optional, SupportsFloat, Union, cast
12
+ from typing import TYPE_CHECKING, Any, SupportsFloat, cast
13
13
 
14
14
  from numpy import float64, inf, isnan, log, maximum, sqrt
15
- from numpy.typing import NDArray
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 openseries._risk import (
34
+ from ._risk import (
33
35
  _cvar_down_calc,
34
36
  _var_down_calc,
35
37
  )
36
- from openseries.datefixer import date_offset_foll, holiday_calendar
37
- from openseries.load_plotly import load_plotly_dict
38
- from openseries.types import (
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) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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) -> Union[float, Series[float]]:
200
- """
201
- Simple return.
191
+ def value_ret(self: Self) -> float | Series[float]:
192
+ """Simple return.
202
193
 
203
194
  Returns
204
195
  -------
205
- Union[float, Pandas.Series[float]]
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) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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) -> Union[dt.date, Series[dt.date]]:
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
- Union[datetime.date, pandas.Series[dt.date]]
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) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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) -> Union[float, Series[float]]:
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) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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( # noqa: C901
450
+ def calc_range(
476
451
  self: Self,
477
- months_offset: Optional[int] = None,
478
- from_dt: Optional[dt.date] = None,
479
- to_dt: Optional[dt.date] = None,
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.tsdf.index[0], self.tsdf.index[-1]
501
- if any([months_offset, from_dt, to_dt]):
502
- if months_offset is not None:
503
- earlier = date_offset_foll(
504
- raw_date=DatetimeIndex(self.tsdf.index)[-1],
505
- months_offset=-months_offset,
506
- adjust=False,
507
- following=True,
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
- if earlier < self.tsdf.index[0]:
510
- msg = "Function calc_range returned earlier date < series start"
511
- raise ValueError(
512
- msg,
513
- )
514
- later = self.tsdf.index[-1]
515
- elif from_dt is not None and to_dt is None:
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, later = from_dt, self.tsdf.index[-1]
520
- elif from_dt is None and to_dt is not None:
521
- if to_dt > self.tsdf.index[-1]:
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
- earlier, later = self.tsdf.index[0], to_dt
525
- elif from_dt is not None and to_dt is not None:
526
- if to_dt > self.tsdf.index[-1] or from_dt < self.tsdf.index[0]:
527
- msg = "Given from_dt or to_dt dates outside series range"
528
- raise ValueError(
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: Optional[DirectoryPath] = None,
659
- ) -> list[dict[str, Union[str, bool, ValueType, list[str], list[float]]]]:
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[Dict[str, Union[str, bool, ValueType, list[str], list[float]]]]
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: Optional[str] = None,
723
- directory: Optional[DirectoryPath] = None,
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: Optional[str] = None,
781
- filename: Optional[str] = None,
782
- directory: Optional[DirectoryPath] = None,
783
- labels: Optional[list[str]] = None,
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: Optional[str] = None,
896
- filename: Optional[str] = None,
897
- directory: Optional[DirectoryPath] = None,
898
- labels: Optional[list[str]] = None,
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: Optional[int] = None,
1028
- from_date: Optional[dt.date] = None,
1029
- to_date: Optional[dt.date] = None,
1030
- periods_in_a_year_fixed: Optional[DaysInYearType] = None,
1031
- ) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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: Optional[int] = None,
1088
- from_date: Optional[dt.date] = None,
1089
- to_date: Optional[dt.date] = None,
1090
- periods_in_a_year_fixed: Optional[DaysInYearType] = None,
1091
- ) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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: Optional[int] = None,
1148
- from_date: Optional[dt.date] = None,
1149
- to_date: Optional[dt.date] = None,
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: Optional[DaysInYearType] = None,
1110
+ periods_in_a_year_fixed: DaysInYearType | None = None,
1152
1111
  *,
1153
1112
  drift_adjust: bool = False,
1154
- ) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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: Optional[int] = None,
1204
- from_date: Optional[dt.date] = None,
1205
- to_date: Optional[dt.date] = None,
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: Optional[DaysInYearType] = None,
1165
+ periods_in_a_year_fixed: DaysInYearType | None = None,
1208
1166
  *,
1209
1167
  drift_adjust: bool = False,
1210
- ) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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: Optional[float] = None,
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: Optional[int] = None,
1269
- from_date: Optional[dt.date] = None,
1270
- to_date: Optional[dt.date] = None,
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: Optional[DaysInYearType] = None,
1229
+ periods_in_a_year_fixed: DaysInYearType | None = None,
1273
1230
  *,
1274
1231
  drift_adjust: bool = False,
1275
- ) -> Union[float, Series[float]]:
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: Optional[float]
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
- Union[float, Pandas.Series[float]]
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: Optional[int] = None,
1377
- from_date: Optional[dt.date] = None,
1378
- to_date: Optional[dt.date] = None,
1379
- ) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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: Optional[int] = None,
1439
- from_date: Optional[dt.date] = None,
1440
- to_date: Optional[dt.date] = None,
1441
- periods_in_a_year_fixed: Optional[DaysInYearType] = None,
1442
- ) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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: Optional[int] = None,
1514
- from_date: Optional[dt.date] = None,
1515
- to_date: Optional[dt.date] = None,
1516
- ) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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: Optional[int] = None,
1568
- from_date: Optional[dt.date] = None,
1569
- to_date: Optional[dt.date] = None,
1570
- ) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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: Optional[int] = None,
1617
- from_date: Optional[dt.date] = None,
1618
- to_date: Optional[dt.date] = None,
1619
- ) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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: Optional[int] = None,
1667
- from_date: Optional[dt.date] = None,
1668
- to_date: Optional[dt.date] = None,
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
- ) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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: Optional[int] = None,
1717
- from_date: Optional[dt.date] = None,
1718
- to_date: Optional[dt.date] = None,
1719
- ) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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: Optional[int] = None,
1774
- from_date: Optional[dt.date] = None,
1775
- to_date: Optional[dt.date] = None,
1776
- periods_in_a_year_fixed: Optional[DaysInYearType] = None,
1777
- ) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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: Optional[int] = None,
1838
- from_date: Optional[dt.date] = None,
1839
- to_date: Optional[dt.date] = None,
1840
- periods_in_a_year_fixed: Optional[DaysInYearType] = None,
1841
- ) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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: Optional[int] = None,
1904
- from_date: Optional[dt.date] = None,
1905
- to_date: Optional[dt.date] = None,
1906
- ) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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: Optional[int] = None,
1957
- from_date: Optional[dt.date] = None,
1958
- to_date: Optional[dt.date] = None,
1959
- ) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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: Optional[int] = None,
2009
- ) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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=cast(str, None)))
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: Optional[int] = None,
2048
- from_date: Optional[dt.date] = None,
2049
- to_date: Optional[dt.date] = None,
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
- ) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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: Optional[int] = None,
2102
- from_date: Optional[dt.date] = None,
2103
- to_date: Optional[dt.date] = None,
2104
- ) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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: Optional[int] = None,
2152
- from_date: Optional[dt.date] = None,
2153
- to_date: Optional[dt.date] = None,
2154
- ) -> Union[float, Series[float]]:
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
- Union[float, Pandas.Series[float]]
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: Optional[DaysInYearType] = None,
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
  ----------