Moving Average of ATR Indicator by Naya
684 downloads / 423 views / Created: 31.05.2025 Average Rating: 0
Indicator Description
Moving Average of ATR Indicator
This indicator calculates a Moving Average (MA) over the Average True Range (ATR), effectively smoothing the market volatility signal and offering insight into evolving volatility trends. It is designed to serve as a filter for entry and exit signals in trading strategies. It is non-directional
Key Features:
* Applies a selected Moving Average method to the Average True Range
* Dual-level smoothing: ATR is first calculated, then smoothed with a Moving Average
* Can be used for both opening and closing trade filters
* Offers signal logic based on trends and relative comparisons between ATR and its MA
Configuration Options:
Logic Options:
For Entry (Open Filter):
* Moving Average rises
* Moving Average falls
* ATR rises
* ATR falls
* ATR is above its Moving Average
* ATR is below its Moving Average
* ATR crosses above its Moving Average
* ATR crosses below its Moving Average
For Exit (Close Filter):
Same as entry, except without the cross-based conditions
Smoothing Method:
* Selectable from standard MA types: Simple, Exponential, Smoothed, Linear Weighted, etc.
Parameters:
*ATR Period: Defines the period for ATR calculation (default: 14, range: 2–50)
*MA Period: Defines the length of the Moving Average applied to ATR (default: 14, range: 2–100)
*Shift: Number of bars to shift the output forward (default: 0, range: 0–2)
Available Signals:
For Entry Filtering:
* Confirm long/short entries based on rising/falling volatility
* Trigger trades when ATR crosses its MA or is above/below it
For Exit Filtering:
* Close positions based on trend in ATR or relation to its MA
Practical Applications:
* Volatility filtering for breakout or trend-following strategies
* Avoiding entries during low-volatility periods
* Exiting positions as volatility conditions reverse
* Useful in risk-adjusted entry models and adaptive stop-loss mechanisms
Technical Notes:
* ATR calculated using the formula: `Max(High, PrevClose) - Min(Low, PrevClose)`
* ATR is first calculated using a 14-period simple moving average (default), then smoothed again
* Output is aligned to the chart with an optional shift
* Works across all timeframes and instruments
* Compatible with both intraday and swing trading systems
Author: NAYA +237674724684
Version: 1.0
The Moving Average of ATR indicator is a refined volatility tool suited for traders looking to dynamically adapt their entries and exits based on smoothed volatility conditions. It integrates seamlessly into systems that rely on volatility as a confirmation or filtering component.
Created with the help of DeepSeek AI and Claude AI
This indicator calculates a Moving Average (MA) over the Average True Range (ATR), effectively smoothing the market volatility signal and offering insight into evolving volatility trends. It is designed to serve as a filter for entry and exit signals in trading strategies. It is non-directional
Key Features:
* Applies a selected Moving Average method to the Average True Range
* Dual-level smoothing: ATR is first calculated, then smoothed with a Moving Average
* Can be used for both opening and closing trade filters
* Offers signal logic based on trends and relative comparisons between ATR and its MA
Configuration Options:
Logic Options:
For Entry (Open Filter):
* Moving Average rises
* Moving Average falls
* ATR rises
* ATR falls
* ATR is above its Moving Average
* ATR is below its Moving Average
* ATR crosses above its Moving Average
* ATR crosses below its Moving Average
For Exit (Close Filter):
Same as entry, except without the cross-based conditions
Smoothing Method:
* Selectable from standard MA types: Simple, Exponential, Smoothed, Linear Weighted, etc.
Parameters:
*ATR Period: Defines the period for ATR calculation (default: 14, range: 2–50)
*MA Period: Defines the length of the Moving Average applied to ATR (default: 14, range: 2–100)
*Shift: Number of bars to shift the output forward (default: 0, range: 0–2)
Available Signals:
For Entry Filtering:
* Confirm long/short entries based on rising/falling volatility
* Trigger trades when ATR crosses its MA or is above/below it
For Exit Filtering:
* Close positions based on trend in ATR or relation to its MA
Practical Applications:
* Volatility filtering for breakout or trend-following strategies
* Avoiding entries during low-volatility periods
* Exiting positions as volatility conditions reverse
* Useful in risk-adjusted entry models and adaptive stop-loss mechanisms
Technical Notes:
* ATR calculated using the formula: `Max(High, PrevClose) - Min(Low, PrevClose)`
* ATR is first calculated using a 14-period simple moving average (default), then smoothed again
* Output is aligned to the chart with an optional shift
* Works across all timeframes and instruments
* Compatible with both intraday and swing trading systems
Author: NAYA +237674724684
Version: 1.0
The Moving Average of ATR indicator is a refined volatility tool suited for traders looking to dynamically adapt their entries and exits based on smoothed volatility conditions. It integrates seamlessly into systems that rely on volatility as a confirmation or filtering component.
Created with the help of DeepSeek AI and Claude AI
Comments
//==============================================================
// THIS CODE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE.
//==============================================================
using System;
using System.Drawing;
using ForexStrategyBuilder.Infrastructure.Entities;
using ForexStrategyBuilder.Infrastructure.Enums;
using ForexStrategyBuilder.Infrastructure.Interfaces;
namespace ForexStrategyBuilder.Indicators.Store
{
public class MovingAverageOfATR : Indicator
{
public MovingAverageOfATR()
{
IndicatorName = "Moving Average of ATR";
PossibleSlots = SlotTypes.OpenFilter | SlotTypes.CloseFilter;
SeparatedChart = true;
IndicatorAuthor = "NAYA +237674724684";
IndicatorVersion = "1.0";
IndicatorDescription = "Moving Average applied to Average True Range";
}
public override void Initialize(SlotTypes slotType)
{
SlotType = slotType;
// The ComboBox parameters
IndParam.ListParam[0].Caption = "Logic";
if (SlotType == SlotTypes.OpenFilter)
{
IndParam.ListParam[0].ItemList = new[]
{
"Moving Average rises",
"Moving Average falls",
"ATR rises",
"ATR falls",
"The ATR is above its Moving Average",
"The ATR is below its Moving Average",
"The ATR crosses above its Moving Average",
"The ATR crosses below its Moving Average"
};
}
else if (SlotType == SlotTypes.CloseFilter)
{
IndParam.ListParam[0].ItemList = new[]
{
"Moving Average rises",
"Moving Average falls",
"ATR rises",
"ATR falls",
"The ATR is above its Moving Average",
"The ATR is below its Moving Average"
};
}
IndParam.ListParam[0].Index = 0;
IndParam.ListParam[0].Text = IndParam.ListParam[0].ItemList[IndParam.ListParam[0].Index];
IndParam.ListParam[0].Enabled = true;
IndParam.ListParam[0].ToolTip = "Logic of application of the indicator.";
IndParam.ListParam[1].Caption = "Smoothing method";
IndParam.ListParam[1].ItemList = Enum.GetNames(typeof(MAMethod));
IndParam.ListParam[1].Index = (int)MAMethod.Simple;
IndParam.ListParam[1].Text = IndParam.ListParam[1].ItemList[IndParam.ListParam[1].Index];
IndParam.ListParam[1].Enabled = true;
IndParam.ListParam[1].ToolTip = "The Moving Average method used for smoothing the ATR.";
// The NumericUpDown parameters
IndParam.NumParam[0].Caption = "ATR period";
IndParam.NumParam[0].Value = 14;
IndParam.NumParam[0].Min = 2;
IndParam.NumParam[0].Max = 50;
IndParam.NumParam[0].Enabled = true;
IndParam.NumParam[0].ToolTip = "The period of ATR.";
IndParam.NumParam[1].Caption = "MA period";
IndParam.NumParam[1].Value = 14;
IndParam.NumParam[1].Min = 2;
IndParam.NumParam[1].Max = 100;
IndParam.NumParam[1].Enabled = true;
IndParam.NumParam[1].ToolTip = "The period of Moving Average.";
IndParam.NumParam[2].Caption = "Shift";
IndParam.NumParam[2].Value = 0;
IndParam.NumParam[2].Min = 0;
IndParam.NumParam[2].Max = 2;
IndParam.NumParam[2].Enabled = true;
IndParam.NumParam[2].ToolTip = "How many bars to shift with.";
// The CheckBox parameters
IndParam.CheckParam[0].Caption = "Use previous bar value";
IndParam.CheckParam[0].Enabled = true;
IndParam.CheckParam[0].ToolTip = "Use the indicator value from the previous bar.";
}
public override void Calculate(IDataSet dataSet)
{
DataSet = dataSet;
// Reading the parameters
var maMethod = (MAMethod)IndParam.ListParam[1].Index;
var atrPeriod = (int)IndParam.NumParam[0].Value;
var maPeriod = (int)IndParam.NumParam[1].Value;
var shift = (int)IndParam.NumParam[2].Value;
var previous = IndParam.CheckParam[0].Checked ? 1 : 0;
// Calculation
int firstBar = Math.Max(atrPeriod, maPeriod) + shift + previous + 2;
// Calculate ATR
var atr = new double[Bars];
for (int bar = 1; bar < Bars; bar++)
{
atr[bar] = Math.Max(High[bar], Close[bar - 1]) - Math.Min(Low[bar], Close[bar - 1]);
}
atr = MovingAverage(atrPeriod, 0, MAMethod.Simple, atr);
// Calculate MA of ATR
var maOfAtr = MovingAverage(maPeriod, shift, maMethod, atr);
// Saving the components
Component = new IndicatorComp[3];
Component[0] = new IndicatorComp
{
CompName = "MA of ATR",
DataType = IndComponentType.IndicatorValue,
ChartType = IndChartType.Line,
ChartColor = Color.Blue,
FirstBar = firstBar,
Value = maOfAtr
};
Component[1] = new IndicatorComp
{
ChartType = IndChartType.NoChart,
FirstBar = firstBar,
Value = new double[Bars]
};
Component[2] = new IndicatorComp
{
ChartType = IndChartType.NoChart,
FirstBar = firstBar,
Value = new double[Bars]
};
// Sets the Component's type
if (SlotType == SlotTypes.OpenFilter)
{
Component[1].DataType = IndComponentType.AllowOpenLong;
Component[1].CompName = "Is long entry allowed";
Component[2].DataType = IndComponentType.AllowOpenShort;
Component[2].CompName = "Is short entry allowed";
}
else if (SlotType == SlotTypes.CloseFilter)
{
Component[1].DataType = IndComponentType.ForceCloseLong;
Component[1].CompName = "Close out long position";
Component[2].DataType = IndComponentType.ForceCloseShort;
Component[2].CompName = "Close out short position";
}
// Calculation of the logic
switch (IndParam.ListParam[0].Text)
{
case "Moving Average rises":
IndicatorRisesLogic(firstBar, previous, maOfAtr, ref Component[1], ref Component[2]);
break;
case "Moving Average falls":
IndicatorFallsLogic(firstBar, previous, maOfAtr, ref Component[1], ref Component[2]);
break;
case "ATR rises":
IndicatorRisesLogic(firstBar, previous, atr, ref Component[1], ref Component[2]);
break;
case "ATR falls":
IndicatorFallsLogic(firstBar, previous, atr, ref Component[1], ref Component[2]);
break;
case "The ATR is above its Moving Average":
IndicatorIsHigherThanAnotherIndicatorLogic(firstBar, previous, atr, maOfAtr, ref Component[1], ref Component[2]);
break;
case "The ATR is below its Moving Average":
IndicatorIsLowerThanAnotherIndicatorLogic(firstBar, previous, atr, maOfAtr, ref Component[1], ref Component[2]);
break;
case "The ATR crosses above its Moving Average":
IndicatorCrossesAnotherIndicatorUpwardLogic(firstBar, previous, atr, maOfAtr, ref Component[1], ref Component[2]);
break;
case "The ATR crosses below its Moving Average":
IndicatorCrossesAnotherIndicatorDownwardLogic(firstBar, previous, atr, maOfAtr, ref Component[1], ref Component[2]);
break;
}
// For all ATR-based signals (including Moving Average of ATR), both components should be the same
// All logics are self-converse since they all relate to ATR volatility
Component[2].Value = Component[1].Value;
}
public override void SetDescription()
{
string maPeriod = IndParam.NumParam[1].ValueToString;
string atrPeriod = IndParam.NumParam[0].ValueToString;
EntryFilterLongDescription = ToString() + " ";
EntryFilterShortDescription = ToString() + " ";
ExitFilterLongDescription = ToString() + " ";
ExitFilterShortDescription = ToString() + " ";
switch (IndParam.ListParam[0].Text)
{
case "Moving Average rises":
EntryFilterLongDescription += "rises";
EntryFilterShortDescription += "rises";
ExitFilterLongDescription += "rises";
ExitFilterShortDescription += "rises";
break;
case "Moving Average falls":
EntryFilterLongDescription += "falls";
EntryFilterShortDescription += "falls";
ExitFilterLongDescription += "falls";
ExitFilterShortDescription += "falls";
break;
case "ATR rises":
EntryFilterLongDescription += "rises";
EntryFilterShortDescription += "rises";
ExitFilterLongDescription += "rises";
ExitFilterShortDescription += "rises";
break;
case "ATR falls":
EntryFilterLongDescription += "falls";
EntryFilterShortDescription += "falls";
ExitFilterLongDescription += "falls";
ExitFilterShortDescription += "falls";
break;
case "The ATR is above its Moving Average":
EntryFilterLongDescription += "is above its Moving Average";
EntryFilterShortDescription += "is above its Moving Average";
ExitFilterLongDescription += "is above its Moving Average";
ExitFilterShortDescription += "is above its Moving Average";
break;
case "The ATR is below its Moving Average":
EntryFilterLongDescription += "is below its Moving Average";
EntryFilterShortDescription += "is below its Moving Average";
ExitFilterLongDescription += "is below its Moving Average";
ExitFilterShortDescription += "is below its Moving Average";
break;
case "The ATR crosses above its Moving Average":
EntryFilterLongDescription += "crosses above its Moving Average";
EntryFilterShortDescription += "crosses above its Moving Average";
break;
case "The ATR crosses below its Moving Average":
EntryFilterLongDescription += "crosses below its Moving Average";
EntryFilterShortDescription += "crosses below its Moving Average";
break;
}
}
public override string ToString()
{
return string.Format("{0}{1} ({2}, ATR={3}, MA={4}, Shift={5})",
IndicatorName,
IndParam.CheckParam[0].Checked ? "*" : "",
IndParam.ListParam[1].Text,
IndParam.NumParam[0].ValueToString,
IndParam.NumParam[1].ValueToString,
IndParam.NumParam[2].ValueToString);
}
}
}
#property copyright "NAYA 2025." #property link "NAYA +237674724684" #property version "1.0" #property strict #include <Forexsb.com/Indicator.mqh> #include <Forexsb.com/Enumerations.mqh> //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class MovingAverageOfATR : public Indicator { public: MovingAverageOfATR(SlotTypes slotType); virtual void Calculate(DataSet &dataSet); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void MovingAverageOfATR::MovingAverageOfATR(SlotTypes slotType) { SlotType = slotType; IndicatorName = "Moving Average of ATR"; WarningMessage = ""; IsAllowLTF = true; ExecTime = ExecutionTime_DuringTheBar; IsSeparateChart = true; IsDiscreteValues = false; IsDefaultGroupAll = false; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void MovingAverageOfATR::Calculate(DataSet &dataSet) { Data=GetPointer(dataSet); MAMethod maMethod=(MAMethod) ListParam[1].Index; int atrPeriod=(int) NumParam[0].Value; int maPeriod=(int) NumParam[1].Value; int shift=(int) NumParam[2].Value; int previous=CheckParam[0].Checked ? 1 : 0; int firstBar=MathMax(atrPeriod,maPeriod)+shift+previous+2; // Calculate ATR double atr1[]; ArrayResize(atr1,Data.Bars); ArrayInitialize(atr1,0); for(int bar=1; bar<Data.Bars; bar++) { atr1[bar]=MathMax(Data.High[bar],Data.Close[bar-1])-MathMin(Data.Low[bar],Data.Close[bar-1]); } double atr[]; MovingAverage(atrPeriod,0,MAMethod_Simple,atr1,atr); // Calculate MA of ATR double maOfAtr[]; MovingAverage(maPeriod,shift,maMethod,atr,maOfAtr); ArrayResize(Component[0].Value,Data.Bars); Component[0].CompName = "MA of ATR"; Component[0].DataType = IndComponentType_IndicatorValue; Component[0].FirstBar = firstBar; ArrayCopy(Component[0].Value,maOfAtr); ArrayResize(Component[1].Value,Data.Bars); Component[1].FirstBar=firstBar; ArrayInitialize(Component[1].Value,0); ArrayResize(Component[2].Value,Data.Bars); Component[2].FirstBar=firstBar; ArrayInitialize(Component[2].Value,0); if(SlotType==SlotTypes_OpenFilter) { Component[1].DataType = IndComponentType_AllowOpenLong; Component[1].CompName = "Is long entry allowed"; Component[2].DataType = IndComponentType_AllowOpenShort; Component[2].CompName = "Is short entry allowed"; } else if(SlotType==SlotTypes_CloseFilter) { Component[1].DataType = IndComponentType_ForceCloseLong; Component[1].CompName = "Close out long position"; Component[2].DataType = IndComponentType_ForceCloseShort; Component[2].CompName = "Close out short position"; } // Calculation of the logic if(ListParam[0].Text=="Moving Average rises") IndicatorRisesLogic(firstBar,previous,maOfAtr,Component[1],Component[2]); else if(ListParam[0].Text=="Moving Average falls") IndicatorFallsLogic(firstBar,previous,maOfAtr,Component[1],Component[2]); else if(ListParam[0].Text=="ATR rises") IndicatorRisesLogic(firstBar,previous,atr,Component[1],Component[2]); else if(ListParam[0].Text=="ATR falls") IndicatorFallsLogic(firstBar,previous,atr,Component[1],Component[2]); else if(ListParam[0].Text=="The ATR is above its Moving Average") IndicatorIsHigherThanAnotherIndicatorLogic(firstBar,previous,atr,maOfAtr,Component[1],Component[2]); else if(ListParam[0].Text=="The ATR is below its Moving Average") IndicatorIsLowerThanAnotherIndicatorLogic(firstBar,previous,atr,maOfAtr,Component[1],Component[2]); else if(ListParam[0].Text=="The ATR crosses above its Moving Average") IndicatorCrossesAnotherIndicatorUpwardLogic(firstBar,previous,atr,maOfAtr,Component[1],Component[2]); else if(ListParam[0].Text=="The ATR crosses below its Moving Average") IndicatorCrossesAnotherIndicatorDownwardLogic(firstBar,previous,atr,maOfAtr,Component[1],Component[2]); // For all ATR-based signals (including Moving Average of ATR), both components should be the same // All logics are self-converse since they all relate to ATR volatility ArrayCopy(Component[2].Value,Component[1].Value); } //+------------------------------------------------------------------+
Risk warning: Forex, spread bets and CFD are leveraged products. They may not be suitable for you as they carry a high degree of risk to your capital and you can lose more than your initial investment. You should ensure you understand all of the risks.
Copyright © 2006 - 2025, Forex Software Ltd.;
Copyright © 2006 - 2025, Forex Software Ltd.;