From fa62b9fcc0e6fc0397e6a5a035161224a02081c9 Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Fri, 1 Dec 2023 19:36:12 +0100 Subject: [PATCH 1/2] Refs #13, #15. WIP. TDI-RT-Clone and Heiken_Ashi_Smoothed indicators made to work in MT5. --- Oscillators/TDI-RT-Clone - New.mq4 | 184 ++++++++++++++++++++++ Oscillators/TDI-RT-Clone.mq4 | 4 +- Oscillators/TDI-RT-Clone.mq5 | 51 ++++-- Price/Multi/OHLC/Heiken_Ashi_Smoothed.mq4 | 168 ++++++++++---------- Price/Multi/OHLC/Heiken_Ashi_Smoothed.mq5 | 60 ++++--- 5 files changed, 350 insertions(+), 117 deletions(-) create mode 100644 Oscillators/TDI-RT-Clone - New.mq4 diff --git a/Oscillators/TDI-RT-Clone - New.mq4 b/Oscillators/TDI-RT-Clone - New.mq4 new file mode 100644 index 0000000..9c2e06e --- /dev/null +++ b/Oscillators/TDI-RT-Clone - New.mq4 @@ -0,0 +1,184 @@ +/*------------------------------------------------------------------------------------ + Name: TDI-RT-Clone.mq4 + + Description: A clone of the TDI indicator. + The volatility bands and the market base line are not exactly +the same but they are close enough. + +-------------------------------------------------------------------------------------*/ +// Indicator properties +#property copyright "www.xaphod.com" +#property link "www.xaphod.com" +#property strict +#property version "1.600" +#property description "A clone of the TDI-RT indicator" +#property description "RT indicating that it updates in Real Time, ie on every tick." +#property description "The volatility bands and the market base line are not exactly the same but they are close enough." +#property indicator_separate_window +#property indicator_buffers 6 +#property indicator_color1 clrBlue +#property indicator_width1 1 +#property indicator_color2 clrBlue +#property indicator_width2 1 +#property indicator_color3 clrYellow +#property indicator_width3 1 +#property indicator_color4 clrRed +#property indicator_width4 2 +#property indicator_color5 clrGreen +#property indicator_width5 2 +#property indicator_color6 clrWhite +#property indicator_width6 1 +#property indicator_level1 32 +#property indicator_level2 50 +#property indicator_level3 68 +#property indicator_levelstyle STYLE_DOT +#property indicator_levelcolor DimGray + +#define INDICATOR_NAME "TDI-RT-Clone" + +// Indicator parameters +extern int RSI_Period = 13; +extern ENUM_APPLIED_PRICE RSI_Price = PRICE_CLOSE; +extern int Volatility_Band = 34; +extern int RSISignal_Period = 2; +extern ENUM_MA_METHOD RSISignal_Mode = MODE_SMA; +extern int TradeSignal_Period = 7; +extern ENUM_MA_METHOD TradeSignal_Mode = MODE_SMA; + +// Global module varables +double gdaRSI[]; +double gdaRSISig[]; +double gdaTradeSig[]; +double gdaMktBase[]; +double gdaVolaTop[]; +double gdaVolaBtm[]; + +//----------------------------------------------------------------------------- +// function: init() +// Description: Custom indicator initialization function. +//----------------------------------------------------------------------------- +int init() { + SetIndexStyle(0, DRAW_LINE); + SetIndexBuffer(0, gdaVolaTop); + SetIndexLabel(0, "Volatility Top"); + SetIndexStyle(1, DRAW_LINE); + SetIndexBuffer(1, gdaVolaBtm); + SetIndexLabel(1, "Volatility Bottom"); + SetIndexStyle(2, DRAW_LINE); + SetIndexBuffer(2, gdaMktBase); + SetIndexLabel(3, "Market Base"); + SetIndexStyle(3, DRAW_LINE); + SetIndexBuffer(3, gdaTradeSig); + SetIndexLabel(3, "Trade Signal"); + SetIndexStyle(4, DRAW_LINE); + SetIndexBuffer(4, gdaRSISig); + SetIndexLabel(4, "RSI Signal"); + + SetIndexStyle(5, DRAW_LINE); + SetIndexBuffer(5, gdaRSI); + SetIndexLabel(5, NULL); + IndicatorDigits(1); + IndicatorShortName(INDICATOR_NAME); + return (0); +} + +//----------------------------------------------------------------------------- +// function: deinit() +// Description: Custom indicator deinitialization function. +//----------------------------------------------------------------------------- +int deinit() { return (0); } + +///----------------------------------------------------------------------------- +// function: start() +// Description: Custom indicator iteration function. +//----------------------------------------------------------------------------- +int start() { + int iNewBars, iCountedBars, i; + + // Get unprocessed bars + iCountedBars = IndicatorCounted(); + if (iCountedBars < 0) + return (-1); + if (iCountedBars > 0) + iCountedBars--; + iNewBars = MathMin(Bars - iCountedBars, Bars - 1); + + int bars = Bars; + + // Calc TDI data + for (i = iNewBars - 1; i >= 0; i--) { + // NOT SERIES: + // gdaRSI[8] = iRSI(NULL, 0, 13, PRICE_CLOSE, 8(shift)); <- RSI over + // bars: >-11 .. [>0, >1, 2, 3, 4, 5, 6, 7, 8, 9] gdaRSI[7] = + // iRSI(NULL, 0, 13, PRICE_CLOSE, 7(shift)); <- RSI over bars: >-12 + // .. [>0, 1, 2, 3, 4, 5, 6, 7, 8, 9] gdaRSI[6] = iRSI(NULL, 0, 13, + // PRICE_CLOSE, 6(shift)); <- RSI over bars: >-13 .. >-1, [ 0, 1, 2, 3, 4, + // 5, 6, 7, 8, 9] + + // SERIES: + // gdaRSI[8] = iRSI(NULL, 0, 13, PRICE_CLOSE, 8(shift)); <- RSI over + // bars: [0, >1, >2, >3, >4, >5, >6, >7, >8, >9] .. >13 gdaRSI[7] = + // iRSI(NULL, 0, 13, PRICE_CLOSE, 7(shift)); <- RSI over bars: [0, + // 1, >2, >3, >4, >5, >6, >7, >8, >9] .. >14 gdaRSI[6] = iRSI(NULL, 0, 13, + // PRICE_CLOSE, 6(shift)); <- RSI over bars: [0, 1, 2, >3, >4, >5, >6, >7, + // >8, >9] .. >15 + gdaRSI[i] = iRSI(NULL, 0, RSI_Period, RSI_Price, i); + + // gdaRSI[i] = 50.0 + (50.0 / 32768 * rand()); + + // Print("gdaRSI[", i, "] = ", gdaRSI[i]); + } + + double a[]; + ArrayResize(a, 10); + for (int i = 0; i < ArraySize(a); ++i) { + a[i] = (double)i; + } + ArraySetAsSeries(a, true); + + double r1 = iMAOnArray(a, 5, 5, 0, MODE_SMA, 0); + double r2 = iStdDevOnArray(a, 5, 5, 0, MODE_SMA, 0); + double r3 = iRSI(NULL, PERIOD_CURRENT, RSI_Period, RSI_Price, 0); + double r4 = iRSI(NULL, PERIOD_CURRENT, RSI_Period, RSI_Price, 1); + + /* + Let's say that iNewBars is 9. + 9 because Bars = 10, so there's 10 bars in history and iNewBars is Bars - 1: + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] <- By default index buffers in MQL5 have + normal indexing (not series). 0 - first bar, 9 - last/current bar. ^ ^ ^ + ^ ^ ^ ^ ^ We iterate over above bars^: 0..(iNewBars(9) - 1) = indices + 0..8 That means that we iterate from the penulitmate received bar (shift 2, + as 9 is the latest/current bar) to the initial bar (shift 9). + */ + + for (i = iNewBars - 1; i >= 0; i--) { + // gdaRSISig[8] = iMAOnArray(gdaRSI, 9, 2, 0, + // MODE_SMA, 8) gdaRSISig[7] = iMAOnArray(gdaRSI, 9, 2, 0, + // MODE_SMA, 7) + gdaRSISig[i] = + iMAOnArray(gdaRSI, 0, RSISignal_Period, 0, RSISignal_Mode, i); + + gdaTradeSig[i] = + iMAOnArray(gdaRSI, 0, TradeSignal_Period, 0, TradeSignal_Mode, i); + gdaMktBase[i] = iMAOnArray(gdaRSI, 0, Volatility_Band, 0, MODE_SMA, i); + double stdDev1, stdDev2; + gdaVolaTop[i] = gdaMktBase[i] + + 1.6185 * (stdDev1 = iStdDevOnArray( + gdaRSI, 0, Volatility_Band, 0, MODE_SMA, i)); + gdaVolaBtm[i] = gdaMktBase[i] - + 1.6185 * (stdDev2 = iStdDevOnArray( + gdaRSI, 0, Volatility_Band, 0, MODE_SMA, i)); + + // if (ArraySize(gdaRSI) > i + 5) + if (iNewBars == 1 && false) + Alert(Bars, ", ", i, ": ", gdaTradeSig[i], ", ", gdaMktBase[i], ", ", + gdaVolaTop[i], ", ", gdaVolaBtm[i], ", RSI: ", gdaRSI[i], ", ", + gdaRSI[i + 1], ", ", gdaRSI[i + 2], ", ", gdaRSI[i + 3], ", ", + gdaRSI[i + 4], ", StdDev: ", stdDev1, ", ", stdDev2, + ", iNewBars = ", iNewBars, ", Bars = ", Bars); + + // gdaRSI[i] = -100; + } + return (0); +} +//+------------------------------------------------------------------+ diff --git a/Oscillators/TDI-RT-Clone.mq4 b/Oscillators/TDI-RT-Clone.mq4 index bed4889..88615ff 100644 --- a/Oscillators/TDI-RT-Clone.mq4 +++ b/Oscillators/TDI-RT-Clone.mq4 @@ -26,7 +26,7 @@ #property indicator_width4 2 #property indicator_color5 clrGreen #property indicator_width5 2 -#property indicator_color6 CLR_NONE +#property indicator_color6 clrWhite #property indicator_width6 1 #property indicator_level1 32 #property indicator_level2 50 @@ -76,7 +76,7 @@ int init() { SetIndexBuffer(4, gdaRSISig); SetIndexLabel(4,"RSI Signal"); - SetIndexStyle(5, DRAW_NONE); + SetIndexStyle(5, DRAW_LINE); SetIndexBuffer(5, gdaRSI); SetIndexLabel(5,NULL); IndicatorDigits(1); diff --git a/Oscillators/TDI-RT-Clone.mq5 b/Oscillators/TDI-RT-Clone.mq5 index f53a6f5..5b8da2c 100644 --- a/Oscillators/TDI-RT-Clone.mq5 +++ b/Oscillators/TDI-RT-Clone.mq5 @@ -3,9 +3,18 @@ * Implements indicator under MQL5. */ +#define ERR_USER_INVALID_HANDLE 1 +#define ERR_USER_INVALID_BUFF_NUM 2 +#define ERR_USER_ITEM_NOT_FOUND 3 +#define ERR_USER_ARRAY_IS_EMPTY 1000 + +// clang-format off +#define INDICATOR_LEGACY_VERSION_MT4 +#include +// clang-format on + // Defines indicator properties. #property indicator_separate_window - #property indicator_buffers 6 #property indicator_plots 5 #property indicator_color1 clrBlue @@ -33,30 +42,42 @@ // Defines macros. #define extern input -#define Bars fmin(10000, (ChartStatic::iBars(_Symbol, _Period))) +//#define Bars fmin(1000, (ChartStatic::iBars(_Symbol, _Period))) +#define Bars ChartStatic::iBars(_Symbol, _Period) #define Bid (SymbolInfoStatic::GetBid(_Symbol)) #define TimeDayOfWeek (DateTime::DateOfWeek()) // Includes the main file. -#include "TDI-RT-Clone.mq4" +#include "TDI-RT-Clone - New.mq4" // Custom indicator initialization function. -void OnInit() { - init(); - if (!ArrayGetAsSeries(gdaRSI)) { - ArraySetAsSeries(gdaRSI, true); - ArraySetAsSeries(gdaRSISig, true); - ArraySetAsSeries(gdaTradeSig, true); - ArraySetAsSeries(gdaMktBase, true); - ArraySetAsSeries(gdaVolaTop, true); - ArraySetAsSeries(gdaVolaBtm, true); - } -} +void OnInit() { init(); } // Custom indicator iteration function. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) { IndicatorCounted(fmin(prev_calculated, Bars)); ResetLastError(); - return start() >= 0 ? rates_total : 0; + + int res; + + bool asSeries = true; + ArraySetAsSeries(gdaRSI, asSeries); + ArraySetAsSeries(gdaRSISig, asSeries); + ArraySetAsSeries(gdaTradeSig, asSeries); + ArraySetAsSeries(gdaMktBase, asSeries); + ArraySetAsSeries(gdaVolaTop, asSeries); + ArraySetAsSeries(gdaVolaBtm, asSeries); + + res = start() >= 0 ? rates_total : 0; + + asSeries = false; + ArraySetAsSeries(gdaRSI, asSeries); + ArraySetAsSeries(gdaRSISig, asSeries); + ArraySetAsSeries(gdaTradeSig, asSeries); + ArraySetAsSeries(gdaMktBase, asSeries); + ArraySetAsSeries(gdaVolaTop, asSeries); + ArraySetAsSeries(gdaVolaBtm, asSeries); + + return res; } diff --git a/Price/Multi/OHLC/Heiken_Ashi_Smoothed.mq4 b/Price/Multi/OHLC/Heiken_Ashi_Smoothed.mq4 index da5f7dc..c1ab09b 100644 --- a/Price/Multi/OHLC/Heiken_Ashi_Smoothed.mq4 +++ b/Price/Multi/OHLC/Heiken_Ashi_Smoothed.mq4 @@ -4,18 +4,23 @@ //| mod by Raff | //+------------------------------------------------------------------+ #property copyright "Copyright © 2006, Forex-TSD.com " -#property link "http://www.forex-tsd.com/" +#property link "http://www.forex-tsd.com/" #property indicator_chart_window #property indicator_buffers 4 +#property indicator_type1 DRAW_HISTOGRAM #property indicator_color1 LightSalmon +#property indicator_type2 DRAW_HISTOGRAM #property indicator_color2 Lime +#property indicator_type3 DRAW_HISTOGRAM #property indicator_color3 LightSalmon +#property indicator_type4 DRAW_HISTOGRAM #property indicator_color4 Lime + //---- parameters -extern int MaMetod = 2; +extern int MaMetod = 2; extern int MaPeriod = 6; -extern int MaMetod2 = 3; +extern int MaMetod2 = 3; extern int MaPeriod2 = 2; //---- buffers double ExtMapBuffer1[]; @@ -27,97 +32,100 @@ double ExtMapBuffer6[]; double ExtMapBuffer7[]; double ExtMapBuffer8[]; //---- -int ExtCountedBars=0; +int ExtCountedBars = 0; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //|------------------------------------------------------------------| -int init() - { -//---- indicators - IndicatorBuffers(8); +int init() { + //---- indicators + IndicatorBuffers(8); - SetIndexStyle(0,DRAW_HISTOGRAM, 0, 1, LightSalmon); - SetIndexBuffer(0, ExtMapBuffer1); - SetIndexStyle(1,DRAW_HISTOGRAM, 0, 1, Lime); - SetIndexBuffer(1, ExtMapBuffer2); - SetIndexStyle(2,DRAW_HISTOGRAM, 0, 3, LightSalmon); - SetIndexBuffer(2, ExtMapBuffer3); - SetIndexStyle(3,DRAW_HISTOGRAM, 0, 3, Lime); - SetIndexBuffer(3, ExtMapBuffer4); -//---- - SetIndexDrawBegin(0,5); -//---- indicator buffers mapping - SetIndexBuffer(0,ExtMapBuffer1); - SetIndexBuffer(1,ExtMapBuffer2); - SetIndexBuffer(2,ExtMapBuffer3); - SetIndexBuffer(3,ExtMapBuffer4); - SetIndexBuffer(4,ExtMapBuffer5); - SetIndexBuffer(5,ExtMapBuffer6); - SetIndexBuffer(6,ExtMapBuffer7); - SetIndexBuffer(7,ExtMapBuffer8); -//---- initialization done - return(0); - } + SetIndexStyle(0, DRAW_HISTOGRAM, 0, 1, LightSalmon); + SetIndexBuffer(0, ExtMapBuffer1); + SetIndexStyle(1, DRAW_HISTOGRAM, 0, 1, Lime); + SetIndexBuffer(1, ExtMapBuffer2); + SetIndexStyle(2, DRAW_HISTOGRAM, 0, 3, LightSalmon); + SetIndexBuffer(2, ExtMapBuffer3); + SetIndexStyle(3, DRAW_HISTOGRAM, 0, 3, Lime); + SetIndexBuffer(3, ExtMapBuffer4); + //---- + SetIndexDrawBegin(0, 5); + //---- indicator buffers mapping + SetIndexBuffer(0, ExtMapBuffer1); + SetIndexBuffer(1, ExtMapBuffer2); + SetIndexBuffer(2, ExtMapBuffer3); + SetIndexBuffer(3, ExtMapBuffer4); + SetIndexBuffer(4, ExtMapBuffer5); + SetIndexBuffer(5, ExtMapBuffer6); + SetIndexBuffer(6, ExtMapBuffer7); + SetIndexBuffer(7, ExtMapBuffer8); + //---- initialization done + return (0); +} //+------------------------------------------------------------------+ //| Custor indicator deinitialization function | //+------------------------------------------------------------------+ -int deinit() - { -//---- TODO: add your code here +int deinit() { + //---- TODO: add your code here -//---- - return(0); - } + //---- + return (0); +} //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ -int start() - { - double maOpen, maClose, maLow, maHigh; - double haOpen, haHigh, haLow, haClose; - if(Bars<=10) return(0); - ExtCountedBars=IndicatorCounted(); -//---- check for possible errors - if (ExtCountedBars<0) return(-1); -//---- last counted bar will be recounted - if (ExtCountedBars>0) ExtCountedBars--; - int pos=Bars-ExtCountedBars-1; - int pos2=pos; - while(pos>=0) - { - maOpen=iMA(NULL,0,MaPeriod,0,MaMetod,PRICE_OPEN,pos); - maClose=iMA(NULL,0,MaPeriod,0,MaMetod,PRICE_CLOSE,pos); - maLow=iMA(NULL,0,MaPeriod,0,MaMetod,PRICE_LOW,pos); - maHigh=iMA(NULL,0,MaPeriod,0,MaMetod,PRICE_HIGH,pos); +int start() { + double maOpen, maClose, maLow, maHigh; + double haOpen, haHigh, haLow, haClose; + if (Bars <= 10) + return (0); + ExtCountedBars = IndicatorCounted(); + //---- check for possible errors + if (ExtCountedBars < 0) + return (-1); + //---- last counted bar will be recounted + if (ExtCountedBars > 0) + ExtCountedBars--; + int pos = Bars - ExtCountedBars - 1; + int pos2 = pos; + while (pos >= 0) { + maOpen = iMA(NULL, 0, MaPeriod, 0, MaMetod, PRICE_OPEN, pos); + maClose = iMA(NULL, 0, MaPeriod, 0, MaMetod, PRICE_CLOSE, pos); + maLow = iMA(NULL, 0, MaPeriod, 0, MaMetod, PRICE_LOW, pos); + maHigh = iMA(NULL, 0, MaPeriod, 0, MaMetod, PRICE_HIGH, pos); - haOpen=(ExtMapBuffer5[pos+1]+ExtMapBuffer6[pos+1])/2; - haClose=(maOpen+maHigh+maLow+maClose)/4; - haHigh=MathMax(maHigh, MathMax(haOpen, haClose)); - haLow=MathMin(maLow, MathMin(haOpen, haClose)); + haOpen = (ExtMapBuffer5[pos + 1] + ExtMapBuffer6[pos + 1]) / 2; + haClose = (maOpen + maHigh + maLow + maClose) / 4; + haHigh = MathMax(maHigh, MathMax(haOpen, haClose)); + haLow = MathMin(maLow, MathMin(haOpen, haClose)); - if (haOpen +// clang-format on #include #include #include // Defines macros. #define extern input -#define Bars fmin(10000, (ChartStatic::iBars(_Symbol, _Period))) +//#define Bars fmin(10000, (ChartStatic::iBars(_Symbol, _Period))) +#define Bars ChartStatic::iBars(_Symbol, _Period) #define Bid (SymbolInfoStatic::GetBid(_Symbol)) #define TimeDayOfWeek (DateTime::DateOfWeek()) @@ -26,24 +37,33 @@ #include "Heiken_Ashi_Smoothed.mq4" // Custom indicator initialization function. -void OnInit() { - init(); - if (!ArrayGetAsSeries(ExtMapBuffer1)) { - ArraySetAsSeries(ExtMapBuffer1, true); - ArraySetAsSeries(ExtMapBuffer2, true); - ArraySetAsSeries(ExtMapBuffer3, true); - ArraySetAsSeries(ExtMapBuffer4, true); - ArraySetAsSeries(ExtMapBuffer5, true); - ArraySetAsSeries(ExtMapBuffer6, true); - ArraySetAsSeries(ExtMapBuffer7, true); - ArraySetAsSeries(ExtMapBuffer8, true); - } -} +void OnInit() { init(); } // Custom indicator iteration function. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) { IndicatorCounted(fmin(prev_calculated, Bars)); ResetLastError(); - return start() >= 0 ? rates_total : 0; + + ArraySetAsSeries(ExtMapBuffer1, true); + ArraySetAsSeries(ExtMapBuffer2, true); + ArraySetAsSeries(ExtMapBuffer3, true); + ArraySetAsSeries(ExtMapBuffer4, true); + ArraySetAsSeries(ExtMapBuffer5, true); + ArraySetAsSeries(ExtMapBuffer6, true); + ArraySetAsSeries(ExtMapBuffer7, true); + ArraySetAsSeries(ExtMapBuffer8, true); + + int _res = start() >= 0 ? rates_total : 0; + + ArraySetAsSeries(ExtMapBuffer1, false); + ArraySetAsSeries(ExtMapBuffer2, false); + ArraySetAsSeries(ExtMapBuffer3, false); + ArraySetAsSeries(ExtMapBuffer4, false); + ArraySetAsSeries(ExtMapBuffer5, false); + ArraySetAsSeries(ExtMapBuffer6, false); + ArraySetAsSeries(ExtMapBuffer7, false); + ArraySetAsSeries(ExtMapBuffer8, false); + + return _res; } From 596858104f1ff954e91bd2d734b4a1980bab1598 Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Fri, 15 Dec 2023 18:01:48 +0100 Subject: [PATCH 2/2] Refs #15. Looks like Heiken_Ashi_Smoothed indicator works correctly. --- Price/Multi/OHLC/Heiken_Ashi_Smoothed.mq4 | 42 ++++++++++----- Price/Multi/OHLC/Heiken_Ashi_Smoothed.mq5 | 65 +++++++++++++++++++---- 2 files changed, 83 insertions(+), 24 deletions(-) diff --git a/Price/Multi/OHLC/Heiken_Ashi_Smoothed.mq4 b/Price/Multi/OHLC/Heiken_Ashi_Smoothed.mq4 index c1ab09b..9facac3 100644 --- a/Price/Multi/OHLC/Heiken_Ashi_Smoothed.mq4 +++ b/Price/Multi/OHLC/Heiken_Ashi_Smoothed.mq4 @@ -6,16 +6,20 @@ #property copyright "Copyright © 2006, Forex-TSD.com " #property link "http://www.forex-tsd.com/" -#property indicator_chart_window +#property indicator_separate_window #property indicator_buffers 4 #property indicator_type1 DRAW_HISTOGRAM #property indicator_color1 LightSalmon +#property indicator_width1 1 #property indicator_type2 DRAW_HISTOGRAM #property indicator_color2 Lime +#property indicator_width2 1 #property indicator_type3 DRAW_HISTOGRAM #property indicator_color3 LightSalmon +#property indicator_width3 5 #property indicator_type4 DRAW_HISTOGRAM #property indicator_color4 Lime +#property indicator_width4 5 //---- parameters extern int MaMetod = 2; @@ -77,24 +81,35 @@ int deinit() { int start() { double maOpen, maClose, maLow, maHigh; double haOpen, haHigh, haLow, haClose; + if (Bars <= 10) return (0); + ExtCountedBars = IndicatorCounted(); + //---- check for possible errors if (ExtCountedBars < 0) return (-1); + //---- last counted bar will be recounted if (ExtCountedBars > 0) ExtCountedBars--; + int pos = Bars - ExtCountedBars - 1; int pos2 = pos; + while (pos >= 0) { maOpen = iMA(NULL, 0, MaPeriod, 0, MaMetod, PRICE_OPEN, pos); maClose = iMA(NULL, 0, MaPeriod, 0, MaMetod, PRICE_CLOSE, pos); maLow = iMA(NULL, 0, MaPeriod, 0, MaMetod, PRICE_LOW, pos); maHigh = iMA(NULL, 0, MaPeriod, 0, MaMetod, PRICE_HIGH, pos); - haOpen = (ExtMapBuffer5[pos + 1] + ExtMapBuffer6[pos + 1]) / 2; + if ((pos + 1) >= Bars) { + haOpen = maOpen; + } else { + haOpen = (ExtMapBuffer5[pos + 1] + ExtMapBuffer6[pos + 1]) / 2; + } + haClose = (maOpen + maHigh + maLow + maClose) / 4; haHigh = MathMax(maHigh, MathMax(haOpen, haClose)); haLow = MathMin(maLow, MathMin(haOpen, haClose)); @@ -113,17 +128,18 @@ int start() { } int i; - for (i = 0; i < pos2; i++) - ExtMapBuffer1[i] = iMAOnArray(ExtMapBuffer7, 0, MaPeriod2, 0, MaMetod2, i); - for (i = 0; i < pos2; i++) - ExtMapBuffer2[i] = iMAOnArray(ExtMapBuffer8, 0, MaPeriod2, 0, MaMetod2, i); - for (i = 0; i < pos2; i++) - ExtMapBuffer3[i] = iMAOnArray(ExtMapBuffer5, 0, MaPeriod2, 0, MaMetod2, i); - for (i = 0; i < pos2; i++) - ExtMapBuffer4[i] = iMAOnArray(ExtMapBuffer6, 0, MaPeriod2, 0, MaMetod2, i); - - Alert(ExtMapBuffer1[i], ", ", ExtMapBuffer2[i], ", ", ExtMapBuffer3[i], ", ", - ExtMapBuffer4[i]); + for (i = 0; i <= pos2; i++) + ExtMapBuffer1[i] = + iMAOnArray(ExtMapBuffer7, Bars, MaPeriod2, 0, MaMetod2, i); + for (i = 0; i <= pos2; i++) + ExtMapBuffer2[i] = + iMAOnArray(ExtMapBuffer8, Bars, MaPeriod2, 0, MaMetod2, i); + for (i = 0; i <= pos2; i++) + ExtMapBuffer3[i] = + iMAOnArray(ExtMapBuffer5, Bars, MaPeriod2, 0, MaMetod2, i); + for (i = 0; i <= pos2; i++) + ExtMapBuffer4[i] = + iMAOnArray(ExtMapBuffer6, Bars, MaPeriod2, 0, MaMetod2, i); //---- return (0); diff --git a/Price/Multi/OHLC/Heiken_Ashi_Smoothed.mq5 b/Price/Multi/OHLC/Heiken_Ashi_Smoothed.mq5 index ef6a822..5345a86 100644 --- a/Price/Multi/OHLC/Heiken_Ashi_Smoothed.mq5 +++ b/Price/Multi/OHLC/Heiken_Ashi_Smoothed.mq5 @@ -6,16 +6,16 @@ #define ERR_USER_INVALID_HANDLE 1 #define ERR_USER_INVALID_BUFF_NUM 2 #define ERR_USER_ITEM_NOT_FOUND 3 -#define ERR_USER_ARRAY_IS_EMPTY 1000 // Defines indicator properties. #property indicator_chart_window -#property indicator_buffers 4 -#property indicator_plots 4 -#property indicator_color1 LightSalmon -#property indicator_color2 Lime -#property indicator_color3 LightSalmon -#property indicator_color4 Lime +#property indicator_buffers 9 +#property indicator_plots 1 +#property indicator_type1 DRAW_COLOR_CANDLES +#property indicator_style1 STYLE_SOLID +#property indicator_color1 clrNONE, clrLime, clrLightSalmon +#property indicator_width1 1 +#property indicator_label1 "HA Open;HA High;HA Low;HA Close" // Includes EA31337 framework. // clang-format off @@ -28,23 +28,45 @@ // Defines macros. #define extern input -//#define Bars fmin(10000, (ChartStatic::iBars(_Symbol, _Period))) -#define Bars ChartStatic::iBars(_Symbol, _Period) +#define Bars fmin(1000, (ChartStatic::iBars(_Symbol, _Period))) #define Bid (SymbolInfoStatic::GetBid(_Symbol)) #define TimeDayOfWeek (DateTime::DateOfWeek()) // Includes the main file. #include "Heiken_Ashi_Smoothed.mq4" +double ExtMapBufferCandleColor[]; + // Custom indicator initialization function. -void OnInit() { init(); } +void OnInit() { + init(); + + IndicatorBuffers(9); + + // Note switched buffers! We've mapped them from OHLC values into problem + // index buffers. + SetIndexBuffer(0, ExtMapBuffer3, INDICATOR_DATA); + SetIndexBuffer(1, ExtMapBuffer1, INDICATOR_DATA); + SetIndexBuffer(2, ExtMapBuffer2, INDICATOR_DATA); + SetIndexBuffer(3, ExtMapBuffer4, INDICATOR_DATA); + SetIndexBuffer(4, ExtMapBufferCandleColor, INDICATOR_COLOR_INDEX); + + SetIndexBuffer(5, ExtMapBuffer5, INDICATOR_CALCULATIONS); + SetIndexBuffer(6, ExtMapBuffer6, INDICATOR_CALCULATIONS); + SetIndexBuffer(7, ExtMapBuffer7, INDICATOR_CALCULATIONS); + SetIndexBuffer(8, ExtMapBuffer8, INDICATOR_CALCULATIONS); + + SetIndexStyle(0, DRAW_COLOR_CANDLES, STYLE_SOLID, 1, clrLime); + + MathSrand(GetTickCount()); +} // Custom indicator iteration function. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) { IndicatorCounted(fmin(prev_calculated, Bars)); ResetLastError(); - + ArraySetAsSeries(ExtMapBuffer1, true); ArraySetAsSeries(ExtMapBuffer2, true); ArraySetAsSeries(ExtMapBuffer3, true); @@ -56,6 +78,14 @@ int OnCalculate(const int rates_total, const int prev_calculated, int _res = start() >= 0 ? rates_total : 0; + if (prev_calculated <= 0) { + // Initializing haOpen and haClose with open/close prices. + for (int i = 0; i < rates_total; ++i) { + ExtMapBuffer5[i] = ::iOpen(NULL, PERIOD_CURRENT, i); + ExtMapBuffer6[i] = ::iClose(NULL, PERIOD_CURRENT, i); + } + } + ArraySetAsSeries(ExtMapBuffer1, false); ArraySetAsSeries(ExtMapBuffer2, false); ArraySetAsSeries(ExtMapBuffer3, false); @@ -65,5 +95,18 @@ int OnCalculate(const int rates_total, const int prev_calculated, ArraySetAsSeries(ExtMapBuffer7, false); ArraySetAsSeries(ExtMapBuffer8, false); + for (int i = prev_calculated; i < rates_total; ++i) { + // Filling candle color index. + ExtMapBufferCandleColor[i] = ExtMapBuffer1[i] > ExtMapBuffer4[i] ? 2 : 1; + } + + for (int i = MathMax(0, prev_calculated - 1); i < rates_total; ++i) { + // Inserting H/L values into proper slots. + double _high = MathMax(ExtMapBuffer1[i], ExtMapBuffer2[i]); + double _low = MathMin(ExtMapBuffer1[i], ExtMapBuffer2[i]); + ExtMapBuffer1[i] = _high; + ExtMapBuffer2[i] = _low; + } + return _res; }