openseries 1.9.6__py3-none-any.whl → 1.9.7__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.
@@ -22,13 +22,13 @@ from numpy import asarray, float64, inf, isnan, log, maximum, sqrt
22
22
 
23
23
  from .owntypes import (
24
24
  CaptorLogoType,
25
- Combo_co,
26
25
  DateAlignmentError,
27
26
  InitialValueZeroError,
28
27
  NumberOfItemsAndLabelsNotSameError,
29
28
  PlotlyConfigType,
30
29
  ResampleDataLossError,
31
30
  Self,
31
+ SeriesOrFloat_co,
32
32
  ValueType,
33
33
  )
34
34
 
@@ -87,8 +87,127 @@ from .datefixer import (
87
87
  from .load_plotly import load_plotly_dict
88
88
 
89
89
 
90
- # noinspection PyTypeChecker
91
- class _CommonModel(BaseModel, Generic[Combo_co]):
90
+ def _get_date_range_and_factor(
91
+ self: _CommonModel[SeriesOrFloat_co],
92
+ months_from_last: int | None = None,
93
+ from_date: dt.date | None = None,
94
+ to_date: dt.date | None = None,
95
+ periods_in_a_year_fixed: DaysInYearType | None = None,
96
+ ) -> tuple[dt.date, dt.date, float, DataFrame]:
97
+ """Common logic for date range and time factor calculation.
98
+
99
+ Parameters
100
+ ----------
101
+ months_from_last : int, optional
102
+ Number of months offset as positive integer. Overrides use of from_date
103
+ and to_date
104
+ from_date : datetime.date, optional
105
+ Specific from date
106
+ to_date : datetime.date, optional
107
+ Specific to date
108
+ periods_in_a_year_fixed : DaysInYearType, optional
109
+ Allows locking the periods-in-a-year to simplify test cases and
110
+ comparisons
111
+
112
+ Returns:
113
+ -------
114
+ tuple[dt.date, dt.date, float, DataFrame]
115
+ earlier, later, time_factor, data
116
+ """
117
+ earlier, later = self.calc_range(
118
+ months_offset=months_from_last,
119
+ from_dt=from_date,
120
+ to_dt=to_date,
121
+ )
122
+
123
+ if periods_in_a_year_fixed:
124
+ time_factor = float(periods_in_a_year_fixed)
125
+ else:
126
+ how_many = (
127
+ self.tsdf.loc[cast("Timestamp", earlier) : cast("Timestamp", later)]
128
+ .count()
129
+ .iloc[0]
130
+ )
131
+ fraction = (later - earlier).days / 365.25
132
+ time_factor = how_many / fraction
133
+
134
+ data = self.tsdf.loc[cast("Timestamp", earlier) : cast("Timestamp", later)]
135
+ return earlier, later, time_factor, data
136
+
137
+
138
+ def _get_base_column_data(
139
+ self: _CommonModel[SeriesOrFloat_co],
140
+ base_column: tuple[str, ValueType] | int,
141
+ earlier: dt.date,
142
+ later: dt.date,
143
+ ) -> tuple[Series[float], tuple[str, ValueType], str]:
144
+ """Common logic for base column data extraction.
145
+
146
+ Parameters
147
+ ----------
148
+ base_column : tuple[str, ValueType] | int
149
+ Column reference
150
+ earlier : dt.date
151
+ Start date
152
+ later : dt.date
153
+ End date
154
+
155
+ Returns:
156
+ -------
157
+ tuple[Series[float], tuple[str, ValueType], str]
158
+ data, item, label
159
+ """
160
+ if isinstance(base_column, tuple):
161
+ data = self.tsdf.loc[cast("Timestamp", earlier) : cast("Timestamp", later)][
162
+ base_column
163
+ ]
164
+ item = base_column
165
+ label = cast("tuple[str, str]", self.tsdf[base_column].name)[0]
166
+ elif isinstance(base_column, int):
167
+ data = self.tsdf.loc[
168
+ cast("Timestamp", earlier) : cast("Timestamp", later)
169
+ ].iloc[:, base_column]
170
+ item = cast("tuple[str, ValueType]", self.tsdf.iloc[:, base_column].name)
171
+ label = cast("tuple[str, str]", self.tsdf.iloc[:, base_column].name)[0]
172
+ else:
173
+ msg = "base_column should be a tuple[str, ValueType] or an integer."
174
+ raise TypeError(msg)
175
+
176
+ return data, item, label
177
+
178
+
179
+ def _calculate_time_factor(
180
+ data: Series[float],
181
+ earlier: dt.date,
182
+ later: dt.date,
183
+ periods_in_a_year_fixed: DaysInYearType | None = None,
184
+ ) -> float:
185
+ """Calculate time factor for annualization.
186
+
187
+ Parameters
188
+ ----------
189
+ data : Series[float]
190
+ Data series for counting observations
191
+ earlier : dt.date
192
+ Start date
193
+ later : dt.date
194
+ End date
195
+ periods_in_a_year_fixed : DaysInYearType, optional
196
+ Fixed periods in year
197
+
198
+ Returns:
199
+ -------
200
+ float
201
+ Time factor
202
+ """
203
+ if periods_in_a_year_fixed:
204
+ return float(periods_in_a_year_fixed)
205
+
206
+ fraction = (later - earlier).days / 365.25
207
+ return data.count() / fraction
208
+
209
+
210
+ class _CommonModel(BaseModel, Generic[SeriesOrFloat_co]):
92
211
  """Declare _CommonModel."""
93
212
 
94
213
  tsdf: DataFrame = DataFrame(dtype="float64")
@@ -99,12 +218,14 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
99
218
  revalidate_instances="always",
100
219
  )
