- Arrays and Bool - Stuck with solving issue in my code

 

Hello!
I’m stuck with figuring out what’s wrong with the code I’m writing and hope somebody over here will be able to help me out. I’ll try to keep it as short as possible.

I’m coding an EA and within it, I have an array that collects crossovers between two MA’s. This code should update the array with each new crossover price as soon as the candle on which the crossover occurred closes and add it to all the previous ones.
This array is then used for a function that analyses the range of the last three crossovers.  

I have the array written in my EA file amongst the rest of the code - the for loop for it is within void OnTick, while the bool function is located at the bottom of the EA file (in the part that is separated by //+------------------------------------------------------------------+)

  1. So far I’ve got that the EA recognises the last three crossovers – good.
  2. It also recognises them being in my specified range – good.
  3. This signals the EA to perform a certain task. Which it does – good. (I’ll call this task “FirstTask” as the reference from now on).

But then starts the issue.
When a new crossover occurs outside the specified range the EA should stop the “FirstTask” and start doing something else. (I’ll call this “NewTask”).  
However, as soon as the last three crossovers are approved to be within the range, the EA is “stuck” doing the “FirstTask” even after all the signals have changed and signalled the EA to switch from “FirstTask” to “NewTask”.

How do I fix it? And where the issue is to begin with? Here's the related snippets of the code:

double crossoverPrice[];
int manyCandles = Bars;
 
void OnTick()
 
     for (int lastCandle = 0; lastCandle < manyCandles; lastCandle++)
     {
        double fastMAnow = iMA(_Symbol, _Period, fastPeriod, 0, MODE_EMA, PRICE_CLOSE, lastCandle);
        double slowMAnow = iMA(_Symbol, _Period, slowPeriod, 0, MODE_EMA, PRICE_CLOSE, lastCandle);
        double fastMApast = iMA(_Symbol, _Period, fastPeriod, 0, MODE_EMA, PRICE_CLOSE, lastCandle + 1);
        double slowMApast = iMA(_Symbol, _Period, slowPeriod, 0, MODE_EMA, PRICE_CLOSE, lastCandle + 1);
 
        if ((slowMAnow > fastMAnow && slowMApast < fastMApast) || (slowMAnow < fastMAnow && slowMApast > fastMApast))
           {
            double currentCrossoverPrice = NormalizeDouble((fastMAnow + slowMAnow + fastMApast + slowMApast) / 4, Digits);
 
            ArrayResize(crossoverPrice, ArraySize(crossoverPrice) + 1);
            crossoverPrice[ArraySize(crossoverPrice) - 1] = currentCrossoverPrice;
           }
      }

// The rest of the onTick code is here
 
//+------------------------------------------------------------------+
bool sideMarketDetected()
{
   bool OvsI = MathAbs(crossoverPrice[0] - crossoverPrice[1]) > crossoverDistance;
   bool OvsZ = MathAbs(crossoverPrice[0] - crossoverPrice[2]) > crossoverDistance;
   bool IvsZ = MathAbs(crossoverPrice[1] - crossoverPrice[2]) > crossoverDistance;
 
   if (!OvsI || !OvsZ) return true;
   if (OvsI && OvsZ && !IvsZ) return true;
   return false;
} 

Improperly formatted code edited by moderator.

 

Improperly formatted code edited by moderator. Please always use the CODE button (Alt-S) when inserting code.

Code button in editor

 
Your topic has been moved to the section: MQL4 and MetaTrader 4
Please consider which section is most appropriate — https://www.mql5.com/en/forum/172166/page6#comment_49114893
 

I have a question (although it's not exactly relevant to solving your problem).

Kristīne Ivanovska:
This code should update the array with each new crossover price as soon as the candle on which the crossover occurred closes and add it to all the previous ones.

If you need intersections only on already formed (closed) bars, then why are you analyzing bar #0 (current)?

for (int lastCandle = 0; lastCandle < manyCandles; lastCandle++)
 
The array is in the global scope, that is, it stores values between ticks. You haven't shown where you are clearing the array.

Or you don't clean it at all. In this case, you will be adding new elements to the end of the array. And in the sideMarketDetected() function you use only #0, #1 and #2 - the values from the very first tick.

 

  • If you always only need the last 3 intersections, then you can do without an array. That is, as for me, you chose too complex an approach.
  • If you need the entire history of intersections on the chart, then you will have to complicate the work with the array. One way is to emulate an indicator buffer that will store intersections (their prices).

But I suspect you only need the last 3 intersections. 

In addition, you don't break the loop when you have found 3 intersections, but continue adding new elements to the array. If you don't clear the array, its size grows with every tick.

So it's actually not very clear what you want to do.

 
Vladislav Boyko #:

  • If you always only need the last 3 intersections, then you can do without an array. That is, as for me, you chose too complex an approach.
  • If you need the entire history of intersections on the chart, then you will have to complicate the work with the array. One way is to emulate an indicator buffer that will store intersections (their prices).

But I suspect you only need the last 3 intersections. 

In addition, you don't break the loop when you have found 3 intersections, but continue adding new elements to the array. If you don't clear the array, its size grows with every tick.

So it's actually not very clear what you want to do.

You're correct - I only need the last 3 crossovers. But I'm new to coding so thought that array is the only way.  I don't know how I can collect the last three crossover prices using array and break so that they update with every new crossover. I thought that with a break the update of the array stops. 

 
Vladislav Boyko #:

I have a question (although it's not exactly relevant to solving your problem).

If you need intersections only on already formed (closed) bars, then why are you analyzing bar #0 (current)?

Does doing so make any difference? 

I do it because I need my EA to perform a task as soon as next candle after the crossover opens
 
Kristīne Ivanovska #:
Does doing so make any difference?

I'm afraid because of this you are adding unformed intersections from bar 0 to the array. But I could be wrong.

Add this to the end of the OnTick function:

Comment("Size of crossoverPrice[] = ", ArraySize(crossoverPrice));

Launch the advisor in the strategy tester (visual mode) and wait a few dozen bars (until several new intersections appear). What is the size of the array? Does the array size grow over time?


[EDIT]

I'm very busy now. I'll be back in 2 days and try to show you my example implementation without using an array

 
Vladislav Boyko #:

I'm afraid because of this you are adding unformed intersections from bar 0 to the array. But I could be wrong.

Add this to the end of the OnTick function:

Launch the advisor in the strategy tester (visual mode) and wait a few dozen bars (until several new intersections appear). What is the size of the array? Does the array size grow over time?


[EDIT]

I'm very busy now. I'll be back in 2 days and try to show you my example implementation without using an array

Hi!

So I switched my lastCandle from 0 to 1, set the max size of the array to 3 and to be updated with each new price. Also added your suggested Comment - all is working perfectly when testing as a script. However,  when adding code to my EA, it sometimes will recognise all the crossover prices and distances between them correctly, but sometimes it will straight away either give the same price for the last three crossovers or will change all three prices from the correct ones to the last crossovers price as the same for all three. I haven't yet understood why or when it happens

 
Kristīne Ivanovska #:

Hi!

So I switched my lastCandle from 0 to 1, set the max size of the array to 3 and to be updated with each new price. Also added your suggested Comment - all is working perfectly when testing as a script. However,  when adding code to my EA, it sometimes will recognise all the crossover prices and distances between them correctly, but sometimes it will straight away either give the same price for the last three crossovers or will change all three prices from the correct ones to the last crossovers price as the same for all three. I haven't yet understood why or when it happens

Hello. Sorry, but I still don't have enough time to create an implementation example for you.


I think your code might be simpler if you ditch the array.

  1. Try creating a function that will return the prices of the last three intersections into 3 corresponding variables (instead of writing them to a global array).
  2. Then pass those 3 values to sideMarketDetected() (instead of sideMarketDetected() getting those values from a global array)

void OnStart()
  {
   double crossoverPrice0,
          crossoverPrice1,
          crossoverPrice2;
   findPricesOfCrossovers(crossoverPrice0, crossoverPrice1, crossoverPrice2);
   bool isSideMarket = sideMarketDetected(crossoverPrice0, crossoverPrice1, crossoverPrice2);
  }

bool sideMarketDetected(double price0, double price1, double price2)
  {
   // You need to change the function so that it uses formal parameters rather than an array
  }

void findPricesOfCrossovers(double &price0, double &price1, double &price2)
  {
   /*
   The purpose of this function is to assign crossover price values to the corresponding reference parameters:
   price0 = ...
   price1 = ...
   price2 = ...
   */
  }

Check out these documentation pages if you're having trouble returning multiple values from a function:

You can also do a forum search (returning multiple values from a function)
Reason: