7.3 KiB
CG: Center of Gravity
"The market's center of mass reveals where momentum shifts before price does."
The Center of Gravity (CG) oscillator, developed by John Ehlers, identifies potential turning points in price action using the physics concept of weighted center of mass. It leads price movement, making it particularly useful for timing entries and exits before traditional indicators signal.
Historical Context
John Ehlers introduced the Center of Gravity oscillator in his 2002 book "Cybernetic Analysis for Stocks and Futures." Ehlers, an electrical engineer turned trader, applied signal processing concepts to financial markets, creating indicators with minimal lag.
The CG oscillator draws from physics: just as the center of gravity of an object determines its balance point, the CG of price determines where momentum is concentrated. When prices cluster toward recent values (uptrend), CG is positive; when prices cluster toward older values (downtrend), CG is negative.
Unlike momentum oscillators that react to price changes, CG measures the distribution of price within the lookback window, providing leading rather than lagging signals.
Architecture & Physics
The CG indicator uses a sliding window (RingBuffer) to maintain price history and calculates a weighted center of mass that oscillates around zero.
Core Components
- RingBuffer: Maintains the sliding window of
periodvalues - Weighted Sum (Numerator): Sum of position-weighted prices
- Simple Sum (Denominator): Sum of all prices in window
- Center Offset: Subtracts the midpoint to center oscillation at zero
Calculation Flow
For each update:
- Add new price to buffer
- Compute weighted sum: Σ(position × price)
- Compute simple sum: Σ(price)
- Calculate center: weighted_sum / simple_sum
- Subtract midpoint: result - (period + 1) / 2
Mathematical Foundation
Center of Gravity Formula
The CG at time t is calculated as:
CG_t = \frac{\sum_{i=1}^{n} i \cdot P_{t-n+i}}{\sum_{i=1}^{n} P_{t-n+i}} - \frac{n + 1}{2}
where:
nis the period (lookback length)P_{t-n+i}is the price at positioniwithin the windowiranges from 1 (oldest) ton(newest)
Numerator (Weighted Sum)
Num = \sum_{i=1}^{n} i \cdot P_i = 1 \cdot P_1 + 2 \cdot P_2 + \ldots + n \cdot P_n
Recent prices (higher i) contribute more to the weighted sum.
Denominator (Simple Sum)
Den = \sum_{i=1}^{n} P_i
Center with Zero Offset
$$ CG = \begin{cases} \frac{Num}{Den} - \frac{n + 1}{2} & \text{if } Den \neq 0 \ 0 & \text{if } Den = 0 \end{cases} $$
The subtraction of (n + 1) / 2 centers the oscillator at zero. Without this offset, CG would oscillate around the midpoint value.
Properties
- Range: Approximately
\pm \frac{n-1}{2}depending on price distribution - Zero Crossing: Indicates potential trend reversal
- Positive Values: Recent prices dominate (uptrend momentum)
- Negative Values: Older prices dominate (downtrend momentum)
- Zero Value: Prices evenly distributed (neutral momentum)
Example Calculation
For prices [10, 12, 11, 13, 15] with period 5:
Num = 1 \times 10 + 2 \times 12 + 3 \times 11 + 4 \times 13 + 5 \times 15 = 194
Den = 10 + 12 + 11 + 13 + 15 = 61
CG = \frac{194}{61} - \frac{5 + 1}{2} = 3.180 - 3.0 = 0.180
The positive value indicates recent prices are weighted higher (uptrend bias).
Performance Profile
| Metric | Score | Notes |
|---|---|---|
| Throughput | ~15 ns/bar | O(1) with running sums |
| Allocations | 0 | Zero-allocation in hot path |
| Complexity | O(1) streaming | Recalculation O(N) on bar correction |
| Accuracy | 10 | Exact calculation, no approximations |
Operation Count (per update)
| Operation | Count | Notes |
|---|---|---|
| ADD/SUB | ~6 | Running sum updates |
| MUL | ~2 | Position weighting |
| DIV | 2 | Center and offset calculation |
Quality Metrics
| Metric | Score | Notes |
|---|---|---|
| Accuracy | 10/10 | Exact weighted average |
| Timeliness | 9/10 | Leads price by design |
| Overshoot | 6/10 | Can overshoot at extremes |
| Smoothness | 7/10 | Some noise; often paired with signal line |
Validation
| Library | Status | Notes |
|---|---|---|
| TA-Lib | N/A | Not available in TA-Lib |
| Skender | N/A | Not available in Skender |
| Tulip | N/A | Not available in Tulip |
| PineScript | ✅ | Validated against original ta.cg() |
CG is validated through mathematical properties:
- Constant price produces zero CG
- Linear uptrend produces positive CG
- Linear downtrend produces negative CG
- Values bounded by approximately ±(period-1)/2
Common Pitfalls
-
Period Selection: Too short periods produce noisy signals; too long periods reduce responsiveness. Ehlers recommended 10 as a starting point.
-
Signal Line: CG is often smoothed with a 3-period SMA signal line. Trading raw CG crossings may produce false signals.
-
Zero Line Crossings: Not all zero crossings are tradeable. Confirm with price action or additional filters.
-
Trending Markets: In strong trends, CG may stay positive/negative for extended periods. Zero crossing may not occur until trend exhaustion.
-
Flat Markets: During consolidation, CG oscillates around zero without clear direction, producing whipsaws.
-
Warmup Period: CG requires a full window (
periodvalues) before producing reliable signals.
Usage
using QuanTAlib;
// Create a 10-period CG indicator
var cg = new Cg(period: 10);
// Update with new values
var result = cg.Update(new TValue(DateTime.UtcNow, 100.0));
// Access the last calculated CG value
Console.WriteLine($"CG: {cg.Last.Value}");
// Chained usage
var source = new TSeries();
var cgChained = new Cg(source, period: 10);
// Static batch calculation
var output = Cg.Calculate(source, period: 10);
// Span-based calculation
Span<double> outputSpan = stackalloc double[source.Count];
Cg.Batch(source.Values, outputSpan, period: 10);
Applications
Trend Reversal Detection
CG zero crossings often precede price reversals:
- CG crosses above zero: potential bullish reversal
- CG crosses below zero: potential bearish reversal
Divergence Analysis
Like other oscillators, CG divergences from price can signal weakening trends:
- Price makes higher high, CG makes lower high: bearish divergence
- Price makes lower low, CG makes higher low: bullish divergence
Momentum Confirmation
Use CG to confirm trend strength:
- Rising CG in uptrend: momentum supporting trend
- Falling CG in uptrend: momentum weakening, potential reversal
Cycle Analysis
CG's leading nature makes it useful for timing cycle turns in conjunction with other Ehlers indicators.
Signal Line Strategy
A common approach pairs CG with a trigger line:
var cg = new Cg(10);
var trigger = new Sma(3); // 3-period smoothing of CG
// After updates:
double cgValue = cg.Last.Value;
double triggerValue = trigger.Update(cg.Last).Value;
// Buy when CG crosses above trigger
// Sell when CG crosses below trigger
References
- Ehlers, J.F. (2002). Cybernetic Analysis for Stocks and Futures. Wiley.
- Ehlers, J.F. (2001). "The Center of Gravity Oscillator." Technical Analysis of Stocks & Commodities.
- TradingView PineScript Reference: ta.cg() function.