101
220
 
102
- def _coerce_result(self: Self, result: Series[float], name: str) -> Combo_co:
221
+ def _coerce_result(
222
+ self: Self, result: Series[float], name: str
223
+ ) -> SeriesOrFloat_co:
103
224
  if self.tsdf.shape[1] == 1:
104
225
  arr = float(asarray(a=result, dtype=float64).squeeze())
105
- return cast("Combo_co", arr) # type: ignore[redundant-cast]
226
+ return cast("SeriesOrFloat_co", arr) # type: ignore[redundant-cast]
106
227
  return cast(
107
- "Combo_co",
228
+ "SeriesOrFloat_co",
108
229
  Series(
109
230
  data=result,
110
231
  index=self.tsdf.columns,
@@ -187,13 +308,14 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
187
308
  return self.length / self.yearfrac
188
309
 
189
310
  @property
190
- def max_drawdown_cal_year(self: Self) -> Combo_co:
311
+ def max_drawdown_cal_year(self: Self) -> SeriesOrFloat_co:
191
312
  """https://www.investopedia.com/terms/m/maximum-drawdown-mdd.asp.
192
313
 
193
314
  Returns:
194
315
  -------
195
- Combo_co
316
+ SeriesOrFloat_co
196
317
  Maximum drawdown in a single calendar year.
318
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
197
319
 
198
320
  """
199
321
  years = Index(d.year for d in self.tsdf.index)
@@ -208,43 +330,49 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
208
330
  return self._coerce_result(result=result, name="Max drawdown in cal yr")
209
331
 
210
332
  @property
211
- def geo_ret(self: Self) -> Combo_co:
333
+ def geo_ret(self: Self) -> SeriesOrFloat_co:
212
334
  """https://www.investopedia.com/terms/c/cagr.asp.
213
335
 
214
336
  Returns:
215
337
  -------
216
- Combo_co
217
- Compounded Annual Growth Rate (CAGR)
338
+ SeriesOrFloat_co
339
+ Compounded Annual Growth Rate (CAGR).
340
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
341
+
218
342
 
219
343
  """
220
344
  return self.geo_ret_func()
221
345
 
222
346
  @property
223
- def arithmetic_ret(self: Self) -> Combo_co:
347
+ def arithmetic_ret(self: Self) -> SeriesOrFloat_co:
224
348
  """https://www.investopedia.com/terms/a/arithmeticmean.asp.
225
349
 
226
350
  Returns:
227
351
  -------
228
- Combo_co
229
- Annualized arithmetic mean of returns
352
+ SeriesOrFloat_co
353
+ Annualized arithmetic mean of returns.
354
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
355
+
230
356
 
231
357
  """
232
358
  return self.arithmetic_ret_func()
233
359
 
234
360
  @property
235
- def value_ret(self: Self) -> Combo_co:
361
+ def value_ret(self: Self) -> SeriesOrFloat_co:
236
362
  """Simple return.
237
363
 
238
364
  Returns:
239
365
  -------
240
- Combo_co
241
- Simple return
366
+ SeriesOrFloat_co
367
+ Simple return.
368
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
369
+
242
370
 
243
371
  """
244
372
  return self.value_ret_func()
245
373
 
246
374
  @property
247
- def vol(self: Self) -> Combo_co:
375
+ def vol(self: Self) -> SeriesOrFloat_co:
248
376
  """Annualized volatility.
249
377
 
250
378
  Based on Pandas .std() which is the equivalent of stdev.s([...]) in MS Excel.
@@ -252,14 +380,16 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
252
380
 
253
381
  Returns:
254
382
  -------
255
- Combo_co
256
- Annualized volatility
383
+ SeriesOrFloat_co
384
+ Annualized volatility.
385
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
386
+
257
387
 
258
388
  """
259
389
  return self.vol_func()
260
390
 
261
391
  @property
262
- def downside_deviation(self: Self) -> Combo_co:
392
+ def downside_deviation(self: Self) -> SeriesOrFloat_co:
263
393
  """Downside Deviation.
264
394
 
265
395
  Standard deviation of returns that are below a Minimum Accepted Return
@@ -268,8 +398,10 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
268
398
 
269
399
  Returns:
270
400
  -------
271
- Combo_co
272
- Downside deviation
401
+ SeriesOrFloat_co
402
+ Downside deviation.
403
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
404
+
273
405
 
274
406
  """
275
407
  min_accepted_return: float = 0.0
@@ -280,29 +412,33 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
280
412
  )
281
413
 
282
414
  @property
283
- def ret_vol_ratio(self: Self) -> Combo_co:
415
+ def ret_vol_ratio(self: Self) -> SeriesOrFloat_co:
284
416
  """Ratio of annualized arithmetic mean of returns and annualized volatility.
285
417
 
286
418
  Returns:
287
419
  -------
288
- Combo_co
289
- Ratio of the annualized arithmetic mean of returns and annualized
420
+ SeriesOrFloat_co
421
+ Ratio of the annualized arithmetic mean of returns and annualized.
422
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
290
423
  volatility.
424
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
291
425
 
292
426
  """
293
427
  riskfree_rate: float = 0.0
294
428
  return self.ret_vol_ratio_func(riskfree_rate=riskfree_rate)
295
429
 
296
430
  @property
297
- def sortino_ratio(self: Self) -> Combo_co:
431
+ def sortino_ratio(self: Self) -> SeriesOrFloat_co:
298
432
  """https://www.investopedia.com/terms/s/sortinoratio.asp.
299
433
 
300
434
  Returns:
301
435
  -------
302
- Combo_co
303
- Sortino ratio calculated as the annualized arithmetic mean of returns
436
+ SeriesOrFloat_co
437
+ Sortino ratio calculated as the annualized arithmetic mean of returns.
438
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame
304
439
  / downside deviation. The ratio implies that the riskfree asset has zero
305
440
  volatility, and a minimum acceptable return of zero.
441
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
306
442
 
307
443
  """
308
444
  riskfree_rate: float = 0.0
@@ -313,7 +449,7 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
313
449
  )
