Momentum and reversal sound like opposites: momentum says “what’s rising keeps rising,” reversal says “what’s risen too much will fall.” Alpha 101 has 23 factors in this category, and their sophistication lies in not blindly picking a side. Instead, they use different conditions to judge whether the current regime favors momentum or mean-reversion.

The overview introduced the broad framework. This article picks 5 classic factors and breaks down the conditional logic embedded in their formulas.

Alpha#4: The Simplest Short-Term Reversal

$$\text{Alpha#4} = -1 \times \text{ts_rank}(\text{rank}(\text{low}), 9)$$

Just two layers of nesting, making it one of the structurally simplest factors in the entire set.

rank(low) is a cross-sectional rank: all stocks ranked by today’s low price, normalized to 0-1. Stocks with higher lows rank near the top.

ts_rank(..., 9) is a time-series rank: where that cross-sectional rank value sits within the past 9 days. If today’s rank(low) is the highest in 9 days, ts_rank approaches 1.0.

Negation: higher ts_rank means more negative factor value (short signal). A stock whose low-price rank has been climbing for 9 consecutive days is persistently strong. Alpha#4 shorts it, betting on reversal.

Why use low instead of close? The low captures a stock’s “weakest moment” of the day. If even a stock’s weakest moment ranks above most other stocks, its strength is thorough, and the probability of reversal is higher. Close can be inflated by end-of-day window dressing, but the intraday low is harder to manipulate.

The original paper specifies ts_rank(rank(low), 9.99922) where the 9.99922 is clearly an optimization artifact. Using 9 or 10 makes no practical difference.

Alpha#9 and Alpha#10: Two Flavors of Conditional Reversal

Alpha#9’s formula appeared in the overview:

$$\text{Alpha#9} = \begin{cases} \text{ts_rank}(\text{delta}(\text{close},1),\ 5) & \text{if } 0 < \text{ts_min}(\text{delta}(\text{close},1),\ 5) \\ \text{ts_rank}(\text{delta}(\text{close},1),\ 5) & \text{if } \text{ts_max}(\text{delta}(\text{close},1),\ 5) < 0 \\ -1 \times \text{delta}(\text{close},1) & \text{otherwise} \end{cases}$$

The conditions check whether the past 5 days show a consistent trend. ts_min(delta(close,1), 5) > 0 means every single day closed higher (even the smallest daily change was positive). ts_max(delta(close,1), 5) < 0 means every day closed lower.

In both trending cases, the factor uses ts_rank(delta(close,1), 5), ranking today’s daily change within the past 5 daily changes. During a consistent uptrend, if today’s gain is the largest in 5 days (high ts_rank), the factor value is high, signaling “momentum is still accelerating.” During a consistent downtrend, if today’s decline is the smallest in 5 days (high ts_rank), it signals “decline is decelerating.”

The “otherwise” branch handles choppy markets: when up and down days alternate, the factor simply uses -1 * delta(close, 1) as a pure reversal signal. Up today, short it. Down today, buy it.

Alpha#10 has a nearly identical structure with different threshold expressions. The core design is the same: assess market regime first, then select strategy. This is the standard template for the “conditional reversal” subfamily in Alpha 101. Factors #46, #49, and #51 follow the same pattern with different condition specifications.

The key insight: no single momentum or reversal strategy works across all market regimes. Alpha 101’s approach uses simple thresholds to classify the regime into “trending” or “choppy,” applying momentum logic to the former and reversal logic to the latter. Far simpler than machine-learning-based regime detection, but often sufficient for daily-frequency data.

Alpha#20: Gap Fill

$$\text{Alpha#20} = -1 \times \text{rank}(\text{open} - \text{delay}(\text{high}, 1)) \times \text{rank}(\text{open} - \text{delay}(\text{close}, 1)) \times \text{rank}(\text{open} - \text{delay}(\text{low}, 1))$$

Three terms measure today’s open relative to three reference points from yesterday’s candle:

  • open - delay(high, 1): open vs yesterday’s high. Positive = gap up above yesterday’s range
  • open - delay(close, 1): open vs yesterday’s close. Positive = opened higher
  • open - delay(low, 1): open vs yesterday’s low. Positive in almost all cases (unless a severe gap down)

Each term is cross-sectionally ranked, multiplied together, and negated.

When is the factor most positive (strongest long signal)? When all three ranks are low, meaning today’s open is well below yesterday’s candle. A large gap down. Alpha#20 bets that gap-downs will fill.

Conversely, stocks that gap up sharply (all three ranks high) receive short signals.

Gap fill is one of the most common patterns observed by day traders. A large gap up often represents overnight good news being overpriced at the open; without follow-through buying, the price drifts back down. A large gap down represents panic selling overshooting; short covering and bargain hunting push the price back up.

The multiplication (rather than simple addition) is elegant: the product is only large when all three dimensions simultaneously signal an extreme gap. If the open is above yesterday’s close but below yesterday’s high, the open - delay(high, 1) term is negative with a low rank, compressing the product. Only a “complete gap” (beyond all of yesterday’s price levels) triggers a strong signal.

Alpha#30: Direction Signature × Volume

$$\text{Alpha#30} = \frac{1.0 - \text{rank}((\text{sign}(\text{close} - \text{delay}(\text{close}, 1)) + \text{sign}(\text{delay}(\text{close}, 1) - \text{delay}(\text{close}, 2)) + \text{sign}(\text{delay}(\text{close}, 2) - \text{delay}(\text{close}, 3))) \times \text{sum}(\text{volume}, 5))}{\text{sum}(\text{volume}, 20)}$$

Long formula, but it decomposes neatly into two parts.

Numerator core:

$$\text{sign}(\Delta_1) + \text{sign}(\Delta_2) + \text{sign}(\Delta_3)$$

where \(\Delta_1\) = today’s close minus yesterday’s, \(\Delta_2\) = yesterday minus the day before, \(\Delta_3\) = two days ago minus three days ago. Each takes sign (+1 or -1), summing to one of: -3, -1, +1, +3.

  • +3 = three consecutive up days
  • +1 = two up, one down
  • -1 = two down, one up
  • -3 = three consecutive down days

This value is multiplied by sum(volume, 5) (5-day total volume), then cross-sectionally ranked. Stocks with consecutive gains on high volume rank highest; 1.0 - rank(...) is then lowest for them.

Denominator: sum(volume, 20) normalizes by 20-day total volume.

Net effect: stocks rising on heavy volume get low factor values (short signal). Stocks declining on light volume get higher values (long signal).

The economic intuition overlaps with price-volume divergence factors: rally on heavy volume signals overheating; decline on light volume signals overselling. Alpha#30’s unique feature is the “direction signature” discretization, caring only about which direction each day moved, not by how much. This makes it more robust to magnitude noise.

Alpha#35: Three-Timeframe Interaction

$$\text{Alpha#35} = \text{ts_rank}(\text{volume}, 32) \times (1 - \text{ts_rank}(\text{close} + \text{high} - \text{low}, 16)) \times (1 - \text{ts_rank}(\text{returns}, 32))$$

Three terms on three different time windows:

ts_rank(volume, 32): current volume ranked within the past 32 days (about 1.5 months). High value = recent volume is elevated.

1 - ts_rank(close + high - low, 16): the expression close + high - low captures “intraday bullish intensity” (higher close plus wider range = more action to the upside). Its 16-day ts_rank measures where this value stands within the past 3 weeks. Taking 1 - ... inverts it: high value = current bullish intensity is at a 16-day low.

1 - ts_rank(returns, 32): current return ranked within 32 days, inverted. High value = current returns are at a 32-day low (poor recent performance).

All three multiplied: the factor is largest when volume is rising + intraday bullish intensity is at a low + returns are at a low. Translation: a stock that has performed poorly over the past month, with prices near the bottom of their range, but volume is picking up.

This is the classic “bottom with rising volume” signal. Low prices indicate sufficient drawdown; rising volume indicates new money entering. The three time windows (32, 16, 32 days) measure medium-term volume trend, short-term price structure, and medium-term return trajectory, avoiding redundant counting on the same timescale.

Design Logic Across 23 Momentum/Reversal Factors

These 23 factors fall into three subfamilies:

Conditional reversal (#9, #10, #46, #49, #51): use if-else conditions to classify the market regime (trending vs choppy), then apply momentum or reversal logic accordingly. The core contribution is the regime-detection mechanism itself, not the signal.

Gap/overnight (#20, #23, #24): exploit the gap between today’s open and yesterday’s close/high/low for reversal trades. These have the highest time resolution, essentially capturing overnight information overreaction.

Multi-timeframe interaction (#30, #35, #52, #53): combine indicators across different window lengths to capture resonance or divergence between short-term and medium-term signals. More robust by design than single-timeframe factors, but with a larger parameter space.

Compared to the price-volume divergence group (32 factors that are mostly variations of “compute correlation between price and volume”), the momentum/reversal group shows more architectural diversity. It incorporates conditional logic, timeframe nesting, and direction discretization. This is why momentum/reversal factors often contribute more independent information in multi-factor models.

The next article covers volatility and intraday structure factors.

Series Navigation

  1. Alpha 101 Full Guide: Factor Classification & Operator Reference
  2. Price-Volume Divergence Factors (32 factors)
  3. This article: Momentum & Reversal Factors (23 factors)
  4. Volatility & Intraday Structure Factors (23 factors)
  5. Liquidity, Composite Factors & Portfolio Construction (23 factors)