Files
mql5_indicators_mt5_part4/Swingchart - indicator for MetaTrader 5/swingchart.mq5
T

262 lines
21 KiB
Plaintext

//+------------------------------------------------------------------+
//| SwingChart.mq5 |
//| Copyright 2016, André S. Enger. |
//| andre_enger@hotmail.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, Andre S. Enger."
#property link "andre_enger@hotmail.com"
#property version "1.0"
#property description "Gann swingchart and hybrid ZigZag implementation."
#property indicator_chart_window
#property indicator_buffers 7
#property indicator_plots 2
#property indicator_label1 "Zig Zag"
#property indicator_type1 DRAW_ZIGZAG
#property indicator_color1 clrGold
#property indicator_style1 STYLE_SOLID
#property indicator_width1 2
#property indicator_type2 DRAW_COLOR_CANDLES
#property indicator_color2 clrRed,clrGray,clrBlue,clrGreen
#property indicator_label2 "Open;High;Low;Close"
//--- Buffers
double ExtPeaksBuffer[];
double ExtTroughsBuffer[];
double ExtOpenBuffer[];
double ExtHighBuffer[];
double ExtLowBuffer[];
double ExtCloseBuffer[];
double ExtColorBuffer[];
//--- Globals
bool lastDirection;
int lastIndex;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
SetIndexBuffer(0,ExtPeaksBuffer,INDICATOR_DATA);
SetIndexBuffer(1,ExtTroughsBuffer,INDICATOR_DATA);
SetIndexBuffer(2,ExtOpenBuffer,INDICATOR_DATA);
SetIndexBuffer(3,ExtHighBuffer,INDICATOR_DATA);
SetIndexBuffer(4,ExtLowBuffer,INDICATOR_DATA);
SetIndexBuffer(5,ExtCloseBuffer,INDICATOR_DATA);
SetIndexBuffer(6,ExtColorBuffer,INDICATOR_COLOR_INDEX);
IndicatorSetInteger(INDICATOR_DIGITS,Digits());
PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0.0);
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
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[])
{
//---
int start;
if(prev_calculated>rates_total || prev_calculated<=0)
{
start=0;
lastIndex=0;
}
else
start=prev_calculated-1;
start=MathMax(1,start);
//--- main loop
for(int bar=start; bar<rates_total-1; bar++)
{
bool upDay=low[bar-1]<=low[bar] && high[bar-1]<high[bar];
bool downDay=low[bar-1]>low[bar] && high[bar-1]>=high[bar];
bool insideDay=low[bar-1]<=low[bar] && high[bar-1]>=high[bar];
bool outsideDay=low[bar-1]>low[bar] && high[bar-1]<high[bar];
bool goingUp=close[bar]>open[bar]; //--- Approximation to the price action on outside days
ExtOpenBuffer[bar]=open[bar];
ExtHighBuffer[bar]=high[bar];
ExtLowBuffer[bar]=low[bar];
ExtCloseBuffer[bar]=close[bar];
if(downDay) ExtColorBuffer[bar]=0;
else if(insideDay) ExtColorBuffer[bar]=1;
else if(outsideDay) ExtColorBuffer[bar]=2;
else if(upDay) ExtColorBuffer[bar]=3;
ExtPeaksBuffer[bar]=0;
ExtTroughsBuffer[bar]=0;
//---
if(lastDirection)
{
if(high[bar]>high[lastIndex])
{
ExtPeaksBuffer[lastIndex]=0;
ExtPeaksBuffer[bar]=high[bar];
if(outsideDay)
{
ExtTroughsBuffer[bar]=low[bar];
if(goingUp)
{
ExtPeaksBuffer[lastIndex]=high[lastIndex];
ResolveUncertainityBull(bar,lastIndex,false,open,high,low,close);
}
else
lastDirection=false;
}
lastIndex=bar;
}
else if(downDay)
{
ResolveUncertainityBull(bar,lastIndex,false,open,high,low,close);
ExtTroughsBuffer[bar]=low[bar];
lastDirection=false;
lastIndex=bar;
}
else if(outsideDay)
{
ExtPeaksBuffer[bar]=high[bar];
ExtTroughsBuffer[bar]=low[bar];
if(goingUp)
ResolveUncertainityBull(bar,lastIndex,false,open,high,low,close);
else if(!goingUp)
{
ResolveUncertainityBull(bar,lastIndex,true,open,high,low,close);
lastDirection=false;
}
lastIndex=bar;
}
}
else
{
if(low[bar]<low[lastIndex])
{
ExtTroughsBuffer[lastIndex]=0;
ExtTroughsBuffer[bar]=low[bar];
if(outsideDay)
{
ExtPeaksBuffer[bar]=high[bar];
if(!goingUp)
{
ExtTroughsBuffer[lastIndex]=low[lastIndex];
ResolveUncertainityBear(bar,lastIndex,false,open,high,low,close);
}
else
lastDirection=true;
}
lastIndex=bar;
}
else if(upDay)
{
ResolveUncertainityBear(bar,lastIndex,false,open,high,low,close);
ExtPeaksBuffer[bar]=high[bar];
lastDirection=true;
lastIndex=bar;
}
else if(outsideDay)
{
ExtPeaksBuffer[bar]=high[bar];
ExtTroughsBuffer[bar]=low[bar];
if(!goingUp)
ResolveUncertainityBear(bar,lastIndex,false,open,high,low,close);
else
{
ResolveUncertainityBear(bar,lastIndex,true,open,high,low,close);
lastDirection=true;
}
lastIndex=bar;
}
}
}
ExtPeaksBuffer[rates_total-1]=0;
ExtTroughsBuffer[rates_total-1]=0;
//--- return value of prev_calculated for next call
return(rates_total);
}
//+------------------------------------------------------------------+
//| Resolves uncertain periods in the ZigZag |
//|------------------------------------------------------------------|
//| Preconditions: There has been a bull trend until lastIndex. |
//| Therefore the ZigZag has a peak there, and if there also is |
//| a trough, the ZigZag points up. There has been atleast one bar,|
//| so 'bar-lastIndex>0'. |
//| Postconditions: Draw proper peaks and troughs upto 'bar'. |
//| Parameter 'tweaked': If true then there is a maximum at 'bar' |
//| and the ZigZag must point down there. |
//+------------------------------------------------------------------+
void ResolveUncertainityBull(int bar,
int index,
bool tweaked,
const double &open[],
const double &high[],
const double &low[],
const double &close[])
{
//--- Skip first possible minimum (at lastIndex) if the ZigZag is vertical there
//--- or the candle at lastIndex points up (approximates price continuity)
int startSkip=ExtTroughsBuffer[index]==0?0:1;
if(open[index]<close[index] && startSkip==0) startSkip++;
//--- Search until bar or one before depending on ZigZag direction at end.
//--- If ZigZag points down at bar, the minimum must come before this.
int minimal=ArrayMinimum(low,index+startSkip,bar-index-startSkip+(tweaked?0:1));
while(minimal!=-1 && minimal<bar)
{
ExtTroughsBuffer[minimal]=low[minimal];
//--- Having added a trough, the next maximum can be on same bar only if
//--- it is a bull candle and there is not a peak there from before
int maxSkip=ExtPeaksBuffer[minimal]==0?0:1;
if(open[minimal]>close[minimal] && maxSkip==0) maxSkip++;
//--- Search until bar or one before depending on tweak.
//--- If ZigZag points down at bar, the "exit" maximum is there.
int maximal=ArrayMaximum(high,minimal+maxSkip,bar-minimal-maxSkip+(tweaked?1:0));
if(maximal==-1 || (tweaked && maximal>=bar))
break;
ExtPeaksBuffer[maximal]=high[maximal];
//--- Having added a peak, the next minimum can be on same bar only if
//--- it is a bear candle and not a trough there from before
int minSkip=ExtTroughsBuffer[maximal]==0?0:1;
if(open[maximal]<close[maximal] && minSkip==0) minSkip++;
//--- Find next minimum
minimal=ArrayMinimum(low,maximal+minSkip,bar-maximal-minSkip+(tweaked?0:1));
}
}
//+------------------------------------------------------------------+
//| Same as above, bear-trend version |
//+------------------------------------------------------------------+
void ResolveUncertainityBear(int bar,
int index,
bool tweaked,
const double &open[],
const double &high[],
const double &low[],
const double &close[])
{
int startSkip=ExtPeaksBuffer[index]==0?0:1;
if(open[index]>close[index] && startSkip==0) startSkip++;
int maximal=ArrayMaximum(high,index+startSkip,bar-index-startSkip+(tweaked?0:1));
while(maximal!=-1 && maximal<bar)
{
ExtPeaksBuffer[maximal]=high[maximal];
int minSkip=ExtTroughsBuffer[maximal]==0?0:1;
if(open[maximal]<close[maximal] && minSkip==0) minSkip++;
int minimal=ArrayMinimum(low,maximal+minSkip,bar-maximal-minSkip+(tweaked?1:0));
if(minimal==-1 || (tweaked && minimal==bar))
break;
ExtTroughsBuffer[minimal]=low[minimal];
int maxSkip=ExtPeaksBuffer[minimal]==0?0:1;
if(open[minimal]>close[minimal] && maxSkip==0) maxSkip++;
maximal=ArrayMaximum(high,minimal+maxSkip,bar-minimal-maxSkip+(tweaked?0:1));
}
}
//+------------------------------------------------------------------+