314
450
 
315
451
  @property
316
- def kappa3_ratio(self: Self) -> Combo_co:
452
+ def kappa3_ratio(self: Self) -> SeriesOrFloat_co:
317
453
  """Kappa-3 ratio.
318
454
 
319
455
  The Kappa-3 ratio is a generalized downside-risk ratio defined as
@@ -324,9 +460,11 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
324
460
 
325
461
  Returns:
326
462
  -------
327
- Combo_co
328
- Kappa-3 ratio calculation with the riskfree rate and
463
+ SeriesOrFloat_co
464
+ Kappa-3 ratio calculation with the riskfree rate and.
465
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame
329
466
  Minimum Acceptable Return (MAR) both set to zero.
467
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
330
468
 
331
469
  """
332
470
  riskfree_rate: float = 0.0
@@ -339,38 +477,44 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
339
477
  )
340
478
 
341
479
  @property
342
- def omega_ratio(self: Self) -> Combo_co:
480
+ def omega_ratio(self: Self) -> SeriesOrFloat_co:
343
481
  """https://en.wikipedia.org/wiki/Omega_ratio.
344
482
 
345
483
  Returns:
346
484
  -------
347
- Combo_co
348
- Omega ratio calculation
485
+ SeriesOrFloat_co
486
+ Omega ratio calculation.
487
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
488
+
349
489
 
350
490
  """
351
491
  minimum_accepted_return: float = 0.0
352
492
  return self.omega_ratio_func(min_accepted_return=minimum_accepted_return)
353
493
 
354
494
  @property
355
- def z_score(self: Self) -> Combo_co:
495
+ def z_score(self: Self) -> SeriesOrFloat_co:
356
496
  """https://www.investopedia.com/terms/z/zscore.asp.
357
497
 
358
498
  Returns:
359
499
  -------
360
- Combo_co
500
+ SeriesOrFloat_co
361
501
  Z-score as (last return - mean return) / standard deviation of returns.
502
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
503
+
362
504
 
363
505
  """
364
506
  return self.z_score_func()
365
507
 
366
508
  @property
367
- def max_drawdown(self: Self) -> Combo_co:
509
+ def max_drawdown(self: Self) -> SeriesOrFloat_co:
368
510
  """https://www.investopedia.com/terms/m/maximum-drawdown-mdd.asp.
369
511
 
370
512
  Returns:
371
513
  -------
372
- Combo_co
373
- Maximum drawdown without any limit on date range
514
+ SeriesOrFloat_co
515
+ Maximum drawdown without any limit on date range.
516
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
517
+
374
518
 
375
519
  """
376
520
  return self.max_drawdown_func()
@@ -401,26 +545,30 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
401
545
  ).dt.date
402
546
 
403
547
  @property
404
- def worst(self: Self) -> Combo_co:
548
+ def worst(self: Self) -> SeriesOrFloat_co:
405
549
  """Most negative percentage change.
406
550
 
407
551
  Returns:
408
552
  -------
409
- Combo_co
410
- Most negative percentage change
553
+ SeriesOrFloat_co
554
+ Most negative percentage change.
555
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
556
+
411
557
 
412
558
  """
