Indi to Function - help needed....

Post Reply
Bruster400
Trader
Posts: 192
Joined: Tue Sep 24, 2013 3:19 pm

Indi to Function - help needed....

Post by Bruster400 »

Hi,

In typical bloke style I've been going round in circles on this one for ages trying to solve it myself but I've finally given up and need some help.

I'm trying to use the attached Heiken Ashi smoothed indicator within an EA as trend direction (based on the last closed candle). I've got it working using an iCustom call but I'd like to incorporate it into the EA as a function - I've tried to do it as an include and couldn't get that working either! The idea is that an internal function call will be less cpu intensive as it doesn't have to calculate all bars and I will only need the opens and closes and not the highs and lows. It also makes it neat and portable without having to move the indicator with the EA each time.

My attempt is here - with comments

Code: Select all

//+------------------------------------------------------------------+
//| HAS_Trend                                                        |
//+------------------------------------------------------------------+

int HAS_Trend(int _period1,int _method1,int _period2,int _method2)
{

// variables:
   double maOpen,maClose,maLow,maHigh,haOpen,haHigh,haLow,haClose;
   int trend;

// Define Arrays: (I've kept the names the same as those in the indicator)
   
   //double ExtMapBuffer1[];  // don't need the high and low as just open and close is sufficient to give trend
   //double ExtMapBuffer2[];
   double ExtMapBuffer3[];
   double ExtMapBuffer4[];
   double ExtMapBuffer5[];
   double ExtMapBuffer6[];
   double ExtMapBuffer7[];
   double ExtMapBuffer8[];
   
   // define the "limit" // don't need to do all bars - a sample of 200 plus the max period length will be sufficient
   int pos=200+MathMax(_period1,_period2);  
   
   // size the arrays 
   ArrayResize(ExtMapBuffer5,pos+2); // to allow poss + 1 to be accessed and including the zero.
   ArrayResize(ExtMapBuffer6,pos+2);
   ArrayResize(ExtMapBuffer7,pos+2);
   ArrayResize(ExtMapBuffer8,pos+2);
     
   ArrayResize(ExtMapBuffer3,6);  // open
   ArrayResize(ExtMapBuffer4,6); // close  
   
   // really not sure these are right!!
   ArraySetAsSeries(ExtMapBuffer3,false);
   ArraySetAsSeries(ExtMapBuffer4,false);
   ArraySetAsSeries(ExtMapBuffer5,false);
   ArraySetAsSeries(ExtMapBuffer6,false);
   ArraySetAsSeries(ExtMapBuffer7,true);
   ArraySetAsSeries(ExtMapBuffer8,true);
   
   
   // calculate the intial HA values and populate buffers
   while(pos>=0)
     {
      maOpen=iMA(NULL,0,_period1,0,_method1,PRICE_OPEN,pos);
      maClose=iMA(NULL,0,_period1,0,_method1,PRICE_CLOSE,pos);
      maLow=iMA(NULL,0,_period1,0,_method1,PRICE_LOW,pos);
      maHigh=iMA(NULL,0,_period1,0,_method1,PRICE_HIGH,pos);
      //----
      
      // populated the first record to prevent a divide by zero - this value won't be used in the smoothed calcs
      ExtMapBuffer5[pos+1]=1;
      ExtMapBuffer6[pos+1]=1;
      
      // populate as per the indicator
      haOpen=(ExtMapBuffer5[pos+1]+ExtMapBuffer6[pos+1])/2;
      haClose=(maOpen+maHigh+maLow+maClose)/4;
      
      // may not need the highs and lows - remove once it's working!
      
      haHigh=MathMax(maHigh,MathMax(haOpen,haClose));
      haLow=MathMin(maLow,MathMin(haOpen,haClose));
     
     // populate buffers according to trend
      if(haOpen<haClose)
        {
         ExtMapBuffer7[pos]=haLow;
         ExtMapBuffer8[pos]=haHigh;
        }
      else
        {
         ExtMapBuffer7[pos]=haHigh;
         ExtMapBuffer8[pos]=haLow;
        }
      // populate the open and close
      ExtMapBuffer5[pos]=haOpen;
      ExtMapBuffer6[pos]=haClose;
      pos--; // next down to zero
     }
   
   // initial HA values are calculated into buffers, now smooth them:
   // only need to do a few because we're only looking at the trend direction on the most recent closed candle
   // I checked this on the indicator and it just draws the last 4 bars as expected
   // for(int i=0; i<limit; i++) {
   for(int i=0; i<5; i++) {
      // only need the open and close
      ExtMapBuffer3[i]=iMAOnArray(ExtMapBuffer5,0,_period2,0,_method2,i); //open
      ExtMapBuffer4[i]=iMAOnArray(ExtMapBuffer6,0,_period2,0,_method2,i); //close
      
   }
      if(ExtMapBuffer3[1]<ExtMapBuffer4[1])trend=1;
      else trend=-1; 
      
      return(trend);
   
  }

