You are in for a huge amount of headache and pain. Nearly all HH LL algos are repainting. You need to find a sophisticated indicator instead of taking this approach in my humble opinion. You need to at least backtest the algorithm before you dare to go ahead with an EA, but continue this if it's just for a learning project.
Since you say you're struggling to generate an EMA value, we should help with a simple example (in this case I'm sure you mean you want to generate an EMA for conditions, and not apply an EMA calculation on another buffer)
input int MA_Period = 20; double ma_buf[]; int handle = INVALID_HANDLE; int OnInit() { handle = iMA(_Symbol, _Period, MA_Period, 0, MODE_EMA, PRICE_CLOSE); ArraySetAsSeries(ma_buf, true); return (INIT_SUCCEEDED); } void OnDeinit(const int reason){ IndicatorRelease(handle); ArrayFree(ma_buf); Comment(""); } void OnTick() { if (CopyBuffer(handle, 0, 0, 2, ma_buf)==-1) { Print("problem loading EMA"); GetLastError(); } double ema_latest_bar = ma_buf[0]; double ema_penultimate_bar = ma_buf[1]; string str = "EMA value on the current bar: " + DoubleToString(ema_latest_bar) + "\n" + "EMA value on the penultimate bar: " + DoubleToString(ema_penultimate_bar); Comment(str); }
Thank you all for responding on my question. I've tried to implement everyone's advice but still can't get it to work.
Conor on the example you provided, you have PRICE_CLOSE as the input:
input int MA_Period = 20; double ma_buf[]; int handle = INVALID_HANDLE; int OnInit() { handle = iMA(_Symbol, _Period, MA_Period, 0, MODE_EMA, PRICE_CLOSE); ArraySetAsSeries(ma_buf, true); return (INIT_SUCCEEDED); }
In my case, I tried to implement HHS and LLS instead of PRICE_CLOSE. I also tried replacing your whole iMA() formula and just have handle = HHS (and another for LLS).
double HHS = MathAbs(High1 > High2) * ((High1 - CurrentLH) / (CurrentHH - CurrentLH)) * 100; double LLS = MathAbs(Low1 < Low2) * ((CurrentHL - Low1) / (CurrentHL - CurrentLL)) * 100;
MovingAverages.mqh provides 2 examples
//+------------------------------------------------------------------+ //| Exponential Moving Average | //+------------------------------------------------------------------+ double ExponentialMA(const int position,const int period,const double prev_value,const double &price[]) { double result=0.0; //--- check period if(period>0) { double pr=2.0/(period+1.0); result=price[position]*pr+prev_value*(1-pr); } return(result); }
and
//+------------------------------------------------------------------+ //| Exponential moving average on price array | //+------------------------------------------------------------------+ int ExponentialMAOnBuffer(const int rates_total,const int prev_calculated,const int begin,const int period,const double& price[],double& buffer[]) { //--- check period if(period<=1 || period>(rates_total-begin)) return(0); //--- save and clear 'as_series' flags bool as_series_price=ArrayGetAsSeries(price); bool as_series_buffer=ArrayGetAsSeries(buffer); ArraySetAsSeries(price,false); ArraySetAsSeries(buffer,false); //--- calculate start position int start_position; double smooth_factor=2.0/(1.0+period); if(prev_calculated==0) // first calculation or number of bars was changed { //--- set empty value for first bars for(int i=0; i<begin; i++) buffer[i]=0.0; //--- calculate first visible value start_position=period+begin; buffer[begin] =price[begin]; for(int i=begin+1; i<start_position; i++) buffer[i]=price[i]*smooth_factor+buffer[i-1]*(1.0-smooth_factor); } else start_position=prev_calculated-1; //--- main loop for(int i=start_position; i<rates_total; i++) buffer[i]=price[i]*smooth_factor+buffer[i-1]*(1.0-smooth_factor); //--- restore as_series flags ArraySetAsSeries(price,as_series_price); ArraySetAsSeries(buffer,as_series_buffer); //--- return(rates_total); }
I've tried every possible way of implementing both of these methods to calculate the EMA.
Could you please give me more guidance on how I could implement it?
Please forgive my ignorance!
here's a working example using that function:
#include <MovingAverages.mqh> int bars; input int iPeriods = 10; input int EMA_Period = 20; double high_shifts[]; double low_shifts[]; double ema_buffer_HH[]; double ema_buffer_LL[]; datetime time[]; //+---------------------------------------------------- --------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { // bars = Bars(Symbol(), Period()); bars = 200; ArrayResize(high_shifts, bars); ArrayResize(low_shifts, bars); ArrayResize(time, bars); ArrayResize(ema_buffer_LL, bars); ArrayResize(ema_buffer_HH, bars); ArraySetAsSeries(ema_buffer_LL, true); ArraySetAsSeries(ema_buffer_HH, true); ArraySetAsSeries(high_shifts, true); ArraySetAsSeries(low_shifts, true); ArraySetAsSeries(time, true); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { Comment(""); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { if (CopyTime(_Symbol, _Period, 0, bars, time) <= 0){ Print("Failed to copy time data."); } for (int i = bars-1; i >= 0; i--){ high_shifts[i] = iHigh(_Symbol, _Period, iHighest(_Symbol, _Period, MODE_HIGH, iPeriods, i)); low_shifts[i] = iLow(_Symbol, _Period, iLowest(_Symbol, _Period, MODE_LOW, iPeriods, i)); if(i < bars - 1){ ema_buffer_HH[i] = ExponentialMA(i, EMA_Period, ema_buffer_HH[i + 1], high_shifts); ema_buffer_LL[i] = ExponentialMA(i, EMA_Period, ema_buffer_LL[i + 1], low_shifts); } } double ema_of_HHS = ema_buffer_HH[0]; double ema_of_LLS = ema_buffer_LL[0]; string s = "HHs (latest bar): " + DoubleToString(high_shifts[0]) + "\n\n" + "EMA of HHS: " + DoubleToString(ema_of_HHS) + "\n" + "EMA of LLS: " + DoubleToString(ema_of_LLS); Comment(s); } //+------------------------------------------------------------------+
but as others have hinted - use an indicator to calculate the buffers, because the speed of calculation in an EA when going through a loop is extremely slow and can cause a lot of problems
u can do this if you only care about the most recent value
void OnTick() { high_shifts[0] = iHigh(_Symbol, _Period, iHighest(_Symbol, _Period, MODE_HIGH, iPeriods, 0)); low_shifts[0] = iLow(_Symbol, _Period, iLowest(_Symbol, _Period, MODE_LOW, iPeriods, 0)); ema_buffer_HH[0] = ExponentialMA(0, EMA_Period, ema_buffer_HH[1], high_shifts); ema_buffer_LL[0] = ExponentialMA(0, EMA_Period, ema_buffer_LL[1], low_shifts); double ema_of_HHS = ema_buffer_HH[0]; double ema_of_LLS = ema_buffer_LL[0]; string s = "HHs (latest bar): " + DoubleToString(high_shifts[0]) + "\n\n" + "EMA of HHS: " + DoubleToString(ema_of_HHS) + "\n" + "EMA of LLS: " + DoubleToString(ema_of_LLS); Comment(s); }
offtopic - but looks like you make a mistake in your logic here:
double CurrentHH = iHigh(Symbol(), Period(), iHighest(Symbol(), Period(), MODE_HIGH, PERIOD, 0)); double CurrentLH = iLow(Symbol(), Period(), iLowest(Symbol(), Period(), MODE_HIGH, PERIOD, 0)); double CurrentLL = iLow(Symbol(), Period(), iLowest(Symbol(), Period(), MODE_LOW, PERIOD, 0)); double CurrentHL = iHigh(Symbol(), Period(), iLowest(Symbol(), Period(), MODE_LOW, PERIOD, 0));
changed:
double CurrentHH = iHigh(Symbol(), Period(), iHighest(Symbol(), Period(), MODE_HIGH, PERIOD, 0)); double CurrentLH = iHigh(Symbol(), Period(), iLowest(Symbol(), Period(), MODE_LOW, PERIOD, 0)); double CurrentLL = iLow(Symbol(), Period(), iLowest(Symbol(), Period(), MODE_LOW, PERIOD, 0)); double CurrentHL = iLow(Symbol(), Period(), iLowest(Symbol(), Period(), MODE_HIGH, PERIOD, 0));
Thank you kindly Conor, I really appreciate you taking the time to work through my code and for giving advice!
It looks like you are calculating the EMA of the Highest High (Hh) and Lowest Low (Ll) in the example you provided, what I'm trying to make EMA of is the final HH and LL calculations
First, first calculates two values, HH and LL:
HH. For bars with the high price greater than the previous high (otherwise 0):
HH = (Hc - Hl)/(Hh-Hl),
Where Hc is the current bar’s high price, Hl and Hh are the lowest and the highest high prices over a certain period.
LL. For bars with the low price less than the previous low (otherwise 0):
LL = (Lh - Lc)/(Lh-Ll),
Where Lc is the current low price, Ll and Lh are the lowest and the highest low prices over a certain period.
Both variables are then smoothed with a moving average, resulting in two main plots HHS and LLS.
Below is essentially the indicator code I'm trying to convert into an EA to trade when a crossover occurs.
I will work through the examples you provided in detail tomorrow and see how I can implement it.
Thank you again for taking the time to assist, I cannot describe how thankful I am.
//------------------------------------------------------------------ #property copyright "© mladen, 2018" #property link "mladenfx@gmail.com" #property description "Higher Highs & Lower Lows" //------------------------------------------------------------------ #property indicator_separate_window #property indicator_buffers 4 #property indicator_plots 3 #property indicator_label1 "Fill zone" #property indicator_type1 DRAW_FILLING #property indicator_color1 C'235,255,235',C'255,235,235' #property indicator_label2 "HH value" #property indicator_type2 DRAW_LINE #property indicator_color2 clrMediumSeaGreen #property indicator_width2 2 #property indicator_label3 "LL value" #property indicator_type3 DRAW_LINE #property indicator_color3 clrOrangeRed #property indicator_width3 2 // //--- input parameters // input int inpPeriod = 20; // Period // //--- buffers declarations // double valhh[],valll[],fillu[],filld[]; double ª_alpha; //------------------------------------------------------------------ // Custom indicator initialization function //------------------------------------------------------------------ int OnInit() { // //--- indicator buffers mapping // SetIndexBuffer(0,fillu,INDICATOR_DATA); SetIndexBuffer(1,filld,INDICATOR_DATA); SetIndexBuffer(2,valhh,INDICATOR_DATA); SetIndexBuffer(3,valll,INDICATOR_DATA); ª_alpha = 2.0/(inpPeriod+1.0); // //--- indicator short name assignment // IndicatorSetString(INDICATOR_SHORTNAME,"Higher Highs & Lower Lows ("+(string)inpPeriod+")"); return (INIT_SUCCEEDED); } void OnDeinit(const int reason) { } //------------------------------------------------------------------ // 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= prev_calculated-1; if (start<0) start=0; for (int i=start; i<rates_total && !_StopFlag; i++) { double _hhmin,_hhmax,_llmin,_llmax; _hhMinMax.calculate(high[i],high[i],inpPeriod,_hhmin,_hhmax,i); _llMinMax.calculate(low[i] ,low[i] ,inpPeriod,_llmin,_llmax,i); // //--- // if (i>0) { double _hhval = (high[i]>high[i-1]) ? 100*(high[i]-_hhmin)/(_hhmax-_hhmin) : 0; double _llval = (low[i] <low[i-1] ) ? 100*(_llmax -low[i])/(_llmax-_llmin) : 0; valhh[i] = fillu[i] = valhh[i-1] + ª_alpha*(_hhval-valhh[i-1]); valll[i] = filld[i] = valll[i-1] + ª_alpha*(_llval-valll[i-1]); } else valhh[i] = valll[i] = 0; } return (rates_total); } //------------------------------------------------------------------ // Custom function(s) //------------------------------------------------------------------ // //--- // class cMinMax { private : int originalPeriod; int period; int prevbar; double currmin; double currmax; double prevmax; double prevmin; double minArray[]; double maxArray[]; public : cMinMax() { originalPeriod = prevbar = INT_MIN; return; } ~cMinMax() { ArrayFree(minArray); ArrayFree(maxArray); return; } // // // void calculate(double valueMin, double valueMax, int forPeriod, double& min, double& max, int i) { if (prevbar!=i) { prevbar = i; if (originalPeriod!=forPeriod) { originalPeriod = forPeriod; period = (forPeriod>0) ? forPeriod : 1; prevmin = valueMin; prevmax = valueMax; currmin = valueMin; currmax = valueMax; ArrayResize(minArray,period-1); ArrayInitialize(minArray,valueMin); ArrayResize(maxArray,period-1); ArrayInitialize(maxArray,valueMax); } if (period>1) { int _pos = (i) % (period-1); minArray[_pos] = currmin; maxArray[_pos] = currmax; prevmin = minArray[ArrayMinimum(minArray)]; prevmax = maxArray[ArrayMaximum(maxArray)]; } else { prevmin = valueMin; prevmax = valueMax; } } // // // currmin = valueMin; currmax = valueMax; max = (prevmax>valueMax) ? prevmax : valueMax; min = (prevmin<valueMin) ? prevmin : valueMin; return; } }; cMinMax _hhMinMax; cMinMax _llMinMax; //------------------------------------------------------------------
what I've showed is basically an example showing how to use "ExponentialMA" from the mqh library on any buffer you want. hence the example to get you there
Below is essentially the indicator code I'm trying to convert into an EA to trade when a crossover occurs.
This isn't the correct approach. It's completely unnecessary and will be an unneeded amount of stress. You need to make an iCustom in the EA to call the ex5 of the indicator you want to use in the EA.
input int inpPeriod = 20; double HH[]; double LL[]; int handle; int OnInit(){ handle = iCustom(_Symbol, _Period, "Examples//[indicator name]", inpPeriod ); return(INIT_SUCCEEDED); } void OnTick() { // take signals for the current bar if (CopyBuffer(handle, 2, 0, 1, HH) < 0) { Print("UNABLE TO GET ENOUGH REQUESTED DATA FOR HH SIGNAL. REVERTING."); } if (CopyBuffer(handle, 3, 0, 1, LL) < 0) { Print("UNABLE TO GET ENOUGH REQUESTED DATA FOR LL SIGNAL. REVERTING."); } }
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Good evening,
I am attempting to write a HHLLS (Higher High Lower Low EA).
First HHS and LLS are calculated as below.
Next I want to calculate the 20 Period EMA of HHS and LLS. When HHSValue crosses above LLSValue then a BUY signal is triggered.
Although I am struggling to calculate the EMA for HHS and LLS.
Below is the my full code. I would appreciate it immensely if someone could assist with the correct formula to calculate EMA for HHS and LLS.