413
559
  observations: int = 1
414
560
  return self.worst_func(observations=observations)
415
561
 
416
562
  @property
417
- def worst_month(self: Self) -> Combo_co:
563
+ def worst_month(self: Self) -> SeriesOrFloat_co:
418
564
  """Most negative month.
419
565
 
420
566
  Returns:
421
567
  -------
422
- Pandas.Series[float]
423
- Most negative month
568
+ SeriesOrFloat_co
569
+ Most negative month.
570
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
571
+
424
572
 
425
573
  """
426
574
  method: LiteralPandasReindexMethod = "nearest"
@@ -458,56 +606,64 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
458
606
  return self._coerce_result(result=result, name="Worst month")
459
607
 
460
608
  @property
461
- def positive_share(self: Self) -> Combo_co:
609
+ def positive_share(self: Self) -> SeriesOrFloat_co:
462
610
  """The share of percentage changes that are greater than zero.
463
611
 
464
612
  Returns:
465
613
  -------
466
- Combo_co
467
- The share of percentage changes that are greater than zero
614
+ SeriesOrFloat_co
615
+ The share of percentage changes that are greater than zero.
616
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
617
+
468
618
 
469
619
  """
470
620
  return self.positive_share_func()
471
621
 
472
622
  @property
473
- def skew(self: Self) -> Combo_co:
623
+ def skew(self: Self) -> SeriesOrFloat_co:
474
624
  """https://www.investopedia.com/terms/s/skewness.asp.
475
625
 
476
626
  Returns:
477
627
  -------
478
- Combo_co
479
- Skew of the return distribution
628
+ SeriesOrFloat_co
629
+ Skew of the return distribution.
630
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
631
+
480
632
 
481
633
  """
482
634
  return self.skew_func()
483
635
 
484
636
  @property
485
- def kurtosis(self: Self) -> Combo_co:
637
+ def kurtosis(self: Self) -> SeriesOrFloat_co:
486
638
  """https://www.investopedia.com/terms/k/kurtosis.asp.
487
639
 
488
640
  Returns:
489
641
  -------
490
- Combo_co
491
- Kurtosis of the return distribution
642
+ SeriesOrFloat_co
643
+ Kurtosis of the return distribution.
644
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
645
+
492
646
 
493
647
  """
494
648
  return self.kurtosis_func()
495
649
 
496
650
  @property
497
- def cvar_down(self: Self) -> Combo_co:
651
+ def cvar_down(self: Self) -> SeriesOrFloat_co:
498
652
  """https://www.investopedia.com/terms/c/conditional_value_at_risk.asp.
499
653
 
500
654
  Returns:
501
655
  -------
502
- Combo_co
503
- Downside 95% Conditional Value At Risk "CVaR"
656
+ SeriesOrFloat_co
657
+ Downside 95% Conditional Value At Risk "CVaR".
658
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
659
+
504
660
 
505
661
  """
506
662
  level: float = 0.95
507
663
  return self.cvar_down_func(level=level)
508
664
 
509
665
  @property
510
- def var_down(self: Self) -> Combo_co:
666
+ def var_down(self: Self) -> SeriesOrFloat_co:
511
667
  """Downside 95% Value At Risk (VaR).
512
668
 
513
669
  The equivalent of percentile.inc([...], 1-level) over returns in MS Excel.
@@ -515,8 +671,10 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
515
671
 
516
672
  Returns:
517
673
  -------
518
- Combo_co
519
- Downside 95% Value At Risk (VaR)
674
+ SeriesOrFloat_co
675
+ Downside 95% Value At Risk (VaR).
676
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
677
+
520
678
 
521
679
  """
522
680
  level: float = 0.95
@@ -524,16 +682,18 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
524
682
  return self.var_down_func(level=level, interpolation=interpolation)
525
683
 
526
684
  @property
527
- def vol_from_var(self: Self) -> Combo_co:
685
+ def vol_from_var(self: Self) -> SeriesOrFloat_co:
528
686
  """Implied annualized volatility from Downside 95% Value at Risk.
529
687
 
530
688
  Assumes that returns are normally distributed.
531
689
 
532
690
  Returns:
533
691
  -------
534
- Combo_co
535
- Implied annualized volatility from the Downside 95% VaR using the
692
+ SeriesOrFloat_co
693
+ Implied annualized volatility from the Downside 95% VaR using the.
694
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
536
695
  assumption that returns are normally distributed.
696
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
537
697
 
538
698
  """
539
699
  level: float = 0.95
@@ -652,7 +812,7 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
652
812
  calendar = holiday_calendar(
653
813
  startyear=startyear,
654
814
  endyear=endyear,
655
- countries=countries,
815
+ countries=countries or "SE",
656
816
  markets=markets,
657
817
  custom_holidays=custom_holidays,
658
818
  )
