Complete thin Dx-composition wrapper indicators with full test coverage: - PlusDi/MinusDi: Directional Indicator wrappers (DiPlus/DiMinus from Dx) - PlusDm/MinusDm: Directional Movement wrappers (DmPlus/DmMinus from Dx) - Individual validation tests per indicator directory (TALib, Skender, bounds) - Combined unit tests (DiDm.Tests.cs) and validation tests (DiDm.Validation.Tests.cs) - Quantower wrappers + tests for all 4 indicators - PineScript v6 implementations with compensated RMA - Normalized .md documentation for all indicators and categories - 182 tests passing, 0 failures
4.9 KiB
MIDBODY: Open-Close Average
The average of open and close reveals the candle body's center — where intent met execution.
| Property | Value |
|---|---|
| Category | Core |
| Inputs | OHLCV bar (TBar) |
| Parameters | None |
| Outputs | Single series (Midbody) |
| Output range | Varies (see docs) |
| Warmup | 1 bars |
Midbody computes the arithmetic mean of Open and Close prices: (O + C) \times 0.5. It captures where price started and ended within a bar, ignoring intra-bar extremes. No lookback period, no state, always hot after the first bar. Equivalent to TBar.OC2.
Historical Context
The Open-Close average has no formal attribution in technical analysis literature. Unlike HL2 (Median Price) or HLC3 (Typical Price) which appear in TA-Lib and classic references, OC2 exists primarily as a computed property in modern libraries like Skender.Stock.Indicators (CandlePart.OC2).
The rationale for OC2 is straightforward: Open and Close represent the consensus prices at session boundaries. High and Low represent transient extremes that may reflect noise or stops being triggered. By averaging only the session endpoints, OC2 filters out intra-bar volatility entirely.
OC2 is useful as an input to trend-following indicators when you want the trend signal to reflect directional bias (where did the bar open and close?) rather than range (how far did it swing?). It also serves as the natural center for Heikin-Ashi calculations (HA Close = OHLC4, but HA state tracking uses the prior bar's OC2).
Architecture & Physics
1. Core Formula
\text{Midbody} = (O + C) \times 0.5
The multiplication form avoids a division operation. The JIT compiles * 0.5 to a single vmulsd instruction.
2. State Management
OC2 is stateless. Each bar's output depends only on that bar's Open and Close values. The State record struct tracks only:
LastValidOpen/LastValidClosefor NaN substitutionLastResultfor fallback when both inputs are non-finiteCountforIsHottracking
3. Complexity
| Metric | Value |
|---|---|
| Time (streaming) | O(1) |
| Time (batch) | O(n) |
| Space | O(1) — no buffers |
| Warmup | 1 bar |
Mathematical Foundation
Parameters
None. OC2 is parameterless.
Weight Distribution
| Component | Weight |
|---|---|
| Open | 0.5 |
| High | 0 |
| Low | 0 |
| Close | 0.5 |
Comparison with Other Price Transforms
| Transform | Formula | Components Used | Bias |
|---|---|---|---|
| Midbody | (O+C) \times 0.5 |
O, C | Session endpoints only |
| MEDPRICE | (H+L) \times 0.5 |
H, L | Range-centered; ignores O/C |
| TYPPRICE | (O+H+L) / 3 |
O, H, L | Opening-biased range |
| HLC3 | (H+L+C) / 3 |
H, L, C | Close-influenced range |
| AVGPRICE | (O+H+L+C) \times 0.25 |
O, H, L, C | Fully balanced |
| WCLPRICE | (H+L+2C) \times 0.25 |
H, L, C | Close double-weighted |
Output Interpretation
- OC2 > Close: bar closed below its midpoint (bearish lean)
- OC2 < Close: bar closed above its midpoint (bullish lean)
- OC2 = Close: Open = Close (doji-like bar)
Performance Profile
Operation Count (Streaming Mode)
| Operation | Count |
|---|---|
| Addition | 1 |
| Multiplication | 1 |
| Comparison | 0 |
| Memory access | 2 (O, C) |
| Total | 4 ops |
Batch Mode (SIMD Analysis)
The batch loop is a trivial element-wise (a[i] + b[i]) * 0.5. Auto-vectorization by the JIT is expected for aligned spans. Manual SIMD is not implemented because the operation is already memory-bandwidth-bound at this simplicity level.
Validation
| Library | Method | Tolerance | Status |
|---|---|---|---|
| Skender | CandlePart.OC2 |
1e-7 |
✅ Batch + Streaming + Span |
| TA-Lib | N/A | — | Not available |
| TBar.OC2 | Property | 1e-10 |
✅ All bars match |
Common Pitfalls
- Confusing OC2 with MEDPRICE. MEDPRICE is
(H+L)/2; OC2 is(O+C)/2. They answer different questions: range center vs. session endpoint average. - Confusing OC2 with Midpoint. Midpoint is
(Highest(V,N) + Lowest(V,N))/2— a rolling indicator with a period parameter. OC2 has no period. - Using OC2 for volatility estimation. OC2 deliberately ignores H and L. For volatility-aware price proxies, use HLC3 or OHLC4 instead.
- Expecting TA-Lib compatibility. TA-Lib does not implement OC2. Validation is against Skender only.
- Gap analysis with OC2. When Open and Close are nearly equal (doji bars), OC2 converges to Close. This is correct behavior, not a bug.
Resources
- Skender.Stock.Indicators
CandlePart.OC2enum documentation. - Murphy, J.J. Technical Analysis of the Financial Markets. New York Institute of Finance, 1999.