Price Relative Tracking System delivers 25% CAGR since 2000
Implementing a successful online portfolio optimization system and how to use basic optimization to achieve better results while avoiding overfitting.
Online portfolio optimization is an area of research that, as the name suggests, attempts to find algorithms that work in a walk-forward fashion to optimize an investment portfolio. This is an area of research that is quite a niche in the academic world, with interesting pockets of research popping out of Asia, but shows very fruitful results.
By optimizing a portfolio in an online fashion, you avoid any potential lookahead bias and you design algorithms in a way that is reactive to the market and not predictive. These systems are less about finding an edge, and more about determining what to do given new information on the market and a current portfolio.
I believe that this area of research is a robust and well-aligned take on the market, which is why I built out an online portfolio optimization framework called portwine that allows you to build and test portfolio strategies in a clear and simple way (you can also use it for single asset allocation and trading problems but that’s a subject for the future.)
If you haven’t checked it out yet, please do! It’s open-source, and all the code and analysis I do in these posts is done with the framework so you can replicate all the findings you read here.
That being said, the algorithm we are analyzing is called "Reweighted Price Relative Tracking System for Automatic Portfolio Optimization" by Zhao-Rong Lai, et al.
The concept is that the market generally moves relative to itself. On down days, everything is down. On up days, everything is up. But, when comparing individual assets to each other and what their relative performance is to one another, we can come up with a portfolio optimization system that outperforms the market.
Quite specifically, it looks at the relative price of assets and calculates an optimal rotation strategy. The assumption is that gains from stocks that are doing very well should be rotated into stocks that are doing relatively worse, as they are more likely to mean-revert back up.
You want to tune the algorithm in such a way that it isn’t acting too ‘quickly’ and throwing all of its capital into the poor performers which actually might continue to go down. You also want to make sure that the window in time that the system sees is long enough to pick up on patterns, but short enough to be able to react in time, much like a moving average filter.
In fact, the RPRT system internally keeps track of a simple moving average of prices to determine which assets are trading above and below of what is ‘normal’ and uses this information to come up with an optimal allocation strategy.
There is a lot of other math in the paper that obfuscates actually what is going on with terms like ‘simplex’ and ‘Mahalanobis distance.’ But the point is, it is actively shifting weights from winners into losers to diversify risk and take advantage of the mean-reverting properties of the market.
And so, enough math. Let’s code the RPRT system and see how it performs!

Let’s test this algorithm with the base parameters set in the initialization function on a few sets of ETFs, like in the previous article.

