Following is the code of Detrended Price Oscilator:

private MovingAverage movingAverage;

protected override void Initialize()
{
    movingAverage = Indicators.SimpleMovingAverage(Source, Periods);
}

public override void Calculate(int index)
{
    Result[index] = Source[index] - movingAverage.Result[index - Periods / 2 - 1];
}

As you can see we just wrote a general rule for calculation, but did not check any boundary conditions.

For example if we use a moving average of 10 periods, the first 9 values can not be properly calculated. So we can not use this formula for any index less then 9. Moreover to calculate the value for a specified index, we use moving average value at index – Periods / 2 – 1. So in general we have to add such condition:

public override void Calculate(int index)
{
    if (index >= Periods + Periods / 2 + 1)
    {
        Result[index] = Source[index] - movingAverage.Result[index - Periods / 2 - 1];
    }
}

The code of the simple moving average also has to check that index >= Periods. Moreover if we use another nested indicator, for example another type of moving average, this condition must be different. Source series also may be result of another indicator and contain not calculated values at the beginning. All of these things make indicators development more complex, as we have to think about things that can be automatically handled.

To solve this problem NaN arithmetic can be used. Let’s say that if indicator value is not defined at specified index it has some special value, let’s call it “Not a number” – NaN. If we use this value in our calculation we always get NaN as a result. If we use not calculated value or value at a negative index from data series, we want it to be NaN.

Fortunately, type for floating numbers – double already has such value: double.NaN, and it has needed behavior. When you perform some operations with NaN and usual number you always get NaN, e.g double.NaN + 1.4 == double.NaN. Since DataSeries returns NaN when you request value at negative index, you can miss all these pre-conditions and implement just general indicator calculation rule. If result contains NaN at some index, this value can just not be drawn on a chart.

Recursive indicators

When you calculate recursive indicator, i.e. indicator which value depends on previous value of this indicator you must handle NaN values explicitly, for example here is exponential moving average calculation:

public override void Calculate(int index)
{
    var previousValue = Result[index - 1];

    if (double.IsNaN(previousValue))
    {
        Result[index] = Source[index];
    }
    else
    {
        Result[index] = Source[index] * _exp + previousValue * (1 - _exp);
    }
}

In EMA, where current value depends on previous one, the first value must be set explicitly. To check this we use double.IsNaN(previousValue) method. Note that we cannot use == operator like this previousValue == double.IsNaN because NaN == x always false even if x is NaN.