Advanced - Enhancing an indicator with paintbars

A paintbar can create a new "indicator" based on an existing indicator. For example, one of our users asked how he can apply a moving average to the Aroon Oscillator indicator.

 

This is how you would do it with a paintbar (the following code creates an EMA(10) of Aroon Oscillator and plots it. You use the paintbar's state-keeping mechanism to do it. In the code, the Aroon variable is the Pre-Defined Indicator Variable for the chart's Aroon Oscillator indicator.

 

 

double fEMAMult; // EMA Multiplier

 

/// <summary>
/// Is called at start of paintbar calculation, should be used to initialize anything needed for the paintbar
/// </summary>
private void PaintbarInitialize()
{
   fEMAMult = 2.0D/(10+1.0D);
}
 
/// <summary>
/// Holds paintbar state - fill with variables needed to be preserved for next paintbar calc
/// </summary>
private struct PaintbarState
{
  public double NowEMA;
}
 
/// <summary>
/// Holds current PB state - use to calc PB, changes to it carry over to next PB calc
/// </summary>
private PaintbarState CurrentState;
 
/// <summary>
/// Holds saved PB state - internal
/// </summary>
private PaintbarState SavedState;
 
/// <summary>
/// Is called at start of paintbar calculation, should be used to clear the paintbar state
/// </summary>
private void PaintbarClearState()
{
   CurrentState = new PaintbarState();
   CurrentState.NowEMA = double.MinValue;
}
 
/// <summary>
/// Saves paintbar state (called internally).
/// </summary>
private void PaintbarSaveState()
{
   SavedState = CurrentState;
}
 
/// <summary>
/// Restores paintbar state (called internally).
/// </summary>
private void PaintbarRestoreState()
{
   CurrentState = SavedState;
}
 
public void MainCalculation()
{
  // calculate the EMA of the EMA
  if (CurrentState.NowEMA == double.MinValue)
      CurrentState.NowEMA = Aroon;
  else
      CurrentState.NowEMA += fEMAMult * (Aroon - CurrentState.NowEMA);
 
   SetColorAndShape("Line", PBShape.Rectangle, SysColor.MainIndicator2);
   SetYValue(CurrentState.NowEMA);

}