Storing and searching data of previous 3 candles

 

Hi,

I am starting to write my first EA which looks at the crosser over of the moving averages and stochastic main/signal lines.

The issue I'm having is that it will only take the trade if the crossover of both the MA's and stoch occur on the same candle. I want it to be able to recognize if both crossovers have occurred in the last 3 candles (example) then take the trade.

My current idea to achieve this:

  • Use an array to store 'Buy' & 'Sell' signals if the crossovers occur. Then to search the other array to see if the signal has occurred

- eg. Crossover of MA's sends signal (True/False) to MA[]. Then check if there is a crossover signal in Stoch[], or if there was one within the 3 candles previous, if there is a crossover a buy trade is taken.

- How would I keep the array updated with the signals from the previous 3 candles?

- Should I limit the size of the array? Or just keep filling it with True,False Signals?

- Is there a downside to continually filling an array with signals?

- If the array size is undefined how do I limit the array search to the last 3 entries?


Thanks for the help and sorry if these are basic questions.

 
amac22:

I am starting to write my first EA which looks at the crosser over of the moving averages and stochastic main/signal lines. [...]

I'd say that it depends, in part, on whether you are re-evaluating the signal on each tick (intra-bar) or whether you only check for a signal when a bar closes.

If the former then, yes, it is worth considering some sort of storage of the values for older bars so that you are not constantly re-evaluating things which cannot have changed since you last did the calculation. This will have minimal impact in forward testing but will probably slow down backtesting.

If you are only looking at the signals when a bar closes/opens, then the benefit of caching is likely to be trivially small even in backtesting, and I would be inclined not to bother.

 
amac22:

Hi,

I am starting to write my first EA which looks at the crosser over of the moving averages and stochastic main/signal lines.

The issue I'm having is that it will only take the trade if the crossover of both the MA's and stoch occur on the same candle. I want it to be able to recognize if both crossovers have occurred in the last 3 candles (example) then take the trade.

My current idea to achieve this:

  • Use an array to store 'Buy' & 'Sell' signals if the crossovers occur. Then to search the other array to see if the signal has occurred

- eg. Crossover of MA's sends signal (True/False) to MA[]. Then check if there is a crossover signal in Stoch[], or if there was one within the 3 candles previous, if there is a crossover a buy trade is taken.

- How would I keep the array updated with the signals from the previous 3 candles?

- Should I limit the size of the array? Or just keep filling it with True,False Signals?

- Is there a downside to continually filling an array with signals?

- If the array size is undefined how do I limit the array search to the last 3 entries?


Thanks for the help and sorry if these are basic questions.

You don't need an array at all. Use 2 integer variables (global), check your crossover, when you have one set related variable to candle index(not indexed as a series). Then check if your other crossover index is within 3 candles.
 
Alain Verleyen:
You don't need an array at all. Use 2 integer variables (global), check your crossover, when you have one set related variable to candle index(not indexed as a series). Then check if your other crossover index is within 3 candles.

We may be thinking of an array being used in different ways, but the array option sounds like a better idea to me because it potentially allows allows amac22 to change, in future, "3 candles" to "2 candles" or "27 candles" without needing to modify the code. It's easy, for example, to envisage a future scenario where amac22 wants to make the "3 candle" crossover period something which is configurable via the Inputs.

If you're going to store the state as-at old candles in order to avoid re-calculating things which cannot have changed, then an array doesn't sound like a bad way of doing it.

But you may be envisaging something completely different to what I'm thinking of.

 
JC:

We may be thinking of an array being used in different ways [...]

Based on the OP's description, I'm thinking of something like the following where the crossover period is variable, and there's a cache meaning that you don't constantly recalculate whether there was a cross 2 bars ago etc. (Also assumes that the OP wants to look at the current intra-bar cross, rather than just evaluating signals at bar-ends.)
#property strict

input int CrossoverPeriod = 3;
input int FastEMAPeriod = 14;   
input int SlowEMAPeriod = 50;   

// States of crosses: cross up compared to previous bar; cross down; no cross
enum CrossValues {
   CrossUp = 1,
   CrossDown = -1,
   CrossNone = 0
};

// Cache of crosses in the last N bars, sized and initialised on the
// first call to OnTick()
CrossValues CrossCache[];

// Time of previous tick, used for detecting formation of new bars
datetime glbPreviousTick = 0;

void OnInit()
{
   ArrayResize(CrossCache, 0);
}

