Creating two pole oscillator in cTrader to use on my charts

Summary

A failed attempt to port a TradingView Pine Script oscillator to cTrader’s C# API resulted in jagged outputs instead of smooth curves. The root cause was incorrect recursion logic in the two-pole filter implementation.

Root Cause

The flawed recursion occurred in the exponential smoothing logic due to two critical errors:

  • Misuse of current index values in recursive calculations
  • Improper handling of lagged values in the smoothing algorithm

Specifically:

// Original flawed logic:  
smooth1[index] = (1 - alpha) * smooth1[index] + alpha * sma_n1[index];  
                                  ^  
// Should use PREVIOUSLY computed smooth1[index-1]

Why This Happens in Real Systems

  • Pine Script automatically handles recursive series with [] operators, while cTrader requires explicit state management
  • Time-series algorithms relying on recurrence relations are vulnerable to off-by-one errors during translation
  • Historical value dependencies aren’t always obvious when porting between languages with different execution models

Real-World Impact

  • False trading signals from erratic oscillator values
  • Distorted technical analysis due to abnormal price filtering
  • Loss of trader confidence in the indicator’s reliability

Example or Code (if necessary and relevant)

Corrected smoothing logic:

if (index == 0)  
{  
    smooth1[index] = sma_n1[index];  
    smooth2[index] = sma_n1[index];  
}  
else  
{  
    smooth1[index] = (1 - alpha) * smooth1[index - 1] + alpha * sma_n1[index];  
    smooth2[index] = (1 - alpha) * smooth2[index - 1] + alpha * smooth1[index];  
}

How Senior Engineers Fix It

  1. Audit dependencies: Map all recursive relationships before porting
  2. Implement boundary handling: Explicit checks for initial values (index=0)
  3. Validate state propagation: Ensure all recursions reference [index-1] not [index]
  4. Backtest with anchors: Verify outputs at specific timestamps against reference implementation
  5. Parameterize normalization: Confirm calculation equivalence of sma_n1 (z-score vs min/max scaling in Pine Script)

Why Juniors Miss It

  • Address-based confusion: Mistaking Pine Script’s relative indexing [i-1] for literal array indices
  • Recursion blindness: Not recognizing implicit state management differences between platforms
  • Over-reliance on syntax: Focusing on operator translation instead of algorithmic behavior
  • Debugging gaps: Insufficient validation of intermediate series (e.g., sma_n1, smooth1)
  • Warmup neglect: Assuming indicators stabilize immediately without initialization period

Key takeaway: Porting indicators requires reconstructing the execution context—not just syntax. The recursive nature of financial filters amplifies small state-handling mistakes into visually obvious distortions.