Disclosure: This article explains a public strategy rule set for technical education. The rules can be reproduced and backtested on AlgoRover.io. It is not individualized investment advice.
A mean-reversion strategy can look simple on paper: identify unusually negative momentum, open a long position, and close it when momentum recovers.
The implementation becomes more interesting when the exit is controlled by both an indicator threshold and a timer. In the Adaptive CMO Mean Reversion strategy, that timer does not necessarily begin at entry. It is tied to the most recent low-CMO condition, so it can reset while a position is already open.
This guide explains the indicator, the complete rule sequence, and the implementation details that can cause two versions of the “same” strategy to behave differently.
What the Chande Momentum Oscillator Measures
The Chande Momentum Oscillator, or CMO, compares recent upward and downward price changes over a selected lookback period.
Figure 1: CMO compares total gains with total losses; it does not estimate reversal probability.
Its basic form is:
CMO = 100 × (sum of gains − sum of losses) ÷ (sum of gains + sum of losses)
The result normally falls between −100 and +100:
A positive value means upward changes dominated the lookback window.
A negative value means downward changes dominated it.
A reading near either extreme means one side dominated more strongly.
CMO is descriptive, not predictive. A reading below −50 does not prove that price has reached a bottom. It only tells us that recent downward changes were sufficiently dominant to cross the strategy’s entry threshold.
The Strategy Rules
The default configuration is long only:
Calculate CMO over nine bars.
Enter when CMO is strictly below −50.
Exit when CMO is strictly above +50.
If the momentum exit does not occur, exit five bars after the latest bar where CMO was below −50.
The comparisons are strict. Exactly −50 does not trigger entry, and exactly +50 does not trigger the momentum exit. This boundary detail is easy to overlook when translating a written strategy into code.
Figure 2: One strict entry condition leads to two independent exit routes.
Why the Five-Bar Timer Is Not a Fixed Holding Period
The timer is the defining implementation detail.
It is tempting to interpret the rule as “exit five bars after entry.” That is not what this state model does. It records the latest bar where CMO is below −50 and counts forward from there.
Figure 3: The timer resets at the latest CMO reading below −50.
Consider this sequence:
Bar 0: CMO falls below −50 and the long condition appears.
Bar 1: the position is active, but CMO remains below −50.
Bar 2: CMO is still below −50.
Bar 3 onward: CMO moves back above −50.
The timer now begins from Bar 2, not Bar 0. If CMO falls below −50 again before the trade closes, the timer resets again.
This makes the exit state-dependent. It is better described as “five bars since the latest low-momentum condition” than “a five-bar holding period.”
Two Exit Routes, Two Different Questions
The strategy can close a position through either route:
Momentum recovery: Has CMO moved strictly above +50?
Timed release: Has the low-CMO condition been absent for five bars?
The first route waits for positive momentum to dominate the lookback window. The second prevents the position from waiting indefinitely when that stronger recovery never appears.
Whichever condition becomes true first closes the position. A timed exit without CMO reaching +50 is therefore expected behavior, not an exception.
A Minimal State Model
The core behavior can be represented with compact Python-like pseudocode:
if not position_open and cmo < -50:
open_long()
last_low_cmo_bar = bar_index
elif position_open:
if cmo < -50:
last_low_cmo_bar = bar_index
momentum_exit = cmo > 50
timed_exit = bar_index - last_low_cmo_bar >= 5
if momentum_exit or timed_exit:
close_long()
This is an explanatory state model, not production trading code. A real implementation still needs indicator warm-up, bar-finalization rules, order-state handling, error recovery, and exchange-specific constraints.
A Step-by-Step Signal Reconstruction
In an offline HYPEUSDT daily-bar example, CMO was −59.62 on 2026-01-22 UTC. Because −59.62 is strictly below −50, the entry condition is satisfied.
Figure 4: The highlighted HYPEUSDT bar satisfies the CMO < −50 entry rule; date in UTC.
An implementation should then process later bars in this order:
Confirm that a long position is active.
Update the latest low-CMO timestamp whenever CMO is again below −50.
Check whether CMO is strictly above +50.
If not, count bars since the latest observation below −50.
Close through whichever exit route qualifies first.
This example reconstructs a signal from bar data. It is not an exchange fill record. Live execution still depends on when a bar is considered complete, order timing, spread, slippage, liquidity, contract precision, and available margin.
How the Main Parameters Change Behavior
The three visible parameters affect different parts of the system:
Figure 5: Changing the period recalculates CMO; changing the threshold only moves the comparison line.
CMO period: Changing nine bars to a shorter or longer window recalculates the entire indicator series. A shorter window gives recent changes more influence; a longer window includes more history.
Entry threshold: Moving −50 changes which existing CMO readings qualify for entry.
Timeout: Moving five bars changes how long the strategy waits after the latest low-CMO condition disappears.
These should be tested separately. Changing the period, threshold, and timeout together makes it difficult to identify which assumption changed the signals.
There is no universal “best” value implied by the rule set. Different markets and bar intervals can produce different CMO distributions, gap behavior, liquidity conditions, and data boundaries.
Implementation Checklist
Before treating two implementations as equivalent, verify the following:
Is CMO calculated from completed bars?
Can the strategy fill on the signal bar, or only afterward?
Are −50 and +50 strict or inclusive comparisons?
Does another reading below −50 reset the timer while already long?
Is the timeout anchored to the signal, the fill, or the latest qualifying bar?
Can a second long position open while one is already active?
How are missing bars and session boundaries handled?
These details often explain discrepancies more clearly than the indicator formula itself.
Main Takeaway
Adaptive CMO Mean Reversion is not simply “buy oversold and sell overbought.” It is a small state machine with a strict momentum entry and two competing exits.
The most important distinction is the timer anchor: counting five bars from entry produces a different strategy from counting five bars since the latest condition below −50.
Prepared with research support from AlgoRover using publicly available strategy materials and documented default parameters. The rule set can be reproduced and backtested on AlgoRover.io. This article is for educational purposes only and is not individualized investment advice.





Top comments (0)