@@ -1316,7 +1476,7 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
1316
1476
  from_date: dt.date | None = None,
1317
1477
  to_date: dt.date | None = None,
1318
1478
  periods_in_a_year_fixed: DaysInYearType | None = None,
1319
- ) -> Combo_co:
1479
+ ) -> SeriesOrFloat_co:
1320
1480
  """https://www.investopedia.com/terms/a/arithmeticmean.asp.
1321
1481
 
1322
1482
  Parameters
@@ -1334,33 +1494,21 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
1334
1494
 
1335
1495
  Returns:
1336
1496
  -------
1337
- Combo_co
1338
- Annualized arithmetic mean of returns
1497
+ SeriesOrFloat_co
1498
+ Annualized arithmetic mean of returns.
1499
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
1500
+
1339
1501
 
1340
1502
  """
1341
- earlier, later = self.calc_range(
1342
- months_offset=months_from_last,
1343
- from_dt=from_date,
1344
- to_dt=to_date,
1503
+ _earlier, _later, time_factor, data = _get_date_range_and_factor(
1504
+ self=self,
1505
+ months_from_last=months_from_last,
1506
+ from_date=from_date,
1507
+ to_date=to_date,
1508
+ periods_in_a_year_fixed=periods_in_a_year_fixed,
1345
1509
  )
1346
- if periods_in_a_year_fixed:
1347
- time_factor = float(periods_in_a_year_fixed)
1348
- else:
1349
- how_many = (
1350
- self.tsdf.loc[cast("Timestamp", earlier) : cast("Timestamp", later)]
1351
- .count()
1352
- .iloc[0]
1353
- )
1354
- fraction = (later - earlier).days / 365.25
1355
- time_factor = how_many / fraction
1356
1510
 
1357
- result = (
1358
- self.tsdf.loc[cast("Timestamp", earlier) : cast("Timestamp", later)]
1359
- .ffill()
1360
- .pct_change()
1361
- .mean()
1362
- * time_factor
1363
- )
1511
+ result = data.ffill().pct_change().mean() * time_factor
1364
1512
 
1365
1513
  return self._coerce_result(result=result, name="Arithmetic return")
1366
1514
 
@@ -1370,7 +1518,7 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
1370
1518
  from_date: dt.date | None = None,
1371
1519
  to_date: dt.date | None = None,
1372
1520
  periods_in_a_year_fixed: DaysInYearType | None = None,
1373
- ) -> Combo_co:
1521
+ ) -> SeriesOrFloat_co:
1374
1522
  """Annualized volatility.
1375
1523
 
1376
1524
  Based on Pandas .std() which is the equivalent of stdev.s([...]) in MS Excel.
@@ -1390,27 +1538,19 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
1390
1538
 
1391
1539
  Returns:
1392
1540
  -------
1393
- Combo_co
1394
- Annualized volatility
1541
+ SeriesOrFloat_co
1542
+ Annualized volatility.
1543
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
1395
1544
 
1396
1545
  """
1397
- earlier, later = self.calc_range(
1398
- months_offset=months_from_last,
1399
- from_dt=from_date,
1400
- to_dt=to_date,
1546
+ _earlier, _later, time_factor, data = _get_date_range_and_factor(
1547
+ self=self,
1548
+ months_from_last=months_from_last,
1549
+ from_date=from_date,
1550
+ to_date=to_date,
1551
+ periods_in_a_year_fixed=periods_in_a_year_fixed,
1401
1552
  )
1402
- if periods_in_a_year_fixed:
1403
- time_factor = float(periods_in_a_year_fixed)
1404
- else:
1405
- how_many = (
1406
- self.tsdf.loc[cast("Timestamp", earlier) : cast("Timestamp", later)]
1407
- .count()
1408
- .iloc[0]
1409
- )
1410
- fraction = (later - earlier).days / 365.25
1411
- time_factor = how_many / fraction
1412
1553
 
1413
- data = self.tsdf.loc[cast("Timestamp", earlier) : cast("Timestamp", later)]
1414
1554
  result = data.ffill().pct_change().std().mul(sqrt(time_factor))
1415
1555
 
1416
1556
  return self._coerce_result(result=result, name="Volatility")
@@ -1425,7 +1565,7 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
1425
1565
  periods_in_a_year_fixed: DaysInYearType | None = None,
1426
1566
  *,
1427
1567
  drift_adjust: bool = False,
1428
- ) -> Combo_co:
1568
+ ) -> SeriesOrFloat_co:
1429
1569
  """Implied annualized volatility.
1430
1570
 
1431
1571
  Implied annualized volatility from the Downside VaR using the assumption
@@ -1452,8 +1592,9 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
1452
1592
 
1453
1593
  Returns:
1454
1594
  -------
1455
- Combo_co
1456
- Implied annualized volatility from the Downside VaR using the
1595
+ SeriesOrFloat_co
1596
+ Implied annualized volatility from the Downside VaR using the.
1597
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
1457
1598
  assumption that returns are normally distributed.
1458
1599
 
1459
1600
  """
