Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Книга по написанию робота под MT4.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
484.02 Кб
Скачать

www.mq4.com

С чего начать при написании советника

Естественно, что первым делом Вы должны иметь представление, а в чем же заключается Ваша торговая тактика, и что Вы хотите запрограммировать. Принципы создания любой торговой тактики подробно описаны в разделе "Торговые тактики", поэтому примем за аксиому, что Вы знаете, что делаете, т.е. в Вашей голове уже сформировался торговый алгоритм, который Вы желаете запрограммировать в виде советника на языке MetaQuotes Language 4. Итак, начнем...

Запустите терминал MetaTrader 4.

 

Окно "Навигатор" позволяет быстро получить доступ к различным возможностям программы. Список возможностей представлен в виде дерева и содержит 5 групп:

  • "Счета" – список счетов.

  • "Индикаторы" - список доступных индикаторов технического анализа.

  • "Советники" - список доступных советников.

  • "Пользовательские индикаторы" - список всех доступных пользовательских индикаторов, т.е. программ, написанных на языке MetaQuotes Language 4 и реализующих функцию индикатора.

  • "Скрипты" - библиотеки пользовательских функций, предназначенные для хранения часто используемых блоков пользовательских программ.

Щелкните правой кнопкой мыши на любом из доступных советников. Появится контекстное меню:

  • Attach to a chart - "прикрепить" советник к активному графику. Это означает, что с каждый тиком по данной валютной паре советник будет совершать запрограммированные трейдером действия.

  • Modify - вызвать MetaQuotes Language Editor и начать редактирование кода советника.

  • Delete - удалить советника.

  • Create - создать нового советника.

  • Add to favorites - добавить советника в закладки (вкладка "Favorites" окна "Навигатор") для последующего быстрого доступа к советнику.

  • Set hotkey - задать "горячую" клавишу для выделенного советника.

Как Вы уже, наверняка, догадались, Вам нужно выбрать пункт "Create". В результате откроется окно MetaQuotes Language Editor и Вы сможете приступить к созданию своего первого советника.

Настраиваем параметры нового эксперта

Итак, в прошлом выпуске мы вызвали контекстное меню окна "Навигатор" группы "Expert Advisors" и выбрали пункт меню "Create". В результате появилось окно, в котором нам предстоит выбрать тип объекта, который мы хотим создать (см. рис. 1).

Рис. 1. Выберем тип объекта, который мы хотим написать на языке MetaQuotes Language 4

