Start with the overview below (about five minutes). The full report follows it.
The requirements sheet listed four trading ideas. We reviewed all four, then built and ran a full test of the second one, momentum. Its question is simple: if a stock has recently been one of the S&P 500's biggest winners, does it keep beating the market? And do the biggest losers bounce back?
We started there because it can be tested with free data, decades of research exist to check our numbers against, and the same tools will serve the politician-trading idea later.
The short answer is no, not reliably. Between 2000 and 2026, recent winners kept winning in some years and fell behind in others. The effects were small, a few percent over a year, and too weak to tell apart from luck. No version of the strategy beat simply buying and holding SPY over the last ten years.
On a typical recent month-end, about 460 index stocks had at least a year of price history. We:
We repeat this at every month-end from January 2000 to October 2026, 322 times in all, and average the results to see what typically happens next.
Three details keep the test honest:
1. The two periods disagree. Figure B follows the previous 12 months' top 10%. In the practice period they fell steadily behind the average stock, ending the year 4.4% behind; in the test period they ended 2.4% ahead. A pattern worth trading would point the same way in both, and neither result passes a standard significance test.
2. A few extreme years drive the averages. Figure C splits the same measure by the year the winners were picked. Most years land within a few percent of zero, either way. The practice-period loss comes mainly from winners picked in 2000, at the top of the dot-com bubble (42% behind), and in 2008–09, when the previous losers led the rebound (13–16% behind). Without those three years the practice average is +0.4%. Likewise, the test-period gain comes almost entirely from winners picked in 2023 and 2024; without them it is −0.3%.
3. Most winners do not keep winning. Over the six months after being picked, between 47 and 50 out of every 100 winners beat the average stock, about the same as for stocks in general (47 out of 100). Any gain on average comes from a handful that keep rising strongly.
4. Losers bounced back a little. The bottom 10% beat the average stock by up to about 4% over the next year in both periods, which fits the sheet's mean-reversion question. The evidence is weak, though, and the practice figure is flattered by missing data: losers that went bankrupt are not in the free price data.
5. As a strategy, nothing beat SPY. The setting that looked best in the practice period became a portfolio: each month, buy the previous week's top 10% in equal amounts and hold each batch for six months, after trading costs. A second version moved to cash whenever SPY was below its 200-day average. Figure D compares both with SPY and with owning every index stock equally.
In the test period the momentum portfolio returned 13.1% a year against SPY's 14.4%, and its worst fall from a peak was deeper (38% against 34%). The version with the cash rule had a smaller worst fall (31%) but returned only 6.7% a year. It tended to move to cash after the market had already dropped, then miss the quick rebounds (early 2019, 2020, 2025).
6. A good-looking result can still be misleading. In the practice period the momentum portfolio beat SPY by about 6 points a year, which looks like a discovery. But owning every index stock in equal amounts did just as well (Figure D, left). The gain came from equal weighting, which favored smaller index companies in those years, plus some help from the missing bankrupt companies, not from momentum. Checking every result against a benchmark built from the same data is what caught this. (Compared with RSP, a real equal-weight index fund, the missing data added about 1.8 points a year in the practice period and 0.7 in the test period.)
The sheet asks for a return above buy-and-hold together with a smaller worst loss. In the test period no version met both. The momentum portfolio met neither, and the cash-rule version met only the second.
With free data, momentum in the 500 largest US stocks has not been strong or consistent enough to trade on its own since 2000. That is still useful: it rules out the simple version before any money goes in, and the tools can be reused. Next steps:
The full write-up follows: the review of all four ideas (Section 2), data (3), the model with formulas (4), all results tables (5) and limitations (7).
The requirements sheet (notes/Modeling requirements.csv) lists four ideas:
| # | Idea | Question | Stated requirement |
|---|---|---|---|
| 1 | Next-day market direction | Can data up to today's close predict the direction of tomorrow's open? | Win rate of at least 75%, return above buy-and-hold, drawdown below buy-and-hold. |
| 2 | Momentum | Do last week's or last month's top S&P 500 performers keep rising? Do most of them? For how long? Do they mean revert, and when? | Backtest; if trends persist for a certain time, test buying and selling after that time. |
| 3 | Politician trades | How do stocks move after politicians' trades become public? Does the move persist or fade? | Same as idea 2, reusing what is learned there. |
| 4 | Macro price floor | Can CPI, PPI, rates, oil, bond yields and similar factors in a regression indicate a floor or direction for the S&P 500 or single stocks? | Buy if the forecast is above the current price, sell or short if below. Maximize return, minimize drawdown. |
The work had two parts: a critique of the four ideas (Section 2), and a proof of concept for the one with the best chance of producing a trustworthy answer with free data (Sections 3–5). We chose idea 2. It can be tested with free data, it has decades of academic research to compare against, and the machinery it needs (a historical index membership list, an event study and a backtester) is the same machinery idea 3 needs.
| Idea | Main problems | Suggested change |
|---|---|---|
| 1. Next-day direction | SPY opens higher than the prior close a bit more than half the time, so the bar to beat is "always hold overnight", not a coin flip. Academic work has found that much of the US market's long-run return has come overnight rather than during the trading day. Trading twice a day makes costs a large share of any edge. | Try to beat "always hold overnight" after costs. Candidate inputs: the day's return, the change in VIX, futures moves after the close, day of the week, earnings season. |
| 2. Momentum | Heavily researched already. Winners over the past week or month tend to reverse (Jegadeesh 1990; Lehmann 1990). Winners over the past 3–12 months tend to keep outperforming for 3–12 months (Jegadeesh & Titman 1993), then fade over several years (De Bondt & Thaler 1985). The biggest trap is using today's S&P 500 list for past years. | Use historical membership. Measure each stock against the average stock, because in a bull market nearly everything rises. Pick the holding period with early data and test it once on later data. |
| 3. Politician trades | The STOCK Act allows trades to be disclosed up to 45 days after they happen. Using the trade date assumes information nobody had yet. Research is mixed (Ziobrowski et al. 2004 found outperformance; Eggers & Hainmueller 2013 did not). Amounts are reported in ranges, samples are small, and free data sources come and go. | Use the disclosure date as the event. Compare against the NANC and KRUZ ETFs, which already follow these trades. Consider corporate insider purchases (SEC Form 4) as well: same idea, free data back decades, filed within two business days, and better research support (Cohen, Malloy & Pomorski 2012). |
| 4. Macro price floor | Regressing price levels on CPI or rate levels finds relationships that are not there, because any two series that trend over time look correlated. Economic data is published with a lag and later revised. Markets react to surprises relative to expectations, not to levels. Monthly data offers few independent observations, so a model with eight or more inputs will overfit. Prediction markets have too little history to backtest. | Predict index returns over the next 3–12 months instead of price levels. Model the "floor" as a bad-case outcome, for example the 10th percentile of future returns given today's conditions. Use rate-hike odds implied by fed funds futures, which go back decades. This works best as an on/off risk filter for other strategies, not on its own. |
A momentum test on "S&P 500 stocks" must use the stocks that were in the index at the time. Today's list contains only the companies that survived and grew, so testing past years with it builds in a large upward bias.
We used the historical membership file from github.com/fja05680/sp500, which records the full list of members on each date the list changed. On each date in our study, a stock is a candidate only if it was a member that day. Across 1999–2026, 1,103 distinct tickers were members at some point.
Daily prices adjusted for splits and dividends came from Yahoo Finance. Yahoo has a gap that matters here: it has no data for companies that no longer trade, whether acquired or bankrupt. We found prices for 724 of the 1,103 tickers. Table 3 shows what share of each year's members we could price.
| Year | 2000 | 2005 | 2010 | 2015 | 2016 | 2020 | 2025 | 2026 |
|---|---|---|---|---|---|---|---|---|
| Coverage | 49% | 56% | 69% | 77% | 81% | 91% | 97% | 99% |
Coverage is good from 2016 on, which is why 2016 onward became the out-of-sample test period. Three problems with tickers needed fixing first:
Even after these fixes, about half the members in 2000 and a fifth in 2016 are missing, mostly companies that were later acquired or went bankrupt. Two steps limit the damage:
Cash returns use the 13-week Treasury bill yield (Yahoo ticker ^IRX). The market benchmark is SPY, with dividends reinvested.
The sheet asks whether recent top performers keep rising, whether most of them do, for how long, and whether and when they mean revert. In testable form:
At the end of each month, rank every eligible index member by its return over a recent window. Take the top 10% ("winners") and bottom 10% ("losers"). Over the following year, how does each group's return compare with the average eligible stock's, day by day? What share of each group beats the average?
This design is called an event study: the "event" is a stock landing in the top or bottom tenth, and we trace what happens afterwards. Repeating it every month from January 2000 to October 2026 gives 322 events of each kind for each lookback window.
Each stock's formation return is its price change over the window:
Ri,t = Pi, t−s / Pi, t−L − 1
We test six windows:
| Name | L (days) | s (days) | Why it is included |
|---|---|---|---|
| 1w | 5 | 0 | "Last week's winners" from the sheet. |
| 1m | 21 | 0 | "Last month's winners" from the sheet. |
| 3m | 63 | 0 | Shortest window in Jegadeesh & Titman (1993). |
| 6m | 126 | 0 | Common middle choice. |
| 12m | 252 | 0 | Full-year return. |
| 12-1m | 252 | 21 | The standard academic signal: last 12 months excluding the most recent one, which avoids the short-term reversal effect. |
Stocks in Ut are sorted by Ri,t. The top 10% form the winner group Wt and the bottom 10% the loser group Dt. That is about 31 stocks per group in 2000–2015 and 46 from 2016. Every window uses the same universe, so differences between windows come from the ranking alone.
Prices at the close on day t are needed to compute the ranking, so nobody could trade at that close. Tracking therefore starts at the next day's close, t+1. Each stock's cumulative return h days later is:
ri(t, h) = Pi, t+1+h / Pi, t+1 − 1
If a stock's price history ends during the year (for example, it is taken over), its last price is carried forward, as if the position had been turned into cash at that price.
Each group's return is the simple average of its members' returns, which is what an equal-weighted portfolio bought on day t+1 and held without rebalancing would earn. From it we subtract the same average across the whole universe:
XW(t, h) = avgi ∈ Wt ri(t, h) − avgj ∈ Ut rj(t, h)
The same is done for losers. This excess return answers "did winners do better than the average stock?" rather than "did winners go up?". In a rising market almost everything goes up, so the second question says little about momentum. As explained in Section 3.3, subtracting the average from the same data also cancels most of the survivorship bias.
For the question "do most winners keep winning?", we also record the hit rate: the share of the group whose own return beats the universe average. We compute the same share for the whole universe as a baseline. That baseline sits below 50%, because single-stock returns are skewed: a few very large gains pull the average above what the typical stock earns.
The curves in Figure 1 are averages of X(t, h) across all formation dates in a period, plotted against h. For the grid in Tables 6–9 we read the average at five holding periods (1 week, 1, 3, 6 and 12 months) and test whether it differs from zero.
The test needs care. Formation dates are a month apart, but a 12-month holding period means consecutive observations share 11 months of returns, so they are far from independent. An ordinary t-statistic would overstate confidence badly. We use the Newey–West (1987) standard error, which allows for this overlap, with the number of lags set to the holding period in months. As a rule of thumb, a t-statistic above 2 in absolute value is evidence of a real effect, and one below 1.5 is consistent with noise.
The data is split into an in-sample period (formation dates from January 2000 to December 2015), used to explore and choose settings, and an out-of-sample period (January 2016 onward), looked at once with settings already fixed.
A simple date split still leaks. A stock picked in November 2015 and held for 12 months earns most of its return in 2016. We drop any in-sample observation whose holding window ends after 31 December 2015, so in-sample statistics never use 2016 prices. This is why the in-sample count falls from 191 months at a 1-month hold to 179 at a 12-month hold.
To turn the study into a strategy we need one formation window and one holding period. The script picks the pair with the highest in-sample t-statistic for winners from 24 candidates (6 windows × 4 holding periods of 1, 3, 6 or 12 months; the 1-week hold is left out because the portfolio trades monthly). It then applies a gate: if the best t-statistic is below 2, the result does not qualify as a strategy. Picking the best of 24 noisy numbers favors whichever had the luckiest draw, so a modest t-statistic for the winner of that contest means even less than it would for a single pre-chosen setting (see Bailey & López de Prado 2014). The backtest runs either way so the machinery and benchmarks can be checked.
The portfolio follows Jegadeesh & Titman (1993). Each month a new cohort of winners is bought at equal weight and held for H months. At any time the portfolio therefore holds the last H cohorts, each with 1/H of the capital. At each monthly rebalance the target weight of stock i is:
wi = Σk=0…H−1 (1/H) · (1/|Wt−k|) · [i ∈ Wt−k]
where the bracket is 1 if the stock was a winner in that month's cohort and 0 otherwise.
Example. With H = 6 and 46 winners per month, each cohort holds 1/6 ≈ 16.7% of capital and each stock in a cohort gets 16.7% / 46 ≈ 0.36%. A stock that was a winner in three of the last six months holds about 1.09%. The portfolio holds up to 276 positions, usually fewer because of repeats.
Between rebalances weights drift with prices. At each rebalance the portfolio is reset to the target weights. Stocks that left the index stay in their cohort until it expires, as they would in a real account.
A second version applies a simple market filter aimed at the drawdown requirement. At each month-end, if SPY closes below its 200-day moving average, the target is 100% cash for that month. The 200-day setting is the conventional one and was not tuned. The filter was in cash in 30% of in-sample months and 17% of out-of-sample months (22 of 130).
--cost-bps 25 to stress it.| Measure | Definition |
|---|---|
| CAGR | Compound annual growth rate: the constant yearly return that produces the same ending value. |
| Volatility | Standard deviation of daily returns × √252. |
| Sharpe ratio | Average daily return above the T-bill rate, divided by its standard deviation, × √252. Return per unit of risk. |
| Max drawdown | Largest peak-to-trough fall in portfolio value. |
| Calmar ratio | CAGR ÷ |max drawdown|. Return per unit of worst loss. |
| Up months | Share of calendar months with a positive return. |
| Beat-SPY months | Share of months in which the strategy returned more than SPY. The nearest equivalent to "win rate" for a monthly strategy. |
| Turnover / yr | Sum of absolute weight changes per year. 1.0 means the equivalent of the whole portfolio was bought and sold once. |
reports/.The two periods disagree. In 2000–2015, winners over 6 and 12 months fell behind the average stock steadily for the whole following year. Most of that comes from two episodes. Stocks picked as 12-month winners during 2000, near the top of the dot-com bubble, lagged the average stock by 42% over the following year. Winners picked during 2008 and 2009 lagged by 13–16% as the market rebounded in 2009 and the previous year's biggest losers rallied hardest, a pattern known as a momentum crash (Daniel & Moskowitz 2016). Leaving out formation dates in 2000, 2008 and 2009, the in-sample average for 12-month winners is close to zero (+0.4%). The out-of-sample gain is similarly concentrated: without winners picked in 2023 and 2024 it falls from +2.4% to −0.3%. Figure C in the overview shows the year-by-year results. From 2016, winners on every window pulled ahead slowly, and losers also beat the average slightly.
| Formation | 2000–2015 winners | 2016–2026 winners | ||||
|---|---|---|---|---|---|---|
| Peak day | At peak | At 12m | Peak day | At peak | At 12m | |
| 1w | 233 | +0.8% | +0.7% | 218 | +1.2% | +1.0% |
| 1m | 233 | +0.7% | +0.6% | 236 | +2.3% | +2.1% |
| 3m | 207 | +0.4% | −0.2% | 228 | +2.4% | +1.9% |
| 6m | none | — | −2.6% | 244 | +2.9% | +2.5% |
| 12m | none | — | −4.4% | 223 | +2.7% | +2.4% |
| 12-1m | none | — | −4.3% | 204 | +2.6% | +2.2% |
Where winners did pull ahead, the gain built slowly for most of the year, peaking between trading days 204 and 244 (about 10 to 12 months), and little of it was given back within the year. These are small numbers, however: 2–3% over a year, before asking whether they are distinguishable from noise.
Each cell is the average excess return over the holding period, with the Newey–West t-statistic in parentheses.
| Formation | 1w hold | 1m | 3m | 6m | 12m |
|---|---|---|---|---|---|
| 1w | −0.2 (−1.2) | −0.3 (−1.4) | −0.4 (−1.2) | +0.7 (+0.9) | +0.7 (+0.5) |
| 1m | −0.0 (−0.1) | −0.3 (−1.4) | −0.4 (−1.1) | +0.0 (+0.0) | +0.6 (+0.5) |
| 3m | −0.2 (−1.7) | −0.2 (−0.9) | −0.4 (−0.8) | −0.1 (−0.1) | −0.2 (−0.1) |
| 6m | −0.1 (−0.9) | −0.2 (−0.6) | −0.5 (−0.8) | −0.7 (−0.5) | −2.6 (−1.0) |
| 12m | −0.2 (−1.4) | −0.3 (−0.9) | −1.2 (−1.6) | −2.8 (−1.8) | −4.4 (−1.4) |
| 12-1m | −0.1 (−0.7) | −0.2 (−0.6) | −1.2 (−1.5) | −2.8 (−1.8) | −4.3 (−1.4) |
| Formation | 1w hold | 1m | 3m | 6m | 12m |
|---|---|---|---|---|---|
| 1w | +0.2 (+1.3) | +0.1 (+0.3) | +0.1 (+0.3) | +0.8 (+1.1) | +1.0 (+0.8) |
| 1m | +0.1 (+0.6) | −0.0 (−0.1) | −0.1 (−0.2) | +0.7 (+1.0) | +2.1 (+1.3) |
| 3m | +0.1 (+0.3) | −0.1 (−0.5) | −0.1 (−0.1) | +1.3 (+1.3) | +1.9 (+1.2) |
| 6m | +0.0 (+0.1) | +0.0 (+0.2) | +0.4 (+0.7) | +2.0 (+1.7) | +2.5 (+1.3) |
| 12m | −0.0 (−0.2) | +0.0 (+0.1) | +0.3 (+0.4) | +1.6 (+1.2) | +2.4 (+1.1) |
| 12-1m | −0.1 (−0.3) | +0.0 (+0.1) | +0.4 (+0.6) | +1.9 (+1.4) | +2.2 (+1.1) |
| Formation | 1w hold | 1m | 3m | 6m | 12m |
|---|---|---|---|---|---|
| In-sample, 2000–2015 | |||||
| 1w | +0.1 (+0.8) | +0.3 (+0.9) | +0.7 (+1.0) | +0.5 (+0.5) | +1.3 (+0.7) |
| 1m | +0.1 (+0.4) | +0.1 (+0.4) | +0.7 (+0.9) | +1.0 (+0.8) | +2.0 (+0.9) |
| 3m | +0.2 (+1.1) | +0.5 (+1.3) | +0.9 (+1.0) | +1.8 (+1.0) | +3.6 (+1.2) |
| 6m | +0.2 (+0.8) | +0.5 (+1.1) | +1.3 (+1.0) | +2.0 (+0.8) | +4.4 (+1.0) |
| 12m | +0.4 (+1.4) | +0.4 (+0.9) | +0.8 (+0.6) | +1.7 (+0.6) | +4.4 (+1.0) |
| 12-1m | +0.3 (+1.2) | +0.3 (+0.6) | +0.6 (+0.5) | +1.2 (+0.5) | +4.2 (+0.9) |
| Out-of-sample, 2016–2026 | |||||
| 1w | −0.0 (−0.2) | +0.2 (+1.0) | +0.5 (+1.2) | +0.5 (+0.5) | +2.0 (+1.2) |
| 1m | +0.1 (+0.7) | +0.2 (+0.7) | +0.5 (+1.3) | +0.6 (+0.9) | +1.2 (+0.8) |
| 3m | +0.2 (+1.0) | +0.3 (+0.9) | +0.5 (+1.0) | +0.0 (+0.0) | +0.7 (+0.3) |
| 6m | +0.1 (+0.5) | +0.0 (+0.1) | −0.3 (−0.6) | −0.5 (−0.4) | +1.1 (+0.4) |
| 12m | +0.4 (+1.4) | +0.4 (+1.0) | +0.7 (+0.7) | +1.0 (+0.5) | +3.5 (+0.9) |
| 12-1m | +0.4 (+1.5) | +0.4 (+1.0) | +0.7 (+0.7) | +0.9 (+0.4) | +3.5 (+0.9) |
None of the 120 cells has a t-statistic above 2 in absolute value. The largest are −1.8 (12-month winners held 6 months, 2000–2015) and +1.7 (6-month winners held 6 months, 2016–2026). The in-sample sign pattern for winners (mostly negative) does not carry into the out-of-sample period (mostly positive). An effect that real money could rely on would show up in both. Losers beat the average in most cells of both periods, which looks like mean reversion, but the evidence is weak (t-statistics of 1.5 or less), and the in-sample figures are the ones most inflated by survivorship bias: losers that kept falling until they were delisted are missing from the data.
| Formation | 1w hold | 1m | 3m | 6m | 12m |
|---|---|---|---|---|---|
| 1w | 51% | 49% | 47% | 47% | 45% |
| 1m | 52% | 48% | 47% | 47% | 46% |
| 3m | 51% | 48% | 46% | 47% | 45% |
| 6m | 52% | 49% | 47% | 50% | 46% |
| 12m | 51% | 48% | 47% | 47% | 47% |
| 12-1m | 51% | 48% | 47% | 48% | 47% |
| All stocks | 50% | 49% | 49% | 47% | 46% |
Winners beat the average about as often as any stock does. The modest average gain in Table 8 therefore comes from a minority of winners that keep going up strongly, not from most winners continuing. In 2000–2015 the share was lower still: 41–46% for 12-month holds.
The highest in-sample t-statistic among the 24 candidates belonged to 1-week winners held for 6 months: +0.7% excess return, t = 0.9. That is far below the gate of 2, so no setting qualified as a strategy. Out of sample, the same setting returned +0.8% (t = 1.1). Results did not fall apart out of sample; there was simply nothing in-sample to begin with. The backtest below uses this setting to show the machinery and benchmarks at work.
| Strategy | CAGR | Vol | Sharpe | Max DD | Calmar | Up mo. | Beat SPY | Turnover |
|---|---|---|---|---|---|---|---|---|
| In-sample, 2000–2015 | ||||||||
| Momentum | 10.6% | 25.4% | 0.46 | −65.8% | 0.16 | 59% | 59% | 3.8 |
| Momentum + trend filter | 12.6% | 14.1% | 0.79 | −21.0% | 0.60 | 72% | 60% | 3.2 |
| S&P 500 equal-weight | 10.8% | 21.4% | 0.51 | −58.3% | 0.19 | 64% | 62% | 0.8 |
| SPY buy & hold | 4.3% | 20.1% | 0.23 | −55.2% | 0.08 | 59% | — | — |
| Out-of-sample, 2016–2026 | ||||||||
| Momentum | 13.1% | 19.4% | 0.62 | −37.8% | 0.35 | 64% | 47% | 4.0 |
| Momentum + trend filter | 6.7% | 14.1% | 0.37 | −31.1% | 0.22 | 65% | 42% | 4.9 |
| S&P 500 equal-weight | 12.6% | 18.3% | 0.62 | −39.9% | 0.32 | 66% | 44% | 0.7 |
| SPY buy & hold | 14.4% | 17.7% | 0.72 | −33.7% | 0.43 | 69% | — | — |
Three things stand out.
The in-sample momentum result is not momentum. In 2000–2015 the momentum portfolio beat SPY by about 6 percentage points a year. Taken alone, that looks like a discovery. But the plain equal-weighted universe did the same (10.8% against momentum's 10.6%). The gap over SPY came from equal weighting, which favored smaller index members after the 2000 technology peak, and from survivorship bias. Without the equal-weight benchmark, this backtest would have been badly misread.
Out of sample, nothing beat SPY. Momentum and equal-weight both trailed SPY by 1–2 points a year, during a decade when the largest companies led the market.
The trend filter's in-sample success did not carry over. In 2000–2015 it cut the worst drawdown from −66% to −21% because it was in cash for much of the 2001–02 and 2008–09 bear markets. From 2016 the market's sharp falls reversed quickly (late 2018, March 2020, April 2025). The filter went to cash after much of the fall had already happened and missed part of each rebound. Its return fell to 6.7% a year, while its worst drawdown (−31.1%) was only slightly smaller than SPY's (−33.7%).
| Period | Our universe | RSP | Estimated bias |
|---|---|---|---|
| May 2003 – Dec 2015 | 12.4% | 10.6% | +1.8 pts/yr |
| Jan 2016 – Nov 2026 | 12.6% | 11.9% | +0.7 pts/yr |
RSP's annual fee (about 0.2%) and quarterly rebalancing explain a small part of each gap, so the true bias is somewhat smaller than shown. The bias is real but much smaller than the equal-weight effect. It is also concentrated where we expected: the early years with the worst coverage. Results measured relative to our own universe (Sections 5.1–5.3) are less affected than raw returns.
Ideas 1 and 4 in the sheet ask for a return above buy-and-hold and a drawdown below it. Applying the same test to the out-of-sample results:
| Strategy | Return above SPY? | Drawdown below SPY? |
|---|---|---|
| Momentum | No (13.1%) | No (−37.8%) |
| Momentum + trend filter | No (6.7%) | Yes (−31.1%) |
| S&P 500 equal-weight | No (12.6%) | No (−39.9%) |
Does the stock continue to rise? Relative to the average S&P 500 stock, not reliably. From 2000 to 2015, 6- and 12-month winners did worse than average over the next year. From 2016 they did 2–2.5% better over a year. Neither result is statistically reliable.
Do most stocks continue to rise? No. Fewer than half of the winners beat the average stock in any holding period beyond a week, about the same share as for stocks in general.
For how long? When winners did pull ahead (2016–2026), the gain built slowly for about 10–12 months. There was no clean point at which the trend stopped.
Does the stock mean revert? Do most? How long until? Losers beat the average stock by 0.7–4.4% over the following year in both periods, which points toward mean reversion, but none of these results is statistically reliable. Last week's and last month's winners showed at most a weak reversal: in 2000–2015 they lagged the average by 0.3–0.4% over the next one to three months (t-statistics between −1.1 and −1.4), and from 2016 there was none. In older US data, short-term reversal is a well-documented effect.
Buying and then selling after that time. The best in-sample combination was not strong enough to justify trading. Out of sample, the momentum portfolio trailed SPY by 1.3 points a year with a deeper drawdown.
uv sync uv run python -I scripts/fetch_data.py # first run ~3 min; cached in data/cache/ uv run python -I scripts/momentum_study.py # ~30 s; tables to the terminal, charts and CSVs to reports/ uv run python -I scripts/momentum_study.py --cost-bps 25 # stress trading costs
| Path | Contents |
|---|---|
src/macrolab/universe.py | Historical index membership, ticker renames, excluded recycled tickers. |
src/macrolab/prices.py | Yahoo download and cache, bad-price cleaning, coverage report. |
src/macrolab/momentum.py | Formation signals, event study, period split, Newey–West tests, grid. |
src/macrolab/backtest.py | Overlapping-cohort weights and the daily portfolio simulation. |
src/macrolab/metrics.py | CAGR, Sharpe, drawdown, Calmar, monthly win rates, turnover. |
src/macrolab/plots.py | The two figures. |
scripts/momentum_study.py | Runs the whole study end to end. |
reports/*.csv | Every number in Tables 6–13, plus the full daily curves behind Figure 1. |
| Setting | Value | Where |
|---|---|---|
| Formation windows | 1w, 1m, 3m, 6m, 12m, 12-1m | momentum.FORMATIONS |
| Holding periods | 5, 21, 63, 126, 252 trading days | momentum.HOLDINGS |
| Group size | Top and bottom 10% | momentum.DECILE |
| Minimum price history | 252 trading days | momentum.MIN_HISTORY |
| Execution delay | 1 trading day | momentum.EXEC_LAG |
| In-sample / out-of-sample | 2000-01-01 to 2015-12-31 / 2016-01-01 onward | momentum_study.PERIODS |
| Significance gate | t > 2 | momentum_study.main |
| Trading cost | 10 bp per side | --cost-bps |
| Trend filter | SPY above its 200-day average at month-end | momentum_study.TREND_SMA_DAYS |
| Bad-print threshold | 75% one-day move that reverses next day | prices.clean_closes |