openseries 1.8.0__py3-none-any.whl → 1.8.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
openseries/frame.py CHANGED
@@ -1,17 +1,21 @@
1
1
  """Defining the OpenFrame class."""
2
2
 
3
- # mypy: disable-error-code="index,assignment,arg-type"
3
+ # mypy: disable-error-code="index,assignment,arg-type,no-any-return"
4
4
  from __future__ import annotations
5
5
 
6
6
  from copy import deepcopy
7
7
  from functools import reduce
8
- from logging import warning
8
+ from logging import getLogger
9
9
  from typing import TYPE_CHECKING, cast
10
10
 
11
- if TYPE_CHECKING:
12
- import datetime as dt # pragma: no cover
11
+ if TYPE_CHECKING: # pragma: no cover
12
+ import datetime as dt
13
13
 
14
- import statsmodels.api as sm # type: ignore[import-untyped,unused-ignore]
14
+ from statsmodels.regression.linear_model import ( # type: ignore[import-untyped]
15
+ OLSResults,
16
+ )
17
+
18
+ import statsmodels.api as sm # type: ignore[import-untyped]
15
19
  from numpy import (
16
20
  array,
17
21
  cov,
@@ -27,7 +31,6 @@ from pandas import (
27
31
  DataFrame,
28
32
  DatetimeIndex,
29
33
  Index,
30
- Int64Dtype,
31
34
  MultiIndex,
32
35
  Series,
33
36
  concat,
@@ -35,17 +38,12 @@ from pandas import (
35
38
  )
36
39
  from pydantic import field_validator
37
40
 
38
- # noinspection PyProtectedMember
39
- from statsmodels.regression.linear_model import ( # type: ignore[import-untyped,unused-ignore]
40
- OLSResults,
41
- )
42
- from typing_extensions import Self
43
-
44
41
  from ._common_model import _CommonModel
45
42
  from .datefixer import _do_resample_to_business_period_ends
46
43
  from .owntypes import (
47
44
  CountriesType,
48
45
  DaysInYearType,
46
+ LabelsNotUniqueError,
49
47
  LiteralBizDayFreq,
50
48
  LiteralCaptureRatio,
51
49
  LiteralFrameProps,
@@ -55,11 +53,18 @@ from .owntypes import (
55
53
  LiteralPandasReindexMethod,
56
54
  LiteralPortfolioWeightings,
57
55
  LiteralTrunc,
56
+ MergingResultedInEmptyError,
57
+ MixedValuetypesError,
58
+ NoWeightsError,
58
59
  OpenFramePropertiesList,
60
+ RatioInputError,
61
+ Self,
59
62
  ValueType,
60
63
  )
61
64
  from .series import OpenTimeSeries
62
65
 
66
+ logger = getLogger(__name__)
67
+
63
68
  __all__ = ["OpenFrame"]
64
69
 
65
70
 
@@ -76,7 +81,7 @@ class OpenFrame(_CommonModel):
76
81
  weights: list[float], optional
77
82
  List of weights in float format.
78
83
 
79
- Returns
84
+ Returns:
80
85
  -------
81
86
  OpenFrame
82
87
  Object of the class OpenFrame
@@ -89,7 +94,7 @@ class OpenFrame(_CommonModel):
89
94
 
90
95
  # noinspection PyMethodParameters
91
96
  @field_validator("constituents") # type: ignore[misc]
92
- def _check_labels_unique(
97
+ def _check_labels_unique( # type: ignore[misc]
93
98
  cls: OpenFrame, # noqa: N805
94
99
  tseries: list[OpenTimeSeries],
95
100
  ) -> list[OpenTimeSeries]:
@@ -97,7 +102,7 @@ class OpenFrame(_CommonModel):
97
102
  labls = [x.label for x in tseries]
98
103
  if len(set(labls)) != len(labls):
99
104
  msg = "TimeSeries names/labels must be unique"
100
- raise ValueError(msg)
105
+ raise LabelsNotUniqueError(msg)
101
106
  return tseries
102
107
 
103
108
  def __init__(
@@ -116,7 +121,7 @@ class OpenFrame(_CommonModel):
116
121
  weights: list[float], optional
117
122
  List of weights in float format.
118
123
 
119
- Returns
124
+ Returns:
120
125
  -------
121
126
  OpenFrame
122
127
  Object of the class OpenFrame
@@ -139,12 +144,12 @@ class OpenFrame(_CommonModel):
139
144
  [x.tsdf for x in self.constituents],
140
145
  )
141
146
  else:
142
- warning("OpenFrame() was passed an empty list.")
147
+ logger.warning("OpenFrame() was passed an empty list.")
143
148
 
144
149
  def from_deepcopy(self: Self) -> Self:
145
150
  """Create copy of the OpenFrame object.
146
151
 
147
- Returns
152
+ Returns:
148
153
  -------
149
154
  OpenFrame
150
155
  An OpenFrame object
@@ -163,7 +168,7 @@ class OpenFrame(_CommonModel):
163
168
  how: LiteralHowMerge, default: "outer"
164
169
  The Pandas merge method.
165
170
 
166
- Returns
171
+ Returns:
167
172
  -------
168
173
  OpenFrame
169
174
  An OpenFrame object
@@ -189,7 +194,7 @@ class OpenFrame(_CommonModel):
189
194
  "Merging OpenTimeSeries DataFrames with "
190
195
  f"argument how={how} produced an empty DataFrame."
191
196
  )
192
- raise ValueError(msg)
197
+ raise MergingResultedInEmptyError(msg)
193
198
 
194
199
  if how == "inner":
195
200
  for xerie in self.constituents:
@@ -207,7 +212,7 @@ class OpenFrame(_CommonModel):
207
212
  properties: list[LiteralFrameProps], optional
208
213
  The properties to calculate. Defaults to calculating all available.
209
214
 
210
- Returns
215
+ Returns:
211
216
  -------
212
217
  pandas.DataFrame
213
218
  Properties of the contituent OpenTimeSeries
@@ -220,30 +225,29 @@ class OpenFrame(_CommonModel):
220
225
  prop_list = [
221
226
  getattr(self, x) for x in OpenFramePropertiesList.allowed_strings
222
227
  ]
223
- return cast(DataFrame, concat(prop_list, axis="columns").T)
228
+ return cast("DataFrame", concat(prop_list, axis="columns").T)
224
229
 
225
230
  @property
226
231
  def lengths_of_items(self: Self) -> Series[int]:
227
232
  """Number of observations of all constituents.
228
233
 
229
- Returns
234
+ Returns:
230
235
  -------
231
236
  Pandas.Series[int]
232
237
  Number of observations of all constituents
233
238
 
234
239
  """
235
240
  return Series(
236
- data=[int(self.tsdf.loc[:, d].count()) for d in self.tsdf],
241
+ data=[self.tsdf.loc[:, d].count() for d in self.tsdf],
237
242
  index=self.tsdf.columns,
238
243
  name="observations",
239
- dtype=Int64Dtype(),
240
- )
244
+ ).astype(int)
241
245
 
242
246
  @property
243
247
  def item_count(self: Self) -> int:
244
248
  """Number of constituents.
245
249
 
246
- Returns
250
+ Returns:
247
251
  -------
248
252
  int
249
253
  Number of constituents
@@ -255,7 +259,7 @@ class OpenFrame(_CommonModel):
255
259
  def columns_lvl_zero(self: Self) -> list[str]:
256
260
  """Level 0 values of the MultiIndex columns in the .tsdf DataFrame.
257
261
 
258
- Returns
262
+ Returns:
259
263
  -------
260
264
  list[str]
261
265
  Level 0 values of the MultiIndex columns in the .tsdf DataFrame
@@ -267,7 +271,7 @@ class OpenFrame(_CommonModel):
267
271
  def columns_lvl_one(self: Self) -> list[ValueType]:
268
272
  """Level 1 values of the MultiIndex columns in the .tsdf DataFrame.
269
273
 
270
- Returns
274
+ Returns:
271
275
  -------
272
276
  list[ValueType]
273
277
  Level 1 values of the MultiIndex columns in the .tsdf DataFrame
@@ -279,7 +283,7 @@ class OpenFrame(_CommonModel):
279
283
  def first_indices(self: Self) -> Series[dt.date]:
280
284
  """The first dates in the timeseries of all constituents.
281
285
 
282
- Returns
286
+ Returns:
283
287
  -------
284
288
  Pandas.Series[dt.date]
285
289
  The first dates in the timeseries of all constituents
@@ -296,7 +300,7 @@ class OpenFrame(_CommonModel):
296
300
  def last_indices(self: Self) -> Series[dt.date]:
297
301
  """The last dates in the timeseries of all constituents.
298
302
 
299
- Returns
303
+ Returns:
300
304
  -------
301
305
  Pandas.Series[dt.date]
302
306
  The last dates in the timeseries of all constituents
@@ -313,7 +317,7 @@ class OpenFrame(_CommonModel):
313
317
  def span_of_days_all(self: Self) -> Series[int]:
314
318
  """Number of days from the first date to the last for all items in the frame.
315
319
 
316
- Returns
320
+ Returns:
317
321
  -------
318
322
  Pandas.Series[int]
319
323
  Number of days from the first date to the last for all
@@ -324,13 +328,12 @@ class OpenFrame(_CommonModel):
324
328
  data=[c.span_of_days for c in self.constituents],
325
329
  index=self.tsdf.columns,
326
330
  name="span of days",
327
- dtype=Int64Dtype(),
328
- )
331
+ ).astype(int)
329
332
 
330
333
  def value_to_ret(self: Self) -> Self:
331
334
  """Convert series of values into series of returns.
332
335
 
333
- Returns
336
+ Returns:
334
337
  -------
335
338
  OpenFrame
336
339
  The returns of the values in the series
@@ -353,7 +356,7 @@ class OpenFrame(_CommonModel):
353
356
  The number of periods between observations over which difference
354
357
  is calculated
355
358
 
356
- Returns
359
+ Returns:
357
360
  -------
358
361
  OpenFrame
359
362
  An OpenFrame object
@@ -369,7 +372,7 @@ class OpenFrame(_CommonModel):
369
372
  def to_cumret(self: Self) -> Self:
370
373
  """Convert series of returns into cumulative series of values.
371
374
 
372
- Returns
375
+ Returns:
373
376
  -------
374
377
  OpenFrame
375
378
  An OpenFrame object
@@ -384,7 +387,7 @@ class OpenFrame(_CommonModel):
384
387
  returns.iloc[0] = 0
385
388
  else:
386
389
  msg = "Mix of series types will give inconsistent results"
387
- raise ValueError(msg)
390
+ raise MixedValuetypesError(msg)
388
391
 
389
392
  returns = returns.add(1.0)
390
393
  self.tsdf = returns.cumprod(axis=0) / returns.iloc[0]
@@ -405,7 +408,7 @@ class OpenFrame(_CommonModel):
405
408
  freq: LiteralBizDayFreq | str, default "BME"
406
409
  The date offset string that sets the resampled frequency
407
410
 
408
- Returns
411
+ Returns:
409
412
  -------
410
413
  OpenFrame
411
414
  An OpenFrame object
@@ -443,7 +446,7 @@ class OpenFrame(_CommonModel):
443
446
  method: LiteralPandasReindexMethod, default: nearest
444
447
  Controls the method used to align values across columns
445
448
 
446
- Returns
449
+ Returns:
447
450
  -------
448
451
  OpenFrame
449
452
  An OpenFrame object
@@ -511,7 +514,7 @@ class OpenFrame(_CommonModel):
511
514
  Allows locking the periods-in-a-year to simplify test cases and
512
515
  comparisons
513
516
 
514
- Returns
517
+ Returns:
515
518
  -------
516
519
  Pandas.DataFrame
517
520
  Series volatilities and correlation
@@ -521,23 +524,25 @@ class OpenFrame(_CommonModel):
521
524
  if periods_in_a_year_fixed is None:
522
525
  fraction = (later - earlier).days / 365.25
523
526
  how_many = (
524
- self.tsdf.loc[cast(int, earlier) : cast(int, later)].count().iloc[0]
527
+ self.tsdf.loc[cast("int", earlier) : cast("int", later)]
528
+ .count()
529
+ .iloc[0]
525
530
  )
526
531
  time_factor = how_many / fraction
527
532
  else:
528
533
  time_factor = periods_in_a_year_fixed
529
534
 
530
535
  corr_label = (
531
- cast(tuple[str, str], self.tsdf.iloc[:, first_column].name)[0]
536
+ cast("tuple[str, str]", self.tsdf.iloc[:, first_column].name)[0]
532
537
  + "_VS_"
533
- + cast(tuple[str, str], self.tsdf.iloc[:, second_column].name)[0]
538
+ + cast("tuple[str, str]", self.tsdf.iloc[:, second_column].name)[0]
534
539
  )
535
540
  cols = [
536
- cast(tuple[str, str], self.tsdf.iloc[:, first_column].name)[0],
537
- cast(tuple[str, str], self.tsdf.iloc[:, second_column].name)[0],
541
+ cast("tuple[str, str]", self.tsdf.iloc[:, first_column].name)[0],
542
+ cast("tuple[str, str]", self.tsdf.iloc[:, second_column].name)[0],
538
543
  ]
539
544
 
540
- data = self.tsdf.loc[cast(int, earlier) : cast(int, later)].copy()
545
+ data = self.tsdf.loc[cast("int", earlier) : cast("int", later)].copy()
541
546
 
542
547
  for rtn in cols:
543
548
  data[rtn, ValueType.RTRN] = (
@@ -597,7 +602,7 @@ class OpenFrame(_CommonModel):
597
602
  def correl_matrix(self: Self) -> DataFrame:
598
603
  """Correlation matrix.
599
604
 
600
- Returns
605
+ Returns:
601
606
  -------
602
607
  Pandas.DataFrame
603
608
  Correlation matrix
@@ -627,7 +632,7 @@ class OpenFrame(_CommonModel):
627
632
  new_series: OpenTimeSeries
628
633
  The timeseries to add
629
634
 
630
- Returns
635
+ Returns:
631
636
  -------
632
637
  OpenFrame
633
638
  An OpenFrame object
@@ -645,7 +650,7 @@ class OpenFrame(_CommonModel):
645
650
  lvl_zero_item: str
646
651
  The .tsdf column level 0 value of the timeseries to delete
647
652
 
648
- Returns
653
+ Returns:
649
654
  -------
650
655
  OpenFrame
651
656
  An OpenFrame object
@@ -684,7 +689,7 @@ class OpenFrame(_CommonModel):
684
689
  Determines where dataframe is truncated also when start_cut
685
690
  or end_cut is None.
686
691
 
687
- Returns
692
+ Returns:
688
693
  -------
689
694
  OpenFrame
690
695
  An OpenFrame object
@@ -709,14 +714,14 @@ class OpenFrame(_CommonModel):
709
714
  f"not truncated to same start dates.\n"
710
715
  f"{self.tsdf.head()}"
711
716
  )
712
- warning(msg=msg)
717
+ logger.warning(msg=msg)
713
718
  if len(set(self.last_indices)) != 1:
714
719
  msg = (
715
720
  f"One or more constituents still "
716
721
  f"not truncated to same end dates.\n"
717
722
  f"{self.tsdf.tail()}"
718
723
  )
719
- warning(msg=msg)
724
+ logger.warning(msg=msg)
720
725
  return self
721
726
 
722
727
  def relative(
@@ -740,9 +745,9 @@ class OpenFrame(_CommonModel):
740
745
 
741
746
  """
742
747
  rel_label = (
743
- cast(tuple[str, str], self.tsdf.iloc[:, long_column].name)[0]
748
+ cast("tuple[str, str]", self.tsdf.iloc[:, long_column].name)[0]
744
749
  + "_over_"
745
- + cast(tuple[str, str], self.tsdf.iloc[:, short_column].name)[0]
750
+ + cast("tuple[str, str]", self.tsdf.iloc[:, short_column].name)[0]
746
751
  )
747
752
  if base_zero:
748
753
  self.tsdf[rel_label, ValueType.RELRTRN] = (
@@ -785,7 +790,7 @@ class OpenFrame(_CommonModel):
785
790
  Allows locking the periods-in-a-year to simplify test cases and
786
791
  comparisons
787
792
 
788
- Returns
793
+ Returns:
789
794
  -------
790
795
  Pandas.Series[float]
791
796
  Tracking Errors
@@ -796,17 +801,17 @@ class OpenFrame(_CommonModel):
796
801
 
797
802
  msg = "base_column should be a tuple[str, ValueType] or an integer."
798
803
  if isinstance(base_column, tuple):
799
- shortdf = self.tsdf.loc[cast(int, earlier) : cast(int, later)].loc[
804
+ shortdf = self.tsdf.loc[cast("int", earlier) : cast("int", later)].loc[
800
805
  :,
801
806
  base_column,
802
807
  ]
803
808
  short_item = base_column
804
809
  short_label = cast(
805
- tuple[str, ValueType],
810
+ "tuple[str, ValueType]",
806
811
  self.tsdf.loc[:, base_column].name,
807
812
  )[0]
808
813
  elif isinstance(base_column, int):
809
- shortdf = self.tsdf.loc[cast(int, earlier) : cast(int, later)].iloc[
814
+ shortdf = self.tsdf.loc[cast("int", earlier) : cast("int", later)].iloc[
810
815
  :,
811
816
  base_column,
812
817
  ]
@@ -814,7 +819,9 @@ class OpenFrame(_CommonModel):
814
819
  :,
815
820
  base_column,
816
821
  ].name
817
- short_label = cast(tuple[str, str], self.tsdf.iloc[:, base_column].name)[0]
822
+ short_label = cast("tuple[str, str]", self.tsdf.iloc[:, base_column].name)[
823
+ 0
824
+ ]
818
825
  else:
819
826
  raise TypeError(msg)
820
827
 
@@ -828,7 +835,7 @@ class OpenFrame(_CommonModel):
828
835
  if item == short_item:
829
836
  terrors.append(0.0)
830
837
  else:
831
- longdf = self.tsdf.loc[cast(int, earlier) : cast(int, later)].loc[
838
+ longdf = self.tsdf.loc[cast("int", earlier) : cast("int", later)].loc[
832
839
  :,
833
840
  item,
834
841
  ]
@@ -875,7 +882,7 @@ class OpenFrame(_CommonModel):
875
882
  Allows locking the periods-in-a-year to simplify test cases and
876
883
  comparisons
877
884
 
878
- Returns
885
+ Returns:
879
886
  -------
880
887
  Pandas.Series[float]
881
888
  Information Ratios
@@ -886,17 +893,17 @@ class OpenFrame(_CommonModel):
886
893
 
887
894
  msg = "base_column should be a tuple[str, ValueType] or an integer."
888
895
  if isinstance(base_column, tuple):
889
- shortdf = self.tsdf.loc[cast(int, earlier) : cast(int, later)].loc[
896
+ shortdf = self.tsdf.loc[cast("int", earlier) : cast("int", later)].loc[
890
897
  :,
891
898
  base_column,
892
899
  ]
893
900
  short_item = base_column
894
901
  short_label = cast(
895
- tuple[str, str],
902
+ "tuple[str, str]",
896
903
  self.tsdf.loc[:, base_column].name,
897
904
  )[0]
898
905
  elif isinstance(base_column, int):
899
- shortdf = self.tsdf.loc[cast(int, earlier) : cast(int, later)].iloc[
906
+ shortdf = self.tsdf.loc[cast("int", earlier) : cast("int", later)].iloc[
900
907
  :,
901
908
  base_column,
902
909
  ]
@@ -904,7 +911,9 @@ class OpenFrame(_CommonModel):
904
911
  :,
905
912
  base_column,
906
913
  ].name
907
- short_label = cast(tuple[str, str], self.tsdf.iloc[:, base_column].name)[0]
914
+ short_label = cast("tuple[str, str]", self.tsdf.iloc[:, base_column].name)[
915
+ 0
916
+ ]
908
917
  else:
909
918
  raise TypeError(msg)
910
919
 
@@ -918,7 +927,7 @@ class OpenFrame(_CommonModel):
918
927
  if item == short_item:
919
928
  ratios.append(0.0)
920
929
  else:
921
- longdf = self.tsdf.loc[cast(int, earlier) : cast(int, later)].loc[
930
+ longdf = self.tsdf.loc[cast("int", earlier) : cast("int", later)].loc[
922
931
  :,
923
932
  item,
924
933
  ]
@@ -938,7 +947,7 @@ class OpenFrame(_CommonModel):
938
947
  dtype="float64",
939
948
  )
940
949
 
941
- def capture_ratio_func( # noqa: C901
950
+ def capture_ratio_func(
942
951
  self: Self,
943
952
  ratio: LiteralCaptureRatio,
944
953
  base_column: tuple[str, ValueType] | int = -1,
@@ -975,7 +984,7 @@ class OpenFrame(_CommonModel):
975
984
  Allows locking the periods-in-a-year to simplify test cases and
976
985
  comparisons
977
986
 
978
- Returns
987
+ Returns:
979
988
  -------
980
989
  Pandas.Series[float]
981
990
  Capture Ratios
@@ -987,17 +996,17 @@ class OpenFrame(_CommonModel):
987
996
 
988
997
  msg = "base_column should be a tuple[str, ValueType] or an integer."
989
998
  if isinstance(base_column, tuple):
990
- shortdf = self.tsdf.loc[cast(int, earlier) : cast(int, later)].loc[
999
+ shortdf = self.tsdf.loc[cast("int", earlier) : cast("int", later)].loc[
991
1000
  :,
992
1001
  base_column,
993
1002
  ]
994
1003
  short_item = base_column
995
1004
  short_label = cast(
996
- tuple[str, str],
1005
+ "tuple[str, str]",
997
1006
  self.tsdf.loc[:, base_column].name,
998
1007
  )[0]
999
1008
  elif isinstance(base_column, int):
1000
- shortdf = self.tsdf.loc[cast(int, earlier) : cast(int, later)].iloc[
1009
+ shortdf = self.tsdf.loc[cast("int", earlier) : cast("int", later)].iloc[
1001
1010
  :,
1002
1011
  base_column,
1003
1012
  ]
@@ -1005,7 +1014,9 @@ class OpenFrame(_CommonModel):
1005
1014
  :,
1006
1015
  base_column,
1007
1016
  ].name
1008
- short_label = cast(tuple[str, str], self.tsdf.iloc[:, base_column].name)[0]
1017
+ short_label = cast("tuple[str, str]", self.tsdf.iloc[:, base_column].name)[
1018
+ 0
1019
+ ]
1009
1020
  else:
1010
1021
  raise TypeError(msg)
1011
1022
 
@@ -1019,7 +1030,7 @@ class OpenFrame(_CommonModel):
1019
1030
  if item == short_item:
1020
1031
  ratios.append(0.0)
1021
1032
  else:
1022
- longdf = self.tsdf.loc[cast(int, earlier) : cast(int, later)].loc[
1033
+ longdf = self.tsdf.loc[cast("int", earlier) : cast("int", later)].loc[
1023
1034
  :,
1024
1035
  item,
1025
1036
  ]
@@ -1119,7 +1130,7 @@ class OpenFrame(_CommonModel):
1119
1130
  (up_rtrn / up_idx_return) / (down_return / down_idx_return),
1120
1131
  )
1121
1132
  else:
1122
- raise ValueError(msg)
1133
+ raise RatioInputError(msg)
1123
1134
 
1124
1135
  if ratio == "up":
1125
1136
  resultname = f"Up Capture Ratios vs {short_label}"
@@ -1155,7 +1166,7 @@ class OpenFrame(_CommonModel):
1155
1166
  dlta_degr_freedms: int, default: 1
1156
1167
  Variance bias factor taking the value 0 or 1.
1157
1168
 
1158
- Returns
1169
+ Returns:
1159
1170
  -------
1160
1171
  float
1161
1172
  Beta as Co-variance of x & y divided by Variance of x
@@ -1188,7 +1199,7 @@ class OpenFrame(_CommonModel):
1188
1199
  )
1189
1200
  elif isinstance(asset, int):
1190
1201
  y_value = log(
1191
- self.tsdf.iloc[:, asset] / cast(float, self.tsdf.iloc[0, asset]),
1202
+ self.tsdf.iloc[:, asset] / cast("float", self.tsdf.iloc[0, asset]),
1192
1203
  )
1193
1204
  else:
1194
1205
  raise TypeError(msg)
@@ -1200,7 +1211,8 @@ class OpenFrame(_CommonModel):
1200
1211
  )
1201
1212
  elif isinstance(market, int):
1202
1213
  x_value = log(
1203
- self.tsdf.iloc[:, market] / cast(float, self.tsdf.iloc[0, market]),
1214
+ self.tsdf.iloc[:, market]
1215
+ / cast("float", self.tsdf.iloc[0, market]),
1204
1216
  )
1205
1217
  else:
1206
1218
  raise TypeError(msg)
@@ -1238,7 +1250,7 @@ class OpenFrame(_CommonModel):
1238
1250
  fitted_series: bool, default: True
1239
1251
  If True the fit is added as a new column in the .tsdf Pandas.DataFrame
1240
1252
 
1241
- Returns
1253
+ Returns:
1242
1254
  -------
1243
1255
  OLSResults
1244
1256
  The Statsmodels regression output
@@ -1248,12 +1260,12 @@ class OpenFrame(_CommonModel):
1248
1260
  if isinstance(y_column, tuple):
1249
1261
  y_value = self.tsdf.loc[:, y_column]
1250
1262
  y_label = cast(
1251
- tuple[str, str],
1263
+ "tuple[str, str]",
1252
1264
  self.tsdf.loc[:, y_column].name,
1253
1265
  )[0]
1254
1266
  elif isinstance(y_column, int):
1255
1267
  y_value = self.tsdf.iloc[:, y_column]
1256
- y_label = cast(tuple[str, str], self.tsdf.iloc[:, y_column].name)[0]
1268
+ y_label = cast("tuple[str, str]", self.tsdf.iloc[:, y_column].name)[0]
1257
1269
  else:
1258
1270
  raise TypeError(msg)
1259
1271
 
@@ -1261,12 +1273,12 @@ class OpenFrame(_CommonModel):
1261
1273
  if isinstance(x_column, tuple):
1262
1274
  x_value = self.tsdf.loc[:, x_column]
1263
1275
  x_label = cast(
1264
- tuple[str, str],
1276
+ "tuple[str, str]",
1265
1277
  self.tsdf.loc[:, x_column].name,
1266
1278
  )[0]
1267
1279
  elif isinstance(x_column, int):
1268
1280
  x_value = self.tsdf.iloc[:, x_column]
1269
- x_label = cast(tuple[str, str], self.tsdf.iloc[:, x_column].name)[0]
1281
+ x_label = cast("tuple[str, str]", self.tsdf.iloc[:, x_column].name)[0]
1270
1282
  else:
1271
1283
  raise TypeError(msg)
1272
1284
 
@@ -1274,9 +1286,9 @@ class OpenFrame(_CommonModel):
1274
1286
  if fitted_series:
1275
1287
  self.tsdf[y_label, x_label] = results.predict(x_value)
1276
1288
 
1277
- return cast(OLSResults, results)
1289
+ return cast("OLSResults", results)
1278
1290
 
1279
- def jensen_alpha( # noqa: C901
1291
+ def jensen_alpha(
1280
1292
  self: Self,
1281
1293
  asset: tuple[str, ValueType] | int,
1282
1294
  market: tuple[str, ValueType] | int,
@@ -1303,7 +1315,7 @@ class OpenFrame(_CommonModel):
1303
1315
  dlta_degr_freedms: int, default: 1
1304
1316
  Variance bias factor taking the value 0 or 1.
1305
1317
 
1306
- Returns
1318
+ Returns:
1307
1319
  -------
1308
1320
  float
1309
1321
  Jensen's alpha
@@ -1330,17 +1342,17 @@ class OpenFrame(_CommonModel):
1330
1342
  )
1331
1343
  elif isinstance(asset, int):
1332
1344
  asset_log = log(
1333
- self.tsdf.iloc[:, asset] / cast(float, self.tsdf.iloc[0, asset]),
1345
+ self.tsdf.iloc[:, asset] / cast("float", self.tsdf.iloc[0, asset]),
1334
1346
  )
1335
1347
  if self.yearfrac > full_year:
1336
1348
  asset_cagr = (
1337
- cast(float, self.tsdf.iloc[-1, asset])
1338
- / cast(float, self.tsdf.iloc[0, asset])
1349
+ cast("float", self.tsdf.iloc[-1, asset])
1350
+ / cast("float", self.tsdf.iloc[0, asset])
1339
1351
  ) ** (1 / self.yearfrac) - 1
1340
1352
  else:
1341
1353
  asset_cagr = (
1342
- cast(float, self.tsdf.iloc[-1, asset])
1343
- / cast(float, self.tsdf.iloc[0, asset])
1354
+ cast("float", self.tsdf.iloc[-1, asset])
1355
+ / cast("float", self.tsdf.iloc[0, asset])
1344
1356
  - 1
1345
1357
  )
1346
1358
  else:
@@ -1364,17 +1376,18 @@ class OpenFrame(_CommonModel):
1364
1376
  )
1365
1377
  elif isinstance(market, int):
1366
1378
  market_log = log(
1367
- self.tsdf.iloc[:, market] / cast(float, self.tsdf.iloc[0, market]),
1379
+ self.tsdf.iloc[:, market]
1380
+ / cast("float", self.tsdf.iloc[0, market]),
1368
1381
  )
1369
1382
  if self.yearfrac > full_year:
1370
1383
  market_cagr = (
1371
- cast(float, self.tsdf.iloc[-1, market])
1372
- / cast(float, self.tsdf.iloc[0, market])
1384
+ cast("float", self.tsdf.iloc[-1, market])
1385
+ / cast("float", self.tsdf.iloc[0, market])
1373
1386
  ) ** (1 / self.yearfrac) - 1
1374
1387
  else:
1375
1388
  market_cagr = (
1376
- cast(float, self.tsdf.iloc[-1, market])
1377
- / cast(float, self.tsdf.iloc[0, market])
1389
+ cast("float", self.tsdf.iloc[-1, market])
1390
+ / cast("float", self.tsdf.iloc[0, market])
1378
1391
  - 1
1379
1392
  )
1380
1393
  else:
@@ -1401,7 +1414,7 @@ class OpenFrame(_CommonModel):
1401
1414
  raise TypeError(msg)
1402
1415
  else:
1403
1416
  msg = "Mix of series types will give inconsistent results"
1404
- raise ValueError(msg)
1417
+ raise MixedValuetypesError(msg)
1405
1418
 
1406
1419
  covariance = cov(asset_log, market_log, ddof=dlta_degr_freedms)
1407
1420
  beta = covariance[0, 1] / covariance[1, 1]
@@ -1422,7 +1435,7 @@ class OpenFrame(_CommonModel):
1422
1435
  weight_strat: LiteralPortfolioWeightings, optional
1423
1436
  weight calculation strategies
1424
1437
 
1425
- Returns
1438
+ Returns:
1426
1439
  -------
1427
1440
  Pandas.DataFrame
1428
1441
  A basket timeseries
@@ -1433,7 +1446,7 @@ class OpenFrame(_CommonModel):
1433
1446
  "OpenFrame weights property must be provided "
1434
1447
  "to run the make_portfolio method."
1435
1448
  )
1436
- raise ValueError(msg)
1449
+ raise NoWeightsError(msg)
1437
1450
 
1438
1451
  vtypes = [x == ValueType.RTRN for x in self.tsdf.columns.get_level_values(1)]
1439
1452
  if not any(vtypes):
@@ -1443,7 +1456,7 @@ class OpenFrame(_CommonModel):
1443
1456
  returns = self.tsdf.copy()
1444
1457
  else:
1445
1458
  msg = "Mix of series types will give inconsistent results"
1446
- raise ValueError(msg)
1459
+ raise MixedValuetypesError(msg)
1447
1460
 
1448
1461
  msg = "Weight strategy not implemented"
1449
1462
  if weight_strat:
@@ -1487,18 +1500,18 @@ class OpenFrame(_CommonModel):
1487
1500
  periods_in_a_year_fixed : DaysInYearType, optional
1488
1501
  Allows locking the periods-in-a-year to simplify test cases and comparisons
1489
1502
 
1490
- Returns
1503
+ Returns:
1491
1504
  -------
1492
1505
  Pandas.DataFrame
1493
1506
  Rolling Information Ratios
1494
1507
 
1495
1508
  """
1496
1509
  long_label = cast(
1497
- tuple[str, str],
1510
+ "tuple[str, str]",
1498
1511
  self.tsdf.iloc[:, long_column].name,
1499
1512
  )[0]
1500
1513
  short_label = cast(
1501
- tuple[str, str],
1514
+ "tuple[str, str]",
1502
1515
  self.tsdf.iloc[:, short_column].name,
1503
1516
  )[0]
1504
1517
  ratio_label = f"{long_label} / {short_label}"
@@ -1553,14 +1566,16 @@ class OpenFrame(_CommonModel):
1553
1566
  dlta_degr_freedms: int, default: 1
1554
1567
  Variance bias factor taking the value 0 or 1.
1555
1568
 
1556
- Returns
1569
+ Returns:
1557
1570
  -------
1558
1571
  Pandas.DataFrame
1559
1572
  Rolling Betas
1560
1573
 
1561
1574
  """
1562
- market_label = cast(tuple[str, str], self.tsdf.iloc[:, market_column].name)[0]
1563
- asset_label = cast(tuple[str, str], self.tsdf.iloc[:, asset_column].name)[0]
1575
+ market_label = cast("tuple[str, str]", self.tsdf.iloc[:, market_column].name)[
1576
+ 0
1577
+ ]
1578
+ asset_label = cast("tuple[str, str]", self.tsdf.iloc[:, asset_column].name)[0]
1564
1579
  beta_label = f"{asset_label} / {market_label}"
1565
1580
 
1566
1581
  rolling = (
@@ -1611,16 +1626,16 @@ class OpenFrame(_CommonModel):
1611
1626
  observations: int, default: 21
1612
1627
  The length of the rolling window to use is set as number of observations
1613
1628
 
1614
- Returns
1629
+ Returns:
1615
1630
  -------
1616
1631
  Pandas.DataFrame
1617
1632
  Rolling Correlations
1618
1633
 
1619
1634
  """
1620
1635
  corr_label = (
1621
- cast(tuple[str, str], self.tsdf.iloc[:, first_column].name)[0]
1636
+ cast("tuple[str, str]", self.tsdf.iloc[:, first_column].name)[0]
1622
1637
  + "_VS_"
1623
- + cast(tuple[str, str], self.tsdf.iloc[:, second_column].name)[0]
1638
+ + cast("tuple[str, str]", self.tsdf.iloc[:, second_column].name)[0]
1624
1639
  )
1625
1640
  first_series = (
1626
1641
  self.tsdf.iloc[:, first_column]