Wow! 100x since 2000 using only ETFs, avoiding the survivorship bias of currently trading stocks. This is really good out of the box performance. What happens on the other baskets?
Broad ETFs
The broad ETFs also look really good. I actually prefer this equity curve to the one above because the variance in the returns is more consistent and the amount of time the strategy is underwater is lower than the sectors ETFs strategy.
Commodity ETFs
Terrible. Like always it seems so far with my strategies on commodities. We will conquer this asset class soon enough.
Stock Basket
Very strange behavior for the stocks basket. Not sure what to make of it at this point in time. But, I believe a lot of these strategies do depend on the basket used and if the basket is ‘describing’ the market in a way that the system expects. Perhaps the stocks in this basket are acting outside of the expected behavior of the mean-reverting assumptions of the RPRT system. Let’s circle back on this later.
Extended Sectors ETFs
Good performance, but a lot of risk. And, ironically, it does worse than the basic sector basket. This goes to show about what I’m saying with the selection of assets for these online portfolio systems.
So, we have a really good strategy with the SPDRs that gives us a CAGR of 20.11% (+166.72% increase in CAGR from benchmark) with a bit more risk than an equally weighted strategy.
The Sharpe ratio has increased +43.67% to 0.84 from 0.58.
The Optimization Siren Song
Wow, amazing. But, what if we could do even more? What if we could optimize? The RPRT system has three parameters that we could tune, and if it worked this good out of the box with the default parameters then surely it will work with the correct parameters for this basket, right?
Well, as you’re probably already aware of, optimization comes with a huge risk of overfit. But at the cost of potentially much higher strategy performance, we have all delved deep into the bowels of optimization hell only to emerge hours later not knowing if our system even had any alpha to begin with.
And for those who are not aware, optimization comes at an extremely high risk of selecting parameters that look really good on the data we test the optimization on, but does terrible on real-world out-of-sample data in the environment.
Luckily, we can check for overfitting in several ways. Also, because our system only has a few parameters, we can create a pretty simple grid search and avoid falling into the trap… right?
Let’s address the concerns:
We will use a very conservative train/test split (50%) to optimize our strategy. This means that we will take the first 50% of the data (about 7.5 years in our case), run every parameter configuration and score it. Then, we will select the parameters with the best score.
We will compare the summary statistics such as drawdown, CAGR, Sharpe ratio, etc. between the train and test sets to see if there is any decay. If the test set performs much worse than the train set based on the comparison of the statistics, we know it’s overfit.
So, let’s create an Optimizer object that accepts a StrategyBase class and a dictionary of potential parameters to iterate through. This class is available on the portwine GitHub repo.
We give the optimization function a dictionary mapping of the keyword arguments / variables we want to optimize and lists of the values we want it to test. This is a pretty basic grid search system that can start to fail once the possible combination count gets exponential. But for now, let’s see what it gives us.
Best params: {'tickers': ('XLP', 'XLY', 'XLF', 'XLV', 'XLK', 'TLT', 'SHY'), 'window_size': 10, 'theta': 0.8, 'eps': 5} train_score=1.0149, test_score=1.0000
Original params: {'tickers': ('XLP', 'XLY', 'XLF', 'XLV', 'XLK', 'TLT', 'SHY'), 'window_size': 5, 'theta': 0.8, 'eps': 50}Well, that didn’t really give any additional benefit. But, it at least we can observe the overfit ratios and know that, with certain certainty, these parameters are not overfitting. In fact, the test set outperforms the train set in every category. So hey. Can’t win them all. We can also compare the original and optimized strategies to each other to see how they stack up.
We see that the two strategies are almost identical, with the optimized one getting about 5% more returns over the course of 25 years. Not too crazy. We also, unsurprisingly, see that the correlation of the two strategies is basically 1, only deviating when the strategies simply trade a bit differently. But, hey, okay. Let’s try optimizing the others.
Broad ETFs Optimization
The broad ETF optimization performs much much better than the sector ETF optimization. And, if we look at the overfit ratio, we can see a little bit of a different story. The CAGR is starting to overfit. Values in between 1.1 - 1.25 are in a ‘danger’ zone. Anything above 1.25 should be considered overfit. However, these values are somewhat subjective as well. A 3.9% decrease in the CAGR is not too crazy. That being said, let’s look at the comparison.
This comparison shows a much more interesting story. Firstly, the correlation between the strategies oscillates between 0.5 and 1, which is potentially exploitable. Secondly, the performance of the optimized strategy against the original strategy fluctuates. It seems that during the 2008 Financial Crisis, the optimized strategy underperforms against the original strategy, only to bounce back up to performing a cumulative 200% better going into 2009, and then finally ‘bleeding’ out against the original strategy until about 2016 when it starts to pick up the slack again.
This is interesting because it shows us that these two strategies tackle the market in different ways. We could potentially come up with a switching strategy based on this relative performance of the two to come up with a metastrategy that captures the best of each strategy during the market conditions they are best at.
I would consider this optimization a great success that also gives us a potential route to go down to further our research into metastrategies.
Stock Basket
The stock basket optimization results shows exactly what we’re not trying to have happen. Pretty much all of the overfit ratios are outside of our acceptable range. And, while the CAGR has technically increased, the distribution of returns shown on the histogram has changed too. The distribution should generally stay around the same, which is not the case here. What is curious is that it seems that the RPRT system chooses not to allocate weights beyond an equally weighted strategy until about 2010-2011. This could be because of a variety of factors. But, most likely, it has to do with this selection of stocks not being wide enough to capture useful market dynamics.
And here, we can see the consequences of overfit. The training data (data before 2012) outperforms the benchmark strategy up until the 2008 Financial Crisis. After that, the two strategies diverge, and the naive strategy outperforms, ironically.
This is because the selected parameters work really well within the training data, but perform poorly in the test. What could be happening as well is that the ‘optimal’ strategy is an equally weighted portfolio up until that point. And, so, the optimized strategy is actually trying to find parameters that prevent the algorithm from doing anything, which could cause it to choose extreme values that are not triggered in the training data, but triggered in the testing data. This is a ‘strategy’ that many metaheuristic optimization algorithms use to find the best solution at all costs and ends up producing unusable results.
Extended Sectors ETFs
The extended sectors ETFs unfortunately suffers an even worse fate than the stocks. All the overfit ratios are at the failing levels, and at much worse ones at that. It goes to show a very important lesson about optimization: you get the best results when you already know roughly what the parameters should be for the problem. When you give parameter sweeps that are too large, or throw an optimizer at a problem too early so that you don’t have to do your job as an analyst, you end up in dangerous territory.
Of course, you also would have no need for an optimizer if you knew the optimal parameters already. So, the lesson here is balance. Luckily, with guardrails, we won’t fall off the ledge too far. We know when we’ve lost our balance and can readjust our strategy with the overfit ratios. As is the case with everything, more clarity, understanding, and transparency always helps to lead us to the optimal solution, whether that’s in trading or in life.
Enough sappiness. Let’s see the comparison charts.
Unsurprisingly, this looks terrible. But, I’m not upset because we already have a really good contender.
In Conclusion
I hope this article has taught you two things.
The Reweighted Price Relative Tracking System is a robust online portfolio allocation system that can greatly outperform the market given the right assets and settings.
Optimization can be a blessing and a curse. By making sure we check for overfit, we can safely optimize our strategies.
All code will be available on the portwine GitHub repository, as usual.
And, if you have not already subscribed, please do. It helps support my work and gives me encouragement to provide you all with the best quality research that I can. Thank you so much!




















What a great share! Thanks for this. I dabbled in online portfolio selection some years back but haven't revisited it since. Now seems to be a good a time as any 🤓
Thanks for sharing, one thought, are you by any chance calculating your equity curve using sum of weighted returns and then using a normalized cumsum? If so any reason why you didnt use cumprod for the compound equity curve? I had done the same strategy a while back and the cumulative returns for broad etfs (similar to yours) looked a lot smaller (magnitude of 2-2.5x benchmark returns). Would love to hear your thoughts