@@ -1480,7 +1621,7 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
1480
1621
  periods_in_a_year_fixed: DaysInYearType | None = None,
1481
1622
  *,
1482
1623
  drift_adjust: bool = False,
1483
- ) -> Combo_co:
1624
+ ) -> SeriesOrFloat_co:
1484
1625
  """Target weight from VaR.
1485
1626
 
1486
1627
  A position weight multiplier from the ratio between a VaR implied
@@ -1513,8 +1654,9 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
1513
1654
 
1514
1655
  Returns:
1515
1656
  -------
1516
- Combo_co
1517
- A position weight multiplier from the ratio between a VaR implied
1657
+ SeriesOrFloat_co
1658
+ A position weight multiplier from the ratio between a VaR implied.
1659
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
1518
1660
  volatility and a given target volatility. Multiplier = 1.0 -> target met
1519
1661
 
1520
1662
  """
@@ -1544,7 +1686,7 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
1544
1686
  periods_in_a_year_fixed: DaysInYearType | None = None,
1545
1687
  *,
1546
1688
  drift_adjust: bool = False,
1547
- ) -> Combo_co:
1689
+ ) -> SeriesOrFloat_co:
1548
1690
  """Volatility implied from VaR or Target Weight.
1549
1691
 
1550
1692
  The function returns a position weight multiplier from the ratio between
@@ -1579,8 +1721,9 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
1579
1721
 
1580
1722
  Returns:
1581
1723
  -------
1582
- Combo_co
1583
- Target volatility if target_vol is provided otherwise the VaR
1724
+ SeriesOrFloat_co
1725
+ Target volatility if target_vol is provided otherwise the VaR.
1726
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
1584
1727
  implied volatility.
1585
1728
 
1586
1729
  """
@@ -1647,7 +1790,7 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
1647
1790
  months_from_last: int | None = None,
1648
1791
  from_date: dt.date | None = None,
1649
1792
  to_date: dt.date | None = None,
1650
- ) -> Combo_co:
1793
+ ) -> SeriesOrFloat_co:
1651
1794
  """Downside Conditional Value At Risk "CVaR".
1652
1795
 
1653
1796
  https://www.investopedia.com/terms/c/conditional_value_at_risk.asp.
@@ -1666,8 +1809,9 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
1666
1809
 
1667
1810
  Returns:
1668
1811
  -------
1669
- Combo_co
1670
- Downside Conditional Value At Risk "CVaR"
1812
+ SeriesOrFloat_co
1813
+ Downside Conditional Value At Risk "CVaR".
1814
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
1671
1815
 
1672
1816
  """
1673
1817
  earlier, later = self.calc_range(
@@ -1698,7 +1842,7 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
1698
1842
  from_date: dt.date | None = None,
1699
1843
  to_date: dt.date | None = None,
1700
1844
  periods_in_a_year_fixed: DaysInYearType | None = None,
1701
- ) -> Combo_co:
1845
+ ) -> SeriesOrFloat_co:
1702
1846
  """Downside Deviation if order set to 2.
1703
1847
 
1704
1848
  If order is set to 2 the function calculates the standard
@@ -1725,8 +1869,9 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
1725
1869
 
1726
1870
  Returns:
1727
1871
  -------
1728
- Combo_co
1729
- Downside deviation if order set to 2
1872
+ SeriesOrFloat_co
1873
+ Downside deviation if order set to 2.
1874
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
1730
1875
 
1731
1876
  """
1732
1877
  msg = f"'order' must be 2 or 3, got {order!r}."
@@ -1781,7 +1926,7 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
1781
1926
  months_from_last: int | None = None,
1782
1927
  from_date: dt.date | None = None,
1783
1928
  to_date: dt.date | None = None,
1784
- ) -> Combo_co:
1929
+ ) -> SeriesOrFloat_co:
1785
1930
  """Compounded Annual Growth Rate (CAGR).
1786
1931
 
1787
1932
  https://www.investopedia.com/terms/c/cagr.asp.
@@ -1798,8 +1943,9 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
1798
1943
 
1799
1944
  Returns:
1800
1945
  -------
1801
- Combo_co
1802
- Compounded Annual Growth Rate (CAGR)
1946
+ SeriesOrFloat_co
1947
+ Compounded Annual Growth Rate (CAGR).
1948
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
1803
1949
 
1804
1950
  """
1805
1951
  zero = 0.0
@@ -1830,7 +1976,7 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
1830
1976
  months_from_last: int | None = None,
1831
1977
  from_date: dt.date | None = None,
1832
1978
  to_date: dt.date | None = None,