Нас интересует создание эксперта, поэтому выбираем пункт "Axpert Advisor". Нажимаем "Далее". В следующем окне (рис. 2.) установим параметры нового эксперта:

  • Name - имя советника (файлу будет присвоено такое же имя с расширением *.mq4;

  • Author - автор советника;

  • Link - адрес веб-сайта автора советника;

  • Parameters - параметры советника, которые можно впоследствии менять при подключении советника к графику;

Рис. 2. Настройка параметров советника

Зададим для тренировки какой-нибудь параметр. Например, MAPeriod. Для этого нажмите кнопку "Add" и настройте каждое поле параметра:

  • Name - имя параметра (в нашем примере MAPeriod);

  • Type - тип параметра;

  • Initial value - начальное значение.

Параметры могут быть следующих типов:

  • int - целое число (от -2147483648 до 2147483647);

  • bool - логический тип (или ложь - false, или истина - true);

  • datetime - дата и время (в формате D'YYYY.MM.DD HH:MM:SS');

  • color - цвет (о формате я расскажу в следующих выпусках);

  • double - вещественное число (-1.7 * 10-308 до 1.7 * 10308, точность - 15 значащих цифр);

  • string - заключенная в двойные кавычки строка (например, "это строка").

Нажмем кнопку "Готово". В результате мы увидим заготовку для кода нашего первого эксперта:

//+------------------------------------------------------------------+ //|                                     My First Expert.mq4 | //|                 Copyright c 2006, Andrey Vedikhin | //|                                http://www.vedikhin.ru | //+------------------------------------------------------------------+ #property copyright "Copyright © 2006, Andrey Vedikhin" #property link      "http://www.vedikhin.ru" //---- input parameters extern int       MAPeriod=0; //+------------------------------------------------------------------+ //| expert initialization function                         | //+------------------------------------------------------------------+ int init()   { //----     //----    return(0);   } //+------------------------------------------------------------------+ //| expert deinitialization function                      | //+------------------------------------------------------------------+ int deinit()   { //----     //----    return(0);   } //+------------------------------------------------------------------+ //| expert start function                                   | //+------------------------------------------------------------------+ int start()   { //----     //----    return(0);   } //+------------------------------------------------------------------+

Анализ кода заготовки эксперта

После совершения действия, описанных в предыдущем выпуске мы получили код-заготовку, который мы можем изменить в соответствии с нашей торговой тактикой и получить работоспособного эксперта. Давайте разберем, что же мы в итоге получили...

//+------------------------------------------------------------------+ //|                                     My First Expert.mq4 | //|                 Copyright c 2006, Andrey Vedikhin | //|                                http://www.vedikhin.ru | //+------------------------------------------------------------------+ #property copyright "Copyright © 2006, Andrey Vedikhin" #property link      "http://www.vedikhin.ru" //---- input parameters extern int       MAPeriod=0; //+------------------------------------------------------------------+ //| expert initialization function                         | //+------------------------------------------------------------------+ int init()   { //----     //----    return(0);   } //+------------------------------------------------------------------+ //| expert deinitialization function                      | //+------------------------------------------------------------------+ int deinit()   { //----     //----    return(0);   } //+------------------------------------------------------------------+ //| expert start function                                   | //+------------------------------------------------------------------+ int start()   { //----     //----    return(0);   } //+------------------------------------------------------------------+

Первые несколько строчек - комментарии. Комментарий - это неисполняемый кусок кода, т.е., иными словами, это любая полезная читателю кода информация. Комментарии бывают однострочными - в этом случае они начинаются с двойного слэша: //, - и весь остаток строчки после // будет считаться комментарием. Также комментарии бывают многострочными. Такие комментарии должны начинаться с /* и заканчиваться */.

#property copyright "Copyright © 2006, Andrey Vedikhin"

C помощью #property copyright "строка" мы можем задать имя/наименование создателя эксперта.

#property link "http://www.vedikhin.ru"

C помощью #property link "веб-сайт" зададим веб-сайт создателя.

extern int MAPeriod=0;

Таким образом мы описываем переменную-параметр эксперта. Этот параметр имеет значение по умолчанию равным 0, но это значение можно будет впоследствии менять и для каждого прикрепленного к графику эксперта задавать свои значения. Этот параметр - аналог параметра технического индикатора (например, период расчета для RSA или период расчета скользящей средней).

Слово extern перед определением переменной показывает, что это внешняя переменная или параметр, которая будет видна в настройках эксперта. int - тип переменной (в нашем примере этот параметр - целое число от -2147483648 до 2147483647 - см. предыдущий выпуск). А MAPeriod - имя параметра. Мы хотим, чтобы по умолчанию значение параметра было равным нулю, поэтому добавим =0 сразу же после имени параметра. Точка с запятой показывает, что мы завершили описание параметра эксперта.

Таких параметров у эксперта может быть несколько. Все они должны быть одного из стандартных типов, описанных в прошлом выпуске.

Следующие три блока, которые представляют для нас интерес - это описания трех функций: init(), start() и deinit(). Что это за функции и для чего они нужны - я расскажу в следующем выпуске.

Создание собственных функций

Любой эксперт, как мы уже увидели в прошлом выпуске, состоит из как минимум трех функций: init(), start() и deinit(). Без понимания, что они делают, невозможно написать своего эксперта, поэтому я в следующем выпуске подробно эти функции рассмотрю.

Для начала же полезно понять, а что такое функция вообще. Допустим Вы в своей программе часто производите одни и те же действия. Вы можете в каждом месте написать код, который выполняет эти действия. Однако это неудобно и неправильно с нескольких точек зрения:

  1. Если вдруг Вам понадобится внести изменения в этот кусок кода, то это придется делать везде, где он используется. Существует большая вероятность, что где-то Вы забудете внести изменения, и советник будет торговать с ошибками.

  2. Гораздо более читабельным будет код, когда выполнение повторяющихся действий вынесено в отдельную функцию, а в соответствующих местах эта функция вызывается. В этом случае изменения (в случае необходимости) надо делать всего в одном месте и читаемость такого кода будет гораздо лучше.

Таким образом, в любой момент Вы можете описать свою функцию, которая будет выполнять определенные действия:

тип    имя ( параметры )    {          действия    }

Функция может возвращать какое значение любого из стандартных типов (int, bool, datetime, double, color, string - см. описание типов в выпуске "Настраиваем параметры нового эксперта"), либо не возвращать никакого значения (тип void).

Имя функции - это любое понятное Вам имя, которое помогает сразу же вспомнить, что делает эта функция. Имя может состоять из цифр (0-9), латинских прописных и строчных букв (а - z и А - Z, следует помнить, что буквы 'a' и 'A' - совершенно разные символы), символа подчеркивания (_). Первый символ не может быть цифрой. Также имя функции не должно совпадать с зарезервированным словом (т.е. словом, которое имеет особый смысл в языке MetaQuotes Language 4 - но об этом позже).

Пример имени функции: GetConnectionStatus.

Каждой функции могут передаваться определенные параметры. Они указываются через через запятую в круглых скобках после имени функции. Для каждого параметра указывается тип.

Приведем пример описания функции, которая вычисляет наименьшее из двух целых чисел:

int GetMinValue(int a1, int a2)    {          if (a1<a2) return(a1); else return(a2);    }

Эта функция возвращает значение типа int (целое число), ее имя - GetMinValue и она имеет два входящих целочисленных параметра: a1 и a2.

Для возврата значения в вызывающую программу используется команда return(значение).

Если в каком-то месте нашего советника нам потребуется вычислить минимальное число из двух, то мы можем вызвать нашу функцию следующим образом: имя(параметры через запятую). Например: GetMinValue(10, 15).

Теперь мы знаем достаточно о функциях, чтобы перейти к подробному рассмотрению трех важнейших функций любого эксперта: init(), start() и deinit().

Функции init(), start() и deinit()

Как я уже говорил в прошлых постах, любой эксперт состоит как минимум из трех функций: init(), start() и deinit(). В этом выпуске я расскажу о них подробнее.

Функция init()

Эта функция вызывается в следующих случаях:

  • после присоединения советника к графику;

  • после старта MetaTrader 4 и подгрузки исторических данных;

  • после смены инструмента или периода графика;

  • после перекомпиляции программы в редакторе MetaEditor;

  • после изменения настроек эксперта;

  • после смены торгового счета.

Функция start()

Функция start() запускается на каждом новом тике. Собственно это основная функция эксперта, т.к. она вызывается на каждом тике и выполняет основную работу.

Важно: Если функция start() не успела завершить свою работу до прихода следующего тика, следующий тик пропускается и функция для него не вызывается.

Функция deinit()

С помощью UninitializeReason() можно узнать причину вызова функции deinit().

Функция deinit() вызвается в следующих случаях:

  • при завершении работы MetaTrader 4 или при закрытии графика (функция UninitializeReason() возвращает REASON_CHARTCLOSE);

  • при удалении эксперта с графика (REASON_REMOVE);

  • перед изменением инструмента графика или периода графика (REASON_CHARTCHANGE);

  • при удачной перекомпиляции программы в MetaEdito (REASON_RECOMPILE)r;

  • при изменении параметров эксперта (REASON_PARAMETERS);

  • при переключении на другой счет (REASON_ACCOUNT).

Функция UninitializeReason() возвращает 0, если скрипт самостоятельно завершил работу.

Если в течение 2.5 секунд фукция deinit() работу не завершила, то она прерывается принудительно.

Пишем простейшего эксперта

На мой взгляд, наиболее простым способом для новичка изучить процесс написания экспертов будет подробный разбор специально написанных мной для этой цели экспертов. На данный момент (да и далее в своих статьях) я не буду ставить перед собой цель написать супер гениального эксперта, который способен будет зарабатывать десятки процентов в месяц и делать это стабильно. Основная цель - показать все аспекты программирования экспертов, а не написать "грааль".

Итак, внимательно изучите код эксперта ниже, но не волнуйтесь, что на данный момент Вам пока еще ничего не понятно. В следующих выпусках я подробно разберу каждую строчку этого эксперта.

//+------------------------------------------------------------------+

//| My First Expert.mq4 |

//| Copyright © 2006, Andrey Vedikhin |

//| http://www.vedikhin.ru |

//+------------------------------------------------------------------+

#property copyright "Copyright © 2006, Andrey Vedikhin"

#property link "http://www.vedikhin.ru"

#define STATE_SQUARE 0

#define STATE_LONG 1

#define STATE_SHORT 2

//---- input parameters

extern int MAPeriod=13;

extern double LotsNumber=1.0;

//---- глобальные переменные

int CurrentState;

int MyOrderTicket;

//+------------------------------------------------------------------+

//| expert initialization function |

//+------------------------------------------------------------------+

int init()

{

//----

if (iMA(NULL, 0, MAPeriod, 0, MODE_EMA, PRICE_CLOSE, 0) > Close[0])

CurrentState = STATE_SHORT;

else CurrentState = STATE_LONG;

MyOrderTicket = 0;

//----

return(0);

}

//+------------------------------------------------------------------+

//| expert deinitialization function |

//+------------------------------------------------------------------+

int deinit()

{

//----

//----

return(0);

}

//+------------------------------------------------------------------+

//| expert start function |

//+------------------------------------------------------------------+

int start()

{

//----

int err;

double MA;

MA = iMA(NULL, 0, MAPeriod, 0, MODE_EMA, PRICE_CLOSE, 0);

if ( CurrentState == STATE_LONG)

{

if (MA > Close[1]) //скользящая средняя выше цены закрытия

{

CurrentState = STATE_SHORT;

//переворачиваемся в продажу

//---закрыть позицию, если была открыта

if ( MyOrderTicket != 0)

{

if (!OrderClose(MyOrderTicket, LotsNumber, Bid, 3, CLR_NONE))

{

err = GetLastError();

Print("Ошибка при закрытии позиции: ", err);

return(0);

}

MyOrderTicket = 0;

}

RefreshRates();

//--- длинная позиция была закрыта успешно

//--- теперь откроем позицию в продажу

//--- проверим на наличие свободных средств

if (!CheckForEnoughMargin()) return(0);

MyOrderTicket = OrderSend(Symbol(), OP_SELL, LotsNumber, Bid, 3, 0, 0,

NULL, 0, 0, CLR_NONE);

if (MyOrderTicket<0)

{

err = GetLastError();

Print("Ошибка при открытии позиции: ", err);

MyOrderTicket = 0;

}

}

}

else

{

if (MA < Close[1]) //скользящая средняя ниже цены закрытия

{

CurrentState = STATE_LONG;

//переворачиваемся в покупку

//---закрыть позицию, если была открыта

if ( MyOrderTicket != 0)

{

if (!OrderClose(MyOrderTicket, LotsNumber, Ask, 3, CLR_NONE))

{

err = GetLastError();

Print("Ошибка при закрытии позиции: ", err);

return(0);

}

MyOrderTicket = 0;

}

RefreshRates();

//--- короткая позиция была закрыта успешно

//--- теперь откроем позицию в покупку

//--- проверим на наличие свободных средств

if (!CheckForEnoughMargin()) return(0);

MyOrderTicket = OrderSend(Symbol(), OP_BUY, LotsNumber, Ask, 3, 0, 0,

NULL, 0, 0, CLR_NONE);

if (MyOrderTicket<0)

{

err = GetLastError();

Print("Ошибка при открытии позиции: ", err);

MyOrderTicket = 0;

}

}

}

//----

return(0);

}

//+------------------------------------------------------------------+

//| Проверка наличия свободной маржи |

//+------------------------------------------------------------------+

bool CheckForEnoughMargin()

{

if (GetOneLotMargin(Symbol())*LotsNumber<AccountFreeMargin()) return(true);

else return(false);

}

//+-------------------------------------------------------------------+

//| Вычисление необходимой маржи на один лот|

//+-------------------------------------------------------------------+

double GetOneLotMargin(string s)

{

double p;

if ((StringSubstr(s, 0, 3) == "EUR")||(StringSubstr(s, 0, 3) == "GBP")||

(StringSubstr(s, 0, 3) == "AUD")||(StringSubstr(s, 0, 3) == "NZD"))

{

if (!IsTesting())

return(MarketInfo(s, MODE_LOTSIZE)*MarketInfo(StringSubstr(s, 0, 3)+"USD",

MODE_BID)/AccountLeverage());

else

{

p = iClose(StringSubstr(s, 0, 3)+"USD", Period(),

iBarShift(StringSubstr(s, 0, 3)+"USD", Period(), CurTime(), true));

return(MarketInfo(s, MODE_LOTSIZE)*p/AccountLeverage());

}

}

if (StringSubstr(s, 0, 3) == "USD")

return(MarketInfo(s, MODE_LOTSIZE)/AccountLeverage());

if (s == "CHFJPY")

{

p = iClose("USDCHF", Period(), iBarShift("USDCHF", Period(), CurTime(), true));

return(MarketInfo(s, MODE_LOTSIZE)/(AccountLeverage()*p));

}

return(77777777777777777777777777.0);

}

//+------------------------------------------------------------------+

Благодарю Вас за то, что Вы мужественно дочитали до этой строчки. Как я уже упомянул ранее, в следующих выпусках я очень подробно остановлюсь на каждой строчке этого эксперта, и проясню Вам все непонятные моменты.

Использование констант в эксперте

В прошлом выпуске я выложил код нашего первого эксперта.

Вначале разберем, что означают следующие строчки:

#define STATE_SQUARE 0

#define STATE_LONG 1

#define STATE_SHORT 2

Эти строчки дают возможность вместо написания малоинформтивных чисел 0, 1 или 2 использовать более понятные имена STATE_SQUARE, STATE_LONG или STATE_SHORT. Результат будет абсолютно таким же - если программа встретит в тексте STATE_SQUARE, STATE_LONG или STATE_SHORT, она заменит их на 0, 1 и 2 соответственно. Такая программа будет более читаемой.

Также константы используются в тех случаях, когда какое-то значение использует в нескольких местах программы и существует вероятность, что трейдеру может понадобиться изменить это значение в будущем. Если использовать константу, достаточно будет это сделать только в одном месте - в директиве #define.

Для объявления константы используйте следующую конструкцию:

#define имя значение

Примеры констант:

#define AUTHOR "Vedikhin Andrey"

#define Lots 1.1

#define ItemsNumber 77

Следующие две строчки абсолютно идентичны, но первая - более читаема:

for(x=1;x<=ItemsNumber;x++) Print(Lots*x);

for(x=1;x<=77;x++) Print(1.1*x);

Константа может быть любого типа: int, bool, datetime, double, color, string - см. описание типов в выпуске "Настраиваем параметры нового эксперта".

Хранение данных в переменных

Любой эксперт оперирует с некоторыми данными - ценами, значениями индикаторов, объемами, количеством открытых позиций и пр. Те, места, где эти данные хранятся в эксперте, называются переменными. В качестве имен переменных можно использовать цифры (0-9), латинские прописные и строчные буквы (а - z и А - Z, следует помнить, что буквы 'a' и 'A' - совершенно разные символы), символ подчеркивания (_). Первый символ не может быть цифрой. Также имя переменной не должно совпадать с зарезервированным словом (т.е. словом, которое имеет особый смысл в языке MetaQuotes Language 4 - но об этом позже).

Желательно в качестве имени переменной использовать такое, из которого сразу становится понятным предназначение переменной. Например, переменная, содержащая количество открытых позиций, может иметь такое имя: OpenPositionsNumber.

Можно создавать переменные разных типов:

  • int - целое число (от -2147483648 до 2147483647);

  • bool - логический тип (или ложь - false, или истина - true);

  • datetime - дата и время (в формате D'YYYY.MM.DD HH:MM:SS');

  • color - цвет (о формате я расскажу в следующих выпусках);

  • double - вещественное число (-1.7 * 10-308 до 1.7 * 10308, точность - 15 значащих цифр);

  • string - заключенная в двойные кавычки строка (например, "это строка").

Перед использованием переменной ее надо объявить. Это можно сделать несколькими способами:

тип имя;

или

тип имя = начальное_значение;

Примеры объявлений переменных:

int Count;

datetime InitialDate = D'2006.07.12 00:00';

string ip_address = "127.0.0.1";

В дальнейшем для того, чтобы обратиться к значению переменной, надо будет просто указать ее имя:

i = 5 + Count;

Иногда требуется сохранить не одно значение, а определенное количество взаимосвязанных значений. Например, значение индикатора на текущем баре, на предыдущем баре, ... , N-баров назад. Для таких целей существуют массивы. Массив - это индексированная совокупность однотипных данных.

Предположим, что у нас в эксперте есть такое описание массива Prices:

double Prices[50];

Это означает, что массив-переменная Prices предоставляет доступ к 50 элементам типа double. Для доступа к i-му элементу надо указать Prices[i]. Нумерация элементов начинается с нуля и заканчивается 49-м элементов (в нашем случае).

Если Вы попробуете обратиться к элементу вне этого диапазона, то будет зафиксирована ошибка ERR_ARRAY_INDEX_OUT_OF_RANGE (4002), которую можно получить при помощи функции GetLastError().

В случае необходимости можно использовать не только одномерные массивы (у которых только один индекс), но и многомерные массивы.

Пример описания двухмерного массива, состоящего из шести массивов, каждый из которых состоит из 50 элементов:

int mas[6] [50];

При описании массива можно в фигурных скобках задать начальные значения для каждого элемента:

int a[4][4] = { 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4 };

Начальные значения элементов массивов могут быть только константами. Если Вы в фигурных скобках при инициализации массива указали меньшее количество начальных значений, чем размерность массива, то недостающие элементы инициализируются нулями.

Существует несколько видов переменных: локальные, статические, внешние, глобальные переменные и формальные параметры функций. В следующем выпуске я более подробно расскажу о локальных и статических переменных.

Локальные и статические переменные

В прошлом выпуске я рассказал о том, как использовать переменные и массивы в эксперте. Единственным нераскрытом моментом остались области видимости переменных. Дело в том, что переменные бывают нескольких типов:

  • локальные переменные,

  • статические переменные,

  • глобальные переменные,

  • внешние переменные,

  • параметры функций.

Локальные переменные

Если переменная объявлена в пределах какой-нибудь функции, то она является локальной переменной и видна только в пределах этой функции. За пределами этой функции к этой переменной обращаться нельзя.

Инициализация (присвоение начального значения) локальной переменной происходит каждый раз при вызове функции. Присваиваемое начальное значение может быть как константой, так и выражением.

Пример объявления и инициализации локальной переменной:

int CalcFactorial(int n)

{

int i = 0;

...

}

Cтатические переменные

Статические переменные объявляются директивой static. Они инициализируются только один раз - при первом вызове функции и сохраняют свое значение даже после выхода из функции. В следующий раз при новом вызове функции статические переменные будут иметь то же значение, которое они имели перед выходом из функции в послений раз.

Статические переменные объявляются в пределах описания функции и поэтому доступны для использования только в пределах той функции, в которой они объявлены.

Пример объявления статической переменной:

int GetOpenPositionsNumber()

{

static int Count = 0;

...

}

В следующем выпуске я расскажу о внешних переменных.

Внешние переменные

В прошлом выпуске я рассказал о локальных и статических переменных. В этом выпуске я остановлюсь на внешних переменных.

Внешние переменные

Мы уже сталкивались с внешними переменными, когда описывали параметры эксперта MAPeriod и LotsNumber в коде нашего первого эксперта.

Внешние переменные описываются с помощью зарезервированного слова extern:

extern int MAPeriod=13;

extern double LotsNumber=1.0;

Внешние переменные не могут быть массивами.

Внешние переменные - это параметры эксперта, которые можно изменять.

"Прикрепите" эксперт к графику. Для этого нажмите правую кнопку мыши на названии эксперта в окне "Навигатор" и в появившемся контекстном меню выберите "Присоединить к графику". Появится окно свойств эксперта. Во вкладке "Входные параметры" Вы можете изменить значения внешних переменных, описанных в эксперте (см. рис. 1).

Рис. 1. Параметры эксперта

Если эксперт уже "прикреплен" к графику (в правом верхнем углу графика Вы видите улыбающуюся или грустную рожицу), то для изменения его параметров - значений внешних переменных - нажмите на рожице правую кнопку мыши и выберите в в появившемся контекстном меню пункт "Советники - Свойства ...". Более быстрый способ - использовать горячую клавишу F7. Появится окно с параметрами эксперта (см. рис. 1), в котором Вы сможете изменить значения внешних переменных.

В следующем выпуске я расскажу о глобальных переменных.

Глобальные переменные

В прошлом выпуске я рассказал о внешних переменных. В этом выпуске я остановлюсь на глобальных переменных.

Глобальные переменные

Для человека, имеющего уже опыт написания экспертов, выражение "глобальные переменные" может внести небольшую путанницу. Дело в том, что на самом деле существует два вида "глобальных переменных":

  1. переменные, которые видны из любой функции ОДНОГО эксперта (т.е. являются глобальными в пределах этого эксперта); и

  2. переменные, которые являются общими для ВСЕХ экспертов.

В этом выпуске речь пойдет именно о глобальных переменных первого типа - тех, которые являются общими для всех функций ОДНОГО эксперта.

Второй же тип глобальных переменных я рассмотрю в следующих выпусках, когда буду рассказывать о функциях, с помощью которых к таким переменным получают доступ, - GlobalVariable...().

Если Вы хотите, чтобы к значению переменной можно было бы обращаться из разных функций одного эксперта, сделайте ее глобальной переменной, т.е. определите ее на том же уровне, что и функции:

//---- глобальные переменные int CurrentState; int MyOrderTicket; //---- определения функций int init() { ... }

Начальное значение глобальной переменной может быть только константой (если не задано никакого значения, то она инициализируется нулем). Это значение присваивается глобальной переменной только один раз, до выполнения функции init().

В следующем выпуске я расскажу о формальных параметрах функций.

Параметры функций

В выпуске "Создание собственных функций" я рассказал достаточно подробно о том, как описывать собственные функции. В этом выпуске я продолжу рассмотрение функций и детально разберу, как в функцию можно передать значения и получить результат функции.