Skip to content

Commit

Permalink
tightened OpenFrame.make_portfolio() method to not allow mixed series…
Browse files Browse the repository at this point in the history
… types. Also updated dependencies
  • Loading branch information
karrmagadgeteer2 committed Sep 25, 2024
1 parent ce7abaa commit 661adc1
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 46 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ default_language_version:

repos:
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.6.6
rev: v0.6.7
hooks:
- id: ruff
args: [ --fix, --exit-non-zero-on-fix ]
Expand Down
21 changes: 12 additions & 9 deletions openseries/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -1407,27 +1407,30 @@ def make_portfolio(
"to run the make_portfolio method."
)
raise ValueError(msg)
dframe = self.tsdf.copy()
if not any(
x == ValueType.RTRN
for x in self.tsdf.columns.get_level_values(1).to_numpy()
):
dframe = dframe.pct_change()
dframe.iloc[0] = 0

vtypes = [x == ValueType.RTRN for x in self.tsdf.columns.get_level_values(1)]
if not any(vtypes):
returns = self.tsdf.ffill().pct_change()
returns.iloc[0] = 0
elif all(vtypes):
returns = self.tsdf.copy()
else:
msg = "Mix of series types will give inconsistent results"
raise ValueError(msg)

msg = "Weight strategy not implemented"
if weight_strat:
if weight_strat == "eq_weights":
self.weights = [1.0 / self.item_count] * self.item_count
elif weight_strat == "inv_vol":
vol = divide(1.0, std(dframe, axis=0, ddof=1))
vol = divide(1.0, std(returns, axis=0, ddof=1))
vol[isinf(vol)] = nan
self.weights = list(divide(vol, vol.sum()))
else:
raise NotImplementedError(msg)

return DataFrame(
data=(dframe @ self.weights).add(1.0).cumprod(),
data=(returns @ self.weights).add(1.0).cumprod(),
index=self.tsdf.index,
columns=[[name], [ValueType.PRICE]],
dtype="float64",
Expand Down
58 changes: 23 additions & 35 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ mypy = "^1.11.2"
pandas-stubs = ">=2.1.2,<3.0.0"
pre-commit = ">=3.7.1,<4.0.0"
pytest = ">=8.2.2,<9.0.0"
ruff = "^0.6.6"
ruff = "^0.6.7"
types-openpyxl = ">=3.1.2,<4.0.0"
types-python-dateutil = ">=2.8.2,<3.0.0"
types-requests = ">=2.20.0,<3.0.0"
Expand Down
11 changes: 11 additions & 0 deletions tests/test_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,17 @@ def test_make_portfolio_weight_strat(self: TestOpenFrame) -> None:
)
raise ValueError(msg)

series = self.randomseries.from_deepcopy()
returns = self.randomseries.from_deepcopy()
returns.set_new_label(lvl_zero="returns")
returns.value_to_ret()
mixframe = OpenFrame(constituents=[series, returns])
with pytest.raises(
expected_exception=ValueError,
match="Mix of series types will give inconsistent results",
):
_ = mixframe.make_portfolio(name=name, weight_strat="eq_weights")

with pytest.raises(
expected_exception=NotImplementedError,
match="Weight strategy not implemented",
Expand Down

0 comments on commit 661adc1

Please sign in to comment.