1833
- ) -> Combo_co:
1979
+ ) -> SeriesOrFloat_co:
1834
1980
  """Skew of the return distribution.
1835
1981
 
1836
1982
  https://www.investopedia.com/terms/s/skewness.asp.
@@ -1847,8 +1993,9 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
1847
1993
 
1848
1994
  Returns:
1849
1995
  -------
1850
- Combo_co
1851
- Skew of the return distribution
1996
+ SeriesOrFloat_co
1997
+ Skew of the return distribution.
1998
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
1852
1999
 
1853
2000
  """
1854
2001
  earlier, later = self.calc_range(
@@ -1873,7 +2020,7 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
1873
2020
  months_from_last: int | None = None,
1874
2021
  from_date: dt.date | None = None,
1875
2022
  to_date: dt.date | None = None,
1876
- ) -> Combo_co:
2023
+ ) -> SeriesOrFloat_co:
1877
2024
  """Kurtosis of the return distribution.
1878
2025
 
1879
2026
  https://www.investopedia.com/terms/k/kurtosis.asp.
@@ -1890,8 +2037,9 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
1890
2037
 
1891
2038
  Returns:
1892
2039
  -------
1893
- Combo_co
1894
- Kurtosis of the return distribution
2040
+ SeriesOrFloat_co
2041
+ Kurtosis of the return distribution.
2042
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
1895
2043
 
1896
2044
  """
1897
2045
  earlier, later = self.calc_range(
@@ -1921,7 +2069,7 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
1921
2069
  from_date: dt.date | None = None,
1922
2070
  to_date: dt.date | None = None,
1923
2071
  min_periods: int = 1,
1924
- ) -> Combo_co:
2072
+ ) -> SeriesOrFloat_co:
1925
2073
  """Maximum drawdown without any limit on date range.
1926
2074
 
1927
2075
  https://www.investopedia.com/terms/m/maximum-drawdown-mdd.asp.
@@ -1940,8 +2088,9 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
1940
2088
 
1941
2089
  Returns:
1942
2090
  -------
1943
- Combo_co
1944
- Maximum drawdown without any limit on date range
2091
+ SeriesOrFloat_co
2092
+ Maximum drawdown without any limit on date range.
2093
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
1945
2094
 
1946
2095
  """
1947
2096
  earlier, later = self.calc_range(
@@ -1963,7 +2112,7 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
1963
2112
  months_from_last: int | None = None,
1964
2113
  from_date: dt.date | None = None,
1965
2114
  to_date: dt.date | None = None,
1966
- ) -> Combo_co:
2115
+ ) -> SeriesOrFloat_co:
1967
2116
  """Calculate share of percentage changes that are greater than zero.
1968
2117
 
1969
2118
  Parameters
@@ -1978,8 +2127,9 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
1978
2127
 
1979
2128
  Returns:
1980
2129
  -------
1981
- Combo_co
1982
- Calculate share of percentage changes that are greater than zero
2130
+ SeriesOrFloat_co
2131
+ Calculate share of percentage changes that are greater than zero.
2132
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
1983
2133
 
1984
2134
  """
1985
2135
  zero: float = 0.0
@@ -2016,7 +2166,7 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
2016
2166
  from_date: dt.date | None = None,
2017
2167
  to_date: dt.date | None = None,
2018
2168
  periods_in_a_year_fixed: DaysInYearType | None = None,
2019
- ) -> Combo_co:
2169
+ ) -> SeriesOrFloat_co:
2020
2170
  """Ratio between arithmetic mean of returns and annualized volatility.
2021
2171
 
2022
2172
  The ratio of annualized arithmetic mean of returns and annualized
@@ -2042,8 +2192,9 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
2042
2192
 
2043
2193
  Returns:
2044
2194
  -------
2045
- Combo_co
2046
- Ratio of the annualized arithmetic mean of returns and annualized
2195
+ SeriesOrFloat_co
2196
+ Ratio of the annualized arithmetic mean of returns and annualized.
2197
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
2047
2198
  volatility or, if risk-free return provided, Sharpe ratio
2048
2199
 
2049
2200
  """
@@ -2073,7 +2224,7 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
2073
2224
  from_date: dt.date | None = None,
2074
2225
  to_date: dt.date | None = None,
2075
2226
  periods_in_a_year_fixed: DaysInYearType | None = None,
2076
- ) -> Combo_co:
2227
+ ) -> SeriesOrFloat_co:
2077
2228
  """Sortino Ratio or Kappa3 Ratio.
2078
2229
 
2079
2230
  The Sortino ratio calculated as ( return - risk free return )
@@ -2106,8 +2257,9 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
2106
2257
 
2107
2258
  Returns:
2108
2259
  -------
2109
- Combo_co
2110
- Sortino ratio calculated as ( return - riskfree return ) /
2260
+ SeriesOrFloat_co
2261
+ Sortino ratio calculated as ( return - riskfree return ) /.
2262
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
2111
2263
  downside deviation (std dev of returns below MAR)
2112
2264
 
2113
2265
  """
@@ -2139,7 +2291,7 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
2139
2291
  months_from_last: int | None = None,
