Download MetaTrader 5
To add comments, please log in or register
Publish the program in the Market and sell it to millions of traders!
The_Rezzer
42
The_Rezzer 2016.05.07 08:51 

Good morning all. Totally though i'd gotten the hang of it then started receiving the following issue...

1. Just for general awareness: I've elected for the current bar to be the value of IndicatorCounted () - and consistently refer to this as "i" - therefore, the oldest bar on the chart is always [0] - right or wrong i found it easier to understand this way
2. I've written two functions (highlighted in pink) which i'm having issues placing within the body of my code; wherever i choose to place text i receive the error message "function can be declared only in the global scope"

//+------------------------------------------------------------------+
//|                                   Heiken Ashi Trend Detector.mq4 |
//|       Copyright © 2016 Carl Carver Software. All Rights Reserved |
//|                                          carl_carver@hotmail.com |
//+------------------------------------------------------------------+

//Indicator Basic Properties
#property copyright "Copyright © 2016 Carl Carver Software. All Rights Reserved."
#property link      "carl_carver@hotmail.com"
#property version   "1.00"
#property description "Heiken Ashi Trend Detector"
#property strict
#property indicator_chart_window
#property indicator_buffers 11

//Indicator Format Properties
//HA Properties
#property indicator_color1 clrBlack
#property indicator_color2 clrRed
#property indicator_color3 clrLimeGreen
#property indicator_width1 1
#property indicator_width2 1
#property indicator_width3 3
#property indicator_width4 3

//Swing Properties
#property indicator_color5 clrBlack
#property indicator_color6 clrBlack
#property indicator_color7 clrBlack
#property indicator_color8 clrBlack
#property indicator_color9 clrBlack
#property indicator_color10 clrBlack
#property indicator_width5 2
#property indicator_width6 2
#property indicator_width7 2
#property indicator_width8 2
#property indicator_width9 2
#property indicator_width10 2 

//User Inputs
//HA Candle Properties                                                      
input color Shadow=clrBlack;
input color Bear_Body = clrRed;
input color Bull_Body = clrLimeGreen;

//Buffer Arrays
//HA Buffers                                               
double HA_High_Buffer[];
double HA_Low_Buffer[];
double HA_Open_Buffer[];
double HA_Close_Buffer[];

//Swing Buffers   
double Swing_1_Buffer[];    //Wingding symbol code: 140 - On-screen symbol: 1
double Swing_2_Buffer[];    //Wingding symbol code: 141 - On-screen symbol: 2
double Swing_LL_Buffer[];   //Wingding symbol code: 142 - On-screen symbol: 3
double Swing_LH_Buffer[];   //Wingding symbol code: 143 - On-screen symbol: 4
double Swing_HL_Buffer[];   //Wingding symbol code: 144 - On-screen symbol: 5
double Swing_HH_Buffer[];   //Wingding symbol code: 145 - On-screen symbol: 6

//Counter Buffer
double Counter_Buffer[];

//Pre-program buffer implementation and mapping
void OnInit(void)
  {
   IndicatorDigits(Digits());

//HA Buffers
   SetIndexBuffer(0,HA_High_Buffer);
   SetIndexStyle(0,DRAW_HISTOGRAM,0,1,Shadow);
   SetIndexDrawBegin(0,0);
   SetIndexLabel(0,"HA High");

   SetIndexBuffer(1,HA_Low_Buffer);
   SetIndexStyle(1,DRAW_HISTOGRAM,0,1,Shadow);
   SetIndexDrawBegin(1,0);
   SetIndexLabel(1,"HA Low");

   SetIndexBuffer(2,HA_Open_Buffer);
   SetIndexStyle(2,DRAW_HISTOGRAM,0,3,Bear_Body);
   SetIndexDrawBegin(2,0);
   SetIndexLabel(2,"HA Open");

   SetIndexBuffer(3,HA_Close_Buffer);
   SetIndexStyle(3,DRAW_HISTOGRAM,0,3,Bull_Body);
   SetIndexDrawBegin(3,0);
   SetIndexLabel(3,"HA Close");

//Swing Buffers   
   SetIndexBuffer(4,Swing_1_Buffer);
   SetIndexStyle(4,DRAW_ARROW);
   SetIndexArrow(4,140);
   SetIndexLabel(4,"Sw. Low");

   SetIndexBuffer(5,Swing_2_Buffer);
   SetIndexStyle(5,DRAW_ARROW);
   SetIndexArrow(5,141);
   SetIndexLabel(5,"Sw. High");

   SetIndexBuffer(6,Swing_LL_Buffer);
   SetIndexStyle(6,DRAW_ARROW);
   SetIndexArrow(6,142);
   SetIndexLabel(6,"Sw. Lower Low");

   SetIndexBuffer(7,Swing_LH_Buffer);
   SetIndexStyle(7,DRAW_ARROW);
   SetIndexArrow(7,143);
   SetIndexLabel(7,"Sw. Lower High");

   SetIndexBuffer(8,Swing_HL_Buffer);
   SetIndexStyle(8,DRAW_ARROW);
   SetIndexArrow(8,144);
   SetIndexLabel(8,"Sw. Higher Low");

   SetIndexBuffer(9,Swing_HH_Buffer);
   SetIndexStyle(9,DRAW_ARROW);
   SetIndexArrow(9,145);
   SetIndexLabel(9,"Sw. Higher High");

//Counter Buffer
   SetIndexBuffer(10,Counter_Buffer,INDICATOR_DATA);
   SetIndexStyle(10,DRAW_LINE,STYLE_SOLID,1,CLR_NONE);
   SetIndexLabel(10,"Bar #");

  }
