1
votes

I am quite new at programming and can't figure out why the code is not compiling and how to make it compile.

It's a simple EA in MetaTrader Terminal 4.

I think the problem is the position, where I declared and initialised variables, I tried placing them under different functions ( indicated with comments in the code ), but still the code wouldn't compile, the code is attached. Any help will be highly appreciated.

#property copyright "Copyright 2017, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

extern double ema_red    = iMA( NULL, 0,  6, 0, MODE_EMA, PRICE_CLOSE, 0 );
extern double ema_purple = iMA( NULL, 0, 30, 0, MODE_EMA, PRICE_CLOSE, 0 );
extern double ema_blue   = iMA( NULL, 0,  8, 1, MODE_EMA, PRICE_CLOSE, 0 );

// int point;
/*
void start()
{
  double ema_red    = iMA( NULL, 0,  6, 0, MODE_EMA, PRICE_CLOSE, 0 );
  double ema_purple = iMA( NULL, 0, 30, 0, MODE_EMA, PRICE_CLOSE, 0 );
  double ema_blue   = iMA( NULL, 0,  8, 1, MODE_EMA, PRICE_CLOSE, 0 );
  return;
 }
*/
void OnTick()
{
 // double ema_red    = iMA( NULL, 0,  6, 0, MODE_EMA, PRICE_CLOSE, 0 );
 // double ema_purple = iMA( NULL, 0, 30, 0, MODE_EMA, PRICE_CLOSE, 0 );
 // double ema_blue   = iMA( NULL, 0,  8, 1, MODE_EMA, PRICE_CLOSE, 0 );
 if (OrdersTotal()<=21)
   {   
      if (ema_red == ema_purple)&&(ema_red > ema_blue) // check when the ea's cross/meet
        Buy_Order();
      if (ema_red == ema_purple)&&(ema_red < ema_blue) // check when the ea's cross/meet
        Sell_Order();                                
   }
  }
void Buy_Order()
{ 
         double TP = Ask +(PipsToPointFactor()*15);
         double SL = (MarketInfo(Symbol(),MODE_TICKVALUE)) - (PipsToPointFactor()*5);
         OrderSend(Symbol(),OP_BUY,0.6,Ask,(3*PipsToPointFactor()),SL,TP,"",0,0,Green);  
  }
