openseries 1.9.5__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.
openseries/datefixer.py CHANGED
@@ -144,7 +144,7 @@ def holiday_calendar(
144
144
  for country in countries:
145
145
  staging = country_holidays(country=country, years=years)
146
146
  countryholidays += list(staging)
147
- hols = list(countryholidays)
147
+ hols = cast("list[dt.date]", list(countryholidays))
148
148
  else:
149
149
  msg = (
150
150
  "Argument countries must be a string country code or "
@@ -154,7 +154,9 @@ def holiday_calendar(
154
154
 
155
155
  if markets:
156
156
  market_hols = market_holidays(
157
- startyear=startyear, endyear=endyear, markets=markets
157
+ startyear=startyear,
158
+ endyear=endyear,
159
+ markets=markets,
158
160
  )
159
161
  dt_mkt_hols = [date_fix(fixerdate=ddate) for ddate in market_hols]
160
162
  hols.extend(dt_mkt_hols)
openseries/frame.py CHANGED
@@ -14,15 +14,14 @@ from functools import reduce
14
14
  from logging import getLogger
15
15
  from typing import TYPE_CHECKING, Any, cast
16
16
 
17
- if TYPE_CHECKING: # pragma: no cover
18
- import datetime as dt
19
-
20
- from numpy import dtype, int64, ndarray
21
-
22
17
  from numpy import (
23
18
  array,
19
+ asarray,
20
+ concatenate,
24
21
  cov,
22
+ diff,
25
23
  divide,
24
+ float64,
26
25
  isinf,
27
26
  log,
28
27
  nan,
@@ -38,10 +37,22 @@ from pandas import (
38
37
  concat,
39
38
  merge,
40
39
  )
40
+
41
+ if TYPE_CHECKING: # pragma: no cover
42
+ import datetime as dt
43
+
44
+ from numpy.typing import NDArray
45
+ from pandas import Series as _Series
46
+ from pandas import Timestamp
47
+
48
+ SeriesFloat = _Series[float]
49
+ else:
50
+ SeriesFloat = Series
51
+
41
52
  from pydantic import field_validator
42
53
  from sklearn.linear_model import LinearRegression # type: ignore[import-untyped]
43
54
 
44
- from ._common_model import _CommonModel
55
+ from ._common_model import _calculate_time_factor, _CommonModel, _get_base_column_data
45
56
  from .datefixer import _do_resample_to_business_period_ends
46
57
  from .owntypes import (
47
58
  DaysInYearType,
@@ -69,8 +80,7 @@ logger = getLogger(__name__)
69
80
  __all__ = ["OpenFrame"]
70
81
 
71
82
 
72
- # noinspection PyUnresolvedReferences,PyTypeChecker
73
- class OpenFrame(_CommonModel):
83
+ class OpenFrame(_CommonModel[SeriesFloat]):
74
84
  """OpenFrame objects hold OpenTimeSeries in the list constituents.
75
85
 
76
86
  The intended use is to allow comparisons across these timeseries.
@@ -93,10 +103,9 @@ class OpenFrame(_CommonModel):
93
103
  tsdf: DataFrame = DataFrame(dtype="float64")
94
104
  weights: list[float] | None = None
95
105
 
96
- # noinspection PyMethodParameters
97
- @field_validator("constituents") # type: ignore[misc]
106
+ @field_validator("constituents")
98
107
  def _check_labels_unique(
99
- cls: OpenFrame, # noqa: N805
108
+ cls: type[OpenFrame], # noqa: N805
100
109
  tseries: list[OpenTimeSeries],
101
110
  ) -> list[OpenTimeSeries]:
102
111
  """Pydantic validator ensuring that OpenFrame labels are unique."""
@@ -130,7 +139,7 @@ class OpenFrame(_CommonModel):
130
139
  """
131
140
  copied_constituents = [ts.from_deepcopy() for ts in constituents]
132
141
 
133
- super().__init__(
142
+ super().__init__( # type: ignore[call-arg]
134
143
  constituents=copied_constituents,
135
144
  weights=weights,
136
145
  )
@@ -142,10 +151,12 @@ class OpenFrame(_CommonModel):
142
151
  def _set_tsdf(self: Self) -> None:
143
152
  """Set the tsdf DataFrame."""
144
153
  if self.constituents is not None and len(self.constituents) != 0:
145
- self.tsdf = reduce(
146
- lambda left, right: concat([left, right], axis="columns", sort=True),
147
- [x.tsdf for x in self.constituents],
148
- )
154
+ if len(self.constituents) == 1:
155
+ self.tsdf = self.constituents[0].tsdf.copy()
156
+ else:
157
+ self.tsdf = concat(
158
+ [x.tsdf for x in self.constituents], axis="columns", sort=True
159
+ )
149
160
  else:
150
161
  logger.warning("OpenFrame() was passed an empty list.")
151
162
 
@@ -241,7 +252,7 @@ class OpenFrame(_CommonModel):
241
252
 
242
253
  """
243
254
  return Series(
244
- data=[self.tsdf.loc[:, d].count() for d in self.tsdf],
255
+ data=[self.tsdf[col].count() for col in self.tsdf.columns],
245
256
  index=self.tsdf.columns,
246
257
  name="observations",
247
258
  ).astype(int)
@@ -557,12 +568,14 @@ class OpenFrame(_CommonModel):
557
568
 
558
569
  """
559
570
  earlier, later = self.calc_range(
560
- months_offset=months_from_last, from_dt=from_date, to_dt=to_date
571
+ months_offset=months_from_last,
572
+ from_dt=from_date,
573
+ to_dt=to_date,
561
574
  )
562
575
  if periods_in_a_year_fixed is None:
563
576
  fraction = (later - earlier).days / 365.25
564
577
  how_many = (
565
- self.tsdf.loc[cast("int", earlier) : cast("int", later)]
578
+ self.tsdf.loc[cast("Timestamp", earlier) : cast("Timestamp", later)]
566
579
  .count()
567
580
  .iloc[0]
568
581
  )
@@ -580,33 +593,35 @@ class OpenFrame(_CommonModel):
580
593
  cast("tuple[str, str]", self.tsdf.iloc[:, second_column].name)[0],
581
594
  ]
582
595
 
583
- data = self.tsdf.loc[cast("int", earlier) : cast("int", later)].copy()
596
+ data = self.tsdf.loc[
597
+ cast("Timestamp", earlier) : cast("Timestamp", later)
598
+ ].copy()
584
599
 
585
600
  for rtn in cols:
586
- data[rtn, ValueType.RTRN] = log(data.loc[:, (rtn, ValueType.PRICE)]).diff()
601
+ arr = concatenate([array([nan]), diff(log(data[(rtn, ValueType.PRICE)]))])
602
+ data[rtn, ValueType.RTRN] = arr
587
603
 
588
604
  raw_one = [
589
- data.loc[:, (cols[0], ValueType.RTRN)]
605
+ data[(cols[0], ValueType.RTRN)]
590
606
  .iloc[1:day_chunk]
591
607
  .std(ddof=dlta_degr_freedms)
592
608
  * sqrt(time_factor),
593
609
  ]
594
610
  raw_two = [
595
- data.loc[:, (cols[1], ValueType.RTRN)]
611
+ data[(cols[1], ValueType.RTRN)]
596
612
  .iloc[1:day_chunk]
597
613
  .std(ddof=dlta_degr_freedms)
598
614
  * sqrt(time_factor),
599
615
  ]
600
- raw_cov = [
601
- cov(
602
- m=data.loc[:, (cols[0], ValueType.RTRN)].iloc[1:day_chunk].to_numpy(),
603
- y=data.loc[:, (cols[1], ValueType.RTRN)].iloc[1:day_chunk].to_numpy(),
604
- ddof=dlta_degr_freedms,
605
- )[0][1],
606
- ]
616
+ rm = data[(cols[0], ValueType.RTRN)].iloc[1:day_chunk]
617
+ m: NDArray[float64] = asarray(rm, dtype=float64)
618
+ ry = data[(cols[1], ValueType.RTRN)].iloc[1:day_chunk]
619
+ y: NDArray[float64] = asarray(ry, dtype=float64)
620
+
621
+ raw_cov = [cov(m=m, y=y, ddof=dlta_degr_freedms)[0][1]]
607
622
 
608
- r1 = data.loc[:, (cols[0], ValueType.RTRN)]
609
- r2 = data.loc[:, (cols[1], ValueType.RTRN)]
623
+ r1 = data[(cols[0], ValueType.RTRN)]
624
+ r2 = data[(cols[1], ValueType.RTRN)]
610
625
 
611
626
  alpha = 1.0 - lmbda
612
627
 
@@ -838,51 +853,33 @@ class OpenFrame(_CommonModel):
838
853
 
839
854
  """
840
855
  earlier, later = self.calc_range(
841
- months_offset=months_from_last, from_dt=from_date, to_dt=to_date
856
+ months_offset=months_from_last,
857
+ from_dt=from_date,
858
+ to_dt=to_date,
842
859
  )
843
- fraction = (later - earlier).days / 365.25
844
860
 
845
- msg = "base_column should be a tuple[str, ValueType] or an integer."
846
- if isinstance(base_column, tuple):
847
- shortdf = self.tsdf.loc[cast("int", earlier) : cast("int", later)].loc[
848
- :,
849
- base_column,
850
- ]
851
- short_item = base_column
852
- short_label = cast(
853
- "tuple[str, ValueType]",
854
- self.tsdf.loc[:, base_column].name,
855
- )[0]
856
- elif isinstance(base_column, int):
857
- shortdf = cast(
858
- "DataFrame",
859
- self.tsdf.loc[cast("int", earlier) : cast("int", later)].iloc[
860
- :, base_column
861
- ],
862
- )
863
- short_item = cast(
864
- "tuple[str, ValueType]", self.tsdf.iloc[:, base_column].name
865
- )
866
- short_label = cast("tuple[str, str]", self.tsdf.iloc[:, base_column].name)[
867
- 0
868
- ]
869
- else:
870
- raise TypeError(msg)
861
+ shortdf, short_item, short_label = _get_base_column_data(
862
+ self=self,
863
+ base_column=base_column,
864
+ earlier=earlier,
865
+ later=later,
866
+ )
871
867
 
872
- if periods_in_a_year_fixed:
873
- time_factor = float(periods_in_a_year_fixed)
874
- else:
875
- time_factor = float(cast("int64", shortdf.count()) / fraction)
868
+ time_factor = _calculate_time_factor(
869
+ data=shortdf,
870
+ earlier=earlier,
871
+ later=later,
872
+ periods_in_a_year_fixed=periods_in_a_year_fixed,
873
+ )
876
874
 
877
875
  terrors = []
878
876
  for item in self.tsdf:
879
877
  if item == short_item:
880
878
  terrors.append(0.0)
881
879
  else:
882
- longdf = self.tsdf.loc[cast("int", earlier) : cast("int", later)].loc[
883
- :,
884
- item,
885
- ]
880
+ longdf = self.tsdf.loc[
881
+ cast("Timestamp", earlier) : cast("Timestamp", later)
882
+ ][item]
886
883
  relative = longdf.ffill().pct_change() - shortdf.ffill().pct_change()
887
884
  vol = float(relative.std() * sqrt(time_factor))
888
885
  terrors.append(vol)
@@ -931,56 +928,33 @@ class OpenFrame(_CommonModel):
931
928
 
932
929
  """
933
930
  earlier, later = self.calc_range(
934
- months_offset=months_from_last, from_dt=from_date, to_dt=to_date
931
+ months_offset=months_from_last,
932
+ from_dt=from_date,
933
+ to_dt=to_date,
935
934
  )
936
- fraction = (later - earlier).days / 365.25
937
935
 
938
- msg = "base_column should be a tuple[str, ValueType] or an integer."
939
- if isinstance(base_column, tuple):
940
- shortdf = self.tsdf.loc[cast("int", earlier) : cast("int", later)].loc[
941
- :,
942
- base_column,
943
- ]
944
- short_item = base_column
945
- short_label = cast(
946
- "tuple[str, str]",
947
- self.tsdf.loc[:, base_column].name,
948
- )[0]
949
- elif isinstance(base_column, int):
950
- shortdf = cast(
951
- "DataFrame",
952
- self.tsdf.loc[cast("int", earlier) : cast("int", later)].iloc[
953
- :,
954
- base_column,
955
- ],
956
- )
957
- short_item = cast(
958
- "tuple[str, ValueType]",
959
- self.tsdf.iloc[
960
- :,
961
- base_column,
962
- ].name,
963
- )
964
- short_label = cast("tuple[str, str]", self.tsdf.iloc[:, base_column].name)[
965
- 0
966
- ]
967
- else:
968
- raise TypeError(msg)
936
+ shortdf, short_item, short_label = _get_base_column_data(
937
+ self=self,
938
+ base_column=base_column,
939
+ earlier=earlier,
940
+ later=later,
941
+ )
969
942
 
970
- if periods_in_a_year_fixed:
971
- time_factor = float(periods_in_a_year_fixed)
972
- else:
973
- time_factor = float(shortdf.count() / fraction) # type: ignore[arg-type]
943
+ time_factor = _calculate_time_factor(
944
+ data=shortdf,
945
+ earlier=earlier,
946
+ later=later,
947
+ periods_in_a_year_fixed=periods_in_a_year_fixed,
948
+ )
974
949
 
975
950
  ratios = []
976
951
  for item in self.tsdf:
977
952
  if item == short_item:
978
953
  ratios.append(0.0)
979
954
  else:
980
- longdf = self.tsdf.loc[cast("int", earlier) : cast("int", later)].loc[
981
- :,
982
- item,
983
- ]
955
+ longdf = self.tsdf.loc[
956
+ cast("Timestamp", earlier) : cast("Timestamp", later)
957
+ ][item]
984
958
  relative = longdf.ffill().pct_change() - shortdf.ffill().pct_change()
985
959
  ret = float(relative.mean() * time_factor)
986
960
  vol = float(relative.std() * sqrt(time_factor))
@@ -1038,29 +1012,26 @@ class OpenFrame(_CommonModel):
1038
1012
  """
1039
1013
  loss_limit: float = 0.0
1040
1014
  earlier, later = self.calc_range(
1041
- months_offset=months_from_last, from_dt=from_date, to_dt=to_date
1015
+ months_offset=months_from_last,
1016
+ from_dt=from_date,
1017
+ to_dt=to_date,
1042
1018
  )
1043
- fraction = (later - earlier).days / 365.25
1019
+ fraction: float = (later - earlier).days / 365.25
1044
1020
 
1045
1021
  msg = "base_column should be a tuple[str, ValueType] or an integer."
1046
1022
  if isinstance(base_column, tuple):
1047
- shortdf = self.tsdf.loc[cast("int", earlier) : cast("int", later)].loc[
1048
- :,
1049
- base_column,
1050
- ]
1023
+ shortdf = self.tsdf.loc[
1024
+ cast("Timestamp", earlier) : cast("Timestamp", later)
1025
+ ][base_column]
1051
1026
  short_item = base_column
1052
1027
  short_label = cast(
1053
1028
  "tuple[str, str]",
1054
- self.tsdf.loc[:, base_column].name,
1029
+ self.tsdf[base_column].name,
1055
1030
  )[0]
1056
1031
  elif isinstance(base_column, int):
1057
- shortdf = cast(
1058
- "DataFrame",
1059
- self.tsdf.loc[cast("int", earlier) : cast("int", later)].iloc[
1060
- :,
1061
- base_column,
1062
- ],
1063
- )
1032
+ shortdf = self.tsdf.loc[
1033
+ cast("Timestamp", earlier) : cast("Timestamp", later)
1034
+ ].iloc[:, base_column]
1064
1035
  short_item = cast(
1065
1036
  "tuple[str, ValueType]",
1066
1037
  self.tsdf.iloc[
@@ -1077,17 +1048,16 @@ class OpenFrame(_CommonModel):
1077
1048
  if periods_in_a_year_fixed:
1078
1049
  time_factor = float(periods_in_a_year_fixed)
1079
1050
  else:
1080
- time_factor = float(shortdf.count() / fraction) # type: ignore[arg-type]
1051
+ time_factor = shortdf.count() / fraction
1081
1052
 
1082
1053
  ratios = []
1083
1054
  for item in self.tsdf:
1084
1055
  if item == short_item:
1085
1056
  ratios.append(0.0)
1086
1057
  else:
1087
- longdf = self.tsdf.loc[cast("int", earlier) : cast("int", later)].loc[
1088
- :,
1089
- item,
1090
- ]
1058
+ longdf = self.tsdf.loc[
1059
+ cast("Timestamp", earlier) : cast("Timestamp", later)
1060
+ ][item]
1091
1061
  msg = "ratio must be one of 'up', 'down' or 'both'."
1092
1062
  if ratio == "up":
1093
1063
  uparray = (
@@ -1230,38 +1200,33 @@ class OpenFrame(_CommonModel):
1230
1200
  if all(vtypes):
1231
1201
  msg = "asset should be a tuple[str, ValueType] or an integer."
1232
1202
  if isinstance(asset, tuple):
1233
- y_value = self.tsdf.loc[:, asset]
1203
+ y_value = self.tsdf[asset]
1234
1204
  elif isinstance(asset, int):
1235
- y_value = cast("DataFrame", self.tsdf.iloc[:, asset])
1205
+ y_value = self.tsdf.iloc[:, asset]
1236
1206
  else:
1237
1207
  raise TypeError(msg)
1238
1208
 
1239
1209
  msg = "market should be a tuple[str, ValueType] or an integer."
1240
1210
  if isinstance(market, tuple):
1241
- x_value = self.tsdf.loc[:, market]
1211
+ x_value = self.tsdf[market]
1242
1212
  elif isinstance(market, int):
1243
- x_value = cast("DataFrame", self.tsdf.iloc[:, market])
1213
+ x_value = self.tsdf.iloc[:, market]
1244
1214
  else:
1245
1215
  raise TypeError(msg)
1246
1216
  elif not any(vtypes):
1247
1217
  msg = "asset should be a tuple[str, ValueType] or an integer."
1248
1218
  if isinstance(asset, tuple):
1249
- y_value = self.tsdf.loc[:, asset].ffill().pct_change().iloc[1:]
1219
+ y_value = self.tsdf[asset].ffill().pct_change().iloc[1:]
1250
1220
  elif isinstance(asset, int):
1251
- y_value = cast(
1252
- "DataFrame", self.tsdf.iloc[:, asset].ffill().pct_change().iloc[1:]
1253
- )
1221
+ y_value = self.tsdf.iloc[:, asset].ffill().pct_change().iloc[1:]
1254
1222
  else:
1255
1223
  raise TypeError(msg)
1256
1224
  msg = "market should be a tuple[str, ValueType] or an integer."
1257
1225
 
1258
1226
  if isinstance(market, tuple):
1259
- x_value = self.tsdf.loc[:, market].ffill().pct_change().iloc[1:]
1227
+ x_value = self.tsdf[market].ffill().pct_change().iloc[1:]
1260
1228
  elif isinstance(market, int):
1261
- x_value = cast(
1262
- "DataFrame",
1263
- self.tsdf.iloc[:, market].ffill().pct_change().iloc[1:],
1264
- )
1229
+ x_value = self.tsdf.iloc[:, market].ffill().pct_change().iloc[1:]
1265
1230
  else:
1266
1231
  raise TypeError(msg)
1267
1232
  else:
@@ -1302,26 +1267,23 @@ class OpenFrame(_CommonModel):
1302
1267
  """
1303
1268
  msg = "y_column should be a tuple[str, ValueType] or an integer."
1304
1269
  if isinstance(y_column, tuple):
1305
- y_value = self.tsdf.loc[:, y_column].to_numpy()
1270
+ y_value = self.tsdf[y_column].to_numpy()
1306
1271
  y_label = cast(
1307
1272
  "tuple[str, str]",
1308
- self.tsdf.loc[:, y_column].name,
1273
+ self.tsdf[y_column].name,
1309
1274
  )[0]
1310
1275
  elif isinstance(y_column, int):
1311
- y_value = cast(
1312
- "ndarray[tuple[int, int], dtype[Any]]",
1313
- self.tsdf.iloc[:, y_column].to_numpy(),
1314
- )
1276
+ y_value = self.tsdf.iloc[:, y_column].to_numpy()
1315
1277
  y_label = cast("tuple[str, str]", self.tsdf.iloc[:, y_column].name)[0]
1316
1278
  else:
1317
1279
  raise TypeError(msg)
1318
1280
 
1319
1281
  msg = "x_column should be a tuple[str, ValueType] or an integer."
1320
1282
  if isinstance(x_column, tuple):
1321
- x_value = self.tsdf.loc[:, x_column].to_numpy().reshape(-1, 1)
1283
+ x_value = self.tsdf[x_column].to_numpy().reshape(-1, 1)
1322
1284
  x_label = cast(
1323
1285
  "tuple[str, str]",
1324
- self.tsdf.loc[:, x_column].name,
1286
+ self.tsdf[x_column].name,
1325
1287
  )[0]
1326
1288
  elif isinstance(x_column, int):
1327
1289
  x_value = self.tsdf.iloc[:, x_column].to_numpy().reshape(-1, 1)
@@ -1376,45 +1338,40 @@ class OpenFrame(_CommonModel):
1376
1338
  if not any(vtypes):
1377
1339
  msg = "asset should be a tuple[str, ValueType] or an integer."
1378
1340
  if isinstance(asset, tuple):
1379
- asset_rtn = self.tsdf.loc[:, asset].ffill().pct_change().iloc[1:]
1341
+ asset_rtn = self.tsdf[asset].ffill().pct_change().iloc[1:]
1380
1342
  asset_rtn_mean = float(asset_rtn.mean() * self.periods_in_a_year)
1381
1343
  elif isinstance(asset, int):
1382
- asset_rtn = cast(
1383
- "DataFrame", self.tsdf.iloc[:, asset].ffill().pct_change().iloc[1:]
1384
- )
1344
+ asset_rtn = self.tsdf.iloc[:, asset].ffill().pct_change().iloc[1:]
1385
1345
  asset_rtn_mean = float(asset_rtn.mean() * self.periods_in_a_year)
1386
1346
  else:
1387
1347
  raise TypeError(msg)
1388
1348
 
1389
1349
  msg = "market should be a tuple[str, ValueType] or an integer."
1390
1350
  if isinstance(market, tuple):
1391
- market_rtn = self.tsdf.loc[:, market].ffill().pct_change().iloc[1:]
1351
+ market_rtn = self.tsdf[market].ffill().pct_change().iloc[1:]
1392
1352
  market_rtn_mean = float(market_rtn.mean() * self.periods_in_a_year)
1393
1353
  elif isinstance(market, int):
1394
- market_rtn = cast(
1395
- "DataFrame",
1396
- self.tsdf.iloc[:, market].ffill().pct_change().iloc[1:],
1397
- )
1354
+ market_rtn = self.tsdf.iloc[:, market].ffill().pct_change().iloc[1:]
1398
1355
  market_rtn_mean = float(market_rtn.mean() * self.periods_in_a_year)
1399
1356
  else:
1400
1357
  raise TypeError(msg)
1401
1358
  elif all(vtypes):
1402
1359
  msg = "asset should be a tuple[str, ValueType] or an integer."
1403
1360
  if isinstance(asset, tuple):
1404
- asset_rtn = self.tsdf.loc[:, asset]
1361
+ asset_rtn = self.tsdf[asset]
1405
1362
  asset_rtn_mean = float(asset_rtn.mean() * self.periods_in_a_year)
1406
1363
  elif isinstance(asset, int):
1407
- asset_rtn = cast("DataFrame", self.tsdf.iloc[:, asset])
1364
+ asset_rtn = self.tsdf.iloc[:, asset]
1408
1365
  asset_rtn_mean = float(asset_rtn.mean() * self.periods_in_a_year)
1409
1366
  else:
1410
1367
  raise TypeError(msg)
1411
1368
 
1412
1369
  msg = "market should be a tuple[str, ValueType] or an integer."
1413
1370
  if isinstance(market, tuple):
1414
- market_rtn = self.tsdf.loc[:, market]
1371
+ market_rtn = self.tsdf[market]
1415
1372
  market_rtn_mean = float(market_rtn.mean() * self.periods_in_a_year)
1416
1373
  elif isinstance(market, int):
1417
- market_rtn = cast("DataFrame", self.tsdf.iloc[:, market])
1374
+ market_rtn = self.tsdf.iloc[:, market]
1418
1375
  market_rtn_mean = float(market_rtn.mean() * self.periods_in_a_year)
1419
1376
  else:
1420
1377
  raise TypeError(msg)
@@ -1426,7 +1383,7 @@ class OpenFrame(_CommonModel):
1426
1383
  beta = covariance[0, 1] / covariance[1, 1]
1427
1384
 
1428
1385
  return float(
1429
- asset_rtn_mean - riskfree_rate - beta * (market_rtn_mean - riskfree_rate)
1386
+ asset_rtn_mean - riskfree_rate - beta * (market_rtn_mean - riskfree_rate),
1430
1387
  )
1431
1388
 
1432
1389
  def make_portfolio(
@@ -1461,7 +1418,7 @@ class OpenFrame(_CommonModel):
1461
1418
  returns = self.tsdf.ffill().pct_change()
1462
1419
  returns.iloc[0] = 0
1463
1420
  elif all(vtypes):
1464
- returns = self.tsdf.copy()
1421
+ returns = self.tsdf
1465
1422
  else:
1466
1423
  msg = "Mix of series types will give inconsistent results"
1467
1424
  raise MixedValuetypesError(msg)
@@ -1612,7 +1569,7 @@ class OpenFrame(_CommonModel):
1612
1569
  rollbeta.index = rollbeta.index.droplevel(level=1)
1613
1570
  rollbeta.columns = MultiIndex.from_arrays([[beta_label], ["Beta"]])
1614
1571
 
1615
- return cast("DataFrame", rollbeta)
1572
+ return rollbeta
1616
1573
 
1617
1574
  def rolling_corr(
1618
1575
  self: Self,