181 lines
7.5 KiB
MQL5
181 lines
7.5 KiB
MQL5
|
//---------------------------------------------------------------------------------------------------------------------
|
||
|
#define MName "Exponential Range Average & Deviation Offset"
|
||
|
#define MVersion "1.0"
|
||
|
#define MBuild "2022-06-25 14:58 WEST"
|
||
|
#define MCopyright "Copyright \x00A9 2022, Fernando M. I. Carreiro, All rights reserved"
|
||
|
#define MProfile "https://www.mql5.com/en/users/FMIC"
|
||
|
//---------------------------------------------------------------------------------------------------------------------
|
||
|
#property strict
|
||
|
#property version MVersion
|
||
|
#property description MName
|
||
|
#property description "MetaTrader Indicator (Build "MBuild")"
|
||
|
#property copyright MCopyright
|
||
|
#property link MProfile
|
||
|
//---------------------------------------------------------------------------------------------------------------------
|
||
|
|
||
|
//--- Setup
|
||
|
|
||
|
#property indicator_separate_window
|
||
|
|
||
|
// Define number of buffers and plots
|
||
|
#define MPlots 2
|
||
|
#define MBuffers 3
|
||
|
#ifdef __MQL4__
|
||
|
#property indicator_buffers MPlots
|
||
|
#else
|
||
|
#property indicator_buffers MBuffers
|
||
|
#property indicator_plots MPlots
|
||
|
#endif
|
||
|
|
||
|
// Display properties for plots
|
||
|
#property indicator_label1 "Range Average"
|
||
|
#property indicator_label2 "Deviation Offset"
|
||
|
#property indicator_color1 C'38,166,154'
|
||
|
#property indicator_color2 C'239,83,80'
|
||
|
#property indicator_width1 1
|
||
|
#property indicator_width2 1
|
||
|
#property indicator_style1 STYLE_SOLID
|
||
|
#property indicator_style2 STYLE_DOT
|
||
|
#property indicator_type1 DRAW_LINE
|
||
|
#property indicator_type2 DRAW_LINE
|
||
|
|
||
|
//--- Parameter settings
|
||
|
|
||
|
input double i_dbPeriod = 13.0; // Averaging period
|
||
|
|
||
|
//--- Macro definitions
|
||
|
|
||
|
// Define OnCalculate loop sequencing macros
|
||
|
#define MOnCalcPrevTest ( prev_calculated < 1 || prev_calculated > rates_total )
|
||
|
#ifdef __MQL4__ // for MQL4 (as series)
|
||
|
#define MOnCalcNext( _index ) ( _index-- )
|
||
|
#define MOnCalcBack( _index, _offset ) ( _index + _offset )
|
||
|
#define MOnCalcCheck( _index ) ( _index >= 0 )
|
||
|
#define MOnCalcValid( _index ) ( _index < rates_total )
|
||
|
#define MOnCalcStart \
|
||
|
( rates_total - ( MOnCalcPrevTest ? 1 : prev_calculated ) )
|
||
|
#else // for MQL5 (as non-series)
|
||
|
#define MOnCalcNext( _index ) ( _index++ )
|
||
|
#define MOnCalcBack( _index, _offset ) ( _index - _offset )
|
||
|
#define MOnCalcCheck( _index ) ( _index < rates_total )
|
||
|
#define MOnCalcValid( _index ) ( _index >= 0 )
|
||
|
#define MOnCalcStart \
|
||
|
( MOnCalcPrevTest ? 0 : prev_calculated - 1 )
|
||
|
#endif
|
||
|
|
||
|
// Define macro for invalid parameter values
|
||
|
#define MCheckParameter( _condition, _text ) if( _condition ) \
|
||
|
{ Print( "Error: Invalid ", _text ); return INIT_PARAMETERS_INCORRECT; }
|
||
|
|
||
|
// Define macro for calculating and assigning exponential moving average
|
||
|
#define MCalcEma( _var, _value, _weight ) \
|
||
|
_var = _var##Prev + ( _value - _var##Prev ) * _weight
|
||
|
|
||
|
//--- Global variable declarations
|
||
|
|
||
|
// Indicator buffers
|
||
|
double
|
||
|
g_adbRangeAverage[], // Buffer for range average
|
||
|
g_adbDeltaAverage[], // Buffer for delta average
|
||
|
g_adbDeviation[]; // Buffer for deviation offset
|
||
|
|
||
|
// Miscellaneous global variables
|
||
|
double
|
||
|
g_dbEmaWeight; // Weight to be used for exponential moving averages
|
||
|
|
||
|
//--- Event handling functions
|
||
|
|
||
|
// Initialisation event handler
|
||
|
int OnInit(void)
|
||
|
{
|
||
|
// Validate input parameters
|
||
|
MCheckParameter( i_dbPeriod < DBL_EPSILON, "Averaging period!" );
|
||
|
|
||
|
// Calculate parameter variables
|
||
|
g_dbEmaWeight = 2.0 / ( i_dbPeriod + 1.0 );
|
||
|
|
||
|
// Set number of significant digits (precision)
|
||
|
IndicatorSetInteger( INDICATOR_DIGITS, _Digits );
|
||
|
|
||
|
// Set buffers
|
||
|
int iBuffer = 0;
|
||
|
#ifdef __MQL4__
|
||
|
IndicatorBuffers( MBuffers ); // Set total number of buffers (MQL4 Only)
|
||
|
#endif
|
||
|
SetIndexBuffer( iBuffer++, g_adbRangeAverage, INDICATOR_DATA );
|
||
|
SetIndexBuffer( iBuffer++, g_adbDeviation, INDICATOR_DATA );
|
||
|
SetIndexBuffer( iBuffer++, g_adbDeltaAverage, INDICATOR_CALCULATIONS );
|
||
|
|
||
|
// Set indicator name
|
||
|
IndicatorSetString( INDICATOR_SHORTNAME,
|
||
|
MName + " (" + DoubleToString( i_dbPeriod, 3 ) + ")" );
|
||
|
|
||
|
return INIT_SUCCEEDED; // Successful initialisation of indicator
|
||
|
};
|
||
|
|
||
|
// Calculation event handler
|
||
|
int
|
||
|
OnCalculate(
|
||
|
const int rates_total,
|
||
|
const int prev_calculated,
|
||
|
const datetime &time[],
|
||
|
const double &open[],
|
||
|
const double &high[],
|
||
|
const double &low[],
|
||
|
const double &close[],
|
||
|
const long &tick_volume[],
|
||
|
const long &volume[],
|
||
|
const int &spread[]
|
||
|
)
|
||
|
{
|
||
|
// Define local variables
|
||
|
double
|
||
|
dbHigh, dbLow, dbClosePrev,
|
||
|
dbRange, dbRangeAverage, dbRangeAveragePrev,
|
||
|
dbDelta, dbDeltaAverage, dbDeltaAveragePrev;
|
||
|
|
||
|
// Main loop — fill in the arrays with data values
|
||
|
for( int iCur = MOnCalcStart, iPrev = MOnCalcBack( iCur, 1 );
|
||
|
!IsStopped() && MOnCalcCheck( iCur );
|
||
|
MOnCalcNext( iCur ), MOnCalcNext( iPrev ) )
|
||
|
{
|
||
|
// Get high and low price quotes
|
||
|
dbHigh = high[ iCur ];
|
||
|
dbLow = low[ iCur ];
|
||
|
|
||
|
// Calculate buffer values
|
||
|
if( MOnCalcValid( iPrev ) ) // Check if index is within array range
|
||
|
{
|
||
|
// Adjust for true range
|
||
|
dbClosePrev = close[ iPrev ];
|
||
|
if( dbClosePrev > dbHigh ) dbHigh = dbClosePrev;
|
||
|
if( dbClosePrev < dbLow ) dbLow = dbClosePrev;
|
||
|
|
||
|
// Calculate range exponential moving average
|
||
|
dbRangeAveragePrev = g_adbRangeAverage[ iPrev ];
|
||
|
dbRange = dbHigh - dbLow;
|
||
|
MCalcEma( dbRangeAverage, dbRange, g_dbEmaWeight );
|
||
|
|
||
|
// Calculate delta exponential moving average
|
||
|
dbDeltaAveragePrev = g_adbDeltaAverage[ iPrev ];
|
||
|
dbDelta = dbRange - dbRangeAveragePrev;
|
||
|
MCalcEma( dbDeltaAverage, dbDelta, g_dbEmaWeight );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
dbRangeAverage = dbHigh - dbLow;
|
||
|
dbDeltaAverage = 0;
|
||
|
};
|
||
|
|
||
|
// Set buffer values
|
||
|
g_adbRangeAverage[ iCur ] = dbRangeAverage;
|
||
|
g_adbDeltaAverage[ iCur ] = dbDeltaAverage;
|
||
|
g_adbDeviation[ iCur ] = dbRangeAverage
|
||
|
+ dbDeltaAverage;
|
||
|
};
|
||
|
|
||
|
return rates_total; // Return value for prev_calculated of next call
|
||
|
};
|
||
|
|
||
|
//---------------------------------------------------------------------------------------------------------------------
|