1

我对编程很陌生,无法弄清楚为什么代码没有编译以及如何使其编译。

这是 MetaTrader 终端 4 中的一个简单 EA。

我认为问题出在我声明和初始化变量的位置,我尝试将它们放在不同的函数下(在代码中用注释表示),但代码仍然无法编译,代码已附加。任何帮助将不胜感激。

#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);
  }
4

3 回答 3

1

您将一些变量声明为“ 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);

如果您计算函数,则您正在函数内部使用它们,在多个函数内部start()。因此,它们至少需要在文件范围内定义。似乎你没有在任何地方定义它们。

定义它们,除了声明它们或只定义它们:

/* 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);

所有代码文件(那些包含访问这些变量的函数)都需要“看到”声明,即带有“ extern”的行。如果您有多个这样的代码文件,则该声明应位于标头中。
然后只需一个代码文件进行定义,即没有“ extern”的行。这就是所谓的“全局变量”。

如果您只有一个这样的代码文件,但还有其他几个文件,并且希望确保无法从其他任何地方访问变量(清洁编码和“安全”的功能),那么您不要使用标题并将可见性限制为进行定义的一个代码文件。您可以通过使用关键字“ static”来做到这一点,这正是您现在拥有“ extern”的位置。这有时被称为“文件范围变量”。

正如另一个答案所说,在定义处初始化只能使用静态值。如果您想在运行时重新初始化,也许使用特定于用例的值,您的函数 " start()" 恰好是这样做的方法。您只需将定义行更改为正常的写访问。然后需要调用该函数来更改用例。

注意:
此答案仅指 C 并且比对问题的编辑更旧,这使得 MT4 范围更加突出并删除了 C 标记。
因此,如果您的需求与 MT4 密切相关,请务必小心。
由于包括 OP 在内的某些人认为该答案很有用,所以我不会删除,直到有一个好的 MT4 答案可用。

于 2017-04-04T19:47:31.383 回答
1

这个问题最初被标记为 C,所以这就是这个答案所要解决的问题。

一个直接的问题 - 在文件范围内(在任何函数的主体之外)声明的对象,如

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);

只能用常量表达式初始化(​​可以在编译时评估的东西)。如果iMA是函数调用(或扩展为常量表达式以外的宏),这将导致编译器出错。

而且,你不需要extern这里。

于 2017-04-04T19:47:49.653 回答
0

虽然语法乍一看可能
与 C 有点相似,
但 MQL4 语言却是另一回事,
它存在于一个相当特定的生态系统
中,具有许多无与伦比的双刃剑特性。

TL;博士; 至少,你已经被警告过了。

自从原始 MQL4 语言的早期状态以来,就有一些重要的概念远远超出了 C 的经典范围。

MQL4 代码单元(无论是 { EA: Expert Advisor | CI: Custom Indicator | Script: Script } 中的任何一个)正在代码执行生态系统的几种不同模式中执行,或者:

  • 已被“放在”图表上,即在实时市场时间或周末
  • 已在终端的 [策略测试器] 回测工具中“设置”为普通模式
  • 在 [策略测试器]中“设置”了优化模块的复杂模式

虽然这对于核心 MetaTrader Quant Modellers来说似乎很明显,但人们也可能同意这是 O/P 上下文的隐藏部分,仅通过解码有点神秘的第二句(引文)即可阅读:

“只是一个简单的 MT4 EA”。


那么,MQL4 使用外部变量的方法是什么?

所有{ extern | input | sinput }声明都应该在 MQL4 代码顶部附近的某个位置,具有有效范围的文件级别。

将相同的extern声明放在文件的底部仍然可以工作,编译器知道正确的范围(因为它的设计还必须小心处理所有潜在的变量名(s)屏蔽/取消屏蔽( s) 如果在某些调用接口声明或“内部”某个更深的嵌入式代码块中也使用了相同的名称)。

这种非正统的做法应该被认为是相当不人道的,因为我们还努力为人类理解我们设计的代码单元创建一个良好的做法,而不管编译器处理尾部定义的能力是否相同它对头部定义的方式,对吧?

在此处输入图像描述

除了属于某个有效范围(在相关范围内)的变量定义的琐碎性之外{ code-block },还有一些主要的含义,适用于externinputMQL4sinput特定的声明修饰符。

//+------------------------------------------------------------------+
//|                                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

*/

通过跟踪这个微不足道的代码,您可能会意识到一些事实:

  • 虽然由于明显的编译时原因,不能ema_red声明一个分配给非(编译时)常量初始化的 et al,但仍然有一种方法可以实现这样的目标,并且可以为此使用强制调用到OnInit(){...}事件处理程序代码块,以将这样的非常量值提供给预期的extern变量。

列出了来自这种构造的EAextern的跟踪报告,显示了在代码执行到达事件触发处理程序之前和之后声明的输入的每次更改(不再使用OnTick(){...}原始处理程序,但历史上仍然在 MQL4 代码中存在很多 -start()根据 ):

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

当心,extern是一个双向接口(!!!)

鉴于上述情况,如果用户使用 GUI 将设置 extern 修改为新值,则当前实时运行的“EA 交易”的代码执行将重置为新的初始化值。这可能会在分布式系统的处理中引起很多问题,并且应该注意将这种“不可见”的重置传播到正确处理返回方格 [1]。

GUI 可点击的 MMI 交互以更改 <code>extern</code> 值

实时市场会话 EA 代码执行重置的影响确实可能是灾难性的,因此请务必小心,您的代码是否被设计为对此类意外事件具有鲁棒性,从而导致Deus Ex Machina神秘的行为变化,非常类似于来自晴朗蓝天的突然雷声。

如果人们没有预料到这种习惯,那么系统日志中的隐藏评论通常不足以让人们了解实时会话发生了什么以及此类事件触发了哪些额外的副作用。

在此处输入图像描述


结语:

在掌握了微不足道extern的同时它也是复杂设置的外部迭代器替代方案,用于 [策略测试器] 优化器(无论是完全正交的蛮力还是有点神奇地标记为遗传模式的),完全双-变量的定向接口角色是externMQL4 量化建模期间人机交互的一个非常强大的工具。

于 2017-04-15T14:28:52.560 回答