v.perevedentsev Опубликовано 12 сентября, 2010 Автор Жалоба Поделиться Опубликовано 12 сентября, 2010 Изменение позицийИзменение текущей позиции заключается в установке новых уровней прикрепленных ордеров Стоп Лосс или Тейк Профит. Для изменения позиции необходимо выполнить команду контекстного меню открытой позиции "Модифицировать или удалить ордер" либо дважды кликнуть левой кнопкой мыши на полях "Стоп Лосс" или "Тейк Профит" строки открытой позиции в окне "Терминал". Затем в появившемся окне необходимо задать новые значения ордеров Стоп Лосс или Тейк Профит и нажать кнопку "Изменить". Для изменения значения Стоп Лосс и Тейк Профит необходимо записать новые значения в соответствующие поля. Для установки ордеров в пунктах от текущей цены необходимо задать требуемое значение в поле "Уровень" и нажать кнопку "Копировать". Если значения этих полей равны нулю, используется минимально допустимое отклонение, которое устанавливается брокером. Если при изменении позиции уровни Стоп Лосс или Тейк Профит расположены слишком близко к текущей цене, кнопка "Изменить" блокируется. Необходимо отодвинуть уровни от текущей цены и повторить запрос на изменение позиции. Изменение торговой позиции произойдет после того, как брокерская компания установит новое значение Стоп Лосс и Тейк Профит. При этом во вкладке "Терминал — Торговля" в строке состояния открытой позиции произойдет изменение значений в полях "S/L" и "T/P". При этом, если включена опция "Показывать торговые уровни", изменятся положения модифицированных ордеров. Внимание: нулевые значения в полях "Стоп Лосс" и "Тейк Профит" означают, что одноименные ордера не выставлены. Ссылка на комментарий Поделиться на другие сайты Поделиться
v.perevedentsev Опубликовано 12 сентября, 2010 Автор Жалоба Поделиться Опубликовано 12 сентября, 2010 Закрытие позицийПокупка или продажа финансового инструмента открывает торговую позицию. Далее, чтобы получить прибыль за счет разницы курсов, необходимо закрыть позицию. При закрытии торговой позиции совершается обратная по отношению к первой торговая операция. Например, если первой торговой операцией была покупка одного лота по GOLD, то для закрытия позиции нужно продать один лот того же финансового инструмента. В клиентском терминале различают закрытие одиночной позиции, закрытие позиции встречной позицией и закрытие нескольких встречных позиций. Закрытие одной позицииАвтоматическое закрытие одиночной открытой торговой позиций производится при равенстве цен значениям ордеров Стоп Лосс или Тейк Профит. Внимание: при закрытии длинной позиции значению уровней ордеров Стоп Лосс или Тейк Профит должна равняться цена Bid, а при закрытии короткой — цена Ask. Для закрытия позиции вручную необходимо выполнить команду контекстного меню открытой позиции окно "Терминал — Торговля" либо дважды кликнуть левой кнопкой мыши на этой же позиции. Если исполнение торговых операций для выбранного инструмента производится по запросу, то сначала необходимо получить котировки, нажав на кнопку "Запрос". После этого активизируется кнопка, позволяющая закрыть позицию. Внимание: в режиме "Исполнение по запросу" предложенные котировки будут активны всего несколько секунд. Если в течение этого времени не будет принято решение, то кнопка "Закрыть ..." будет снова заблокирована; клиентский терминал позволяет совершать частичное закрытие позиции. Для этого перед нажатием кнопки "Закрыть..." в поле "Объем" нужно указать меньшее, чем у открытой позиции, значение лотов; брокер также может закрывать позиции. Например, это происходит при достижении уровня "Стоп Аут", который устанавливает брокер; исторические графики в терминале строятся только по Bid-ценам. При этом часть отображаемых на графиках ордеров строятся по Ask-ценам. Чтобы включить отображение Ask-цены последнего бара, необходимо выставить флажок "Показывать линию Ask" в настройках терминала. Закрытие встречных позициийВстречной позицией по отношению к данной считается противоположная позиция по тому же финансовому инструменту. Если среди открытых позиций имеется одна или несколько встречных, то можно закрыть выбранную позицию вместе со встречной. Для этого необходимо сначала открыть окно "Ордер" (способы открытия описаны выше). Затем нужно в поле "Тип" выбрать "Закрыть встречной позицией". При этом в нижней части окна появится список всех встречных позиций. В этом списке необходимо выбрать встречную позицию, после чего активизируется кнопка "Закрыть ...". Она позволяет закрыть сразу две позиции. Если встречные позиции имели разное количество лотов, открытой остается только одна из них. Объем этой позиции (количество лотов) будет равен разности лотов закрытых позиций, а ее направление и цена открытия (короткая или длинная) — большей (по объему) из закрываемых позиций. Закрытие нескольких встречных позицийЗакрытие нескольких встречных позиций позволяет закрыть не две встречные позиции по одному инструменту, а сразу несколько. Для проведения данной операции необходимо также открыть окно "Ордер" (способы открытия описаны выше). Затем в поле "Тип" выбрать "Множественное закрытие встречных позиций". При этом нижней части окна появится список всех встречных позиций и активизируется кнопка "Множественное закрытие встречных позиций ...". Она позволяет закрыть встречные позиции. Закрытие происходит попарно, в соответствии со временем открытия позиций, по алгоритму закрытия двух встречных позициий. Если разница сумм объемов противоположных позиций не равна нулю, в результате операции будет открыта новая позиция с объемом, равным этой разности. Вновь открытая позиция будет участвовать в дальнейшем процессе множественного закрытия, но в соответствии со своим временем открытия. И так — до тех пор, пока не закроются все позиции либо пока не откроется последняя результирующая позиция. Внимание: после закрытия встречных позиций в окне "Терминал — История счета" появятся соответствующие записи. При этом в поле "Комментарий" записывается служебная информация о закрытии встречных позиций. Ссылка на комментарий Поделиться на другие сайты Поделиться
v.perevedentsev Опубликовано 12 сентября, 2010 Автор Жалоба Поделиться Опубликовано 12 сентября, 2010 Установка отложенных ордеровДля установки отложенных ордеров необходимо открыть окно "Ордер". Это можно сделать командой меню "Сервис — Новый ордер", кнопкой панели инструментов "Стандартная", клавишей F9, командой "Новый ордер" контекстных меню окон "Обзор рынка" и "Терминал — Торговля", а также двойным щелчком на наименовании финансового инструмента в окне "Обзор рынка". В поле "Тип" этого окна необходимо выбрать "Отложенный ордер". Далее потребуется выбрать финансовый инструмент (символ), указать объем, а также задать значения ордеров Стоп Лосс и Тейк Профит. Если необходимо, можно также записать комментарий в одноименном поле. В полях "Отложенный ордер" нужно: Тип — выбрать тип отложенного ордера: Buy Limit, Buy Stop, Sell Limit или Sell Stop; По цене — установить уровень цены, по достижении которого должен сработать ордер; Истечение — задать срок действия ордера. Если до этого времени ордер не сработает, он будет удален автоматически. Внимание: срок действия ордера должен быть не менее 10 минут!Кнопка "Установить ордер" отправляет ордер на исполнение, которое происходит в два этапа. После выдачи ордера брокерская компания производит его установку. При этом во вкладке "Терминал — Торговля" появится строка с номером и состоянием отложенного ордера. На графике, если включена опция "Показывать торговые уровни", появятся отметки уровней выставленного отложенного ордера (включая уровни Стоп Лосс и Тейк Профит). На втором этапе, если цены будут соответствовать условию ордера, происходит его удаление и открытие вместо него торговой позиции. При этом тикет открытой позиции будет совпадать с тикетом отложенного ордера. Эти изменения отражаются в окне "Терминал — Торговля". Внимание: ордера Стоп Лосс или Тейк Профит срабатывают только на открытых позициях и не работают на отложенных ордерах. Ссылка на комментарий Поделиться на другие сайты Поделиться
v.perevedentsev Опубликовано 12 сентября, 2010 Автор Жалоба Поделиться Опубликовано 12 сентября, 2010 Изменение отложенных ордеровПри работе на рынке часто возникает необходимость изменить либо удалить выставленный отложенный ордер. Чтобы это сделать, необходимо выполнить команду контекстного меню отложенного ордера "Модифицировать или удалить ордер" либо дважды щелкнуть левой кнопкой мыши на строке состояния отложенного ордера в окне "Терминал — Торговля". При этом откроется окно управления ордерами. В нем можно задать новую цену срабатывания отложенного ордера, новые уровни Стоп Лосс и Тейк Профит, а также изменить срок действия ордера. После модификации ордера необходимо нажать кнопку "Изменить". Внимание: установка нулевых значений Стоп Лосс и Тейк Профит равносильна отключению одноименных ордеров. При успешном изменении отложенного ордера в окне "Терминал — Торговля" произойдет изменение значений соответствующих полей. Если в настройках терминала включена опция "Показывать торговые уровни", на графике также произойдет перемещение уровней отложенного ордера и прикрепленных к нему ордеров Стоп Лосс и Тейк Профит. Удаление отложенного ордераПри изменении рыночной ситуации может потребоваться удалить отложенный ордер. Для этого необходимо выполнить команду контекстного меню отложенного ордера "Модифицировать или удалить ордер" либо дважды щелкнуть левой кнопкой мыши на строке состояния отложенного ордера в окне "Терминал — Торговля". При этом откроется окно управления ордерами. В нем для удаления ордера необходимо нажать одноименную кнопку. Также отложенные ордера могут удаляться автоматически при наступлении времени, указанного в поле "Истечение". При удалении отложенного ордера в окне "Терминал — История счета" появляется соответствующая информация. Ссылка на комментарий Поделиться на другие сайты Поделиться
v.perevedentsev Опубликовано 12 сентября, 2010 Автор Жалоба Поделиться Опубликовано 12 сентября, 2010 На этом краткое описание функций МТ4 закончено. Этого достаточно для начала ручной торговли на демо-счете. Ниже будет дано краткое описание создания собственных индикаторов, скриптов и советников. Ссылка на комментарий Поделиться на другие сайты Поделиться
v.perevedentsev Опубликовано 12 сентября, 2010 Автор Жалоба Поделиться Опубликовано 12 сентября, 2010 Язык MetaQuotes Language 4В клиентский терминал встроен язык программирования торговых стратегий MetaQuotes Language 4 (MQL 4). Он позволяет писать собственные советники, автоматизирующие управление торговыми процессами и идеально подходящие для реализации собственных торговых стратегий. Кроме того, на MQL 4 можно создавать собственные пользовательские индикаторы, скрипты и библиотеки функций. Синтаксис MQL 4 очень похож на синтаксис языка Си, он прост в изучении и использовании. В состав MQL 4 включено большое количество функций, необходимых для анализа котировок, управления позициями, вызова технических индикаторов и других. Для написания исходного текста программ используется редактор советников MetaEditor. В редактор встроен словарь MetaQuotes Language Dictionary, содержащий описания всех конструкций языка и функций. Программы, написанные на MQL 4, имеют различные свойства и предназначение: Советник — это механическая торговая система (МТС), запускающаяся с приходом нового тика. Он может не только работать в режиме информирования о торговых сигналах, но также самостоятельно совершать торговые операции. Терминал поддерживает тестирование стратегий на исторических данных, что позволяет выявить особенности поведения советника в различных рыночных условиях; Пользовательский индикатор — самостоятельно написанный технический индикатор. Пользовательские индикаторы используются только для анализа динамики цен; Скрипт — программы, предназначенные для одноразового выполнения каких-либо действий. В отличие от экспертов, скрипты запускаются не потиково, а по команде. Ссылка на комментарий Поделиться на другие сайты Поделиться
v.perevedentsev Опубликовано 12 сентября, 2010 Автор Жалоба Поделиться Опубликовано 12 сентября, 2010 СоветникиСоветниками (экспертами) в терминале называются программы, разработанные на языке программирования MetaQuotes Language 4 (MQL 4), с помощью которых автоматизируются аналитические и торговые процессы. Они позволяют оперативно проводить технический анализ ценовых данных и на основе полученных сигналов управлять торговой деятельностью. На советников можно возложить всю рутинную работу по проведению технического анализа и выполнению всех торговых операций. Советник может совершать аналитические и торговые операции по любым финансовым инструментам и периодам независимо от того, открыт соответствующий график или нет. Работа с советниками предполагает: Создание экспертаДля создания и компиляции советника используется встроенный редактор "MetaEditor". Он является составной частью клиентского терминала и представляет собой удобную среду разработки MQL4-программ. Настройка работы советниковПеред началом использования советников необходимо произвести их предварительную настройку. Общие для всех экспертов параметры работы задаются в окне настройки клиентского терминала. Кроме того, каждый советник обладает своими собственными настройками. Запуск экспертаДля запуска эксперта необходимо наложить его на график. С приходом нового тика эксперт начинает исполняться. Завершение работы экспертаЗавершение работы советника происходит, когда он удаляется с графика. Ссылка на комментарий Поделиться на другие сайты Поделиться
v.perevedentsev Опубликовано 12 сентября, 2010 Автор Жалоба Поделиться Опубликовано 12 сентября, 2010 Пример создания эксперта Принципы построения пользовательских программ на языке MQL 4 рассматриваются на примере создания простейшей экспертной системы на основе стандартного индикатора MACD. В данной экспертной системе также рассмотрены примеры реализации таких функций как выставление уровней тейкпрофита с поддержкой трейлинг-стопа и большинство предохраняющих условий для безопасной работы. В предлагаемом примере торговля идет с открытием и контролем одной позиции. Принципы торговли: ■вход в Long (BUY) – индикатор MACD ниже нуля, идет снизу вверх, а его сверху вниз пересекает сигнальная линия. http://s51.radikal.ru/i131/1009/2f/308a17b045f8.png ■вход в Short (SELL) – индикатор MACD выше нуля, идет cверху вниз, а его снизу вверх пересекает сигнальная линия. http://s58.radikal.ru/i162/1009/54/c7de0fa58dcc.png ■выход из Long – по тейкпрофиту, по трейлинг-стопу или при пересечении MACD со своей сигнальной линией (MACD выше нуля, идет cверху вниз, а его снизу вверх пересекает сигнальная линия). ■выход из Short – по тейкпрофиту, по трейлинг-стопу или при пересечении MACD со своей сигнальной линией (MACD ниже нуля, идет снизу вверх, а его сверху вниз пересекает сигнальная линия). Важное замечание: Для исключения из анализа незначительных(мелкие 'бугорки' на графике) изменений индикатора MACD введем дополнительный контроль за размером рисуемых 'бугров' в виде следующего условия – величина индикатора должна составлять не менее 5 единиц минимальной цены (5*Point, что для USD/CHF равно 0.0005, для USD/JPY = 0.05). http://s003.radikal.ru/i204/1009/96/1e43b47477bf.png 1-й этап – создание описания экспертаВ окне "Navigator" устанавливаем курсор мыши на разделе "Expert Advisors", нажимаем на правую кнопку мыши и в появившемся меню выбираем команду "Create". Мастер первоначальных настроек эксперта предложит ввести некоторые данные: "Name" – название программы, "Author" – автор программы, "Link" – ссылка на веб-сайт. http://s51.radikal.ru/i134/1009/43/ed622ce3bca5.png 2-й этап – создание первичной структуры программы Код тестового эксперта будет занимать всего несколько страниц, но и такой объем зачастую бывает труден для восприятия. Особенно, если мы с вами не профессиональные программисты... Так ведь? Иначе этого описания не пришлось бы писать :) Для ознакомления со структурой стандартного эксперта взглянем на предлагаемое описание: 1.Инициализация переменных 2.Первичные проверки данных ■проверка графика, количество баров на графике ■проверка значений внешних переменных Lots, S/L, T/P, T/S 3.Установка внутренних переменных для быстрого доступа к данным 4.Проверка торгового терминала – пустой ли? Eсли да, то: ■проверки: если ли деньги на счету и тд... ■можно встать в длинную позицию(BUY)? ■открыть длинную позицию и выйти ■можно встать в короткую позицию(SELL)? ■открыть короткую позицию и выйти выход из эксперта... 5.Контроль открытых ранее позиций в цикле ■если это длинная позиция ■нужно ли закрыть? ■нужно ли передвинуть трейлинг-стоп? ■если это короткая позиция ■нужно ли закрыть? ■нужно ли передвинуть трейлинг-стоп? Получилось достаточно просто, всего 4 основных блока. Теперь попробуем по шагам сформировать куски кода под каждый раздел структурной схемы: 1.Инициализация переменныхВсе переменные, которые будут использоваться в программе-эксперте, должны быть предварительно описаны в соответствии с синтаксисом языка MetaQuotes Language 4. Поэтому в начале программы вставляем блок инициализации переменных extern double TakeProfit = 50;extern double Lots = 0.1;extern double TrailingStop = 30;extern double MACDOpenLevel=3;extern double MACDCloseLevel=2;extern double MATrendPeriod=26; В MetaQuotes Language 4 введено такое понятие, как дополнительные пользовательские переменные, которые могут быть установлены извне, без вмешательства в исходный текст программы-эксперта. Это придает дополнительную гибкость. Переменная MATrendPeriod как раз и является такой пользовательской переменной. В начале программы вставляем описание этой переменной. extern double MATrendPeriod=26; 2.Первичные проверки данныхЭтот кусок кода обычно кочует из одного эксперта в другой с мелкими изменениями – практически стандартный блок проверок: // первичные проверки данных// важно удостовериться что эксперт работает на нормальном графике и// пользователь правильно выставил внешние переменные (Lots, StopLoss,// TakeProfit, TrailingStop)// в нашем случае проверяем только TakeProfit if(Bars<100) { Print("bars less than 100"); return(0); } if(TakeProfit<10) { Print("TakeProfit less than 10"); return(0); // проверяем TakeProfit } 3.Установка внутренних переменных для быстрого доступа к данным В коде программы приходится достаточно часто обращаться к значениям индикаторов или оперировать вычисляемыми значениями. int start() { double MacdCurrent, MacdPrevious, SignalCurrent; double SignalPrevious, MaCurrent, MaPrevious; int cnt, ticket, total; Для облегчения кодирования и ускорения доступа применяется предварительное помещение данных во внутренние переменные. MacdCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0); MacdPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,1); SignalCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,0); SignalPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,1); MaCurrent=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,0); MaPrevious=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,1); Теперь вместо громадной записи iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0) в тексте программы можно использовать MacdCurrent. 4.Проверка торгового терминала – пустой ли? Если да, то:В нашем эксперте мы используем только позиции, открытые по маркету и не трогаем отложенные ордеры. Но для безопасности лучше внесем проверку торгового терминала на наличие выставленных ордеров: // теперь надо определиться - в каком состоянии торговый терминал?// проверим, есть ли ранее открытые позиции или ордеры? total=OrdersTotal(); if(total<1) {■проверки: если ли деньги на счету и тд... Перед анализом рыночной ситуации желательно проверить состояние своего счета – есть ли свободные деньги для открытия позиции? // нет ни одного открытого ордера // на всякий случай проверим, если у нас свободные деньги на счету? // значение 1000 взято для примера, обычно можно открыть 1 лот if(AccountFreeMargin()<(1000*Lots)) { Print("We have no money. Free Margin = ", AccountFreeMargin()); return(0); }■проверка возможности встать в длинную позицию (BUY) Условие входа в длинную позицию: MACD ниже нуля, идет снизу вверх, а его сверху вниз пересекает сигнальная линия. Как это записывается на MQL 4 (обратите внимание что работа идет с сохраненными ранее в переменных значениями индикаторов): // проверяем на возможность встать в длинную позицию (BUY) if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MathAbs(MacdCurrent)>(MACDOpenLevel*Point) && MaCurrent>MaPrevious) { ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0, Ask+TakeProfit*Point,"macd sample", 16384,0,Green); if(ticket>0) { if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) Print("BUY order opened : ",OrderOpenPrice()); } else Print("Error opening BUY order : ",GetLastError()); return(0); } Выше говорилось о дополнительном контроле за размером рисуемых 'бугров'. Переменная MACDOpenLevel является 'пользовательской' переменной, которую можно менять, не трогая текста программы, для гибкости контроля. В начале программы вставляем описание этой переменной (заодно и описание переменной, используемой ниже). ■проверка возможности встать в короткую позицию (SELL) Условие входа в короткую позицию: MACD выше нуля, идет сверху вниз, а его снизу вверх пересекает сигнальная линия. Как это записывается: // проверяем на возможность встать в короткую позицию (SELL) if(MacdCurrent>0 && MacdPrevious>SignalPrevious && MacdCurrent>(MACDOpenLevel*Point) && MaCurrent { ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,3,0, Bid-TakeProfit*Point,"macd sample", 16384,0,Red); if(ticket>0) { if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) Print("SELL order opened : ",OrderOpenPrice()); } else Print("Error opening SELL order : ",GetLastError()); return(0); } // здесь мы завершили проверку на возможность открытия новых позиций. // новые позиции открыты не были и просто выходим return(0); } 5.Контроль открытых ранее позиций в цикле // переходим к важной части эксперта - контролю открытых позиций // 'важно правильно войти в рынок, но выйти - еще важнее...' for(cnt=0;cnt { OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES); if(OrderType()<=OP_SELL && // это открытая позиция? OP_BUY или OP_SELL OrderSymbol()==Symbol()) // инструмент совпадает? {"Cnt" – это переменная цикла, которая должна быть описана в начале программы следующим образом : int cnt = 0; ■Eсли это длинная позиция if(OrderType()==OP_BUY) // открыта длинная позиция {■нужно ли закрыть?Условие выхода из длиной позиции: при пересечении MACD со своей сигнальной линией, когда MACD выше нуля, идет вверху вниз, а его снизу вверх пересекает сигнальная линия. // проверим, может уже пора закрываться?if(MacdCurrent>0 && MacdCurrent && MacdPrevious>SignalPrevious && MacdCurrent>(MACDCloseLevel*Point)) { OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); // закрываем позицию return(0); // выходим }■нужно ли передвинуть трейлинг-стоп? Трейлинг-стоп выставляем только тогда, когда у позиции уже есть прибыль, превышающая величину трейлинг-стопа в пунктах и если новый уровень стопа лучше предыдущего. // проверим - может можно/нужно уже трейлинг стоп ставить?if(TrailingStop>0) { if(Bid-OrderOpenPrice()>Point*TrailingStop) { if(OrderStopLoss() { OrderModify(OrderTicket(),OrderOpenPrice(), Bid-Point*TrailingStop,OrderTakeProfit(),0,Green); return(0); } } }Закрываем операторную скобку }■Eсли это короткая позиция else // иначе это короткая позиция {■нужно ли закрыть?Условие выхода из короткой позиции: при пересечении MACD со своей сигнальной линией, когда MACD ниже нуля, идет снизу вверх, а его сверху вниз пересекает сигнальная линия. // проверим, может уже пора закрываться?if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious MathAbs(MacdCurrent)>(MACDCloseLevel*Point)) { OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet); // закрываем позицию return(0); // выходим } ■нужно ли передвинуть трейлинг-стоп?Трейлинг-стоп выставляем только тогда, когда у позиции уже есть прибыль, превышающая величину трейлинг-стопа в пунктах и если новый уровень стопа лучше предыдущего. // проверим - может можно/нужно уже трейлинг стоп ставить?if(TrailingStop>0) { if((OrderOpenPrice()-Ask)>(Point*TrailingStop)) { if((OrderStopLoss()>(Ask+Point*TrailingStop)) || (OrderStopLoss()==0)) { OrderModify(OrderTicket(),OrderOpenPrice(), Ask+Point*TrailingStop,OrderTakeProfit(),0,Red); return(0); } } } Закрываем все оставшиеся открытые операторные скобки } } } return(0); }Вот так, шаг за шагом и написан эксперт... 3-й этап – сборка результирующего кода программы Откроем настройки эксперта (кнопка F7 или строка меню "Properties..."). Перед нами появится окно, в котором необходимо выставить внешние настройки параметров работы: http://s49.radikal.ru/i124/1009/8c/38d17a746fa7.png Соберем весь код из предыдущего раздела воедино... //+------------------------------------------------------------------+//| MACD Sample.mq4 |//| Copyright © 2005, MetaQuotes Software Corp. |//| http://www.metaquotes.net/ |//+------------------------------------------------------------------+ extern double TakeProfit = 50;extern double Lots = 0.1;extern double TrailingStop = 30;extern double MACDOpenLevel=3;extern double MACDCloseLevel=2;extern double MATrendPeriod=26;//+------------------------------------------------------------------+//| |//+------------------------------------------------------------------+int start() { double MacdCurrent, MacdPrevious, SignalCurrent; double SignalPrevious, MaCurrent, MaPrevious; int cnt=0, ticket, total;// первичные проверки данных// важно удостовериться что эксперт работает на нормальном графике и// пользователь правильно выставил внешние переменные (Lots, StopLoss,// TakeProfit, TrailingStop)// в нашем случае проверяем только TakeProfit if(Bars<100) { Print("bars less than 100"); return(0); } if(TakeProfit<10) { Print("TakeProfit less than 10"); return(0); // проверяем TakeProfit }// ради упрощения и ускорения кода, сохраним необходимые// данные индикаторов во временных переменных MacdCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0); MacdPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,1); SignalCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,0); SignalPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,1); MaCurrent=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,0); MaPrevious=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,1); total=OrdersTotal(); if(total<1) { // нет ни одного открытого ордера if(AccountFreeMargin()<(1000*Lots)) { Print("We have no money. Free Margin = ", AccountFreeMargin()); return(0); } // проверяем на возможность встать в длинную позицию (BUY) if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious<SignalPrevious && MathAbs(MacdCurrent)>(MACDOpenLevel*Point) && MaCurrent>MaPrevious) { ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,Ask+TakeProfit*Point, "macd sample",16384,0,Green); if(ticket>0) { if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) Print("BUY order opened : ",OrderOpenPrice()); } else Print("Error opening BUY order : ",GetLastError()); return(0); } // проверяем на возможность встать в короткую позицию (SELL) if(MacdCurrent>0 && MacdCurrent<SignalCurrent && MacdPrevious>SignalPrevious && MacdCurrent>(MACDOpenLevel*Point) && MaCurrent<MaPrevious) { ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,3,0,Bid-TakeProfit*Point, "macd sample",16384,0,Red); if(ticket>0) { if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) Print("SELL order opened : ",OrderOpenPrice()); } else Print("Error opening SELL order : ",GetLastError()); return(0); } return(0); } // переходим к важной части эксперта - контролю открытых позиций // 'важно правильно войти в рынок, но выйти - еще важнее...' for(cnt=0;cnt<total;cnt++) { OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES); if(OrderType()<=OP_SELL && // это открытая позиция? OP_BUY или OP_SELL OrderSymbol()==Symbol()) // инструмент совпадает? { if(OrderType()==OP_BUY) // открыта длинная позиция { // проверим, может уже пора закрываться? if(MacdCurrent>0 && MacdCurrent<SignalCurrent && MacdPrevious>SignalPrevious && MacdCurrent>(MACDCloseLevel*Point)) { OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); // закрываем позицию return(0); // выходим } // проверим - может можно/нужно уже трейлинг стоп ставить? if(TrailingStop>0) { if(Bid-OrderOpenPrice()>Point*TrailingStop) { if(OrderStopLoss()<Bid-Point*TrailingStop) { OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop, OrderTakeProfit(),0,Green); return(0); } } } } else // иначе это короткая позиция { // проверим, может уже пора закрываться? if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious<SignalPrevious && MathAbs(MacdCurrent)>(MACDCloseLevel*Point)) { OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet); // закрываем позицию return(0); // выходим } // проверим - может можно/нужно уже трейлинг стоп ставить? if(TrailingStop>0) { if((OrderOpenPrice()-Ask)>(Point*TrailingStop)) { if((OrderStopLoss()>(Ask+Point*TrailingStop)) || (OrderStopLoss()==0)) { OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Point*TrailingStop, OrderTakeProfit(),0,Red); return(0); } } } } } } return(0); }// конец. Для финальной настройки эксперта необходимо лишь указать значения внешних переменных "Lots = 1", "Stop Loss (S/L) = 0" (не используется), "Take Profit (T/P) = 120" (для часовок подходит), "Trailing Stop (T/S) = 30". Конечно же, значения вы можете поставить свои.Нажмите на кнопку "Compile" и, если не обнаружатся ошибки (кстати, в редактор MetaEditor можно скопировать текст из вышеприведенной распечатки программы), нажмите на кнопку "Save", чтобы эксперт сохранился. Ссылка на комментарий Поделиться на другие сайты Поделиться
v.perevedentsev Опубликовано 12 сентября, 2010 Автор Жалоба Поделиться Опубликовано 12 сентября, 2010 Пользовательские индикаторыПользовательским индикатором называется программа, самостоятельно разработанная пользователем на языке MetaQuotes Language 4 и выполняющая функцию технического индикатора. Техническим индикатором называется математическое преобразование цены и/или объемов финансового инструмента для прогнозирования будущих изменений цен. Использование индикаторов позволяет ответить на вопросы о том, сохранится ли текущая тенденция и где произойдет разворот тренда. Индикаторы предназначены для того, чтобы сделать сложный процесс принятия торговых решения относительно простым и понятным. На основе алгоритмов индикаторов строятся торговые тактики и разрабатываются советники. Внимание: пользовательские индикаторы предназначены только для анализа динамики цен финансовых инструментов, но не для совершения торговых операций.Работа с пользовательскими индикаторами предполагает: Создание индикатораДля создания и компиляции пользовательского индикатора используется встроенный редактор "MetaEditor". Он является составной частью клиентского терминала и представляет собой удобную среду разработки MQL4-программ. Настройка работы индикатораПеред началом использования пользовательских индикаторов необходимо произвести их предварительную настройку. Общие для всех индикаторов параметры работы задаются в окне настройки клиентского терминала. Кроме того, каждый индикатор обладает своими собственными настройками. Наложение индикатораПри наложении индикатора на график просчитываются его параметры и осуществляется его отрисовка. Удаление индикатораЕсли индикатор больше не нужен, его можно удалить с графика. Ссылка на комментарий Поделиться на другие сайты Поделиться
v.perevedentsev Опубликовано 12 сентября, 2010 Автор Жалоба Поделиться Опубликовано 12 сентября, 2010 Пример создания собственного индикатора Запускаем Meta Editor, выбираем Файл->Создать:Появляется окно Мастера создания советника, выбираем Пользовательский индикатор, нажимаем Далее: http://s49.radikal.ru/i123/1009/51/0599764761b8.png Заполняем поля Имя, Автор и Ссылка. Тут все как обычно, но теперь вы можете добавлять параметры. Что же это такое?? Параметры - это обычные переменные, которые может настраивать пользователь. И что очень важно, эти переменные можно использовать в коде индикатора. Назначение параметров очевидно - вы позволяете пользователям настраивать некоторые аспекты работы индикатора. Это может быть что угодно. Например: какой таймфрейм использовать, в каком режиме работать, сколько баров брать для усреднения и т.д. Сейчас (для наглядного примера) мы добавим параметр, который будет указывать, сколько баров должно обрабатываться для расчета показателя нашего индикатора. Где это может быть использовано?? Представьте, например, что ваш индикатор серьезно нагружает процессор, так как проводит много сложных вычислений. При этом вы часто меняете таймфрейм графика и просматриваете лишь 100-200 последних баров. Зачем в таком случае проводить лишние вычисления и ждать несколько лишних секунд?? Вот тут нас и выручит этот параметр. Конечно, в нашем индикаторе не будет ничего сложного и затратного для ресурсов компьютера. Это просто один из вариантов использования параметров индикатора. Итак, чтобы добавить параметр нужно нажать на кнопку Добавить (1). После этого вы можете изменить название переменной на что-нибудь более подходящее (2). В нашем случае меняем название на barsToProcess (баров для обработки). Также вы можете изменить начальное значение (3), то есть значение по умолчанию. Меняем на 100. Кроме того, вы можете изменить тип переменной, но в нашем случае ничего менять не нужно, так как тип int идеально подходит для наших целей. После внесения всех необходимых изменений нажимаем Далее: http://s003.radikal.ru/i203/1009/37/90f840803dfb.png Почти все готово. Теперь нужно указать, как рисовать индикатор: в отдельном окне или в окне графика цен. Также вы можете ограничить диапазон. Ставим галочку напротив Индикатор в отдельном окне. Ниже мы видим пустое поле Индексы(буферы данных). Здесь вы можете добавить, сколько вам нужно буферов данных (максимум 8). Кроме того, вы всегда сможете добавить или убрать буфера позже, изменив код. Нажимаем Добавить, чтобы добавить один буфер. Теперь вы можете изменить то, как будет отображаться буфер: обычная линия, гистограмма, отрезки или стрелки (символы). Оставим все как есть, то есть тип - Line. Настройте цвет для рисования этого буфера. Нажимаем Готово: http://s56.radikal.ru/i154/1009/33/bb3a7d2eb0c9.png Вуаля!! Ваш первый индикатор готов! Ну и что, что он ничего не рисует, зато сколько кода. Файл с исходным кодом будет размещен в папке с индикаторами: MetaTrader4\experts\indicators. Разбираем каждую строчкуА теперь давайте посмотри, что для нас создал Meta Editor: //+------------------------------------------------------------------+//| myFirstIndicator.mq4 |//| ХХХХХХХХХХХХХ|//| ХХХХХХХХХХХХХХ |//+------------------------------------------------------------------+ Как всегда, "шапка" из однострочных комментариев включает введенные ранее вами данные. Очень мило, смотрим дальше: #property copyright "ХХХХХХХХХХХ" Это еще одна директива. Она используется для того, чтобы указать какие-то специфические свойства индикатора. В нашем случае, чтобы указать авторство. Обратите внимание, что сначала идет специальный знак - # (решетка), потом ключевое слово property (без пробела). Property означает свойство. Дальше идет конкретное свойство, которое мы хотим задать, в нашем случае copyright, а потом значение этого свойства. В нашем случае - это строка с вашим именем. С помощью директивы #property можно настроить много специфических аспектов индикатора, в чем вы сейчас убедитесь. Все эти свойства будут заданы по умолчанию. Смотрим дальше: #property link "ХХХХХХХХХХХ" Эта директива указывает, как можно связаться с автором. Вы можете спросить: где же эти данные (имя автора, как связаться), они ведь нигде не отображаются? Да, не отображаются, но они "прошиваются" в исполняемый файл. Если просмотреть исполняемый файл как обычный текст, то вы сможете увидеть эти данные. Смотрим дальше: #property indicator_separate_window Эта директива указывает, что индикатор должен рисоваться в отдельном подокне. Как видите, никаких дополнительных параметров не указывается, как, например, в предыдущей директиве. #property indicator_buffers 1 Эта директива указывает, сколько буферов данных будет использовать индикатор. Как вы заметили, директивы чем-то похожи на обычные функции: Они тоже принимают какие-то параметры и что-то делают в ответ. Но есть важное отличие: директивы выполняются в первую очередь (еще до начала компиляции). #property indicator_color1 DarkOrchid Указываем цвет по умолчанию для первого буфера. Обратите внимание, что нумерация буферов в директивах начинается с единицы, а не с нуля. Постарайтесь запомнить это, чтобы в дальнейшем не возникало никакой путаницы. Цвет указывается с помощью одного из множества предопределенных названий. Посмотреть ключевые слова для всех доступных цветов можно в справке: Справочник MQL4 -> Стандартные константы -> Набор Web-цветов. Аналогично можно указать цвет и для других буферов, нужно просто изменить номер буфера. extern int barsToProcess=100; Это наш параметр индикатора. Мы его настраивали в Мастере. Обратите внимание, что единственное отличие от обычной переменной - это наличие ключевого слова extern перед типом переменной. Вот как будет выглядеть этот параметр для пользователя при запуске индикатора: http://s53.radikal.ru/i140/1009/77/50f29fc6287c.png Смотри далее: double ExtMapBuffer1[]; Это обычный массив. Просто не указывается размерность и не выполняется инициализация. Этот массив в дальнейшем будет настроен как буфер данных. Дальше у нас идет объявление и описание функций. В отличие от привычного для вас скрипта, в каждом индикаторе имеется 3, а не 1 функция: ■init() - эта функция вызывается терминалом только один раз, когда вы запускаете индикатор. Ее назначение: подготовить индикатор для работы. Настроить буфера данных, проверить параметры (мало ли что там мог пользователь ввести) и другие подготовительные действия. Эта функция не является обязательной. Если вы не выполняете никакого кода в ней, то можете ее просто удалить. ■deinit() - эта функция также вызывается только один раз, когда вы удаляете индикатор с графика. В ней вы должны подготовить индикатор для завершения работы. Например, закрыть открытые файлы, удалить графические объекты с графика (не переживайте, еще научитесь). Эта функция также необязательная. ■start() - эта функция в отличие от скриптов, в индикаторе вызывается каждый тик. То есть, как только поступают новые котировки от валютной пары, к графику которой вы применили индикатор, так и будет сразу вызвана эта функция. Кроме того, эта функция вызывается при первом запуске индикатора, то есть после функции init(). Посмотрим, что происходит в каждой функции: int init(){ SetIndexStyle(0,DRAW_LINE); SetIndexBuffer(0,ExtMapBuffer1); return(0);} Здесь у нас вызываются 2 важные функции для настройки буфера данных: SetIndexStyle(0,DRAW_LINE); Эта функция задает, каким образом рисовать буфер данных. Первый параметр указывает, к какому буферу применить изменение. Обратите внимание, что в этой функции (и подобной ей) нумерация буферов начинается с нуля, а не с единицы как в директивах. Это важный момент, смотрите не наломайте дров. Второй параметр указывает, как рисовать выбранный буфер. В нашем случае используется константа DRAW_LINE, которая указывает, что буфер следует рисовать в виде линии. Конечно, имеются и другие константы, но к ним мы вернемся позже. SetIndexBuffer(0,ExtMapBuffer1); Эта функция "привязывает" массив к номеру буфера. То есть она указывает, что буфер с указанным номером будет использовать указанный массив для хранения данных. Таким образом, в результате, изменяя элементы этого массива, вы будете изменять значения самого буфера. Фактически массив - это и есть буфер данных. Первый аргумент - номер буфера, к которому нужно привязать массив (нумерация с нуля). Второй аргумент - название массива, который следует привязать. return(0); Завершение функции, возвращаем нуль - инициализация прошла успешно. int deinit(){//---- //---- return(0);} Функция деинициализации по умолчанию пуста. int start(){ int counted_bars=IndicatorCounted();//---- //---- return(0);} Вот мы и добрались до самой главной функции. Весь основной код размещается здесь. Обратите внимание, что заранее объявлена переменная counted_bars (посчитанные бары), которая инициализируется функцией IndicatorCounted(). Эта переменная обычно используется для оптимизации и ускорения работы индикатора, о чем мы поговорим позже. А сейчас давайте наконец-то что-то нарисуем в окне индикатора! Дописываем индикаторОпределимся что выводить. Что вообще нам будет показывать индикатор? Что-нибудь простое. Для начала давайте рисовать случайные числа. А что?? Этот индикатор гарантирует вам 50% прибыльных сигналов. Решено. Идем к нашей функции init() и дописываем код для инициализации генератора случайных чисел: int init(){ SetIndexStyle(0,DRAW_LINE); SetIndexBuffer(0,ExtMapBuffer1); // инициализация генератора случайных чисел MathSrand(TimeLocal()); return(0);} Инициализация готова, переходим к функции start(): int start(){ int counted_bars=IndicatorCounted(); for(int i=0;i<Bars;i++) { ExtMapBuffer1=MathRand()%1001; } return(0);} Компилируем - F7. Запускаем терминал, находим панель Навигатор, выбираем раздел Пользовательские Индикаторы и делаем двойной клик на названии нашего индикатора: http://s43.radikal.ru/i100/1009/ff/b8a3a9cb8c69.png Индикатор будет добавлен к активному графику: http://s001.radikal.ru/i194/1009/df/f1f13da23b67.png Как видите, все работает, теперь давайте хорошенько разберемся, что делает этот код: for(int i=0;i<Bars;i++) Мы используем цикл for для того, чтобы пройтись по всем элементам буфера данных. Так как каждому элементу буфера соответствует определенный бар, то мы используем цикл, начиная проход с нулевого бара (последнего доступного) и заканчиваем первым доступным, который по счету меньше на единицу, чем переменная Bars (потому что мы считаем бары с нуля). { ExtMapBuffer1=MathRand()%1001;} Каждую итерацию счетчик увеличивается на единицу, и мы двигаемся от последнего до первого доступного бара и одновременно присваиваем каждому элементу буфера (который соответствует своему бару) случайное число от 0 до 1000. Если вам сложно понять, как каждому элементу буфера соответствует свой бар, то попробуйте изменить цикл следующим образом и посмотрите на результат в терминале: for(int i=0;i<Bars;i++){ ExtMapBuffer1=i;} Теперь индикатор будет показывать номер каждого бара, посмотрите: http://s08.radikal.ru/i181/1009/dd/9c85d22d5504.png Как видите, номер бара постепенно увеличивается от последнего к первому (от 0 до Bars). Надеюсь теперь вы поняли, каким образом элементы буфера данных соответствуют барам на графике. Давайте вернемся к коду "случайного" индикатора. Если бы вы начали использовать его хотя бы на протяжении нескольких минут, то заметили бы, что каждый тик индикатор будет рисовать абсолютно другой график. То есть каждый тик индикатор выполняет повторные вычисления того, что мы уже посчитали в прошлый раз. Нам это будет неудобно хотя бы потому, что мы не будем видеть даже то, что было тик назад. Но дело даже не в этом, потому что такой индикатор никто использовать не будет - мы всего лишь учимся. Дело в другом. Представьте, что ваш индикатор выполняет очень много сложных вычислений и расчет одного бара занимает много ресурсов процессора. В таком случае, когда появится новая цена, ваш индикатор снова и снова будет рассчитывать показатель для каждого доступного бара, даже если это уже происходило раньше. Понимаете? Вместо того, чтобы один раз посчитать, он будет делать это снова и снова. Устранение подобных проблем, которые связаны с нерациональным использованием ресурсов и называется оптимизацией. Как же решить эту проблему? Обычно поступают следующим образом. Сначала индикатор рассчитывается на всех доступных свечах, а уже потом по мере поступления котировок, будет пересчитываться показатель только для последней свечи. То есть поступаем рационально - никаких лишних телодвижений. Давайте оптимизируем функцию start(), чтобы она работала именно так: int start(){ int counted_bars=IndicatorCounted(), limit; if(counted_bars>0) counted_bars--; limit=Bars-counted_bars; for(int i=0;i<limit;i++) { ExtMapBuffer1=MathRand()%1001; } return(0);} Разбираем каждую строку: int counted_bars=IndicatorCounted(), Объявляем переменную counted_bars, которая будет хранить количество посчитанных индикатором баров. На самом деле функция IndicatorCounted() возвращает количество неизмененных баров после прошлого вызова функции start(). Таким образом, если это первый вызов функции start(), то IndicatorBars() возвратит нам 0, так как все бары для нас новые. Если же, это не первый вызов, то очевидно, что изменился только последний бар, поэтому IndicatorBars() возвратит число равное Bars-1. limit; Еще одна переменная, которая будет использована как ограничитель, то есть позволит циклу завершиться раньше, пропуская уже пересчитанные свечи. if(counted_bars>0) counted_bars--; Как уже было сказано, если IndicatorCounted() возвращает 0, то это значит, что функция start() вызывается впервые и все бары для нас "новые" (еще не рассчитывался индикатор для них). Но если это не первый вызов start(), то нам будет возвращено значение равное Bars-1. Так вот, это условие отслеживает как раз такую ситуацию. После чего мы уменьшаем переменную counted_bars на 1. Зачем это делается, ведь измениться может лишь последний бар?? Оказывается, что бывают ситуации, при которых последний тик предыдущего бара оказывается необработанным из-за того, что в момент прихода этого последнего тика обрабатывался предпоследний тик. Поэтому пользовательский индикатор не был вызван и не был рассчитан. Именно поэтому мы уменьшаем на 1 переменную counted_bars, чтобы исключить эту ситуацию. limit=Bars-counted_bars; Здесь мы присваиваем переменной limit (ограничителю) количество последних баров, которые нужно пересчитать. Так как в переменной counted_bars хранится количество свечей, которые уже рассчитаны, то мы просто находим разницу между Bars (всего доступных баров) и counted_bars, чтобы определить, сколько свечей необходимо пересчитать. for(int i=0;i<limit;i++){ ExtMapBuffer1=MathRand()%1001;} Сам цикл почти не изменился. Мы всего лишь поменяли условие выполнения. Теперь цикл будет выполняться пока счетчик i меньше чем ограничитель limit. Теперь оптимизация завершена. Если вы понаблюдаете за обновленной версией индикатора, то заметите, что при приходе нового тика изменяется показатели лишь для последних баров. Приучите себя всегда использовать такую оптимизацию, даже если ваш индикатор не вычисляет ничего сложного. Это просто хороший тон. Вы еще не забыли про параметр индикатора (barsToProcess), который мы добавили в мастере. Сейчас самое время чтобы его задействовать. Нужно добавить всего пару строк перед циклом: int start(){ int counted_bars=IndicatorCounted(), limit; if(counted_bars>0) counted_bars--; limit=Bars-counted_bars; if(limit>barsToProcess) limit=barsToProcess; for(int i=0;i<limit;i++) { ExtMapBuffer1=MathRand()%1001; } return(0);} Как видите, все достаточно тривиально. Мы проверяем или больше limit чем barsToProcess и если да, то уменьшаем ограничитель через присваивание. В результате, если установить barsToProcess=100, то вы сможете наблюдать похожую картину: http://s49.radikal.ru/i125/1009/d4/459110bf43b9.png Как видите, рассчитывается только определенное нами количество баров. Наш индикатор практически готов. Но у нас нет четких сигналов для входа в рынок. Поэтому нужно добавить определенности. Для этой цели нам подойдут уровни. Уровни - это горизонтальные линии, которые рисуются индикатором определенным стилем, цветом и толщиной. Важно отметить, что максимальное количество уровней на одном баре: 8. Кроме того вы можете задавать уровни как с помощью директив, так и используя функции. Предпочтительнее использовать первый вариант, если вы собираетесь настроить уровни по умолчанию. Для динамического изменения уровней во время работы индикатора используйте функции. Итак, разместим 2 уровня: первый на отметке 800, второй - 200. Для этого добавим несколько директив в начале кода индикатора: //+------------------------------------------------------------------+//| myFirstIndicator.mq4 |//| Antonuk Oleg |//| banderass@i.ua |//+------------------------------------------------------------------+#property copyright "Antonuk Oleg"#property link "banderass@i.ua" #property indicator_level1 800.0#property indicator_level2 200.0#property indicator_levelcolor LimeGreen#property indicator_levelwidth 2#property indicator_levelstyle 0 #property indicator_separate_window Разберемся в новых директивах: #property indicator_level1 800.0 Эта директива указывает, что уровень номер 1 следует разместить на отметке 800.0. Обратите внимание, что нумерация буферов начинается с единицы, подобно тому, как это сделано в директивах для настройки буферов. Чтобы настроить другой уровень, следует просто поменять номер уровня в конце директивы: #property indicator_level2 200.0 Есть важное ограничение в настройке внешнего вида уровней. Вы не можете настроить каждый уровень индивидуально. Все настройки применяются ко всем уровням без исключений. Если вам нужно настроить каждый уровень индивидуально, то вам нужно использовать объекты (а сами уровни вообще не использовать), о которых мы поговорим в следующей статье. #property indicator_levelcolor LimeGreen Эта директива устанавливает цвет, который будет использоваться для рисования всех уровней. #property indicator_levelwidth 2 Эта директива задает толщину для рисования линий всех уровней. Вы можете установить толщину в пределах от 1 до 5. Вы должны помнить, что, если толщина уровня больше 1, то уровни будут рисоваться только сплошной линией. Если вам нужен другой стиль рисования уровней, то вы должны использовать только единичную толщину. #property indicator_levelstyle STYLE_SOLID Эта директива задает стиль для рисования линии. Доступны такие предопределенные константы: ■STYLE_SOLID - сплошная линия■STYLE_DASH - штриховая линия■STYLE_DOT - пунктирная линия■STYLE_DASHDOT - штрих-пунктирная линия■STYLE_DASHDOTDOT - штрих-пунктирная линия с двойными точками http://s53.radikal.ru/i139/1009/f9/302f5e32c016.png На этом разработка нашего "случайного" индикатора закончена. Давайте сохраним исходный файл с более подходящим названием - randomIndicator.mq4. Перекомпилируйте исходники еще раз. В следующем разделе этот индикатор нам еще пригодиться. Финальная версия с уровнями должна выглядеть примерно так: http://s60.radikal.ru/i167/1009/86/16e1e319ce3b.png Ссылка на комментарий Поделиться на другие сайты Поделиться
v.perevedentsev Опубликовано 12 сентября, 2010 Автор Жалоба Поделиться Опубликовано 12 сентября, 2010 Скрипты Скриптом называется программа, написанная на языке MetaQuotes Language 4 (MQL 4) и предназначенная для одноразового выполнения любых действий. Скрипт может выполнять как аналитические, так и торговые функции. В отличие от советников, скрипты исполняются по запросу, а не потиково. Иными словами, если советник работает практически постоянно, то скрипт, отработав один раз, самостоятельно завершает работу. Работа со скриптами предполагает: Создание скриптаДля создания и компиляции скрипта используется встроенный редактор "MetaEditor". Он является составной частью клиентского терминала и представляет собой удобную среду разработки MQL4-программ. Настройка работы скриптовПеред началом использования скриптов необходимо произвести их предварительную настройку. Общие для всех скриптов параметры работы задаются в окне настройки клиентского терминала. Кроме того, каждый скрипт обладает своими собственными настройками. Запуск скриптаДля запуска скрипта необходимо наложить его на график. Сразу после этого запускается алгоритм скрипта. Удаление скриптаЗавершение работы скрипта происходит, когда он удаляется с графика. Ссылка на комментарий Поделиться на другие сайты Поделиться
v.perevedentsev Опубликовано 12 сентября, 2010 Автор Жалоба Поделиться Опубликовано 12 сентября, 2010 Пример создания собственного скрипта В этой статье мы научимся писать обычные скрипты. Для этого используется специальная программа - редактор MetaEditor 4. Чтобы её запустить, нажмите на клавишу F4 при открытом клиентском терминале. Чтобы создать новый скрипт, нажмите в редакторе MetaEditor 4 на кнопки меню File->New или исопльзуйте сочетание клавиш Ctrl+N на клавиатуре: http://s48.radikal.ru/i121/1009/6c/6c7553a84b88.png После этого появится окно, в котором вам следует указать, что вы собираетесь создать. Выбираем Script и жмём на кнопку Далее: http://s39.radikal.ru/i086/1009/59/27b40178ca80.png В следующем окне следует ввести название скрипта в поле Name. Укажите свое имя в поле Author и e-mail или адрес вашего веб-узла в поле Link. Далее нажимаем на кнопку Готово: http://i065.radikal.ru/1009/05/edb6ff7ce261.png После этого откроется новое окно, с которым вы в дальнейшем будете работать больше всего. В нём отображается исходный текст: http://i053.radikal.ru/1009/53/01696f21c688.png Обратите внимание, что даже пустой, ничего не делающий скрипт включает в себя какой-то код. Теперь всё готово для начала программирования. Но, к сожалению, вы не имеете представления, как это делается. Давайте попробуем исправить ситуацию. Исходный текст, компиляция и прочееВы должны понять важную вещь. То, что будет написано в MetaEditor'e, - это исходный код. То есть последовательность команд, которую будет выполнять терминал одну за другой сверху вниз. Но терминал не может выполнять исходные коды. Исходный код понятен вам, но не MetaTrader'у. Чтобы исходный код был понятен терминалу, его нужно "перевести" на соответствующий "язык". Чтобы это сделать, нужно нажать на клавишу F5 в MetaEditor'е. После этого будет выполнена компиляция исходного кода в исполняемый файл. Компиляция - это процесс "перевода" исходного кода, написанного вами и понятного вам, в специальный исполняемый файл, который понимает и способен выполнить MetaTrader. Проверьте это сами. Создайте новый скрипт под названием Test1 и сохраните, но не компилируйте. Запустите терминал и, используя Навигатор, зайдите в раздел "Скрипты". Как видно, скрипта с названием Test1 нет: http://s58.radikal.ru/i161/1009/b5/69cf01657d19.png Теперь скомпилируйте скрипт (клавиша F5): http://s47.radikal.ru/i117/1009/13/976c5ce052b4.png Опять загляните в терминал. Скрипт Test1 появился: http://s54.radikal.ru/i145/1009/87/d8928882002d.png Двойной клик на названии скрипта в Навигаторе терминала - и он запускается. Но ничего не происходит, так как скрипт пуст. Вы уже должны представлять, на что похож процесс написания скрипта: вы пишете исходный код, компилируете, запускаете скрипт в терминале, смотрите на результат, изменяете исходный код, компилируете, смотрите ... и так - до тех пор, пока не получите нужный результат. Где писать скрипты?Вы уже заметили, что пустой скрипт содержит в себе определённый код. Но в каком месте вам следует вписывать исходный код, чтобы он работал? Его нужно вписывать между строками int start(){ и return(0);}, как показано на рисунке: http://s03.radikal.ru/i176/1009/7e/10214adb33dd.png Всё, что я дальше буду вам предлагать писать, размещайте в этом месте - и всё будет работать. Позже мы рассмотрим более детально, что означают все эти строки. ПеременныеЧто такое переменная? Попробуйте сами ответить на этот вопрос, а я вам помогу. Сколько вам лет? Сколько вам будет лет через пять лет? Теперь смотрите: возраст - это и есть переменная. Возраст изменяется с течением времени, как и любая другая переменная. То есть первая особенность переменной заключается в её изменении с течением времени. Другой пример: какой был ваш рост в пять лет? Очевидно, намного меньше, чем сейчас. Рост - ещё один пример переменной. Но есть важное отличие. Обратите внимание на то, что возраст мы измеряли, используя целые числа. Рост намного удобнее измерять, используя десятичные дроби ("числа с плавающей точкой"). Возраст: 20 лет, 30 лет. Рост: 1,8 метра, 1,95 метра. Это очень важная особенность: каждая переменная относится к определённому типу. Давайте посмотрим, какие еще бывают типы переменных. Вы можете описать числами многие параметры, но как представить текст? Для этого используются специальные типы - строковые. Эти типы переменных хранят только строки. Теперь давайте посмотрим, как можно создать и описать переменную на языке MQL4. Пример: int age = 25; Здесь мы объявили переменную целого типа (int - integer - целое число). int - это ключевое слово языка MQL4, которое указывает, что мы используем тип целых чисел. Дальше мы написали age (возраст) - это название переменной, то есть слово, по которому мы будем обращаться к значению, хранящемуся в этой переменной. Затем мы присвоили переменной значение 25, используя символ "=". После каждой инструкции ставится точка с запятой, что мы и сделали. Обратите внимание - объявление и инициализация любой переменной сводятся к такой форме: [тип переменной] [название переменной] = [значение переменной]; Кстати, присваивать какое-то значение переменной (совершать инициализацию) необязательно, вы могли бы написать и так: int age; Еще один пример: double height = 1.95; Здесь мы объявляем переменную с названием height (рост), которая хранит значения типа double (число с плавающей запятой, десятичная дробь) и которой мы сразу присваиваем значение 1.95, используя оператор "=". Теперь рассмотрим строковую переменную: string name = "Janet"; string - тип переменной, name - название переменной, "Janet" - значение переменной. Обратите внимание, что значения для переменной типа string размещаются между двойными кавычками ("). Существует еще один очень полезный тип переменной - bool. Переменные этого типа могут принимать только два значения: либо true (правда), либо false (ложь). Пример: bool trend = false; Теперь вам нужно запомнить несколько важных вещей. Язык MQL4 - это регистрозависимый язык, то есть имеет большое значение, ПРОПИСНЫМИ буквами вы пишете код или строчными. Например, если вы объявите несколько переменных с одинаковыми названиями, но разным регистром, то это будут совершенно разные переменные: double HIGHTPRICE; double hightprice; double HightPrice; double hightPrice; Вышеприведённый код создаст четыре совершенно разных переменных. Также обратите внимание на то, что все ключевые слова языка MQL4 пишутся строчными буквами. Следующий пример: DOUBLE hightPrice1; Double hightPrice2; Вышеприведённый код работать не будет, потому что слово double не будет воспринято как ключевое слово языка MQL4. Ещё один важный момент заключается в том, что названия переменных не могут начинаться с цифр или специальных знаков (*,&, ,%,$). Например: double 1price; double %price; Ещё один элемент языка - комментарии. Если вы напишете "//" перед строкой, то она целиком закомментируется. Это значит, что при компиляции она будет игнорироваться. Например: // this is a comment // это комментарий Теперь вы должны заметить, что код пустого скрипта включает в себя много комментариев, которые несут информативный характер. Комментируйте свой код, иногда это может сэкономить вам много времени. Работа с переменнымиТеперь давайте разберёмся, что можно делать с переменными после того, как мы их объявили. Рассмотрим простой пример: double a = 50.0; // объявляем переменную с плавающей запятой и // присваиваем ей значение 50 double b = 2.0; double c; c = a + b; // присваиваем переменной c сумму переменных // a и b. Теперь значение с равно 52. Как и // после любой другой инструкции, ставим точку // с запятой (";") c = a - b; // вычитание, с = 48 c = a*b; // умножение, с = 100 c = a / b; // деление, c = 25 c = (a + b)*a; // в скобках нужно размещать операции, которые // должны выполняться в первую очередь. Так, в // нашем случае сначала будет найдена сумма a и // b, а потом эта сумма умножена на а и присвоена с// если есть несколько операций в кавычках, то они c = (a + b) / (a - b); // будут выполняться слева направо // в соответствиями с правилами математики, сначала будет // найдено c = a + b*3.0; // произведение b и 3, а уже потом суммаЕсли нужно выполнить какую-то операцию с переменной и присвоить ей же результат, например, увеличить на 5, то поступают одним из следующих способов: int a = 5;a = a + 5; // увеличиваем a на 5 a += 5; // аналогично a = a*5;a *= 5; // умножаем а на 5 и присваиваем ей жеa /= 5; // делим и присваиваемЕсли хотите увеличить или уменьшить переменную на 1, используйте такой метод: int a = 5; a++; // увеличиваем а на 1, это называется инкремента--; // уменьшаем а на 1, это декрементЭто всё очень хорошо, но вы при выполнении подобных скриптов можете только догадываться, правильно всё работает или нет, так как на экране ничего не происходит.Поэтому удобно выводить результаты. Для этого существует встроенная функция MessageBox(). MessageBox()Функция - это какой-то набор инструкций, который принимает параметры и в зависимости от них выводит результат. В нашем случае функция MessageBox() принимает два параметра: первый - текст сообщения, второй - текст заголовка. Вот пример использования функции: MessageBox("Hello, World! There is some text.","caption"); Чтобы вызвать функцию, сначала пишут её название. Не забывайте про регистр! Потом открываются скобки, и в них через запятую пишутся параметры. В нашем случае параметры имеют строковый тип. Как мы помним, все строки пишутся между двойными кавычками ("). Как в любой инструкции, в конце ставим точку с запятой. Чтобы окончательно разобраться, посмотрите на рисунок. Он показывает, как связаны код и результат: http://s004.radikal.ru/i208/1009/3d/960b65d258eb.png Да, это всё, конечно, хорошо. Но как можно вывести переменные других типов? Очень просто - мотайте на ус: int a = 50; int b = 100; MessageBox("It is very simple. a+b=" + (a + b), "a+b=?"); В результате получим: http://s46.radikal.ru/i113/1009/37/bf74d2912579.png Как вы уже догадались, MQL4 устроен таким образом, что когда мы пытаемся добавить к строке какой-то другой числовой тип, то он автоматически переводит числа в строки и объединяет их. Это действительно замечательное свойство! Подобные операции вы можете делать и с переменными-строками: int a = 50; int b = 100; string str1 = "a + b ="; str1 += a + b; // теперь str1 = "a + b = 150" // теперь используем переменную str1 в качестве // первого параметраMessageBox(str1, "a + b = ?"); Теперь вы знаете, как можно выводить различные данные с помощью функции MessageBox(). Но какой интерес выводить результаты элементарных математических операций? Нам ведь MQL4 нужен не для того, чтобы находить суммы и произведения, не так ли? МассивыНе пугайтесь. Это очень просто. Смотрите. Допустим, вы хотите запомнить пять цен. Как можно поступить? Ну, можно вот так: double price1 = 1.2341; double price2 = 1.2321; double price3 = 1.2361; double price4 = 1.2411; double price5 = 1.2301; У нас получается пять переменных, которые имеют один тип данных и описывают один и тот же параметр - цену. Но можно поступить иначе, используя массив. Массив - это всего лишь серия переменных, которые отличаются между собой индексами, но имеют одно общее название. Посмотрите, как нужно объявлять массив из пяти элементов: double price[5];бщая форма: (тип массива) (название массива) [количество элементов]; В нашем случае: тип массива - double, название - price, количество элементов - 5. Давайте посмотрим, как можно обратиться к элементам массива: double price[5]; // объявляем массив из 5 элементов price[0] = 1.2341; // обращаемся к первому элементу массива и // присваиваем ему цену. Обратите внимание // на то, что индекс первого элемента // начинается с 0. Это важная особенность, // к которой нужно привыкнуть. price[1] = 1.2321; // обращаемся ко второму элементу price[2] = 1.2361; // и так далее price[3] = 1.2411; price[4] = 1.2301; С элементами массива можно проделывать любые операции, как и с обычными переменными. Собственно, элементы массива - и есть обычные переменные: double price[2]; price[0] = 1.2234; price[1] = 1.2421; MessageBox("Middle price is " + (price[0] + price[1]) / 2.0,"middle price"); При объявлении массива можно также присвоить всем элементам начальные значения: double price[2] = {1.2234, 1.2421}; Мы просто перечисляем через запятую начальные значения элементов в фигурных скобках. В таком случае вы можете даже не указывать количество элементов, компилятор автоматически вставит нужное значение: double price[] = {1.2234, 1.2421}; Это всё, безусловно, очень хорошо, но... К сожалению, бесполезно. Нам нужно как-то добраться до реальных данных! Например, текущих цен, времени, количества свободных денег и так далее. Встроенные или предопределённые массивы и переменныеКонечно же, без реальных данных не обойтись. Чтобы получить к ним доступ, достаточно обратиться к соответствующему предопределённому массиву. Таких имеется несколько, например: High[0]; // обращаемся к последней максимальной цене, // которой достиг бар на текущем таймфрейме // и текущей валютной паре. Валютная пара и // таймфрейм зависят от графика, на котором // вы запустили скрипт. Это очень важно // запомнить!Low[0]; // минимальная цена последнего бара на // текущем графике. Volume[0]; // объём последнего бара на текущем графике.Чтобы окончательно разобраться в предопределённых массивах и индексах, посмотрите на это: http://i078.radikal.ru/1009/31/7d9957e111b3.png Как видите, индекс (номер) последнего бара - 0, предпоследнего - 1 и так далее.Также существуют предопределённые обычные переменные. Например, Bars показывает, сколько баров загружено на текущем графике. То есть это самая обычная переменная, но её объявили до вас и вне вашего скрипта. Эта переменная существует всегда, как и любые другие предопределённые массивы и переменные. ЦиклыДопустим вы решили посчитать среднее значение максимальных цен всех баров на графике. Для этого вы поочерёдно добавляете каждый элемент к какой-то переменной, например, так: double AveragePrice = 0.0; AveragePrice += High[0];AveragePrice += High[1]; AveragePrice += High[2]; AveragePrice += High[3]; AveragePrice += High[4]; // ... и так далееAveragePrice /= Bars; Скажу вам одно: это может сработать, но это - очень глупо. Для таких целей существуют циклы. Обратите внимание, что все операции абсолютно одинаковы, лишь индекс изменяется от 0 до значения переменной Bars-1. Было бы намного удобнее каким-то образом определить счётчик и с его помошью обращаться к элементам массива. Вот как можно решить эту же задачу, используя циклы: double AveragePrice = 0.0; for(int a = 0; a < Bars; a++){ AveragePrice += High[a];} Рассмотрим каждую строку: double AveragePrice = 0.0; // тут всё и так понятно// а это самый настоящий цикл.for(int a = 0; a < Bars; a++) Как видите, цикл начинается с ключевого слова for. (Существуют и другие типы циклов, например, while, но их мы пока не будем рассматривать.) Далее следуют кавычки, в которых размещаются последовательно через точку с запятой счётчик, условие выполнения цикла и операция увеличения счётчика. В общем случае это может быть представлено в виде: for(объявление счетчика; условие выполнения цикла; изменение счетчика) { // между фигурными скобками размещается исходный код, // который будет повторяться }Рассмотрим каждую стадию объявления цикла более детально. Объявление счетчика: используется тип int для счётчика. Название переменной-счётчика не имеет никакого значения. Также обязательно производите инициализацию начального значения, например, нулём. Условие выполнения цикла: тут всё очень просто. Здесь определяется условие, и если оно истинно, то цикл продолжается. Иначе - цикл заканчивается. Например, в нашем случае: a < Bars Видно, что пока переменная-счётчик а будет меньше, чем переменная Bars, то цикл будет выполняться дальше. Допустим, переменная Bars=10, тогда с каждым проходом по телу цикла переменная а будет увеличиваться на 1, пока не достигнет 10, после чего цикл прекратится. Изменение счетчика: если мы не будем изменять счётчик каким-то образом (в нашем случае не будем его увеличивать), то цикл никогда не закончится, так как условие никогда не будет выполнено. Чтобы лучше понять суть цикла, я написал код, который будет выполнять цикл с поясняющими комментариями: // этот цикл:// double AveragePrice=0.0;//// for(int a=0;a>// {// AveragePrice+=High[a];// }//// будет будет выполнен следующим образом:// double AveragePrice=0.0;int a=0;AveragePrice+=High[a];a++; // теперь а=1, предположим, что Bars=3. // Тогда, так как Bars больше чем а, // то цикл продолжается AveragePrice+=High[a];a++; // а=2 AveragePrice+=High[a];а++; // a=3 // но так как условие уже не выполняется, то цикл // прекращается, ведь теперь и а, и Bars равны трём.Теперь вы должны понимать, как работает цикл. Но нужно знать ещё несколько моментов. Условие выполнения цикла может быть другим. Например, таким: a>10 // цикл выполняется, пока a больше 10a!=10 // цикл выполняется, пока а не равно 10a==20 // пока а равно 20a>=2 // пока а больше или равно 2a<=30 // пока а меньше или равно 30Изменение счётчика может производиться и по-другому. Например, вам необязательно увеличивать его каждый раз на 1. Вы можете поступить иначе: a-- // счётчик будет каждый раз уменьшаться на 1 a += 2 // счётчик будет каждый раз увеличиваться на 2Кроме того, вы можете разместить изменение счётчика внутри тела цикла. Например, так: for(int a=0; a<Bars;) { AveragePrice+=High[a]; a++; // счётчик изменяется внутри тела цикла } Аналогично - необязательно объявлять переменную-счётчик в цикле. Можно сделать иначе: int a = 0; for(;a < Bars;) { AveragePrice += High[a]; a++; // счётчик изменяется внутри тела цикла } Если тело цикла содержит всего один оператор, например, вот так: for(int a = 0; a < Bars; a++) { AveragePrice += High[a]; } то фигурные скобки писать необязательно: for(int a = 0; a < Bars; a++) AveragePrice += High[a]; Пока это - всё, что касается циклов. Есть и другие виды циклов, но о них мы поговорим на следующем уроке. Сейчас вы должны уяснить, когда нужно использовать циклы, и запомнить их синтаксис. Попробуйте самостоятельно написать несколько циклов, которые бы выводили значения счётчика функцией MessageBox(). Попробуйте написать бесконечный цикл и посмотрите, что произойдет, если его запустить. УсловияОсталась ещё одна важная вещь, которую вы будете постоянно использовать, - условия. В нашей жизни много условий и действий, которые следуют за этими условиями. Мы очень часто даже мыслим условными предложениями. Например: "Если у меня будет достаточно времени, я успею прочитать эту книгу. Если нет, то, пожалуй, лучше полистать свежий журнал. " Вы и сами можете придумать сотни подобных условий и действий. Но как записать их на MQL4? Вот пример: // конечно, писать условия нужно на языке MQL4if( у меня будет достаточно времени ) { // а тут мы размещаем любые действия, команды на MQL4 то дочитаю эту книжечку; }// если первое условие не выполняется, то выполняется // второе условиеelse { полистаю свежий журнальчик; // код } Теперь вы должны понимать синтаксис условий. Давайте посмотрим на условия, полностью написанные на языке MQL4: int a = 10;int b = 0; if(a > 10 ) { b = 1; }else { b = 2; } MessageBox("b=" + b,"."); Всё довольно-таки просто. Чему равно b после выполнения? Конечно, b = 2, потому что условие a > 10 не выполняется. Это элементарно. Кстати, использовать ключевое слово else (иначе) необязательно: int a = 10;int b = 0; if(a > 10) { b = 1; } В таком случае, если условие не выполняется, блок кода, который следует после условия между фигурными скобками, пропускается. В нашем случае после выполнения b = 0. Также следует обратить внимание на то, как строятся условия. Нам известно, что разные типы переменных могут принимать разные значения, например: ■int - целые значения (1, 60, 772);■double - с плавающей запятой (1.0021, 0.221);■string - только строки ("Word", "Some text.");■bool - только правда или неправда (true, false).Так вот, к чему я веду: в условиях сравнивайте переменные только с теми значениями, которые они могут принимать, например: int Integer=10;double Double=1.0;string String="JustWord";bool Bool=true; if(Integer<10) // условие построено правильно{ MessageBox("It works!","Really!");} if(Double!=1.0) // условие построено правильно{ MessageBox("works!","Simple!");} if(String==10) // а вот это уже полный бред!! // Мы определили переменную //String с типом string, а 10 это int{ MessageBox("Wrong type","u can't c this");} if(String!="Word") // другое дело{ // ...} if(Bool==true) // правильно{ // ...} Обратите внимание, что мы производим сравнения при помощи условных операторов (==, !=, >, <, >=, <=). Для типов string и bool используйте только такие операторы сравнения как == и !=. Теперь вы должны ознакомиться с таким понятием, как вложенность. Да, вы можете использовать условия в циклах, а циклы в условиях; вы можете использовать в условиях другие условия и так далее. Например: int a=0;double b=0.0;bool e; if(a==0){ for(int c=0;c<Bars;c++) { b+=High[c]; } if(b>500.0) { e=true; } else { e=false; }} Следующий пример показывает ещё один способ использования условий: int a=0;int result; if(a==0){ result=1;}else if(a==1){ result=2;}else if(a==2){ result=3;}else{ result=4;} Если при невыполнении какого-то условия у вас имеется другое условие, тогда напишите его после ключевого слова else, как в коде выше. Это тоже замечательно сработает. Количество других условий не ограничено. Если действия по выполнению условия умещаются в одну операцию, то фигурные скобки, как и в циклах, можно упустить: if(a==1){ b=2;} // а можно и так: if(a==1) b=2; Сложные условияЧасто одного условия бывает маловато. Приходится сравнивать много параметров, и в таком случае без сложных условий не обойтись. Например, если у меня будет достаточно времени и терпения, я выучу язык MQL4. Это можно записать в виде кода так: if((достаточно времени) && (достаточно терпения)){ я выучу язык MQL 4;}То есть сложное условие сначала нужно разбить на простые условия, заключить их в скобки, а потом между ними поставить && (логическое И) или || (логическое ИЛИ). Если нужно, чтобы оба условия были истинны, тогда используем && (И). Если нужно, чтобы истинным было или первое, или второе условие, то используем || (ИЛИ). Вот настоящий пример: int a=10;int b=20; if((a>5) && (b<50)) MessageBox("Its works!","Yes");Кроме того, вы можете вкладывать и объединять сколько угодно условий: int a=10;int b=20; if ( ((a>5) || (a<15)) && ( b==20)) MessageBox("It works, too!","Yes"); Всё вместеИспользуя вместе сложные и простые условия, а также циклы, вы можете написать очень сложный код. Практически любой алгоритм можно описать, используя эти незамысловатые структуры языка MQL4. Если вы поймете, как пишутся и работают эти простые вещи, вы поймёте половину из того, что из себя представляет MQL4 или любой другой язык программирования! Это действительно очень просто! Всё, что вам нужно, - это практика. Постарайтесь написать как можно больше скриптов, чтобы запомнить синтаксис языка и набраться опыта. Кроме того, просмотрите примеры, которые размещены в прикреплённом файле examples.mq4 и постарайтесь разобраться в них. Другие предопределённые переменные и массивыВам уже известны массивы High[], Low[], Volume[] и переменная Bars. Ниже приведены еще некоторые полезные переменные: double Open[] // массив цен открытия баров текущего // графикаdouble Close[] // массив цен закрытия баров текущего // графика double Bid // последняя известная цена покупки на // текущей валютной пареdouble Ask // последняя известная цена продажи на // текущей валютной паре ЗаключениеИтак, вы узнали много нового. Уверен, что в вашей голове сейчас полный беспорядок. Перечитывайте текст, запоминайте, практикуйтесь и вникайте в суть. Обещаю, скоро всё станет на свои места. То, что описано в этой статье, - основа всего языка MQL4. Чем лучше вы освоите этот материал, тем проще вам будет учиться дальше. Скажу больше - учиться дальше будет намного легче, так как изложенный здесь материал - это самая трудная часть. В следующих статьях мы изучим различные особенности языка MQL4, а также ознакомимся с другими встроенными функциями, которые предоставляют огромные возможности для программирования. Ссылка на комментарий Поделиться на другие сайты Поделиться
gorush Опубликовано 27 декабря, 2010 Жалоба Поделиться Опубликовано 27 декабря, 2010 Подскажите пожалуйста, что надо прописывать в уровнях фибо, чтобы на сетке вместе с процентами отражалось и ценовое значение? Ссылка на комментарий Поделиться на другие сайты Поделиться
v.perevedentsev Опубликовано 27 декабря, 2010 Автор Жалоба Поделиться Опубликовано 27 декабря, 2010 Подскажите пожалуйста, что надо прописывать в уровнях фибо, чтобы на сетке вместе с процентами отражалось и ценовое значение? В свойствах фибо сетки добавте символы как на рисунке, Ссылка на комментарий Поделиться на другие сайты Поделиться
Elisey A Опубликовано 4 января, 2011 Жалоба Поделиться Опубликовано 4 января, 2011 Подскажите пожайлуста,при работе в терминале несколько месяцев,он начинает тормозить, зависать. Приходится заново загружать терминал, устанавливать и настраивать. После чего, он работает нормально. Это очень неудобно. Что можно сделать? Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения