Help with heiken ashi

 

Hi, I hope someone can shed some light on this.. I am trying to make a simple EA using the change in momentum using heiken ashi candles. 


The basic jist of what im trying to do is if there is a red candle the EA will place a trade under the red candle and await to see if the next candle will trigger the trade. 

My understanding of this was this could be done using the simpleheikenashi indicator with function of "if(heikenAshiLow[0]<heikenAshiLowPrev[0]" however when i back test this it enters here (see picture)


the previous 2 heiken ashi lows are: 183.314 and  183.373. Simply the low isnt lower than the previous low so why does it enter? i cannot work it out please somebody help :)


My code is below (i understand other aspects in this code may not be correct but i am just looking to solve the heiken ashi issue):

//+------------------------------------------------------------------+
//|                                             heikenAshiSystem.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#include<Trade\Trade.mqh>
CTrade trade;
int heikenAshi;
int OnInit()
  {
   heikenAshi=iCustom(_Symbol,_Period,"My Files\\SimpleHeikenAshi");
   return(INIT_SUCCEEDED);
  }
void OnDeinit(const int reason)
  {
   Print("Heiken Ashi System Removed");
  }
void OnTick()
  {

//heikenashi
   
  double heikenAshiOpen[], heikenAshiHigh[], heikenAshiLow[], heikenAshiClose[],heikenAshiOpenPrev[], heikenAshiHighPrev[], heikenAshiLowPrev[], heikenAshiClosePrev[];
   CopyBuffer(heikenAshi,0,0,2,heikenAshiOpen);
   CopyBuffer(heikenAshi,1,0,2,heikenAshiHigh);
   CopyBuffer(heikenAshi,2,0,2,heikenAshiLow);
   CopyBuffer(heikenAshi,3,0,2,heikenAshiClose);
   CopyBuffer(heikenAshi,0,0,3,heikenAshiOpenPrev);
   CopyBuffer(heikenAshi,1,0,3,heikenAshiHighPrev);
   CopyBuffer(heikenAshi,2,0,3,heikenAshiLowPrev);
   CopyBuffer(heikenAshi,3,0,3,heikenAshiClosePrev);
   
   
   
   
  double ask=NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);

//candle data

   int Highestcandle;
   double High[];
   ArraySetAsSeries(High,true);
   CopyHigh(_Symbol,PERIOD_M15,0,10,High);
   Highestcandle= ArrayMaximum(High,0,10);
   
   int Lowestcandle;
   double Low[];
   ArraySetAsSeries(Low,true);
   CopyLow(_Symbol,PERIOD_M15,0,10,Low);
   Lowestcandle= ArrayMinimum(Low,0,10);
   
   MqlRates PriceInfomation[];
   ArraySetAsSeries(PriceInfomation,true);
   
   int Data=CopyRates(Symbol(),Period(),0,10,PriceInfomation);
   double HighestPrice= PriceInfomation[Highestcandle].high;
   double LowestPrice= PriceInfomation[Lowestcandle].low;
   
   
// SL and TP



   double shortSLCalc = NormalizeDouble(HighestPrice,_Digits);
   double shortSLPips= shortSLCalc - heikenAshiLow[0];
   double shortSL= (heikenAshiLow[0] + shortSLPips);
   double shortTP = (heikenAshiLow[0] - shortSLPips);
   double shortEntry = NormalizeDouble(heikenAshiLowPrev[0],_Digits); 
   
      Comment("SL" , DoubleToString(shortSL,_Digits),
              "\n TP" , DoubleToString(shortTP,_Digits),
              "\n SLpips" , DoubleToString(shortSLPips,_Digits),
              "\n shortEntry" , DoubleToString(shortEntry,_Digits),
              "\n High", DoubleToString(Highestcandle,_Digits),
              "\n HeikenAshiLow", DoubleToString(heikenAshiLow[0],_Digits),
              "\n HeikenAshiLowPrev", DoubleToString(heikenAshiLowPrev[0],_Digits),
              "\n HighestPrice", DoubleToString(HighestPrice,_Digits));
              
