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/_common_model.py +596 -509
- openseries/datefixer.py +4 -2
- openseries/frame.py +122 -165
- openseries/owntypes.py +48 -47
- openseries/portfoliotools.py +16 -32
- openseries/py.typed +0 -0
- openseries/report.py +15 -16
- openseries/series.py +43 -40
- openseries/simulation.py +95 -23
- {openseries-1.9.5.dist-info → openseries-1.9.7.dist-info}/METADATA +17 -20
- openseries-1.9.7.dist-info/RECORD +18 -0
- {openseries-1.9.5.dist-info → openseries-1.9.7.dist-info}/WHEEL +1 -1
- openseries-1.9.5.dist-info/RECORD +0 -17
- {openseries-1.9.5.dist-info → openseries-1.9.7.dist-info/licenses}/LICENSE.md +0 -0
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,
|
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
|
-
|
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
|
-
|
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.
|
146
|
-
|
147
|
-
|
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
|
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,
|
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("
|
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[
|
596
|
+
data = self.tsdf.loc[
|
597
|
+
cast("Timestamp", earlier) : cast("Timestamp", later)
|
598
|
+
].copy()
|
584
599
|
|
585
600
|
for rtn in cols:
|
586
|
-
|
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
|
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
|
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
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
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
|
609
|
-
r2 = data
|
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,
|
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
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
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
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
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[
|
883
|
-
|
884
|
-
|
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,
|
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
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
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
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
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[
|
981
|
-
|
982
|
-
|
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,
|
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[
|
1048
|
-
|
1049
|
-
|
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
|
1029
|
+
self.tsdf[base_column].name,
|
1055
1030
|
)[0]
|
1056
1031
|
elif isinstance(base_column, int):
|
1057
|
-
shortdf =
|
1058
|
-
"
|
1059
|
-
|
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 =
|
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[
|
1088
|
-
|
1089
|
-
|
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
|
1203
|
+
y_value = self.tsdf[asset]
|
1234
1204
|
elif isinstance(asset, int):
|
1235
|
-
y_value =
|
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
|
1211
|
+
x_value = self.tsdf[market]
|
1242
1212
|
elif isinstance(market, int):
|
1243
|
-
x_value =
|
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
|
1219
|
+
y_value = self.tsdf[asset].ffill().pct_change().iloc[1:]
|
1250
1220
|
elif isinstance(asset, int):
|
1251
|
-
y_value =
|
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
|
1227
|
+
x_value = self.tsdf[market].ffill().pct_change().iloc[1:]
|
1260
1228
|
elif isinstance(market, int):
|
1261
|
-
x_value =
|
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
|
1270
|
+
y_value = self.tsdf[y_column].to_numpy()
|
1306
1271
|
y_label = cast(
|
1307
1272
|
"tuple[str, str]",
|
1308
|
-
self.tsdf
|
1273
|
+
self.tsdf[y_column].name,
|
1309
1274
|
)[0]
|
1310
1275
|
elif isinstance(y_column, int):
|
1311
|
-
y_value =
|
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
|
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
|
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
|
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 =
|
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
|
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 =
|
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
|
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 =
|
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
|
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 =
|
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
|
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
|
1572
|
+
return rollbeta
|
1616
1573
|
|
1617
1574
|
def rolling_corr(
|
1618
1575
|
self: Self,
|