163 lines
6.8 KiB
MQL4
163 lines
6.8 KiB
MQL4
//---------------------------------------------------------------------------------------------------------------------
|
|
#define MName "Constant Range Channel"
|
|
#define MVersion "1.0"
|
|
#define MBuild "2022-05-11 11:31 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_chart_window
|
|
|
|
// Define number of buffers and plots
|
|
#define MPlots 3
|
|
#define MBuffers 3
|
|
#ifndef __MQL4__
|
|
#property indicator_buffers MBuffers
|
|
#property indicator_plots MPlots
|
|
#else
|
|
#property indicator_buffers MPlots
|
|
#endif
|
|
|
|
// Display properties
|
|
#define MClrUpper C'38, 166,154'
|
|
#define MClrMiddle C'239,166,154'
|
|
#define MClrLower C'239, 83, 80'
|
|
#property indicator_label1 "Upper"
|
|
#property indicator_label2 "Middle"
|
|
#property indicator_label3 "Lower"
|
|
#property indicator_color1 MClrUpper
|
|
#property indicator_color2 MClrMiddle
|
|
#property indicator_color3 MClrLower
|
|
#property indicator_width1 1
|
|
#property indicator_width2 1
|
|
#property indicator_width3 1
|
|
#property indicator_style1 STYLE_SOLID
|
|
#property indicator_style2 STYLE_DOT
|
|
#property indicator_style3 STYLE_SOLID
|
|
#property indicator_type1 DRAW_LINE
|
|
#property indicator_type2 DRAW_LINE
|
|
#property indicator_type3 DRAW_LINE
|
|
|
|
//--- Parameter settings
|
|
|
|
input uint i_nStepTicks = 50; // Channel range step size (ticks)
|
|
|
|
//--- Macro definitions
|
|
|
|
// Define OnCalculate loop sequencing macros
|
|
#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 - ( prev_calculated < 1 ? 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 \
|
|
( prev_calculated < 1 ? 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; }
|
|
|
|
//--- Global variable declarations
|
|
|
|
// Indicator buffers
|
|
double
|
|
g_dbStepRange, // Channel range step size
|
|
g_adbUpper[], // Buffer for channel's upper level
|
|
g_adbMiddle[], // Buffer for channel's middle level
|
|
g_adbLower[]; // Buffer for channel's lower level
|
|
|
|
//--- Event handling functions
|
|
|
|
// Initialisation event handler
|
|
int OnInit(void)
|
|
{
|
|
// Validate input parameters
|
|
MCheckParameter( i_nStepTicks < 1, "Range step size!" );
|
|
|
|
// Set initial values
|
|
g_dbStepRange = WRONG_VALUE;
|
|
|
|
// Set number of significant digits (precision)
|
|
IndicatorSetInteger( INDICATOR_DIGITS, _Digits );
|
|
|
|
// Set buffers
|
|
#ifdef __MQL4__
|
|
IndicatorBuffers( MBuffers ); // Set total number of buffers (MQL4 Only)
|
|
#endif
|
|
int iBuffer = 0;
|
|
SetIndexBuffer( iBuffer++, g_adbUpper, INDICATOR_DATA );
|
|
SetIndexBuffer( iBuffer++, g_adbMiddle, INDICATOR_DATA );
|
|
SetIndexBuffer( iBuffer++, g_adbLower, INDICATOR_DATA );
|
|
|
|
// Set indicator name
|
|
IndicatorSetString( INDICATOR_SHORTNAME,
|
|
MName + "(" + (string) i_nStepTicks + ")" );
|
|
|
|
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[]
|
|
)
|
|
{
|
|
// Convert range step siz from ticks to price quote difference
|
|
if( ( g_dbStepRange < 0 ) && ( rates_total > 0 ) )
|
|
{
|
|
double dbTickSize = WRONG_VALUE;
|
|
if( SymbolInfoDouble( _Symbol, SYMBOL_TRADE_TICK_SIZE, dbTickSize ) && ( dbTickSize > 0 ) )
|
|
g_dbStepRange = dbTickSize * i_nStepTicks;
|
|
else
|
|
return 0;
|
|
};
|
|
|
|
// Main loop — fill in the buffer arrays with data values
|
|
for( int iCur = MOnCalcStart, iPrev = MOnCalcBack( iCur, 1 );
|
|
!IsStopped() && MOnCalcCheck( iCur );
|
|
MOnCalcNext( iCur ), MOnCalcNext( iPrev ) )
|
|
{
|
|
// Calculate middle value
|
|
double dbLow = low[ iCur ],
|
|
dbHigh = high[ iCur ],
|
|
dbMiddle = MOnCalcValid( iPrev )
|
|
? ( dbLow > g_adbUpper[ iPrev ] ? dbLow
|
|
: dbHigh < g_adbLower[ iPrev ] ? dbHigh : g_adbMiddle[ iPrev ] )
|
|
: close[ iCur ];
|
|
|
|
// Set buffer values
|
|
g_adbMiddle[ iCur ] = dbMiddle;
|
|
g_adbUpper[ iCur ] = dbMiddle + g_dbStepRange;
|
|
g_adbLower[ iCur ] = dbMiddle - g_dbStepRange;
|
|
};
|
|
|
|
return rates_total; // Return value for prev_calculated of next call
|
|
};
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|