Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inconsistent results in using equally-weighted portfolio. #192

Open
stanleyrazor opened this issue Jan 19, 2025 · 4 comments
Open

Inconsistent results in using equally-weighted portfolio. #192

stanleyrazor opened this issue Jan 19, 2025 · 4 comments

Comments

@stanleyrazor
Copy link

Greetings,
I am comparing two methods - which should both be implementing an equally weighted portfolio
(1) specifying Return.portfolio(assets, geometric = T)
(2) specifying a weights its object, where in each date, the returns are equal weights, and then using: Return.portfolio(assets,weights = wts_xts, geometric = T)

These two however give different results, as can be confirmed by other downstream functions e.g. table.Annualizedreturns

library(PerformanceAnalytics)

e1 <- Return.portfolio(edhec, geometric = T)

eq_wts_ts <- xts(
  matrix(rep(1/13, nrow(edhec)*ncol(edhec)), ncol = 13),
  order.by = index(edhec))

e2 <- Return.portfolio(edhec, weights = eq_wts_ts, geometric = T)

> table.AnnualizedReturns(merge(e1, e2))
                                 portfolio.returns portfolio.returns.1
Annualized Return                    0.0621              0.0574
Annualized Std Dev                   0.0383              0.0343
Annualized Sharpe (Rf=0%)            1.6193              1.6767
@braverock
Copy link
Owner

These formulations aren't the same at all.

The first formulation:

e1 <- Return.portfolio(edhec, geometric = TRUE)

creates an equal weight portfolio and then lets the weights float (no rebalancing)

the second formulation:

eq_wts_ts <- xts(
  matrix(rep(1/13, nrow(edhec)*ncol(edhec)), ncol = 13),
  order.by = index(edhec))

e2 <- Return.portfolio(edhec, weights = eq_wts_ts, geometric = TRUE)

rebalances to equal weight on every period. Which one do you actually want?

@braverock
Copy link
Owner

Perhaps (if you want to rebalance every period) since the edhec series is monthly, what you really want is:

e3 <- Return.portfolio(edhec, geometric = TRUE, rebalance_on='months')

by passing an xts object in weights, as described in the documentation and the vignette that talks about chaining returns, you've told it to rebalance on the index dates/times of the xts object.

You could also see the difference in what is happening by specifying

verbose=TRUE

@stanleyrazor
Copy link
Author

Thank you for your prompt response to my earlier query. I have read the documentation and used verbose=TRUE to better understand the behaviour of the function.

My goal was to develop a general formulation where I could specify dynamic portfolio weights. This would allow for the following scenarios:

  1. Running an equally weighted portfolio where weights remain constant over all time periods (simply buy & hold).
  2. Handling portfolios with dynamically changing weights, for example, to account for additional capital allocated to certain positions over time/rebalancing the portfolio over time.

To achieve this, I opted to represent the weights as a matrix, with each row corresponding to a specific date and each column to an asset. Which is why, even for equally weighted portfolios, I chose to represent the weight matrix to contain the same weights (e.g., equal weights) across all periods. This weight matrix set-up is preferred as its more general (can handle equally weighted buy & hold, as well as dynamic changing due to rebalancing/adding to positions), without having to write separate functions to handle the two scenarios.

The below might not be desirable, as the rebalancing could be irregular
e3 <- Return.portfolio(edhec, geometric = TRUE, rebalance_on='months')

How could I represent the equally weighted portfolio, matrix wise ?

@braverock
Copy link
Owner

your scenario 1. which you describe as "simple buy and hold" is not correct. "buy and hold" means you buy once, and then the weights float. This is equivalent to your e1.

A dynamic rebalancing is possible on whatever frequency and weights you want by creating an xts object of rebalance periods (dates and/or times) and the weights that you want to rebalance to on those periods.

If you want to dynamically rebalance when you have a view, you would enter that date/time and express your view with new weigts. if your 'neutral' view is to rebalance to equal weight and then "buy and hold" you would do that once, at the beginning of your "buy and hold" period, and let the weights float till your next periodic rebalancing. It is extremely unlikely that you would do tiny trades every day to maintain an equal weight portfolio. This would be very expensive both in time and taxes.

to answer your question about how you would represent an arbitrary rebalancing schedule (and weights), create an xts object with an index of your (regular or irregular) rebalancing periods and weights and pass that in the rebalance_on parameter. the periodicity parameters are for people who want a regular rebalance schedule. See the documentation and the return chaining vignette for more details, but this should make this clear.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants