1
votes

I have an EA that trades breakouts. I run this on multiple pairs. The problem arises when two pairs with high correlation trades the same direction ( or opposite, if negative correlation ). That doubles my risk. So, I added a snippet in my EA that prevents opening a new trade if there is already an open position of a symbol that is highly correlated with the current symbol.

( this is what I tried ):

string       strSymbol;
string       HighCorrelationPairs[];

int OnInit() {
   strSymbol = Symbol();
   if (  strSymbol == "EURAUD" ) {
         ArrayResize( HighCorrelationPairs, 1 );
         string HighCorrelationPairs[1] = { "EURJPY" };
   }
   else if (  strSymbol == "EURJPY" ) {
              ArrayResize( HighCorrelationPairs, 2 );
              string HighCorrelationPairs[2] = { "EURAUD", "EURUSD" };
        }
        else if (  strSymbol == "EURUSD" ) {
                   ArrayResize( HighCorrelationPairs, 2 );
                   string HighCorrelationPairs[2] = { "EURJPY", "USDCHF" };
             }
             else if (  strSymbol == "GBPJPY" ) {
                        ArrayResize( HighCorrelationPairs, 1 );
                        string HighCorrelationPairs[1] = { "GBPUSD" };
                  }
                  else if (  strSymbol == "GBPUSD" ) {
                             ArrayResize( HighCorrelationPairs, 1 );
                             string HighCorrelationPairs[1] = { "GBPJPY" };
                       }
                       else if (  strSymbol == "USDCHF" ) {
                                  ArrayResize( HighCorrelationPairs, 1 );
                                  string HighCorrelationPairs[1] = { "EURUSD" };
                            }
                            else if (  strSymbol == "USDJPY" ) {
                                       ArrayResize( HighCorrelationPairs, 1 );
                                       string HighCorrelationPairs[1] = {};
                                 }
                                 else {
                                        ArrayResize( HighCorrelationPairs, 1 );
                                        string HighCorrelationPairs[1] = {};
                                 }
}

void OnTick() {          //--- Check Correlation and Number of Trades
   for ( k = OrdersTotal() - 1; k >= 0; k-- ) {
         if (  OrderSelect( k, SELECT_BY_POS, MODE_TRADES ) ) {
               if (  OrderType() == OP_BUY
                  || OrderType() == OP_SELL
                     ) {
                     if (  OrderSymbol()      == Symbol()
                        && OrderMagicNumber() == MagicNumber
                           ) {
                           return;
                     }
                     if (  TimeCurrent() - OrderOpenTime() <= 18000 ) {
                           for ( int i = 0;i <  ArraySize( HighCorrelationPairs ); i++ ) {
                                 if (  OrderSymbol() == HighCorrelationPairs[i] ) { return; }
                           }
                     }
               }
         }
   }
}

Upon compiling, this is the warning/s that I got

variable 'HighCorrelationPairs' not used
declaration of 'HighCorrelationPairs' hides global declaration at line 120

It's only a warning, not an error.

2

2 Answers

1
votes

The primary problem is called a variable "scope-of-declaration"

given a code instructs the compiler to do this:

if (  strSymbol == "EURAUD" ) {
         ArrayResize( HighCorrelationPairs, 1 );
         string HighCorrelationPairs[1] = { "EURJPY" };
   }

the last row inside the lexical-scope of the if's body -- the if(){...} body-part, being the {...} -- is the only ephemeral zone, where the newly "locally" created statically pre-sized object, into which a value is going to get assigned string HighCorrelationPairs[1] = ... ; is immediatelly lost
once the "scope-of-declaration" will be crossed ( i.e. immediately after it's creation / assignment )

Next comes the variable name masking:

Next after a new, "local" string HighCorrelationPairs[] is created, the compiler has to at least inform you, that any colliding object-name, defined on any other level ( higher in the already visited hierarchy ) becomes un-available at the same time, thus leaving the most recently declared object's name to effectively mask all previously defined objects, bearing the lexically "same" name. So, you have been warned.

Refine your code, so as to avoid variable names' masking and do obey the variable lexical "scope-of-declaration".

switch( _Symbol ){
     case "EURAUD" : {  ArrayResize( HighCorrelationPairs, 1 );
                                     HighCorrelationPairs[0] = "EURJPY";
                        break;
                        }
     case "EURUSD" : {  ArrayResize( HighCorrelationPairs, 2 );
                                     HighCorrelationPairs[0] = "EURJPY";
                                     HighCorrelationPairs[1] = "USDCHF";
                        break;
                        }
     ...
}

Well, right, MQL4 documentation was not clear in this. The specification stated a switch( selector ) must have the selector part as an expression ( which was met ).

Switch Operator
Compares the expression value with constants in all the case variants and passes control to the operator that corresponds to the expression value. Each variant of case can be marked with an integer constant, a literal constant or a constant expression.

Nevertheless, the compiler rejects any other but int type to serve in this syntax-constructor.

So, best to use some trivial HASH-function to get int:

int   Symbol2HASH( const string aSymbol = "EURUSD" ) {
// -----------------------------------
// NAIVE, BUT WORKING:
// ------------------UUID--------------
#define DEF_EURUSD      0
#define DEF_EURJPY      1
#define DEF_EURAUD      2
#define DEF_EURCHF      3
//          ...       ...
// ------------------UUID--------------
// MAINTAIN HERE ALL UUID #s PLUS aSymbol MAPPINGS:
// --------vvvvvvv----------------------vvvvvvvvvv
      if ( aSymbol == "EURUSD" ) return DEF_EURUSD;
      if ( aSymbol == "EURJPY" ) return DEF_EURJPY;
      if ( aSymbol == "EURAUD" ) return DEF_EURAUD;
      if ( aSymbol == "EURCHF" ) return DEF_EURCHF;

      return EMPTY;
  }

switch( Symbol2HASH( _Symbol ) ) {
       case DEF_EURAUD: {  ArrayResize( HighCorrelationPairs, 1 );
                                        HighCorrelationPairs[0] = "EURJPY";
                           break;
                           }
       case DEF_EURUSD: {  ArrayResize( HighCorrelationPairs, 2 );
                                        HighCorrelationPairs[0] = "EURJPY";
                                        HighCorrelationPairs[1] = "USDCHF";
                           break;
                           }
       case EMPTY: {       PrintFormat( "Symbol()==[%s] not included inside Symbol2HASH() function. Edit source.", _Symbol );
                           ExpertRemove();
                           }
       default:    {       PrintFormat( "Symbol()==[%s] code [%d] was not served inside switch(){ case-s }. Edit source.", _Symbol, Symbol2HASH( _Symbol ) );
                           ExpertRemove();
                           }
  }
0
votes

That warning is really important, as most of warnings are. It says the following: You declared HighCorrelationPairs[] inside OnInit() and now you do all operations with this newly declared array, and that array is only visible inside OnInit() function. when you try to call that array from OnTick() function, it calls an array that was declared but never initiated in line 120 (outside OnInit(), in global variables).

what to do? Try to fill your array but not create a new one!

string HighCorrelationPairs[];
int OnInit(){
   string strSymbol = Symbol();
   if(strSymbol == "EURAUD") {
      ArrayResize(HighCorrelationPairs,1);
      HighCorrelationPairs[0] = "EURJPY";
   }else if(strSymbol == "EURJPY") {
      ArrayResize(HighCorrelationPairs,2); 
      HighCorrelationPairs[0] = "EURAUD";
      HighCorrelationPairs[1] = "EURUSD";
   }
   //also you may print all elements of the array here if you wish
   return (INIT_SUCCEEDED);
}