void Sell_Order()
{  
         double TP = (Bid - (15*PipsToPointFactor()));
         double SL = ((MarketInfo(Symbol(),MODE_TICKVALUE)) + (PipsToPointFactor()*5 );
         OrderSend(Symbol(),OP_SELL,0.6,Bid,(3*PipsToPointFactor()),SL,TP,"",0,0,Red); 
  }
int OnInit()
{
    return(INIT_SUCCEEDED);
  }
void OnDeinit(const int reason)
{  
  }
int PipsToPointFactor()              // NOT MY OWN FUNCTION, takes care of pips to points issue
{
   int point;
   if(Digits==5 || Digits==3)        // Check whether it's a 5 digit broker ( 3 digits for Yen )
   point=10;                         // 1 pip to 10 point if 5 digit
   else if(Digits==4 || Digits==2)
   point=1;                          // 1 pip to 1 point if 4 digit
   return(point);
  }
3
What error are you getting when you compile?John Bode
I'm not sure how your copyright notice works with the stack overflow licensing policy. I'd recommend to remove it. Better concentrate on providing a minimal reproducible example.too honest for this site
During the act of not-compiling, certainly there were error messages provided giving some hint as to why. Those error messages belong verbatim in your question.WhozCraig

3 Answers

1
votes

You declare some variables as "extern":

extern double ema_red    = iMA(NULL, 0,  6, 0, MODE_EMA, PRICE_CLOSE, 0);
extern double ema_purple = iMA(NULL, 0, 30, 0, MODE_EMA, PRICE_CLOSE, 0);
extern double ema_blue   = iMA(NULL, 0,  8, 1, MODE_EMA, PRICE_CLOSE, 0);

You are using them inside functions, inside more than one function, if you count the function start(). So, they need to be defined at least on a file scope. It seems that you define them nowhere.

Define them, in addition to declaring them or just define them:

/* extern */ double ema_red =    iMA(NULL, 0,  6, 0, MODE_EMA, PRICE_CLOSE, 0);
/* extern */ double ema_purple = iMA(NULL, 0, 30, 0, MODE_EMA, PRICE_CLOSE, 0);
/* extern */ double ema_blue =   iMA(NULL, 0,  8, 1, MODE_EMA, PRICE_CLOSE, 0);

All code files ( those which contain functions which access these variables ) need to "see" the declaration, i.e. the lines with "extern". If you have more than one such code file, that declaration should be in a header.
Exactly one code file then has to do the definition, i.e. the lines without "extern". That is called "global variables".

If you only have one such code file but several others and want to make sure that the variables are not accessible from anywhere else ( a feature for clean coding and for "safety" ), then you do not use a header and restrict the visibility to the one code file doing the definition. You do that by using the keyword "static", exactly where you now have "extern". That is sometimes called "file scope variables".

As another answer said, initialising at definition can only use static values. If you want to reinitialise at runtime, maybe with usecase specific values, your function "start()" happens to be the way to do it. You just have to change the definition lines to normal write accesses. The function then needs to be called for changing use cases.

Note:
This answer is referring only to C and is older than the edits to the question, which made the MT4-scope more prominent and deleted the C tag.
So be careful if your needs are heavily MT4 related.
Since somebody, including OP, considered the answer useful, I wont delete until a good MT4 answer is available.

1
votes

This question was originally tagged for C, so that's what this answer addresses.

One immediate issue - objects that are declared at file scope (outside the body of any function), as in

extern double ema_red = iMA(NULL, 0, 6, 0, MODE_EMA, PRICE_CLOSE, 0);
extern double ema_purple = iMA(NULL, 0, 30, 0, MODE_EMA, PRICE_CLOSE, 0);
extern double ema_blue = iMA(NULL, 0, 8, 1, MODE_EMA, PRICE_CLOSE, 0);

may only be initialized with constant expressions (something that can be evaluated at compile time). If iMA is a function call (or a macro that expands into something other than a constant expression), that will cause the compiler to yak.

And, you don't need the extern here.

0
votes

While syntax may look on a first look
somewhat similar to C,
the MQL4 language is by far a different cup of tea,
it lives inside a rather specific eco-system
with many un-paralleled and dual-edge sword features.

TL;DR; at least, you've been warned.

Since the early state of the original MQL4 language, there were important concepts, that go well beyond the classics of C.

The units of MQL4 code ( be it any of { EA: Expert Advisor | CI: Custom Indicator | Script: Script } ) are being executed in several different modes of the code-execution eco-system, either:

  • having been "put on" a graph, being that during live-market hours or weekends
  • having been "setup in" a trivial mode in a [Strategy Tester] back-testing facility of the Terminal
  • having been "setup in" a complex mode of an optimisation module in a [Strategy Tester]

While this may seem obvious for hard-core MetaTrader Quant Modellers, one may also agree this is a hidden part of the O/P context, which was readable just from decoding a bit cryptic second sentence ( cit. orig. ) :

"just a simple EA in MT4".


So, what are the MQL4-ways to use external variables?

All of the { extern | input | sinput } declarations ought be somewhere near the top of the MQL4-code, having a file-level of the scope-of-validity.

Placing the same extern declarations right to the bottom of the file will still work, compiler is aware of the proper scoping ( as it by-design also has to carefully handle all the potential variable name(s) masking(s) / un-masking(s) in case the same names were also used in some call-interface(s) declaration(s) or somewhere "inside" some deeper embedded code-block(s) ).

Such un-orthodox practice should be considered rather in-humane, as we also strive to create a good practice for human-understanding of the code-unit(s) we design, irrespective of compiler's ability to process the tail-definitions the very same way it does for the head-definitions, right?

enter image description here

Besides the trivialities of a variable-definition, belonging to a certain scope-of-validity ( inside a relevant { code-block }-scope ), there are some major implications for extern, input and sinput MQL4-specific declaration modifiers.

//+------------------------------------------------------------------+
//|                                StackOverflow__test_EA_extern.mq4 |
//|                                       Copyright © 1987-2017 [MS] |
//|                                                       nowhere.no |
//+------------------------------------------------------------------+
#property copyright "Copyright © 1987-2017 [MS]"
#property link      "nowhere.no"
#property version   "1.00"
#property strict         // New-MQL4.56789 <--- this CHANGES SOME RUN-TIME FEATURES OF THE SAME SOURCE-CODE (!!!)
//--- extern parameters ---     MQL4 declared <extern>-variables have at least DUAL-INTERFACE ROLE
extern double   ama_red;      // _RED    /*| (1) is a LIVE, knowingly bidirectional INTERFACE   */
extern double   ama_blue;    //  _BLUE   /*|                between a code-execution ecosystem  */
extern double   ama_purple; //   _PURPLE /*|                & MT4  GUI user-interactions        */
                           //    ^           (2) is an ITERATOR, unidirectional INTERFACE ROLE
                          //     ^                          from MetaTrader Terminal 4 [StrategyTester]
                         //      ^                          into MetaTrader Terminal 4 Optimisation Tool
                        //       ^
                       // comment^-strings are DISPLAYED in GUI dialogue boxes ( on #property strict // mode )
                      //  + each user-interaction, done via GUI, RESETs the STATE of the so far running EA (!!!)
                     //   + variables are always RE-INITIALISED immediately before the OnInit() is called
                    //                    ^^^^^^^^^^^^^^^^^^^^^
                   //     
                  //      - Arrays[] and variables of complex types can't act as <extern>-variables.
/*
//--- input parameters --- New-MQL4.56789 Build 1065+ EA-templates started to be proposed as <input>-based
input double   ama_red;       // can never be assigned a value to <input>-defined variables
input double   ama_blue;     //  can never be used for a man-machine user-interaction
input double   ama_purple;  //
*/
#property show_inputs    

int  aTracePointNUMBER(){ static int aTracePointORDINAL = EMPTY; return( ++aTracePointORDINAL ); }
void aTracePointREPORT( const string aTracePointCALLER,
                        const double aTracePointDOUBLE_VALUE,
                        const string aTracePointDOUBLE_NAME
                        ){
     PrintFormat( "[%d] In(%s): <_%s_> == %f",     // PrintFormat( "[%d] In(%s): <_%s_> == %f",
                   aTracePointNUMBER(),            //               aTracePointNUMBER(),
                   aTracePointCALLER,              //               __FUNCTION__,
                   aTracePointDOUBLE_NAME,         //              "ama_red"
                   aTracePointDOUBLE_VALUE         //               ama_red
                   );                              //               );
     }
/*
#include MQL4_Project_common_HEADERS_FILE.mqh      // may help with #define-s, but not that much with { extern | input | sinput }-s in MQL4
*/

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit() {
    aTracePointREPORT( __FUNCTION__, ama_red, "ama_red" );

    ama_red = iMA( NULL, 0, 6, 0, MODE_EMA, PRICE_CLOSE, 0 );
    aTracePointREPORT( __FUNCTION__, ama_red, "ama_red" );

    ama_red = EMPTY;
    aTracePointREPORT( __FUNCTION__, ama_red, "ama_red" );

    return( INIT_SUCCEEDED ); }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit( const int reason ) {
  // aTracePointREPORT( __FUNCTION__, ama_red, "ama_red" );
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick() {
  // uponEntry:                                            // EACH TIME anExternalFxEventSTREAM QUOTE.ARRIVAL
     aTracePointREPORT( __FUNCTION__, ama_red, "ama_red" );
  // ... EA code ...
     ama_red = iMA( NULL, 0, 6, 0, MODE_EMA, PRICE_CLOSE, 0 );
  // ...
     }
//+------------------------------------------------------------------+
/*
2017.04.15 14:40:45.030 2013.01.01 00:00:00  StackOverflow__test_EA_extern inputs: ama_red=-123456789; ama_blue=-987654321; ama_purple=918273645; 
2017.04.15 14:40:45.030 2013.03.21 13:20:00  StackOverflow__test_EA_extern XAUUSD,M1: [0] In(OnInit): <_ama_red_> == -123456789.000000
2017.04.15 14:40:45.030 2013.03.21 13:20:00  StackOverflow__test_EA_extern XAUUSD,M1: [1] In(OnInit): <_ama_red_> == 1608.298571
2017.04.15 14:40:45.030 2013.03.21 13:20:00  StackOverflow__test_EA_extern XAUUSD,M1: [2] In(OnInit): <_ama_red_> == -1.000000
2017.04.15 14:40:45.030 2013.03.21 13:20:00  StackOverflow__test_EA_extern XAUUSD,M1: [3] In(OnTick): <_ama_red_> == -1.000000
2017.04.15 14:43:14.764 2013.03.21 13:20:02  StackOverflow__test_EA_extern XAUUSD,M1: [4] In(OnTick): <_ama_red_> == 1608.298571
2017.04.15 14:43:16.827 2013.03.21 13:20:05  StackOverflow__test_EA_extern XAUUSD,M1: [5] In(OnTick): <_ama_red_> == 1608.296000
2017.04.15 14:43:18.889 2013.03.21 13:20:07  StackOverflow__test_EA_extern XAUUSD,M1: [6] In(OnTick): <_ama_red_> == 1608.293428
2017.04.15 14:43:20.952 2013.03.21 13:20:10  StackOverflow__test_EA_extern XAUUSD,M1: [7] In(OnTick): <_ama_red_> == 1608.295142
2017.04.15 14:43:23.014 2013.03.21 13:20:12  StackOverflow__test_EA_extern XAUUSD,M1: [8] In(OnTick): <_ama_red_> == 1608.296857
2017.04.15 14:43:25.077 2013.03.21 13:20:15  StackOverflow__test_EA_extern XAUUSD,M1: [9] In(OnTick): <_ama_red_> == 1608.293428

*/

By tracing this trivial code, you may realise a few facts:

  • While one cannot, for obvious compile-time reasons, declare an ema_red et al with being assigned to a non-(compile-time)-constant initialisation, there still is a way to achieve such aimed target and one may use for this a mandatory call to an OnInit(){...} event-handler code-block, to provide such a non-constant value into the intended extern variable.

Listed are the trace-reports from such constructed EA, showing each change of extern-declared inputs, before and after the code-execution reached the event-triggered OnTick(){...} handler ( original start() handler is not used anymore, yet historically still present a lot in MQL4 code-base ):

2017.04.15 14:40:45.030 2013.01.01 00:00:00 StackOverflow__test_EA_extern inputs: ama_red=-123456789; ama_blue=-987654321; ama_purple=918273645; 
2017.04.15 14:40:45.030 2013.03.21 13:20:00 StackOverflow__test_EA_extern XAUUSD,M1: [0] In(OnInit): <_ama_red_> == -123456789.000000
2017.04.15 14:40:45.030 2013.03.21 13:20:00 StackOverflow__test_EA_extern XAUUSD,M1: [1] In(OnInit): <_ama_red_> == 1608.298571
2017.04.15 14:40:45.030 2013.03.21 13:20:00 StackOverflow__test_EA_extern XAUUSD,M1: [2] In(OnInit): <_ama_red_> == -1.000000
2017.04.15 14:40:45.030 2013.03.21 13:20:00 StackOverflow__test_EA_extern XAUUSD,M1: [3] In(OnTick): <_ama_red_> == -1.000000
2017.04.15 14:43:14.764 2013.03.21 13:20:02 StackOverflow__test_EA_extern XAUUSD,M1: [4] In(OnTick): <_ama_red_> == 1608.298571
2017.04.15 14:43:16.827 2013.03.21 13:20:05 StackOverflow__test_EA_extern XAUUSD,M1: [5] In(OnTick): <_ama_red_> == 1608.296000
2017.04.15 14:43:18.889 2013.03.21 13:20:07 StackOverflow__test_EA_extern XAUUSD,M1: [6] In(OnTick): <_ama_red_> == 1608.293428
2017.04.15 14:43:20.952 2013.03.21 13:20:10 StackOverflow__test_EA_extern XAUUSD,M1: [7] In(OnTick): <_ama_red_> == 1608.295142
2017.04.15 14:43:23.014 2013.03.21 13:20:12 StackOverflow__test_EA_extern XAUUSD,M1: [8] In(OnTick): <_ama_red_> == 1608.296857
2017.04.15 14:43:25.077 2013.03.21 13:20:15 StackOverflow__test_EA_extern XAUUSD,M1: [9] In(OnTick): <_ama_red_> == 1608.293428

Beware, extern is a BI-DIRECTIONAL INTERFACE (!!!)

Given the above, on condition a user uses the GUI to modify once setup extern to a new value, the code-execution of the currently live-running Expert Advisor is reset to a new initialised values. That may cause a lot of problems in distributed-system's processing and one ought take due care to propagate such "invisible" reset to proper handling of going back to square [ 1 ].

GUI-clickable MMI interaction to change <code>extern</code> value(s)

The impact of the live-Market session Expert Advisor code-execution reset could be indeed disastrous, so be always careful, whether your code is being designed as being robust against such unintentional event(s), causing a Deus Ex Machina mystical changes of behaviour, very similar to a sudden thunder from a clear, blue sky.

If one does not expect such habit, a hidden remark in the system journal will typically not suffice for one to realise what happened to the live-session and what cascade of additional side-effects was triggered by such event.

enter image description here


Epilogue:

Upon mastering both the trivial extern and also it's external-iterator alternative for the complex-setup, used in [Strategy Tester] optimiser ( be it a fully-orthogonal brute-force or a somewhat magically labeled Genetic-mode one ), the fully bi-directional interface role of the extern-variables are a very powerful tool for Man-Machine-Interactions during MQL4 Quant Modelling.