//Main program
int OnCalculate
(
 //Standard bar price and data arrays
 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[]
 )
  {

//Price Arrays
   ArraySetAsSeries(open,false);
   ArraySetAsSeries(high,false);
   ArraySetAsSeries(low,false);
   ArraySetAsSeries(close,false);
   ArraySetAsSeries(time,false);

//Heiken Ashi Arrays
   ArraySetAsSeries(HA_High_Buffer,false);
   ArraySetAsSeries(HA_Low_Buffer,false);
   ArraySetAsSeries(HA_Open_Buffer,false);
   ArraySetAsSeries(HA_Close_Buffer,false);

//Swing Arrays
   ArraySetAsSeries(Swing_1_Buffer,false);
   ArraySetAsSeries(Swing_2_Buffer,false);
   ArraySetAsSeries(Swing_LL_Buffer,false);
   ArraySetAsSeries(Swing_LH_Buffer,false);
   ArraySetAsSeries(Swing_HL_Buffer,false);
   ArraySetAsSeries(Swing_HH_Buffer,false);

//Counter Array
   ArraySetAsSeries(Counter_Buffer,false);
    
   int i;
   int Lookback=IndicatorCounted();
   int Counter=0;
   int Last_Swing=0;
   int Swing_Rule=0;
   double HA_Open,HA_High,HA_Low,HA_Close;

//Error Check - Sufficient candles on chart to complete calculations? 
   if(Lookback<1) return(-1);

   for(i=0; i<1; i++)
     {
      if(open[i]<close[i] || open[i]>close[i])
        {
         //Update the counter on each iteration of the loop - in this case once
         Counter=i;
         Counter_Buffer[i]=Counter;
         //Prints as follows
         HA_Low_Buffer[i]=low[i];
         HA_High_Buffer[i]=high[i];
         HA_Open_Buffer[i]=open[i];
         HA_Close_Buffer[i]=close[i];
        }
      //Setting the first swing - If the first candle is red
      if(open[i]<close[i])
        {
         Swing_1_Buffer[i]=HA_Low_Buffer[i];
        }
      //Setting the first swing - If the first candle is green
      else if(open[i]>close[i])
        {
         Swing_2_Buffer[i]=HA_High_Buffer[i];
        }
     }

//Setting the first 3 HA candles - necessary so to avoid an "array out of range" error during the swing calc
   for(i=1; i<4; i++)
     {
      //Update the counter on each iteration of the loop - in this case thrice
      Counter=i;
      Counter_Buffer[i]=Counter;
      //Establish current bar OHLC on each iteration of the loop
      HA_Open=(HA_Open_Buffer[i-1]+HA_Close_Buffer[i-1])/2;
      HA_Close=(open[i]+high[i]+low[i]+close[i])/4;
      HA_High=MathMax(high[i],MathMax(HA_Open,HA_Close));
      HA_Low=MathMin(low[i],MathMin(HA_Open,HA_Close));
      //Prints as follows:
      HA_Low_Buffer[i]=HA_Low;
      HA_High_Buffer[i]=HA_High;
      HA_Open_Buffer[i]=HA_Open;
      HA_Close_Buffer[i]=HA_Close;
     }
//Range/swing detection variables/functions     
   //Custom range function 1
   int RangeStart(int CurrentBarVal)
     {
      return (CurrentBarVal-CurrentBarVal);
     }
     
   //Custom range function 2
   int BarsInRange(int HighVal,int LowVal)
     {
      return (HighVal-LowVal);
     }
   int Range_Start=RangeStart(Counter);    int Bars_In_Range=BarsInRange(Last_Swing,Counter);    int SL_Range = iLowest(NULL, 0, MODE_LOW, Bars_In_Range, Range_Start);    int SH_Range = iHighest(NULL, 0, MODE_HIGH, Bars_In_Range, Range_Start); //Main HA candle and swing detection calculations and loop    for(i=4; i<=Lookback; i++)      {       //Update the counter on each iteration of the loop - in this case on every new candle       Counter=i;       Counter_Buffer[i]=Counter;       //Establish current bar OHLC on each iteration of the loop       HA_Open=(HA_Open_Buffer[i-1]+HA_Close_Buffer[i-1])/2;       HA_Close=(open[i]+high[i]+low[i]+close[i])/4;       HA_High=MathMax(high[i],MathMax(HA_Open,HA_Close));       HA_Low=MathMin(low[i],MathMin(HA_Open,HA_Close));       //Prints as follows:       HA_Low_Buffer[i]=HA_Low;       HA_High_Buffer[i]=HA_High;       HA_Open_Buffer[i]=HA_Open;       HA_Close_Buffer[i]=HA_Close;      }    return(rates_total);   }       

Can anyone suggest where i'm going wrong, please?

Any and all help, as always, is very much appreciated. 

Thanks,
Carl.  

Alain Verleyen
Moderator
28524
Alain Verleyen 2016.05.07 09:55  

These 2 functions need to be moved outside OnCalculate(). You can't declare a function inside an other function.

//Main program
int OnCalculate(...)
  {
   ...
  }
//Custom range function 1
int RangeStart(int CurrentBarVal)
  {
   return (CurrentBarVal-CurrentBarVal);
  }
//Custom range function 2
int BarsInRange(int HighVal,int LowVal)
  {
   return (HighVal-LowVal);
  }
The_Rezzer
42
The_Rezzer 2016.05.07 10:25  

Alain, you're a wonderful, wonderful man. That simple fact had sailed straight past me. Thank you very much. :)

Carl.  

Fernando Carreiro
1438
Fernando Carreiro 2016.05.07 11:09  

Just as a suggestion - try not to mix the use of the parameter arrays (open[], high[], etc.)  with the old style Chart data arrays (Open[], High[], etc.).

Instead of the iHighest() and iLowest() which works on the Chart Data arrays, rather use ArrayMaximum() and ArrayMinimum() on the high[] and low[] arrays which are the parameters of the function.

This will surely prevent any future inconsistencies (as there may be differences between the data sources) and make your OnCalculate() portable.

The_Rezzer
42
The_Rezzer 2016.05.09 07:48  

Fernando, i was yet to make the distinction between the two and this was what was causing me to go this route - creating the functions - in the first place. Thanks for taking the time to point this out. Hopefully things should be somewhat more straightforward. :)

Carl.

The_Rezzer
42
The_Rezzer 2016.05.09 08:44  
Quick question: am i right in thinking that iLowest/Highest has the benefit, over ArrayMaximum/Minimum, of being able to pull data from other timeframes? I'm working towards making this a multi-timeframe EA. 
Alain Verleyen
Moderator
28524
Alain Verleyen 2016.05.09 09:58  
The_Rezzer:
Quick question: am i right in thinking that iLowest/Highest has the benefit, over ArrayMaximum/Minimum, of being able to pull data from other timeframes? I'm working towards making this a multi-timeframe EA. 
You can do the similar things with both, but ArrayMaximum/Minimum are more generic, as they are working with any arrays. So if you provide them an array of data from any timeframe, it will work.
The_Rezzer
42
The_Rezzer 2016.05.09 10:49  
Ok. It's just clicked. Fernando, your advice makes sense as per the way i count bars/index positions. What i'll plan to do is create the EA which will utilise an iCustom function call to the indicator i'm creating - as ArrayMax/Min will be a inherent part of the indicator i don't need to use iLowest/Highest. This works way better for me. Thank you both! :)
/
To add comments, please log in or register