//stoch 

  double KArray[];
  double DArray[];
  ArraySetAsSeries(KArray,true);
  ArraySetAsSeries(DArray,true);
  int StochDefinition=iStochastic(_Symbol,_Period,8,3,3,MODE_SMA,STO_LOWHIGH);
  CopyBuffer(StochDefinition,0,0,3,KArray);
  CopyBuffer(StochDefinition,1,0,3,DArray);
  double KValue0=KArray[0];
  double DValue0=DArray[0];
  double KValue1=KArray[1];
  double DValue1=DArray[1];
  double KValue2=KArray[2];
  double DValue2=DArray[2];
  


   if(PositionsTotal()==0 &&OrdersTotal()==0)
   if(heikenAshiLow[0]<heikenAshiLowPrev[0]&& KValue1>80||KValue2>80)
         
         {
         trade.SellStop(0.1,shortEntry,NULL,shortSL,shortTP,ORDER_TIME_DAY,100,NULL);
         }
         

           
          
   
       
  }


Not sure if it will help but this is the heiken ashi candle code:

//+------------------------------------------------------------------+
//|                                             simpleHeikenAshi.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 5
#property indicator_plots   1
#property indicator_type1   DRAW_COLOR_CANDLES
#property indicator_color1  clrBlue, clrRed
#property indicator_width1  2
#property indicator_label1  "Heiken Ashi Open;Heiken Ashi High;Heiken Ashi Low;Heiken Ashi Close"
double haOpen[];
double haHigh[];
double haLow[];
double haClose[];
double haColor[];
int OnInit()
  {
   SetIndexBuffer(0,haOpen,INDICATOR_DATA);
   SetIndexBuffer(1,haHigh,INDICATOR_DATA);
   SetIndexBuffer(2,haLow,INDICATOR_DATA);
   SetIndexBuffer(3,haClose,INDICATOR_DATA);
   SetIndexBuffer(4,haColor,INDICATOR_COLOR_INDEX);
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
   IndicatorSetString(INDICATOR_SHORTNAME,"Simple Heiken Ashi");
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
   return(INIT_SUCCEEDED);
  }
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==0)
     {
      haLow[0]=low[0];
      haHigh[0]=high[0];
      haOpen[0]=open[0];
      haClose[0]=close[0];
      start=1;
     }
   else
      start=prev_calculated-1;
   for(int i=start; i<rates_total && !IsStopped(); i++)
     {
      double haOpenVal =(haOpen[i-1]+haClose[i-1])/2;
      double haCloseVal=(open[i]+high[i]+low[i]+close[i])/4;
      double haHighVal =MathMax(high[i],MathMax(haOpenVal,haCloseVal));
      double haLowVal  =MathMin(low[i],MathMin(haOpenVal,haCloseVal));

      haLow[i]=haLowVal;
      haHigh[i]=haHighVal;
      haOpen[i]=haOpenVal;
      haClose[i]=haCloseVal;
      if(haOpenVal<haCloseVal)
         haColor[i]=0.0;
      else
         haColor[i]=1.0;
     }
   return(rates_total);
  }
Discover new MetaTrader 5 opportunities with MQL5 community and services
Discover new MetaTrader 5 opportunities with MQL5 community and services
  • 2024.08.31
  • www.mql5.com
MQL5: language of trade strategies built-in the MetaTrader 5 Trading Platform, allows writing your own trading robots, technical indicators, scripts and libraries of functions
Files:
mql5_error.png  94 kb
 
the "prev" buffer isn't told that it needs to be the previous bar because index [0] will be the current bar no matter what you name the buffer. You gave that buffer 3 bars instead of 2, but that's all so far.
You need to use index [1] for the previous bar. But to make that work correctly, you should set ArraysSetAsSeries to true on all the buffers
 
Conor Mcnamara #:
the "prev" buffer isn't told that it needs to be the previous bar because index [0] will be the current bar no matter what you name the buffer. You gave that buffer 3 bars instead of 2, but that's all so far.
You need to use index [1] for the previous bar. But to make that work correctly, you should set ArraysSetAsSeries to true on all the buffers
Thanks so much for your reply! Sorry to be annoying but do you mean like this: 
//+------------------------------------------------------------------+
//|                                             heikenAshiSystem.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#include<Trade\Trade.mqh>
CTrade trade;
int heikenAshi;
int OnInit()
  {
   heikenAshi=iCustom(_Symbol,_Period,"My Files\\SimpleHeikenAshi");
   return(INIT_SUCCEEDED);
  }
void OnDeinit(const int reason)
  {
   Print("Heiken Ashi System Removed");
  }