I think the issue might be with the arrays as series but I can't find a combination that works. I'm sure this should be done as an include file in OOP but that's well beyond me at the moment.

If anyone can help point me in the right direction that would be great!

Thanks

Bruce
You do not have the required permissions to view the files attached to this post.
User avatar
renexxxx
Trader
Posts: 860
Joined: Sat Dec 31, 2011 3:48 am

Indi to Function - help needed....

Post by renexxxx »

Bruce,

I am like you and I loathe iCustom calls, especially, if/when they are totally unnecessary. However, in this case, an iCustom call (to the Heiken Ashi Smoothed indicator) is not a lot worse (in terms of efficiency) than a function call to a function that does the calculations internally. Why is that? Because, in this case, the calculated values for shift=n depend on the calculated values for shift=n+1. In other words, this is a Markov Chain. Even if we are only interested in the calculated values for shift=0, we need a sufficiently large lead-up (i.e. lookback) to ensure that the calculated values for shift=0 have converged to their final values. (The calculated values for shift=0, depend on the calculated values for shift=1, which in turn depend on the calculated values for shift=2, which in turn ... .... etc etc.)

I have attached a script with two functions: getHARates() and getHASmoothedRates() (the latter one is the one you are interested in). Both these functions fill an internal array HA[] of type Rates with their OHLC values. The script calls these functions with a lookback of 200 bars, which is sufficient to ensure that the values at shift=0 are converged. (The script prints the OHLC values to the "Experts"-tab, so that you can verify that indeed the values from the getHASmoothedRates() function are the same as those from the indicator.

In any case, whether you use an iCustom call, or the internal function, you should try to limit the number of calls. (eg. don't call them for every tick, but perhaps only on a new bar).

Hope that this is of any help to you.
You do not have the required permissions to view the files attached to this post.
Bruster400
Trader
Posts: 192
Joined: Tue Sep 24, 2013 3:19 pm

Indi to Function - help needed....

Post by Bruster400 »

Thank you so much!

As always you've shown me how far I've got to go with learning this stuff!!

I really like the use of a Structure for assigning variables to the main array - much easier to keep track of than coordinates! I've also not seen the ternary operator before instead of if/else - very neat. I'll need to look at this more closely though because I can't currently see where I've gone wrong. You use separate dimensions in one array to capture the values rather than the 4 arrays I used and you've used a "for loop" rather than a "while" but essentially the order of things seems similar. I'll need to look again at my arrays and make sure I've got the sizes and series correct etc. - All just to learn from of course because I'll be using your excellent solution in my EA!!

Thanks once again for sharing your time and expertise - it really does help.

Bruce
ruktoa
Posts: 5
Joined: Fri Aug 10, 2012 8:50 am

Indi to Function - help needed....

Post by ruktoa »

The attached code calculates MA*MA - MA*MA*MA using weighting coefficient tables.
WeightingCoefficientTable.jpg
dMs: EMA(34)*EMA(8)
dSs: EMA(34)*EMA(3)*EMA(8)
dWts: dMs-dSs
You do not have the required permissions to view the files attached to this post.
Post Reply

Return to “Coders Hangout”