universal-portfolios
universal-portfolios copied to clipboard
Equity calculation, shift issue?
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!
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.
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 :)
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.
Had a deeper look into it and it seems to be doing things correctly, sorry for bringing this issue up for nothing.
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.