void OnTick()
  {

//heikenashi
   
  double heikenAshiOpen[], heikenAshiHigh[], heikenAshiLow[], heikenAshiClose[],heikenAshiOpenPrev[], heikenAshiHighPrev[], heikenAshiLowPrev[], heikenAshiClosePrev[];
   CopyBuffer(heikenAshi,0,0,2,heikenAshiOpen);
   CopyBuffer(heikenAshi,1,0,2,heikenAshiHigh);
   CopyBuffer(heikenAshi,2,0,3,heikenAshiLow);
   CopyBuffer(heikenAshi,3,0,2,heikenAshiClose);
   CopyBuffer(heikenAshi,0,0,2,heikenAshiOpenPrev);
   CopyBuffer(heikenAshi,1,0,2,heikenAshiHighPrev);
   CopyBuffer(heikenAshi,2,0,3,heikenAshiLowPrev);
   CopyBuffer(heikenAshi,3,0,2,heikenAshiClosePrev);
   ArraySetAsSeries(heikenAshiLow,true);
   ArraySetAsSeries(heikenAshiLowPrev,true);
   double heikenAshiLowValue=heikenAshiLow[1];
   double heikenAshiLowPrevValue=heikenAshiLow[2];
   
   
   
  double ask=NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);

//candle data

   int Highestcandle;
   double High[];
   ArraySetAsSeries(High,true);
   CopyHigh(_Symbol,PERIOD_M15,0,10,High);
   Highestcandle= ArrayMaximum(High,0,10);
   
   int Lowestcandle;
   double Low[];
   ArraySetAsSeries(Low,true);
   CopyLow(_Symbol,PERIOD_M15,0,10,Low);
   Lowestcandle= ArrayMinimum(Low,0,10);
   
   MqlRates PriceInfomation[];
   ArraySetAsSeries(PriceInfomation,true);
   
   int Data=CopyRates(Symbol(),Period(),0,10,PriceInfomation);
   double HighestPrice= PriceInfomation[Highestcandle].high;
   double LowestPrice= PriceInfomation[Lowestcandle].low;
   
   
// SL and TP



   double shortSLCalc = NormalizeDouble(HighestPrice,_Digits);
   double shortSLPips= shortSLCalc - heikenAshiLow[0];
   double shortSL= (heikenAshiLow[0] + shortSLPips);
   double shortTP = (heikenAshiLow[0] - shortSLPips);
   double shortEntry = NormalizeDouble(heikenAshiLowPrev[0],_Digits); 
   
      Comment("SL" , DoubleToString(shortSL,_Digits),
              "\n TP" , DoubleToString(shortTP,_Digits),
              "\n SLpips" , DoubleToString(shortSLPips,_Digits),
              "\n shortEntry" , DoubleToString(shortEntry,_Digits),
              "\n High", DoubleToString(Highestcandle,_Digits),
              "\n HeikenAshiLow", DoubleToString(heikenAshiLow[0],_Digits),
              "\n HeikenAshiLowPrev", DoubleToString(heikenAshiLowPrev[0],_Digits),
              "\n HighestPrice", DoubleToString(HighestPrice,_Digits));
              
//stoch 

  double KArray[];
  double DArray[];
  ArraySetAsSeries(KArray,true);
  ArraySetAsSeries(DArray,true);
  int StochDefinition=iStochastic(_Symbol,_Period,8,3,3,MODE_SMA,STO_LOWHIGH);
  CopyBuffer(StochDefinition,0,0,3,KArray);
  CopyBuffer(StochDefinition,1,0,3,DArray);
  double KValue0=KArray[0];
  double DValue0=DArray[0];
  double KValue1=KArray[1];
  double DValue1=DArray[1];
  double KValue2=KArray[2];
  double DValue2=DArray[2];
  


   if(PositionsTotal()==0 &&OrdersTotal()==0)
   if(heikenAshiLowValue<heikenAshiLowPrevValue && KValue1>80||KValue2>80)
         
         {
         trade.SellStop(0.1,shortEntry,NULL,shortSL,shortTP,ORDER_TIME_DAY,100,NULL);
         }
         

           
          
   
       
  }
It seems no matter what i do the same error still persists.
 

You're not mentioning the error or what it's saying. Anyway, the buffer logic is fine now, but your trade execution logic isn't right. A  sell stop is a pending order, and for this to be valid, it needs to be some points below the current bid price.

How can you know if it will be a valid sell stop order in the present based on a historic bars price data? Think about the logic there


Not clear on what you're going for, but such an adjustment will avoid any errors with the trade execution

void OnTick()
  {

//heikenashi


   double heikenAshiOpen[], heikenAshiHigh[], heikenAshiLow[], heikenAshiClose[],heikenAshiOpenPrev[], heikenAshiHighPrev[], heikenAshiLowPrev[], heikenAshiClosePrev[];
   CopyBuffer(heikenAshi,0,0,2,heikenAshiOpen);
   CopyBuffer(heikenAshi,1,0,2,heikenAshiHigh);
   CopyBuffer(heikenAshi,2,0,3,heikenAshiLow);
   CopyBuffer(heikenAshi,3,0,2,heikenAshiClose);
   CopyBuffer(heikenAshi,0,0,2,heikenAshiOpenPrev);
   CopyBuffer(heikenAshi,1,0,2,heikenAshiHighPrev);
   CopyBuffer(heikenAshi,2,0,3,heikenAshiLowPrev);
   CopyBuffer(heikenAshi,3,0,2,heikenAshiClosePrev);
   ArraySetAsSeries(heikenAshiLow,true);
   ArraySetAsSeries(heikenAshiLowPrev,true);
   double heikenAshiLowValue=heikenAshiLow[1];
   double heikenAshiLowPrevValue=heikenAshiLow[2];


   double bid=NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
   double ask=NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);

//candle data

   int Highestcandle;
   double High[];
   ArraySetAsSeries(High,true);
   CopyHigh(_Symbol,PERIOD_M15,0,10,High);
   Highestcandle= ArrayMaximum(High,0,10);

   int Lowestcandle;
   double Low[];
   ArraySetAsSeries(Low,true);
   CopyLow(_Symbol,PERIOD_M15,0,10,Low);
   Lowestcandle= ArrayMinimum(Low,0,10);

   MqlRates PriceInfomation[];
   ArraySetAsSeries(PriceInfomation,true);

   int Data=CopyRates(Symbol(),Period(),0,10,PriceInfomation);
   double HighestPrice= PriceInfomation[Highestcandle].high;
   double LowestPrice= PriceInfomation[Lowestcandle].low;


// SL and TP

   double LowerThanMarket = 50*_Point;

   double shortSLCalc = NormalizeDouble(HighestPrice,_Digits);
   double shortSLPips= shortSLCalc - heikenAshiLow[1];

   double shortEntry = NormalizeDouble(bid - LowerThanMarket,_Digits);
   
   double shortSL= (shortEntry + 100*_Point);
   double shortTP = (shortEntry - 100*_Point);

   Comment("SL", DoubleToString(shortSL,_Digits),
           "\n TP", DoubleToString(shortTP,_Digits),
           "\n SLpips", DoubleToString(shortSLPips,_Digits),
           "\n shortEntry", DoubleToString(shortEntry,_Digits),
           "\n High", DoubleToString(Highestcandle,_Digits),
           "\n HeikenAshiLow", DoubleToString(heikenAshiLow[0],_Digits),
           "\n HeikenAshiLowPrev", DoubleToString(heikenAshiLowPrev[0],_Digits),
           "\n HighestPrice", DoubleToString(HighestPrice,_Digits));

//stoch

   double KArray[];
   double DArray[];
   ArraySetAsSeries(KArray,true);
   ArraySetAsSeries(DArray,true);
   int StochDefinition=iStochastic(_Symbol,_Period,8,3,3,MODE_SMA,STO_LOWHIGH);
   CopyBuffer(StochDefinition,0,0,3,KArray);
   CopyBuffer(StochDefinition,1,0,3,DArray);
   double KValue0=KArray[0];
   double DValue0=DArray[0];
   double KValue1=KArray[1];
   double DValue1=DArray[1];
   double KValue2=KArray[2];
   double DValue2=DArray[2];



   if(PositionsTotal()==0 &&OrdersTotal()==0)
     {
      if(heikenAshiLowValue<heikenAshiLowPrevValue && (KValue1>80||KValue2>80) )
        {
         trade.SellStop(0.1,shortEntry,NULL,shortSL,shortTP,ORDER_TIME_DAY,100,NULL);
        }
     }

  }
//+------------------------------------------------------------------+