Где разместить внешние переменные на языке MQL4?
Я новичок в программировании и не могу понять, почему код не компилируется и как его компилировать.
Это простой советник в терминале 4 MetaTrader.
Я думаю, что проблема заключается в положении, в котором я объявил и инициализировал переменные, я попытался поместить их в другие функции (обозначенные в коде комментариями), но все равно код не будет компилироваться, код прикреплен. Любая помощь будет высоко оценена.
#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 ответа
Вы объявляете некоторые переменные как 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
Msgstr "Если у вас есть более одного такого файла кода, это объявление должно быть в заголовке.
Точно один файл кода должен выполнить определение, то есть строки без extern
"Это называется" глобальные переменные ".
Если у вас есть только один такой файл кода, но несколько других и вы хотите убедиться, что переменные недоступны из других источников (функция для чистого кодирования и для "безопасности"), то вы не используете заголовок и ограничиваете видимость один кодовый файл делает определение. Вы делаете это с помощью ключевого слова static
"именно там, где ты сейчас" extern
Msgstr "Это иногда называют" переменными области видимости файла ".
Как сказал другой ответ, инициализация при определении может использовать только статические значения. Если вы хотите выполнить повторную инициализацию во время выполнения, возможно, с использованием значений, специфичных для прецедента, ваша функция " start()
"Это способ сделать это. Вам просто нужно изменить строки определения на обычный доступ для записи. Затем необходимо вызвать функцию для изменения вариантов использования.
Замечания:
Этот ответ относится только к языку C и является более старым, чем правки вопроса, что сделало область видимости MT4 более заметной и удалило тег C.
Так что будьте осторожны, если ваши потребности сильно связаны с MT4.
Поскольку кто-то, включая OP, посчитал ответ полезным, я не буду удалять, пока не будет доступен хороший ответ MT4.
Этот вопрос был изначально помечен для 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
Вот.
Хотя синтаксис может выглядеть на первый взгляд
чем-то похож на C,
язык MQL4- это, безусловно, другая чашка чая,
он живет в довольно специфической экосистеме
со многими непараллельными и двойными характеристиками меча.
TL; DR; по крайней мере, вы были предупреждены.
Начиная с раннего состояния оригинального языка MQL4, были важные понятия, которые выходят далеко за рамки классики C.
Модули кода MQL4 (будь то { EA: Expert Advisor | CI: Custom Indicator | Script: Script}) выполняются в нескольких различных режимах экосистемы выполнения кода, либо:
- будучи "надетым" на график, будь то в часы работы рынка или выходные дни
- будучи "настроенным" в тривиальном режиме в средстве бэк-тестирования [Тестера стратегий] Терминала
- будучи "настроенным" в сложном режиме модуля оптимизации в [тестере стратегий]
Хотя это может показаться очевидным для хардкорных MetaTrader Quant Modellers, можно также согласиться с тем, что это скрытая часть контекста O/P, которая была читаема только при расшифровке загадочного второго предложения ( cit. Orig.):
msgstr "простой советник в МТ4".
Итак, каковы MQL4-способы использования внешних переменных?
Все { extern | input | sinput }
объявления должны быть где-то ближе к вершине MQL4-кода и иметь файловый уровень области действия.
Размещение же extern
объявления в самом низу файла все еще будут работать, компилятор знает о надлежащей области видимости (так как он должен также тщательно обрабатывать все потенциальные имена переменных, маскирующие / не маскирующие) в В случае, если те же имена были использованы в некоторых объявлениях интерфейса (ов) call-интерфейса или где-то "внутри" некоторых более глубоких встроенных блоков кода.
Такая неортодоксальная практика должна считаться довольно гуманной, поскольку мы также стремимся создать хорошую практику для понимания человеком кодовых единиц (единиц), которые мы проектируем, независимо от способности компилятора обрабатывать определения хвоста одинаково как это происходит с определениями головы, верно?
Помимо тривиальности определения переменной, принадлежащей определенной области действия (внутри соответствующей { code-block }
-области), есть некоторые важные последствия для extern
, input
а также sinput
MQL4-специфичные модификаторы объявлений.
//+------------------------------------------------------------------+
//| Stackru__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 Stackru__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 Stackru__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 Stackru__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 Stackru__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 Stackru__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 Stackru__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 Stackru__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 Stackru__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 Stackru__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 Stackru__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 Stackru__test_EA_extern XAUUSD,M1: [9] In(OnTick): <_ama_red_> == 1608.293428
*/
Прослеживая этот тривиальный код, вы можете понять несколько фактов:
- Хотя по очевидным причинам времени компиляции нельзя объявить
ema_red
и др. с назначением не-(время компиляции) -константной инициализации, все еще есть способ достичь такой целевой цели, и для этого можно использовать обязательный вызовOnInit(){...}
код-блок обработчика событий, чтобы обеспечить такое непостоянное значение в предполагаемомextern
переменная.
Перечислены трассировочные отчеты от такого построенного советника, показывающие каждое изменение extern
-объявленные входы до и после выполнения кода достигли события OnTick(){...}
обработчик (оригинал start()
обработчик больше не используется, но исторически все еще присутствует в кодовой базе MQL4:
2017.04.15 14:40:45.030 2013.01.01 00:00:00 Stackru__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 Stackru__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 Stackru__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 Stackru__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 Stackru__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 Stackru__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 Stackru__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 Stackru__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 Stackru__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 Stackru__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 Stackru__test_EA_extern XAUUSD,M1: [9] In(OnTick): <_ama_red_> == 1608.293428
Осторожно, extern
это двунаправленный интерфейс (!!!)
Учитывая вышесказанное, при условии, что пользователь использует графический интерфейс для изменения после установки extern нового значения, выполнение кода текущего работающего советника сбрасывается до новых инициализированных значений. Это может вызвать много проблем в обработке распределенной системы, и следует должным образом позаботиться о том, чтобы распространить такой "невидимый" сброс на правильную обработку возврата к квадрату [ 1 ].
Влияние сброса при выполнении кода эксперта сеанса реального рынка может быть действительно катастрофическим, поэтому всегда будьте осторожны, если ваш код разрабатывается как устойчивый к таким непреднамеренным событиям, вызывающим мистические изменения поведения Deus Ex Machina, очень похоже на внезапный гром с ясного голубого неба.
Если не ожидать такой привычки, то скрытого замечания в системном журнале, как правило, недостаточно, чтобы понять, что произошло с сеансом в реальном времени и какой каскад дополнительных побочных эффектов был вызван таким событием.
Эпилог:
Освоив оба тривиальных extern
а также это альтернатива внешнего итератора для комплексной настройки, используемая в оптимизаторе [Strategy Tester] (будь то полностью ортогональная грубая сила или несколько магически помеченная как Genetic-mode), полностью двунаправленная интерфейсная роль extern
Переменные - очень мощный инструмент для взаимодействия человек-машина во время квантового моделирования MQL4.