2140
2292
  from_date: dt.date | None = None,
2141
2293
  to_date: dt.date | None = None,
2142
- ) -> Combo_co:
2294
+ ) -> SeriesOrFloat_co:
2143
2295
  """Omega Ratio.
2144
2296
 
2145
2297
  The Omega Ratio compares returns above a certain target level
@@ -2161,8 +2313,9 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
2161
2313
 
2162
2314
  Returns:
2163
2315
  -------
2164
- Combo_co
2165
- Omega ratio calculation
2316
+ SeriesOrFloat_co
2317
+ Omega ratio calculation.
2318
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
2166
2319
 
2167
2320
  """
2168
2321
  earlier, later = self.calc_range(
@@ -2186,7 +2339,7 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
2186
2339
  months_from_last: int | None = None,
2187
2340
  from_date: dt.date | None = None,
2188
2341
  to_date: dt.date | None = None,
2189
- ) -> Combo_co:
2342
+ ) -> SeriesOrFloat_co:
2190
2343
  """Calculate simple return.
2191
2344
 
2192
2345
  Parameters
@@ -2201,8 +2354,9 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
2201
2354
 
2202
2355
  Returns:
2203
2356
  -------
2204
- Combo_co
2205
- Calculate simple return
2357
+ SeriesOrFloat_co
2358
+ Calculate simple return.
2359
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
2206
2360
 
2207
2361
  """
2208
2362
  zero: float = 0.0
@@ -2229,7 +2383,7 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
2229
2383
  self: Self,
2230
2384
  year: int,
2231
2385
  month: int | None = None,
2232
- ) -> Combo_co:
2386
+ ) -> SeriesOrFloat_co:
2233
2387
  """Calculate simple return for a specific calendar period.
2234
2388
 
2235
2389
  Parameters
@@ -2241,8 +2395,9 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
2241
2395
 
2242
2396
  Returns:
2243
2397
  -------
2244
- Combo_co
2245
- Calculate simple return for a specific calendar period
2398
+ SeriesOrFloat_co
2399
+ Calculate simple return for a specific calendar period.
2400
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
2246
2401
 
2247
2402
  """
2248
2403
  if month is None:
@@ -2264,7 +2419,7 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
2264
2419
  from_date: dt.date | None = None,
2265
2420
  to_date: dt.date | None = None,
2266
2421
  interpolation: LiteralQuantileInterp = "lower",
2267
- ) -> Combo_co:
2422
+ ) -> SeriesOrFloat_co:
2268
2423
  """Downside Value At Risk, "VaR".
2269
2424
 
2270
2425
  The equivalent of percentile.inc([...], 1-level) over returns in MS Excel.
@@ -2286,8 +2441,9 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
2286
2441
 
2287
2442
  Returns:
2288
2443
  -------
2289
- Combo_co
2290
- Downside Value At Risk
2444
+ SeriesOrFloat_co
2445
+ Downside Value At Risk.
2446
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
2291
2447
 
2292
2448
  """
2293
2449
  earlier, later = self.calc_range(
@@ -2310,7 +2466,7 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
2310
2466
  months_from_last: int | None = None,
2311
2467
  from_date: dt.date | None = None,
2312
2468
  to_date: dt.date | None = None,
2313
- ) -> Combo_co:
2469
+ ) -> SeriesOrFloat_co:
2314
2470
  """Most negative percentage change over a rolling number of observations.
2315
2471
 
2316
2472
  Parameters
@@ -2327,8 +2483,9 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
2327
2483
 
2328
2484
  Returns:
2329
2485
  -------
2330
- Combo_co
2331
- Most negative percentage change over a rolling number of observations
2486
+ SeriesOrFloat_co
2487
+ Most negative percentage change over a rolling number of observations.
2488
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
2332
2489
  within a chosen date range
2333
2490
 
2334
2491
  """
@@ -2353,7 +2510,7 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
2353
2510
  months_from_last: int | None = None,
2354
2511
  from_date: dt.date | None = None,
2355
2512
  to_date: dt.date | None = None,
2356
- ) -> Combo_co:
2513
+ ) -> SeriesOrFloat_co:
2357
2514
  """Z-score as (last return - mean return) / standard deviation of returns.
2358
2515
 
2359
2516
  https://www.investopedia.com/terms/z/zscore.asp.
@@ -2370,8 +2527,9 @@ class _CommonModel(BaseModel, Generic[Combo_co]):
2370
2527
 
2371
2528
  Returns:
2372
2529
  -------
2373
- Combo_co
2374
- Z-score as (last return - mean return) / standard deviation of returns
2530
+ SeriesOrFloat_co
2531
+ Z-score as (last return - mean return) / standard deviation of returns.
2532
+ Returns float for OpenTimeSeries, Series[float] for OpenFrame.
2375
2533
 
2376
2534
  """
2377
2535
  earlier, later = self.calc_range(