universal-portfolios icon indicating copy to clipboard operation
universal-portfolios copied to clipboard

Equity calculation, shift issue?

Open psemdel opened this issue 1 year ago • 5 comments

Hi, first thx for the great library. I am writing, as I was wondering this morning why I obtained different results using your library directly and via vectorbt. I must do a thinking mistake, but cannot find where.

Let's take On-line portfolios.ipynb as an example. I restrain the data to the 10 first "days" data=data.iloc[0:10]. Then I use OLMAR algorithm as in the example. "Y" has a weight of 1 at index 6 and 0 before and after.

data["Y"] is 5 0.946035 6 0.971436 7 0.974613 8 0.961913

(we will need it later) result.X["Y"] is 5 1.01361 6 1.02685 7 1.00327

I expect the weight 1 at index 6 to mean "I buy Y at step 6". So for a price of 0.9714. As at index 7, the weight is 0. It is sold for 0.9746, so 0.003 more (Note that is also how it is interpreted in vectorbt). Now if I look at equity, I see:

6 1.131178 7 1.211978

1.21/1.13 >> 0.003 Having a deeper look in the code, I see that at line 99 of the result.py r = (self.X - 1) * self.B So 0.026 * 1. The 0.026 means however that you bought Y at step 5 and sell it at step 6. Maybe I am just reading wrong. If however it is the case, and the weight 6 is determined with the info from step 1 to 5, it would mean that we are buying with information from the future. I would have expected a .shift() here. Thx for your explanation!

psemdel avatar Apr 03 '23 11:04 psemdel

It's a bit convoluted, sorry. I followed original papers, but I'd have done it differently this time.

Every algorithm has PRICE_TYPE property determining type of price going into its step function. OLMAR uses raw price, so you're passing the correct one.

As for that line r = (self.X - 1) * self.B, self.X is not raw price anymore, but instead price relative (i.e. today's close divided by previous close). So for instance r = (1.03 - 1) * 1.5 means 3% increase with weight 1.5 which is 4.5% return.

I am writing, as I was wondering this morning why I obtained different results using your library directly and via vectorbt.

I don't know vectorbt, but different results between libraries are quite normal... If you really want to dig deeper, I'd recommend creating a super simple toy example and comparing it. Or just go with vectorbt, that library is definitely better mantained than mine.

Marigold avatar Apr 04 '23 17:04 Marigold

Hi, thanks for the library, i want to expand a bit on this issue.

I'm having the same problems as the OP of the issue, OLMAR seems to get extremely high results in my tests and the only reason i find for it is that the weights are shifted. (Which would affect OLMAR's results the most since it shifts weigths assuming next weights will be like past couple of weights).

I will look into it better tomorrow, but if self.X is, as you stated, price relative at time t, then for r = (self.X - 1) * self.B to make sense self.B would have to be the weights at time t-1. returns for having b_t-1 weights at time t-1 are b_t-1 * (p_t/p_(t-1) -1), which is b_t-1 * x_t (x_t is how much we would win today when having bought the asset yesterday). Again, i could be wrong so i will look deeper into it tomorrow, but this being the problem would explain a lot of weird stuff i've stumbled across the past days.

Whenever you read this, have a nice day :)

Aguspanale avatar Aug 02 '24 03:08 Aguspanale

I'm curious what you find! If you find an issue, it'd be great if you could post an example here so I can replicate & fix it.

Marigold avatar Aug 02 '24 12:08 Marigold

Had a deeper look into it and it seems to be doing things correctly, sorry for bringing this issue up for nothing.

Aguspanale avatar Aug 02 '24 13:08 Aguspanale

No worries, it's actually not that trivial. I have to remind myself every time I revisit my code. I should have done a better job documenting what weights correspond to returns.

Marigold avatar Aug 13 '24 11:08 Marigold