openseries 1.8.1__py3-none-any.whl → 1.8.3__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.
@@ -33,6 +33,10 @@ if TYPE_CHECKING: # pragma: no cover
33
33
  LiteralLinePlotMode,
34
34
  LiteralNanMethod,
35
35
  LiteralPandasReindexMethod,
36
+ LiteralPlotlyHistogramBarMode,
37
+ LiteralPlotlyHistogramCurveType,
38
+ LiteralPlotlyHistogramHistNorm,
39
+ LiteralPlotlyHistogramPlotType,
36
40
  LiteralPlotlyJSlib,
37
41
  LiteralPlotlyOutput,
38
42
  LiteralQuantileInterp,
@@ -50,11 +54,12 @@ from pandas import (
50
54
  to_datetime,
51
55
  )
52
56
  from pandas.tseries.offsets import CustomBusinessDay
53
- from plotly.graph_objs import Figure # type: ignore[import-untyped,unused-ignore]
54
- from plotly.io import to_html # type: ignore[import-untyped,unused-ignore]
55
- from plotly.offline import plot # type: ignore[import-untyped,unused-ignore]
57
+ from plotly.figure_factory import create_distplot # type: ignore[import-untyped]
58
+ from plotly.graph_objs import Figure # type: ignore[import-untyped]
59
+ from plotly.io import to_html # type: ignore[import-untyped]
60
+ from plotly.offline import plot # type: ignore[import-untyped]
56
61
  from pydantic import BaseModel, ConfigDict, DirectoryPath
57
- from scipy.stats import ( # type: ignore[import-untyped,unused-ignore]
62
+ from scipy.stats import ( # type: ignore[import-untyped]
58
63
  kurtosis,
59
64
  norm,
60
65
  skew,
@@ -73,7 +78,7 @@ from .load_plotly import load_plotly_dict
73
78
 
74
79
 
75
80
  # noinspection PyTypeChecker
76
- class _CommonModel(BaseModel):
81
+ class _CommonModel(BaseModel): # type: ignore[misc]
77
82
  """Declare _CommonModel."""
78
83
 
79
84
  tsdf: DataFrame = DataFrame(dtype="float64")
@@ -88,7 +93,7 @@ class _CommonModel(BaseModel):
88
93
  def length(self: Self) -> int:
89
94
  """Number of observations.
90
95
 
91
- Returns
96
+ Returns:
92
97
  -------
93
98
  int
94
99
  Number of observations
@@ -100,7 +105,7 @@ class _CommonModel(BaseModel):
100
105
  def first_idx(self: Self) -> dt.date:
101
106
  """The first date in the timeseries.
102
107
 
103
- Returns
108
+ Returns:
104
109
  -------
105
110
  datetime.date
106
111
  The first date in the timeseries
@@ -112,7 +117,7 @@ class _CommonModel(BaseModel):
112
117
  def last_idx(self: Self) -> dt.date:
113
118
  """The last date in the timeseries.
114
119
 
115
- Returns
120
+ Returns:
116
121
  -------
117
122
  datetime.date
118
123
  The last date in the timeseries
@@ -124,7 +129,7 @@ class _CommonModel(BaseModel):
124
129
  def span_of_days(self: Self) -> int:
125
130
  """Number of days from the first date to the last.
126
131
 
127
- Returns
132
+ Returns:
128
133
  -------
129
134
  int
130
135
  Number of days from the first date to the last
@@ -136,7 +141,7 @@ class _CommonModel(BaseModel):
136
141
  def yearfrac(self: Self) -> float:
137
142
  """Length of series expressed in years assuming all years have 365.25 days.
138
143
 
139
- Returns
144
+ Returns:
140
145
  -------
141
146
  float
142
147
  Length of the timeseries expressed in years assuming all years
@@ -149,7 +154,7 @@ class _CommonModel(BaseModel):
149
154
  def periods_in_a_year(self: Self) -> float:
150
155
  """The average number of observations per year.
151
156
 
152
- Returns
157
+ Returns:
153
158
  -------
154
159
  float
155
160
  The average number of observations per year
@@ -161,7 +166,7 @@ class _CommonModel(BaseModel):
161
166
  def max_drawdown_cal_year(self: Self) -> float | Series[float]:
162
167
  """https://www.investopedia.com/terms/m/maximum-drawdown-mdd.asp.
163
168
 
164
- Returns
169
+ Returns:
165
170
  -------
166
171
  float | Pandas.Series[float]
167
172
  Maximum drawdown in a single calendar year.
@@ -189,7 +194,7 @@ class _CommonModel(BaseModel):
189
194
  def geo_ret(self: Self) -> float | Series[float]:
190
195
  """https://www.investopedia.com/terms/c/cagr.asp.
191
196
 
192
- Returns
197
+ Returns:
193
198
  -------
194
199
  float | Pandas.Series[float]
195
200
  Compounded Annual Growth Rate (CAGR)
@@ -201,7 +206,7 @@ class _CommonModel(BaseModel):
201
206
  def arithmetic_ret(self: Self) -> float | Series[float]:
202
207
  """https://www.investopedia.com/terms/a/arithmeticmean.asp.
203
208
 
204
- Returns
209
+ Returns:
205
210
  -------
206
211
  float | Pandas.Series[float]
207
212
  Annualized arithmetic mean of returns
@@ -213,7 +218,7 @@ class _CommonModel(BaseModel):
213
218
  def value_ret(self: Self) -> float | Series[float]:
214
219
  """Simple return.
215
220
 
216
- Returns
221
+ Returns:
217
222
  -------
218
223
  float | Pandas.Series[float]
219
224
  Simple return
@@ -228,7 +233,7 @@ class _CommonModel(BaseModel):
228
233
  Based on Pandas .std() which is the equivalent of stdev.s([...]) in MS Excel.
229
234
  https://www.investopedia.com/terms/v/volatility.asp.
230
235
 
231
- Returns
236
+ Returns:
232
237
  -------
233
238
  float | Pandas.Series[float]
234
239
  Annualized volatility
@@ -244,7 +249,7 @@ class _CommonModel(BaseModel):
244
249
  of zero. It is used to calculate the Sortino Ratio.
245
250
  https://www.investopedia.com/terms/d/downside-deviation.asp.
246
251
 
247
- Returns
252
+ Returns:
248
253
  -------
249
254
  float | Pandas.Series[float]
250
255
  Downside deviation
@@ -257,7 +262,7 @@ class _CommonModel(BaseModel):
257
262
  def ret_vol_ratio(self: Self) -> float | Series[float]:
258
263
  """Ratio of annualized arithmetic mean of returns and annualized volatility.
259
264
 
260
- Returns
265
+ Returns:
261
266
  -------
262
267
  float | Pandas.Series[float]
263
268
  Ratio of the annualized arithmetic mean of returns and annualized
@@ -271,7 +276,7 @@ class _CommonModel(BaseModel):
271
276
  def sortino_ratio(self: Self) -> float | Series[float]:
272
277
  """https://www.investopedia.com/terms/s/sortinoratio.asp.
273
278
 
274
- Returns
279
+ Returns:
275
280
  -------
276
281
  float | Pandas.Series[float]
277
282
  Sortino ratio calculated as the annualized arithmetic mean of returns
@@ -290,7 +295,7 @@ class _CommonModel(BaseModel):
290
295
  def omega_ratio(self: Self) -> float | Series[float]:
291
296
  """https://en.wikipedia.org/wiki/Omega_ratio.
292
297
 
293
- Returns
298
+ Returns:
294
299
  -------
295
300
  float | Pandas.Series[float]
296
301
  Omega ratio calculation
@@ -303,7 +308,7 @@ class _CommonModel(BaseModel):
303
308
  def z_score(self: Self) -> float | Series[float]:
304
309
  """https://www.investopedia.com/terms/z/zscore.asp.
305
310
 
306
- Returns
311
+ Returns:
307
312
  -------
308
313
  float | Pandas.Series[float]
309
314
  Z-score as (last return - mean return) / standard deviation of returns.
@@ -315,7 +320,7 @@ class _CommonModel(BaseModel):
315
320
  def max_drawdown(self: Self) -> float | Series[float]:
316
321
  """https://www.investopedia.com/terms/m/maximum-drawdown-mdd.asp.
317
322
 
318
- Returns
323
+ Returns:
319
324
  -------
320
325
  float | Pandas.Series[float]
321
326
  Maximum drawdown without any limit on date range
@@ -329,7 +334,7 @@ class _CommonModel(BaseModel):
329
334
 
330
335
  https://www.investopedia.com/terms/m/maximum-drawdown-mdd.asp.
331
336
 
332
- Returns
337
+ Returns:
333
338
  -------
334
339
  datetime.date | pandas.Series[dt.date]
335
340
  Date when the maximum drawdown occurred
@@ -352,7 +357,7 @@ class _CommonModel(BaseModel):
352
357
  def worst(self: Self) -> float | Series[float]:
353
358
  """Most negative percentage change.
354
359
 
355
- Returns
360
+ Returns:
356
361
  -------
357
362
  float | Pandas.Series[float]
358
363
  Most negative percentage change
@@ -365,7 +370,7 @@ class _CommonModel(BaseModel):
365
370
  def worst_month(self: Self) -> float | Series[float]:
366
371
  """Most negative month.
367
372
 
368
- Returns
373
+ Returns:
369
374
  -------
370
375
  Pandas.Series[float]
371
376
  Most negative month
@@ -396,7 +401,7 @@ class _CommonModel(BaseModel):
396
401
  def positive_share(self: Self) -> float | Series[float]:
397
402
  """The share of percentage changes that are greater than zero.
398
403
 
399
- Returns
404
+ Returns:
400
405
  -------
401
406
  float | Pandas.Series[float]
402
407
  The share of percentage changes that are greater than zero
@@ -408,7 +413,7 @@ class _CommonModel(BaseModel):
408
413
  def skew(self: Self) -> float | Series[float]:
409
414
  """https://www.investopedia.com/terms/s/skewness.asp.
410
415
 
411
- Returns
416
+ Returns:
412
417
  -------
413
418
  float | Pandas.Series[float]
414
419
  Skew of the return distribution
@@ -420,7 +425,7 @@ class _CommonModel(BaseModel):
420
425
  def kurtosis(self: Self) -> float | Series[float]:
421
426
  """https://www.investopedia.com/terms/k/kurtosis.asp.
422
427
 
423
- Returns
428
+ Returns:
424
429
  -------
425
430
  float | Pandas.Series[float]
426
431
  Kurtosis of the return distribution
@@ -432,7 +437,7 @@ class _CommonModel(BaseModel):
432
437
  def cvar_down(self: Self) -> float | Series[float]:
433
438
  """https://www.investopedia.com/terms/c/conditional_value_at_risk.asp.
434
439
 
435
- Returns
440
+ Returns:
436
441
  -------
437
442
  float | Pandas.Series[float]
438
443
  Downside 95% Conditional Value At Risk "CVaR"
@@ -448,7 +453,7 @@ class _CommonModel(BaseModel):
448
453
  The equivalent of percentile.inc([...], 1-level) over returns in MS Excel.
449
454
  https://www.investopedia.com/terms/v/var.asp.
450
455
 
451
- Returns
456
+ Returns:
452
457
  -------
453
458
  float | Pandas.Series[float]
454
459
  Downside 95% Value At Risk (VaR)
@@ -464,7 +469,7 @@ class _CommonModel(BaseModel):
464
469
 
465
470
  Assumes that returns are normally distributed.
466
471
 
467
- Returns
472
+ Returns:
468
473
  -------
469
474
  float | Pandas.Series[float]
470
475
  Implied annualized volatility from the Downside 95% VaR using the
@@ -493,7 +498,7 @@ class _CommonModel(BaseModel):
493
498
  to_dt: datetime.date, optional
494
499
  Specific from date
495
500
 
496
- Returns
501
+ Returns:
497
502
  -------
498
503
  tuple[datetime.date, datetime.date]
499
504
  Start and end date of the chosen date range
@@ -543,14 +548,14 @@ class _CommonModel(BaseModel):
543
548
  countries: CountriesType, default: "SE"
544
549
  (List of) country code(s) according to ISO 3166-1 alpha-2
545
550
 
546
- Returns
551
+ Returns:
547
552
  -------
548
553
  OpenFrame
549
554
  An OpenFrame object
550
555
 
551
556
  """
552
- startyear = to_datetime(self.tsdf.index[0]).year
553
- endyear = to_datetime(self.tsdf.index[-1]).year
557
+ startyear = cast("int", to_datetime(self.tsdf.index[0]).year)
558
+ endyear = cast("int", to_datetime(self.tsdf.index[-1]).year)
554
559
  calendar = holiday_calendar(
555
560
  startyear=startyear,
556
561
  endyear=endyear,
@@ -574,7 +579,7 @@ class _CommonModel(BaseModel):
574
579
 
575
580
  Equivalent to LN(value[t] / value[t=0]) in Excel.
576
581
 
577
- Returns
582
+ Returns:
578
583
  -------
579
584
  self
580
585
  An object of the same class
@@ -595,7 +600,7 @@ class _CommonModel(BaseModel):
595
600
  method: LiteralNanMethod, default: "fill"
596
601
  Method used to handle NaN. Either fill with last known or drop
597
602
 
598
- Returns
603
+ Returns:
599
604
  -------
600
605
  self
601
606
  An object of the same class
@@ -615,7 +620,7 @@ class _CommonModel(BaseModel):
615
620
  method: LiteralNanMethod, default: "fill"
616
621
  Method used to handle NaN. Either fill with zero or drop
617
622
 
618
- Returns
623
+ Returns:
619
624
  -------
620
625
  self
621
626
  An object of the same class
@@ -630,7 +635,7 @@ class _CommonModel(BaseModel):
630
635
  def to_drawdown_series(self: Self) -> Self:
631
636
  """Convert timeseries into a drawdown series.
632
637
 
633
- Returns
638
+ Returns:
634
639
  -------
635
640
  self
636
641
  An object of the same class
@@ -660,7 +665,7 @@ class _CommonModel(BaseModel):
660
665
  directory: DirectoryPath, optional
661
666
  File folder location
662
667
 
663
- Returns
668
+ Returns:
664
669
  -------
665
670
  list[dict[str, str | bool | ValueType | list[str] | list[float]]]
666
671
  A list of dictionaries with the data of the series
@@ -678,7 +683,7 @@ class _CommonModel(BaseModel):
678
683
  output = []
679
684
  if "label" in data:
680
685
  if what_output == "tsdf":
681
- values = self.tsdf.iloc[:, 0].tolist()
686
+ values = Series(self.tsdf.iloc[:, 0]).tolist()
682
687
  else:
683
688
  values = list(cast("list[float]", data.get("values")))
684
689
  for item in cleaner_list:
@@ -727,7 +732,7 @@ class _CommonModel(BaseModel):
727
732
  overwrite: bool, default: True
728
733
  Flag whether to overwrite an existing file
729
734
 
730
- Returns
735
+ Returns:
731
736
  -------
732
737
  str
733
738
  The Excel file path
@@ -802,7 +807,7 @@ class _CommonModel(BaseModel):
802
807
  add_logo: bool, default: True
803
808
  If True a Captor logo is added to the plot
804
809
 
805
- Returns
810
+ Returns:
806
811
  -------
807
812
  tuple[plotly.go.Figure, str]
808
813
  Plotly Figure and a div section or a html filename with location
@@ -917,7 +922,7 @@ class _CommonModel(BaseModel):
917
922
  show_last: bool, default: False
918
923
  If True the last self.tsdf point is highlighted as red dot with a label
919
924
 
920
- Returns
925
+ Returns:
921
926
  -------
922
927
  tuple[plotly.go.Figure, str]
923
928
  Plotly Figure and a div section or a html filename with location
@@ -966,7 +971,7 @@ class _CommonModel(BaseModel):
966
971
 
967
972
  for item in range(self.tsdf.shape[1]):
968
973
  figure.add_scatter(
969
- x=[self.tsdf.iloc[:, item].index[-1]],
974
+ x=[Series(self.tsdf.iloc[:, item]).index[-1]],
970
975
  y=[self.tsdf.iloc[-1, item]],
971
976
  mode="markers + text",
972
977
  marker={"color": "red", "size": 12},
@@ -1005,6 +1010,174 @@ class _CommonModel(BaseModel):
1005
1010
 
1006
1011
  return figure, string_output
1007
1012
 
1013
+ def plot_histogram(
1014
+ self: Self,
1015
+ plot_type: LiteralPlotlyHistogramPlotType = "bars",
1016
+ histnorm: LiteralPlotlyHistogramHistNorm = "percent",
1017
+ barmode: LiteralPlotlyHistogramBarMode = "overlay",
1018
+ xbins_size: float | None = None,
1019
+ opacity: float = 0.75,
1020
+ bargap: float = 0.0,
1021
+ bargroupgap: float = 0.0,
1022
+ curve_type: LiteralPlotlyHistogramCurveType = "kde",
1023
+ x_fmt: str | None = None,
1024
+ y_fmt: str | None = None,
1025
+ filename: str | None = None,
1026
+ directory: DirectoryPath | None = None,
1027
+ labels: list[str] | None = None,
1028
+ output_type: LiteralPlotlyOutput = "file",
1029
+ include_plotlyjs: LiteralPlotlyJSlib = "cdn",
1030
+ *,
1031
+ cumulative: bool = False,
1032
+ show_rug: bool = False,
1033
+ auto_open: bool = True,
1034
+ add_logo: bool = True,
1035
+ ) -> tuple[Figure, str]:
1036
+ """Create a Plotly Histogram Figure.
1037
+
1038
+ Parameters
1039
+ ----------
1040
+ plot_type: LiteralPlotlyHistogramPlotType, default: bars
1041
+ Type of plot
1042
+ histnorm: LiteralPlotlyHistogramHistNorm, default: percent
1043
+ Sets the normalization mode
1044
+ barmode: LiteralPlotlyHistogramBarMode, default: overlay
1045
+ Specifies how bar traces are displayed relative to one another
1046
+ xbins_size: float, optional
1047
+ Explicitly sets the width of each bin along the x-axis in data units
1048
+ opacity: float, default: 0.75
1049
+ Sets the trace opacity, must be between 0 (fully transparent) and 1
1050
+ bargap: float, default: 0.0
1051
+ Sets the gap between bars of adjacent location coordinates
1052
+ bargroupgap: float, default: 0.0
1053
+ Sets the gap between bar “groups” at the same location coordinate
1054
+ curve_type: LiteralPlotlyHistogramCurveType, default: kde
1055
+ Specifies the type of distribution curve to overlay on the histogram
1056
+ y_fmt: str, optional
1057
+ None, '%', '.1%' depending on number of decimals to show on the y-axis
1058
+ x_fmt: str, optional
1059
+ None, '%', '.1%' depending on number of decimals to show on the x-axis
1060
+ filename: str, optional
1061
+ Name of the Plotly html file
1062
+ directory: DirectoryPath, optional
1063
+ Directory where Plotly html file is saved
1064
+ labels: list[str], optional
1065
+ A list of labels to manually override using the names of
1066
+ the input self.tsdf
1067
+ output_type: LiteralPlotlyOutput, default: "file"
1068
+ Determines output type
1069
+ include_plotlyjs: LiteralPlotlyJSlib, default: "cdn"
1070
+ Determines how the plotly.js library is included in the output
1071
+ cumulative: bool, default: False
1072
+ Determines whether to compute a cumulative histogram
1073
+ show_rug: bool, default: False
1074
+ Determines whether to draw a rug plot alongside the distribution
1075
+ auto_open: bool, default: True
1076
+ Determines whether to open a browser window with the plot
1077
+ add_logo: bool, default: True
1078
+ If True a Captor logo is added to the plot
1079
+
1080
+ Returns:
1081
+ -------
1082
+ tuple[plotly.go.Figure, str]
1083
+ Plotly Figure and a div section or a html filename with location
1084
+
1085
+ """
1086
+ if labels:
1087
+ if len(labels) != self.tsdf.shape[1]:
1088
+ msg = "Must provide same number of labels as items in frame."
1089
+ raise NumberOfItemsAndLabelsNotSameError(msg)
1090
+ else:
1091
+ labels = list(self.tsdf.columns.get_level_values(0))
1092
+
1093
+ if directory:
1094
+ dirpath = Path(directory).resolve()
1095
+ elif Path.home().joinpath("Documents").exists():
1096
+ dirpath = Path.home().joinpath("Documents")
1097
+ else:
1098
+ dirpath = Path(stack()[1].filename).parent
1099
+
1100
+ if not filename:
1101
+ filename = "".join(choice(ascii_letters) for _ in range(6)) + ".html"
1102
+ plotfile = dirpath.joinpath(filename)
1103
+
1104
+ fig_dict, logo = load_plotly_dict()
1105
+
1106
+ hovertemplate = f"Count: %{{y:{y_fmt}}}" if y_fmt else "Count: %{y}"
1107
+
1108
+ if x_fmt:
1109
+ hovertemplate += f"<br>%{{x:{x_fmt}}}"
1110
+ else:
1111
+ hovertemplate += "<br>%{x}"
1112
+
1113
+ msg = "plot_type must be 'bars' or 'lines'."
1114
+ if plot_type == "bars":
1115
+ figure = Figure(fig_dict)
1116
+ for item in range(self.tsdf.shape[1]):
1117
+ figure.add_histogram(
1118
+ x=self.tsdf.iloc[:, item],
1119
+ cumulative={"enabled": cumulative},
1120
+ histnorm=histnorm,
1121
+ name=labels[item],
1122
+ xbins={"size": xbins_size},
1123
+ opacity=opacity,
1124
+ hovertemplate=hovertemplate,
1125
+ )
1126
+ figure.update_layout(
1127
+ barmode=barmode,
1128
+ bargap=bargap,
1129
+ bargroupgap=bargroupgap,
1130
+ )
1131
+ elif plot_type == "lines":
1132
+ hist_data = [
1133
+ cast("Series[float]", self.tsdf.loc[:, ds]).dropna().tolist()
1134
+ for ds in self.tsdf
1135
+ ]
1136
+ figure = create_distplot(
1137
+ hist_data=hist_data,
1138
+ curve_type=curve_type,
1139
+ group_labels=labels,
1140
+ show_hist=False,
1141
+ show_rug=show_rug,
1142
+ histnorm=histnorm,
1143
+ )
1144
+ figure.update_layout(dict1=fig_dict["layout"])
1145
+ else:
1146
+ raise TypeError(msg)
1147
+
1148
+ figure.update_layout(xaxis={"tickformat": x_fmt}, yaxis={"tickformat": y_fmt})
1149
+
1150
+ figure.update_xaxes(zeroline=True, zerolinewidth=2, zerolinecolor="lightgrey")
1151
+ figure.update_yaxes(zeroline=True, zerolinewidth=2, zerolinecolor="lightgrey")
1152
+
1153
+ if add_logo:
1154
+ figure.add_layout_image(logo)
1155
+
1156
+ if output_type == "file":
1157
+ plot(
1158
+ figure_or_data=figure,
1159
+ filename=str(plotfile),
1160
+ auto_open=auto_open,
1161
+ auto_play=False,
1162
+ link_text="",
1163
+ include_plotlyjs=cast("bool", include_plotlyjs),
1164
+ config=fig_dict["config"],
1165
+ output_type=output_type,
1166
+ )
1167
+ string_output = str(plotfile)
1168
+ else:
1169
+ div_id = filename.rsplit(".", 1)[0]
1170
+ string_output = to_html(
1171
+ fig=figure,
1172
+ config=fig_dict["config"],
1173
+ auto_play=False,
1174
+ include_plotlyjs=cast("bool", include_plotlyjs),
1175
+ full_html=False,
1176
+ div_id=div_id,
1177
+ )
1178
+
1179
+ return figure, string_output
1180
+
1008
1181
  def arithmetic_ret_func(
1009
1182
  self: Self,
1010
1183
  months_from_last: int | None = None,
@@ -1027,7 +1200,7 @@ class _CommonModel(BaseModel):
1027
1200
  Allows locking the periods-in-a-year to simplify test cases and
1028
1201
  comparisons
1029
1202
 
1030
- Returns
1203
+ Returns:
1031
1204
  -------
1032
1205
  float | Pandas.Series[float]
1033
1206
  Annualized arithmetic mean of returns
@@ -1046,7 +1219,7 @@ class _CommonModel(BaseModel):
1046
1219
  cast("int", earlier) : cast("int", later),
1047
1220
  self.tsdf.columns.to_numpy()[0],
1048
1221
  ].count()
1049
- time_factor = how_many / fraction
1222
+ time_factor = cast("int", how_many) / fraction
1050
1223
 
1051
1224
  result = (
1052
1225
  self.tsdf.loc[cast("int", earlier) : cast("int", later)]
@@ -1089,7 +1262,7 @@ class _CommonModel(BaseModel):
1089
1262
  periods_in_a_year_fixed : DaysInYearType, optional
1090
1263
  Allows locking the periods-in-a-year to simplify test cases and comparisons
1091
1264
 
1092
- Returns
1265
+ Returns:
1093
1266
  -------
1094
1267
  float | Pandas.Series[float]
1095
1268
  Annualized volatility
@@ -1158,7 +1331,7 @@ class _CommonModel(BaseModel):
1158
1331
  drift_adjust: bool, default: False
1159
1332
  An adjustment to remove the bias implied by the average return
1160
1333
 
1161
- Returns
1334
+ Returns:
1162
1335
  -------
1163
1336
  float | Pandas.Series[float]
1164
1337
  Implied annualized volatility from the Downside VaR using the
@@ -1219,7 +1392,7 @@ class _CommonModel(BaseModel):
1219
1392
  drift_adjust: bool, default: False
1220
1393
  An adjustment to remove the bias implied by the average return
1221
1394
 
1222
- Returns
1395
+ Returns:
1223
1396
  -------
1224
1397
  float | Pandas.Series[float]
1225
1398
  A position weight multiplier from the ratio between a VaR implied
@@ -1285,7 +1458,7 @@ class _CommonModel(BaseModel):
1285
1458
  drift_adjust: bool, default: False
1286
1459
  An adjustment to remove the bias implied by the average return
1287
1460
 
1288
- Returns
1461
+ Returns:
1289
1462
  -------
1290
1463
  float | Pandas.Series[float]
1291
1464
  Target volatility if target_vol is provided otherwise the VaR
@@ -1377,7 +1550,7 @@ class _CommonModel(BaseModel):
1377
1550
  to_date : datetime.date, optional
1378
1551
  Specific to date
1379
1552
 
1380
- Returns
1553
+ Returns:
1381
1554
  -------
1382
1555
  float | Pandas.Series[float]
1383
1556
  Downside Conditional Value At Risk "CVaR"
@@ -1392,14 +1565,14 @@ class _CommonModel(BaseModel):
1392
1565
  deep=True
1393
1566
  )
1394
1567
  result = [
1395
- cvar_df.loc[:, x] # type: ignore[call-overload,index,unused-ignore]
1568
+ cvar_df.loc[:, x] # type: ignore[call-overload,index]
1396
1569
  .ffill()
1397
1570
  .pct_change()
1398
1571
  .sort_values()
1399
1572
  .iloc[
1400
1573
  : ceil(
1401
1574
  (1 - level)
1402
- * cvar_df.loc[:, x] # type: ignore[index,unused-ignore]
1575
+ * cvar_df.loc[:, x] # type: ignore[index]
1403
1576
  .ffill()
1404
1577
  .pct_change()
1405
1578
  .count(),
@@ -1446,7 +1619,7 @@ class _CommonModel(BaseModel):
1446
1619
  Allows locking the periods-in-a-year to simplify test cases and
1447
1620
  comparisons
1448
1621
 
1449
- Returns
1622
+ Returns:
1450
1623
  -------
1451
1624
  float | Pandas.Series[float]
1452
1625
  Downside deviation
@@ -1514,7 +1687,7 @@ class _CommonModel(BaseModel):
1514
1687
  to_date : datetime.date, optional
1515
1688
  Specific to date
1516
1689
 
1517
- Returns
1690
+ Returns:
1518
1691
  -------
1519
1692
  float | Pandas.Series[float]
1520
1693
  Compounded Annual Growth Rate (CAGR)
@@ -1529,7 +1702,7 @@ class _CommonModel(BaseModel):
1529
1702
  fraction = (later - earlier).days / 365.25
1530
1703
 
1531
1704
  any_below_zero = any(
1532
- self.tsdf.loc[[earlier, later]] # type: ignore[index,unused-ignore]
1705
+ self.tsdf.loc[[earlier, later]] # type: ignore[index]
1533
1706
  .lt(0.0)
1534
1707
  .any()
1535
1708
  .to_numpy()
@@ -1572,7 +1745,7 @@ class _CommonModel(BaseModel):
1572
1745
  to_date : datetime.date, optional
1573
1746
  Specific to date
1574
1747
 
1575
- Returns
1748
+ Returns:
1576
1749
  -------
1577
1750
  float | Pandas.Series[float]
1578
1751
  Skew of the return distribution
@@ -1621,7 +1794,7 @@ class _CommonModel(BaseModel):
1621
1794
  to_date : datetime.date, optional
1622
1795
  Specific to date
1623
1796
 
1624
- Returns
1797
+ Returns:
1625
1798
  -------
1626
1799
  float | Pandas.Series[float]
1627
1800
  Kurtosis of the return distribution
@@ -1675,7 +1848,7 @@ class _CommonModel(BaseModel):
1675
1848
  min_periods: int, default: 1
1676
1849
  Smallest number of observations to use to find the maximum drawdown
1677
1850
 
1678
- Returns
1851
+ Returns:
1679
1852
  -------
1680
1853
  float | Pandas.Series[float]
1681
1854
  Maximum drawdown without any limit on date range
@@ -1719,7 +1892,7 @@ class _CommonModel(BaseModel):
1719
1892
  to_date : datetime.date, optional
1720
1893
  Specific to date
1721
1894
 
1722
- Returns
1895
+ Returns:
1723
1896
  -------
1724
1897
  float | Pandas.Series[float]
1725
1898
  Calculate share of percentage changes that are greater than zero
@@ -1789,7 +1962,7 @@ class _CommonModel(BaseModel):
1789
1962
  Allows locking the periods-in-a-year to simplify test cases and
1790
1963
  comparisons
1791
1964
 
1792
- Returns
1965
+ Returns:
1793
1966
  -------
1794
1967
  float | Pandas.Series[float]
1795
1968
  Ratio of the annualized arithmetic mean of returns and annualized
@@ -1854,7 +2027,7 @@ class _CommonModel(BaseModel):
1854
2027
  Allows locking the periods-in-a-year to simplify test cases and
1855
2028
  comparisons
1856
2029
 
1857
- Returns
2030
+ Returns:
1858
2031
  -------
1859
2032
  float | Pandas.Series[float]
1860
2033
  Sortino ratio calculated as ( return - riskfree return ) /
@@ -1912,7 +2085,7 @@ class _CommonModel(BaseModel):
1912
2085
  to_date : datetime.date, optional
1913
2086
  Specific to date
1914
2087
 
1915
- Returns
2088
+ Returns:
1916
2089
  -------
1917
2090
  float | Pandas.Series[float]
1918
2091
  Omega ratio calculation
@@ -1959,7 +2132,7 @@ class _CommonModel(BaseModel):
1959
2132
  to_date : datetime.date, optional
1960
2133
  Specific to date
1961
2134
 
1962
- Returns
2135
+ Returns:
1963
2136
  -------
1964
2137
  float | Pandas.Series[float]
1965
2138
  Calculate simple return
@@ -2003,7 +2176,7 @@ class _CommonModel(BaseModel):
2003
2176
  month : int, optional
2004
2177
  Calendar month of the period to calculate.
2005
2178
 
2006
- Returns
2179
+ Returns:
2007
2180
  -------
2008
2181
  float | Pandas.Series[float]
2009
2182
  Calculate simple return for a specific calendar period
@@ -2054,7 +2227,7 @@ class _CommonModel(BaseModel):
2054
2227
  interpolation: LiteralQuantileInterp, default: "lower"
2055
2228
  Type of interpolation in Pandas.DataFrame.quantile() function.
2056
2229
 
2057
- Returns
2230
+ Returns:
2058
2231
  -------
2059
2232
  float | Pandas.Series[float]
2060
2233
  Downside Value At Risk
@@ -2102,7 +2275,7 @@ class _CommonModel(BaseModel):
2102
2275
  to_date : datetime.date, optional
2103
2276
  Specific to date
2104
2277
 
2105
- Returns
2278
+ Returns:
2106
2279
  -------
2107
2280
  float | Pandas.Series[float]
2108
2281
  Most negative percentage change over a rolling number of observations
@@ -2152,7 +2325,7 @@ class _CommonModel(BaseModel):
2152
2325
  to_date : datetime.date, optional
2153
2326
  Specific to date
2154
2327
 
2155
- Returns
2328
+ Returns:
2156
2329
  -------
2157
2330
  float | Pandas.Series[float]
2158
2331
  Z-score as (last return - mean return) / standard deviation of returns
@@ -2196,7 +2369,7 @@ class _CommonModel(BaseModel):
2196
2369
  observations: int, default: 252
2197
2370
  Number of observations in the overlapping window.
2198
2371
 
2199
- Returns
2372
+ Returns:
2200
2373
  -------
2201
2374
  Pandas.DataFrame
2202
2375
  Calculate rolling annualized downside CVaR
@@ -2204,7 +2377,7 @@ class _CommonModel(BaseModel):
2204
2377
  """
2205
2378
  cvar_label = cast("tuple[str]", self.tsdf.iloc[:, column].name)[0]
2206
2379
  cvarseries = (
2207
- self.tsdf.iloc[:, column]
2380
+ Series(self.tsdf.iloc[:, column])
2208
2381
  .rolling(observations, min_periods=observations)
2209
2382
  .apply(lambda x: _cvar_down_calc(x, level=level))
2210
2383
  )
@@ -2227,7 +2400,7 @@ class _CommonModel(BaseModel):
2227
2400
  observations: int, default: 21
2228
2401
  Number of observations in the overlapping window.
2229
2402
 
2230
- Returns
2403
+ Returns:
2231
2404
  -------
2232
2405
  Pandas.DataFrame
2233
2406
  Calculate rolling returns
@@ -2235,7 +2408,7 @@ class _CommonModel(BaseModel):
2235
2408
  """
2236
2409
  ret_label = cast("tuple[str]", self.tsdf.iloc[:, column].name)[0]
2237
2410
  retseries = (
2238
- self.tsdf.iloc[:, column]
2411
+ Series(self.tsdf.iloc[:, column])
2239
2412
  .ffill()
2240
2413
  .pct_change()
2241
2414
  .rolling(observations, min_periods=observations)
@@ -2266,7 +2439,7 @@ class _CommonModel(BaseModel):
2266
2439
  interpolation: LiteralQuantileInterp, default: "lower"
2267
2440
  Type of interpolation in Pandas.DataFrame.quantile() function.
2268
2441
 
2269
- Returns
2442
+ Returns:
2270
2443
  -------
2271
2444
  Pandas.DataFrame
2272
2445
  Calculate rolling annualized downside Value At Risk "VaR"
@@ -2274,7 +2447,7 @@ class _CommonModel(BaseModel):
2274
2447
  """
2275
2448
  var_label = cast("tuple[str]", self.tsdf.iloc[:, column].name)[0]
2276
2449
  varseries = (
2277
- self.tsdf.iloc[:, column]
2450
+ Series(self.tsdf.iloc[:, column])
2278
2451
  .rolling(observations, min_periods=observations)
2279
2452
  .apply(
2280
2453
  lambda x: _var_down_calc(x, level=level, interpolation=interpolation),
@@ -2303,7 +2476,7 @@ class _CommonModel(BaseModel):
2303
2476
  Allows locking the periods-in-a-year to simplify test cases and
2304
2477
  comparisons
2305
2478
 
2306
- Returns
2479
+ Returns:
2307
2480
  -------
2308
2481
  Pandas.DataFrame
2309
2482
  Calculate rolling annualised volatilities
@@ -2314,7 +2487,7 @@ class _CommonModel(BaseModel):
2314
2487
  else:
2315
2488
  time_factor = self.periods_in_a_year
2316
2489
  vol_label = cast("tuple[str, ValueType]", self.tsdf.iloc[:, column].name)[0]
2317
- dframe = self.tsdf.iloc[:, column].ffill().pct_change()
2490
+ dframe = Series(self.tsdf.iloc[:, column]).ffill().pct_change()
2318
2491
  volseries = dframe.rolling(
2319
2492
  observations,
2320
2493
  min_periods=observations,