In a previous post that I made here (and in r/ValueInvesting) earlier this year, I presented the results of a machine learning model that used fundamentals from stocks listed on the S&P 100 to predict stock returns and then used quarterly re-balancing. While I thought that this method worked well, I have had problems with my data provider (SimFin) and noticed that tickers were not consistently present in my dataset, in addition to some errors.
As such, I abandoned that approach and decided to directly pull the data from SEC's EDGAR database. In addition, I wanted to test out a rules-based approach that did not use machine learning and required even less turnover/maintenance.
To that end, I would like to present my current system which uses 9 factors (8 fundamental factors and 1 technical indicator) to pick a basket of stocks at the end of each year and hold them for the entirety of the following year.
The Universe: I focused on S&P 100 stocks for several reasons. For one, I was able to build a fairly robust constituent list going back a decade using the Wayback Machine and Wikipedia; I essentially pulled the constituent list as close to the end of the year as I could and use that for the following year. Another reason is that it is challenging to get stock data for tickers that no longer exist - this accounts for dozens of tickers in the S&P 500, including numerous bankruptcies. The reason a ticker may not be included in the SP100 universe is usually due to acquisitions, rather than bankruptcies. As such I believe my back test is likely more accurate for the SP100 rather than SP500 universe. That being said, the number of tickers in my backtest grows over the years from 54 in 2016 to 82 in 2025. This is a real caveat as well and due to numerous tickers for companies that were acquired and thus no longer have stock data on yahoo finance. This could cut both ways in the sense that we miss the bump that M&A may lead to but also miss the losses associated with poor performers that may have been ranked high in their fundamentals.
The Data: I pulled data from SEC's EDGAR system and focused on pulling 10-Qs AND 10-Ks published during the last calendar quarter (October 1 - December 31) regardless of the company's own fiscal calendar. In cases where the 10K wasn't available, 10Qs was used to produce the same metrics. Only companies with complete data for all factors were included.
The Factors: I used the following 9 factors (8 fundamentals and 1 technical indicator) to rank stocks. The factor and the category they fall into are:
- Profitability & Efficiency: Return on Assets (TTM), Operating Margin (TTM).
- Cash Flow Quality & Accruals: Free Cash Flow to Assets, Cash Flow to Net Income Ratio.
- Solvency & Capital Structure: Current Ratio, Share Dilution (inverted).
- Growth Dynamics: YoY Revenue Growth, YoY Net Income Growth.
- Price Momentum: 1-Year Trailing Return.
Each factor is converted into a standardized score; all scores are then averaged to create a final score/ranking.
The 8 fundamental factors were selected a priori, and I added momentum later after the first batch of testing just based on a hunch. Beyond that, the factors were not further iterated upon.
Trade Execution: Trades are quite simple; we simply buy x top scored stocks on the first trading day of the year and hold until the last trading day of the year.
Results
Total returns from 2016 to present are below for three following basket sizes: 10, 15 and 20.
| Strategy |
Total Return |
CAGR |
Ann Vol |
Sharpe |
Daily Max DD |
|
|
|
|
|
|
| Top 10 |
850.0% |
22.7% |
22.7% |
1.09 |
-30.0% |
| Top 15 |
647.9% |
20.1% |
18.6% |
1.16 |
-28.9% |
| Top 20 |
637.5% |
19.9% |
17.5% |
1.21 |
-29.1% |
| SPY Benchmark |
349.7% |
14.6% |
15.3% |
1.03 |
-33.7% |
Yearly results are presented below:
| Holding Year |
Top 10 |
Top 15 |
Top 20 |
SPY Benchmark |
|
|
|
|
|
| 2016 |
4.8% |
6.1% |
7.4% |
13.6% |
| 2017 |
29.4% |
27.1% |
28.4% |
20.8% |
| 2018 |
-6.0% |
-4.4% |
-3.2% |
-5.2% |
| 2019 |
34.0% |
33.3% |
34.5% |
31.1% |
| 2020 |
36.6% |
29.3% |
28.9% |
17.2% |
| 2021 |
45.9% |
36.3% |
29.1% |
30.5% |
| 2022 |
-17.2% |
-16.3% |
-13.2% |
-18.6% |
| 2023 |
45.0% |
36.9% |
45.1% |
26.7% |
| 2024 |
51.0% |
36.8% |
30.7% |
25.6% |
| 2025 |
13.2% |
17.0% |
16.5% |
18.0% |
| 2026 |
36.2% |
34.5% |
28.7% |
12.9% |
Overall, all three baskets outperform SPY by roughly ~300% to 500% over a 10-year period and produce better CAGRs, Sharpe scores, and drawdowns. On a yearly basis, the top 10 basket outperformed SPY 8/11 years (including YTD); the Top 15 and 20 baskets outperformed SPY 9/11 years.
I conducted further statistical testing using the top 10 basket to determine whether my results were statistically significant.
The results of the Monte Carlo testing (1000 random draws) are below:
| Metric |
Value |
|
|
| Top 10 Actual CAGR |
22.7% |
| Monte Carlo Random 10 Average CAGR |
14.9% |
| Monte Carlo 95th Percentile CAGR |
19.5% |
| Monte Carlo CAGR p-value (Skill vs Luck) |
0.0030 (Statistically Significant) |
| Paired t-test Statistic (Excess Return) |
2.55 |
| t-test p-value (vs SPY) |
0.0145 (Statistically Significant) |
| Tracking Error (vs SPY) |
11.9% |
| Information Ratio (IR) |
0.77 |
As can be seen, our results are above beyond luck (p = 0.003) and a t-test comparing yearly returns (should be taken with a grain of salt given there are only 11 years) are also significant suggesting that our results are not a function of luck.
To further test whether our returns were driven by a tech bull run, I ran a linear regression that sought to determine whether our returns could be predicted by XLK's performance. When running the regression on yearly returns the result is not significant (p = 0.3); however - as with the pairwise t-test, our n is only 11; as such I ran the same regression on monthly returns (which expands our sample size to ~130) and this model was significant (p < 0.001; R2 = 0.2946). This means that 30% of the variance seen in our returns can be explained by XLK. Considering how much tech companies have driven broader market returns and the S&P 100 universe we are selecting from, this is largely unavoidable. Ultimately, this remains a strong result in my opinion as 70% of the variance in our returns is independent of the tech sector bull run.
Overall, I think these results are promising but would love to hear what people think. Happy to answer any questions you may have!