void OnTick()
{
   if (ArraySize(CrossCache) == 0) {
      // First tick (which we know because CrossCache is unsized).
      // Get the historic crosses at the end of prior bars. The current
      // cross is calculated below
      ArrayResize(CrossCache, CrossoverPeriod);
      for (int i = 1; i < CrossoverPeriod; i++) {
         CrossCache[i] = GetCrossAsAtBar(i, FastEMAPeriod, SlowEMAPeriod);
      }
   
   } else {
      // Not the first tick. But have we entered a new bar?
      if (TimeCurrent() / PeriodSeconds(Period()) != glbPreviousTick / PeriodSeconds(Period())) {
         // New bar. Shift the array up, losing its oldest member.
         // [ Note: the MQL documentation describes the result of an ArrayCopy() onto itself 
         // as "undefined". However, it seems to work fine in practice, probably because
         // it's just a thin wrapper around Win32 RtlMoveMemory() which does allow
         // overlapping source and destination. ]
         ArrayCopy(CrossCache, CrossCache, 1, 0);
      }
   }

   // Store the current intra-bar cross value, and the time of the current tick (for detecting
   // when we enter a new bar)
   CrossCache[0] = GetCrossAsAtBar(0, FastEMAPeriod, SlowEMAPeriod);
   glbPreviousTick = TimeCurrent();
   
   // Look for a cross in the cache. If CrossoverPeriod > 1 then there can be more than
   // one cross; for example, a cross-up followed by a later cross-down. This 
   // gets the most recent cross, if any, putting its +1/-1 direction into FoundCross
   CrossValues FoundCross = CrossNone;
   for (int i = 0; i < CrossoverPeriod; i++) {
      if (CrossCache[i] != CrossNone) {
         FoundCross = CrossCache[i];
         break;
      }
   }
   
   // And now, do something based on whether FoundCross is +1/-1/0
   // ...
}

// Looks for a cross at bar N, i.e. compares the MA values in bar N
// to the values in bar N+1
// Returns +1 for the "fast" EMA crossing above the "slow" EMA between
// bars N+1 and N; -1 for a cross below; or zero for no cross
CrossValues GetCrossAsAtBar(int barindex, int FastPeriod, int SlowPeriod)
{
   double vFast_Later = iMA(Symbol(), Period(), FastPeriod, 0, MODE_EMA, PRICE_CLOSE, barindex);
   double vFast_Older = iMA(Symbol(), Period(), FastPeriod, 0, MODE_EMA, PRICE_CLOSE, barindex + 1);

   double vSlow_Later = iMA(Symbol(), Period(), SlowPeriod, 0, MODE_EMA, PRICE_CLOSE, barindex);
   double vSlow_Older = iMA(Symbol(), Period(), SlowPeriod, 0, MODE_EMA, PRICE_CLOSE, barindex + 1);

   if (vFast_Later > vSlow_Later && vFast_Older < vSlow_Older) {
      return CrossUp;
   } else if (vFast_Later < vSlow_Later && vFast_Older > vSlow_Older) {
      return CrossDown;
   } else {
      return CrossNone;
   }
}
 
JC:
Based on the OP's description, I'm thinking of something [...]
(It would actually be more efficient to cache the MA values, as well as the cross status, because this code unnecessarily and repeatedly gets the unchanging iMA() for bar 1. But it demonstrates the principle.)
 

Alternate method

  1. Check for MA cross, remember the bar time
  2. Check for stochastic cross, remember the bar time.
  3. If the iBarShift of both times is less than three, you have your signal.
 
whroeder1:

Alternate method

  1. Check for MA cross, remember the bar time
  2. Check for stochastic cross, remember the bar time.
  3. If the iBarShift of both times is less than three, you have your signal.
Yes it's similar to what I proposed.
 
Alain Verleyen:
Yes it's similar to what I proposed.
You're both right. I was over-thinking it. The OP's description chimed with various things I've got where maintaining the full history of the last N signals is important, but you're absolutely right that it's completely unnecessary for the scenario which the OP actually describes.
 
JC:
Based on the OP's description, I'm thinking of something like the following where the crossover period is variable, and there's a cache meaning that you don't constantly recalculate whether there was a cross 2 bars ago etc. (Also assumes that the OP wants to look at the current intra-bar cross, rather than just evaluating signals at bar-ends.)

It would work of course, but the array is useless as you only need the last cross. So your solution seems to me a bit "heavy".

From the OP description we only need the last MA cross and Stochastic cross.

enum ENUM_CROSS_TYPE
  {
   CROSS_UP,
   CROSS_DOWN,
   CROSS_NONE
  };
//---
struct SCross
  {
   ENUM_CROSS_TYPE   type;
   int               index;
   datetime          time;
  };

SCross lastMACross,lastStoCross;

void Main()
  {
   bool getNewCross=false;
   ENUM_CROSS_TYPE newCross=CROSS_NONE;

//--- check MA cross
   if(CheckMACross())
     {
      getNewCross=true;
      //--- save last MA cross data
      lastMACross=...;
     }

//--- check STO cross
   if(checkStoCross())
     {
      getNewCross=true;
      //--- save last STO cross data
      lastStoCross=...;
      
     }

//--- if new cross, check for a signal
   if(getNewCross)
     {
      //--- use index or time or both to check the "3 candles" condition
      if(lastMACross<="3 candles" && lastStoCrossw="3 candles")
        {
         //--- new signal
         ...
        }
     }
  }
 
JC:
You're both right. I was over-thinking it. The OP's description chimed with various things I've got where maintaining the full history of the last N signals is important, but you're absolutely right that it's completely unnecessary for the scenario which the OP actually describes.
Exactly. (was writing previous post while you posted this).