- •Внешние переменные
- •Глобальные переменные
- •Формальные параметры функций
- •Операции отношения
- •Логическая операция и (&&)
- •Побитовые операции
- •Объединение арифметических и побитовых операций с операцией присваивания
- •Формат оператора цикла while:
- •Формат оператора цикла for:
- •Оператор досрочного завершения цикла break
- •Формат оператора switch:
- •Формат функции OrderSelect():
- •IsStopped(): как проверить, что эксперт был остановлен
- •Выдерживаем паузу между торговыми операциями
- •Index - индекс элемента
- •Реализация трейлинг стопа в эксперте
- •Функция iAlligator() - Аллигатор Билла Вильямса (Alligator)
- •IGator() - определение периодов сна и бодроствования Аллигатора с помощью Gator Oscillator
- •Функция iGator()
- •IFractals(): фракталы б.Вильямса - первое измерение рынка
- •IAo(): Волшебный Осциллятор Билла Вильямса (Awesome Oscillator - ao) - второе измерение рынка
- •Сигналы Волшебного осциллятора (Awesome Oscillator)
Реализация трейлинг стопа в эксперте
Вначале мы перебираем открытые позиции и выставленные ордера и ищем позицию, открытую по данному инструменту и чье магическое число равно MyMagicNumber:
// управление трейлинг стопом
for (i=0; i<OrdersTotal(); i++)
{
if (!OrderSelect(i, SELECT_BY_POS))
{
Print("Error ", GetLastError(), ": Start()->OrderSelect(", i, ") [OrderTotal()=", OrdersTotal(),"]");
continue;
}
if (OrderSymbol()!=Symbol()) continue;
if (OrderMagicNumber()!=MyMagicNumber) continue;
double diff;
if (OrderType() == OP_BUY)
{
...
}
if (OrderType() == OP_SELL)
{
...
}
}
Далее мы рассчитываем для найденных позиций расстояние между текущей ценой и ценой Stop Loss ордера для этой позиции. Если это расстояние превышает TrailingStop пипсов, то эксперт посылает команду на изменение уровня Stop Loss ордера.
Для открытой позиции на покупку:
if (OrderType() == OP_BUY)
{
diff = Bid-Point*TrailingStop-OrderStopLoss();
if (diff>0)
{
if (!OrderModify(OrderTicket(), OrderOpenPrice(), Bid-Point*TrailingStop, 0,0))
Print("Error ", GetLastError(), ": Start()->OrderModify() [trailing stop]");
else
Print("Trailing stop on #", OrderTicket()," [place stop loss at ",
Bid-Point*TrailingStop, "]");
}
return(0);
}
Для позиции на продажу:
if (OrderType() == OP_SELL)
{
diff = OrderStopLoss()-Ask-Point*TrailingStop;
if (diff>0)
{
if (!OrderModify(OrderTicket(), OrderOpenPrice(), Ask+Point*TrailingStop,0,0))
Print("Error ", GetLastError(), ": Start()->OrderModify() [trailing stop]");
else
Print("Trailing stop on #", OrderTicket()," [place stop loss at ",
Ask+Point*TrailingStop, "]");
}
return(0);
}
}
В следующем выпуске я расскажу о сортировке методом пузырька.
Сортировка методом пузырька
В прошлых выпусках я начал рассмотрение способа реализации глобальных массивов и рассказал о функциях Count(), AddItem(), SearchItem(), GetItem() и DeleteItem().
В этом выпуске я расскажу о том, как можно отсортировать глобальный массив по возрастанию или убыванию. Один из наиболее простых в реализации, но медленных по скорости методов сортировки - метод пузырька.
Основная идея сортировки (например, по возрастанию) методом пузырька очень простая. Предположим, что у нас N элементов в массиве и индекс каждого элемента лежит в промежутке от 1 до N.
Первый шаг сортировки методом пузырька
Сравниваем первый и второй элементы массива. Если первый элемент больше, чем второй, то меняем их местами.
Сравниваем второй и третий элементы массива. Если второй элемент больше, чем третий, то меняем их местами.
...
Cравниваем предпоследний (N-1) и последний (N) элементы массива. Если предпоследний элемент больше, чем последний, то меняем их местами.
В результате самым последним элементом в массиве у нас окажется самый большой элемент.
Повторяем вышеуказанные действия для части массива, начиная с 1 позиции до N-1 (шаг 2).
Второй шаг сортировки методом пузырька
Сравниваем первый и второй элементы массива. Если первый элемент больше, чем второй, то меняем их местами.
Сравниваем второй и третий элементы массива. Если второй элемент больше, чем третий, то меняем их местами.
...
Cравниваем элемент N-2 и элемент N-1 массива. Если (N-2)-й элемент больше, чем элемент N-1, то меняем их местами.
В результате предпоследний элемент в массиве у нас тоже будет на своем, "отсортированном" месте.
Последующие шаги сортировки методом пузырька
Повторяем вышеуказанные действия для части массива, начиная с 1 позиции до N-2 (шаг 3), а потом для диапазона 1..N-3 и так далее до диапазона 1..2.
После завершения последнего шага наш массив будет отсортирован по возрастанию.
В следующем выпуске я приведу исходный код функции Sort(), которая сортирует глобальный массив, переданный ей в качестве параметра.
Исходный код функции сортировки методом пузырька
В прошлом выпуске я рассказал о сортировке методом пузырька. В этом выпуске я приведу исходный код функции, которая сортирует массив таким методом.
//+---------------------------------------------------------------------------------------------------+
//| Функция Sort() - сортирует массив методом пузырька |
//| |
//| Возвращает true, если не было ошибки, и false, если ошибка была |
//| |
//| Параметры: |
//| array - имя массива |
//| is_asc_order - если true, то сортируется по возрастанию; если |
//| false, то по убыванию |
//+--------------------------------------------------------------------------------------------------+
bool Sort(string array, bool is_asc_order)
{
// Залокируем критическую секцию
string critical_section = array+"Lock";
if (Lock(critical_section)!=0) return(false);
// Количество элементов массива хранится в переменной с именем,
// равным имя массива + "Count"
string gv_count;
gv_count = array+"Count";
int count, err;
// Если глобальная переменная не существует, то элементов нет
if (!GlobalVariableCheck(gv_count))
{
err = GetLastError();
if (err!=0)
{
// Разлокировать критическую секцию
Unlock(critical_section);
// Вывести сообщение об ошибке и выйти
Print("Sort()->GlobalVariableCheck(): ошибка ", err);
return(false);
}
else
count = 0;
}
else
// переменная существует, получим количество элементов
count = GlobalVariableGet(gv_count);
int i, up_idx;
for (up_idx=count; up_idx>1; up_idx--)
{
// обработаем участок массива 1..up_idx
for (i=1; i<up_idx; i++)
{
// m1 - элемент i
// m2 - элемент i+1
double m1 = GlobalVariableGet(array+DoubleToStr(i, 0));
double m2 = GlobalVariableGet(array+DoubleToStr(i+1, 0));
bool is_sorted; // если true, то не надо переставлять элементы
is_sorted = true;
if (is_asc_order)
{
// сортируем по возрастанию
if (m1>m2) is_sorted = false;
}
else
{
// сортируем по убыванию
if (m1<m2) is_sorted = false;
}
// переставим элементы местами
if (is_sorted) continue;
if (GlobalVariableSet(array+DoubleToStr(i, 0),m2)==0)
{
// произошла ошибка при изменении элемента
// Разлокировать критическую секцию
Unlock(critical_section);
// Вывести сообщение об ошибке и выйти
Print("Sort()->GlobalVariableSet(): ошибка ", GetLastError());
return(false);
}
if (GlobalVariableSet(array+DoubleToStr(i+1, 0),m1)==0)
{
// произошла ошибка при изменении элемента
// Разлокировать критическую секцию
Unlock(critical_section);
// Вывести сообщение об ошибке и выйти
Print("Sort()->GlobalVariableSet(): ошибка ", GetLastError());
return(false);
}
}
}
// Разлокировать критическую секцию
Unlock(critical_section);
return(true);
}
В следующем выпуске я покажу на примере, как работает эта функция.
Пример работы функции Sort() - сортировки методом пузырька
В прошлом выпуске я привел исходный код функции Sort() глобального массива, которая осуществляет сортировку методом пузырька.
На мой взгляд, подробно разбирать ее не имеет смысла, т.к. она содержит много комментариев. Проблема с пониманием может возникнуть только на этом участке кода:
int i, up_idx;
for (up_idx=count; up_idx>1; up_idx--)
{
// обработаем участок массива 1..up_idx
for (i=1; i<up_idx; i++)
{
// m1 - элемент i
// m2 - элемент i+1
double m1 = GlobalVariableGet(array+DoubleToStr(i, 0));
double m2 = GlobalVariableGet(array+DoubleToStr(i+1, 0));
bool is_sorted; // если true, то не надо переставлять элементы
is_sorted = true;
if (is_asc_order)
{
// сортируем по возрастанию
if (m1>m2) is_sorted = false;
}
else
{
// сортируем по убыванию
if (m1<m2) is_sorted = false;
}
// переставим элементы местами
if (is_sorted) continue;
if (GlobalVariableSet(array+DoubleToStr(i, 0),m2)==0)
{
// произошла ошибка при изменении элемента
...
return(false);
}
if (GlobalVariableSet(array+DoubleToStr(i+1, 0),m1)==0)
{
// произошла ошибка при изменении элемента
...
return(false);
}
}
}
Понять, что же делает этот кусок кода будет полегче, если Вы еще раз прочитаете описание алгоритма сортировки методом пузырька. Для облегчения Вашей задачи я приведу пример.
Допустим, что у нас есть неотсортированный массив и мы хотим его отсортировать по убыванию.
№ элемента |
|
Исходное состояние |
|
После шага 1 |
|
После шага 2 |
|
После шага 3 |
|
После шага 4 |
|
После шага 5 |
|
6 |
|
89 |
|
2 |
|
2 |
|
2 |
|
2 |
|
2 |
|
5 |
|
2 |
|
89 |
|
7 |
|
7 |
|
7 |
|
7 |
|
4 |
|
45 |
|
7 |
|
89 |
|
8 |
|
8 |
|
8 |
|
3 |
|
7 |
|
45 |
|
8 |
|
89 |
|
24 |
|
24 |
|
2 |
|
8 |
|
8 |
|
45 |
|
24 |
|
89 |
|
45 |
|
1 |
|
24 |
|
24 |
|
24 |
|
45 |
|
45 |
|
89 |
|
Под "шагами" здесь понимается "внешний" цикл for (up_idx=count; up_idx>1; up_idx--).
Во внутреннем же цикле, например, на первом шаге мы осуществляем следующие действия:
Сравниваем первый элемент (24) и второй (8). Т.к. они расположены по убыванию, то ничего с ними не делаем.
Сравниваем второй элемент (8) и третий (7). Т.к. они расположены по убыванию, то ничего с ними не делаем.
Сравниваем третий элемент (7) и четвертый (45). Т.к. они не расположены по убыванию, то поменяем их местами.
Сравниваем новый четвертый элемент (7) и пятый (2). Т.к. они расположены по убыванию, то ничего с ними не делаем.
Сравниваем пятый элемент (2) и шестой (89). Т.к. они расположены по убыванию, то ничего с ними не делаем.
Сравниваем первый элемент (24) и второй (8). Т.к. они не расположены по убыванию, то поменяем их местами.
Результат первого шага изображен в таблице.
По аналогии мы проходим наш массив еще 4 раза (четыре шага) и получае массив, отсортированный по убыванию.
Стандартные индикаторы технического анализа в MQL4
Этим постом я начинаю рассматривать стандартные индикаторы технического анализа, которые можно использовать в экспертах.
MetaTrader 4 - один из лучших клиентских терминалов, с очень большим списком встроенных индикаторов технического анализа.
В своих предыдущих выпусках, посвященных техническому анализу, теории хаоса Б.Вильямса, индикатору Ишимоку и теории Демарка, я рассказал почти о каждом из них.
Вот полный список функций языка MQL4, с помощью которых Вы можете использовать встроенные индикаторы технического анализа в своих экспертах:
iAC - Индикатор Ускорения/Замедления (Acceleration/Deceleration, AC)
iAD - Индикатор накопления/распределения (Accumulation Distribution, A/D)
iAlligator - Аллигатор Билла Вильямса (Alligator)
iADX - Индекс Среднего Направления Движения (Average Directional Movement Index, ADX)
iATR - Средний Истинный Диапазон (Average True Range, ATR)
iAO - Волшебный Осциллятор Билла Вильямса (Awesome Oscillator - AO)
iBearsPower - индекс силы медведей
iBands - Полосы Боллинджера (Bollinger Bands)
iBandsOnArray - Полосы Боллинджера (Bollinger Bands), построенные по данным, хранящимся в массиве
iBullsPower - индекс силы быков
iCCI - Индекс торгового канала (Commodity Channel Index, CCI)
iCCIOnArray - индикатор CCI, построенный по данным, хранящимся в массиве
iCustom - вызов самописного индикатора (о том, как создать свой индикатор на языке MQL4, я расскажу в следующих выпусках)
iDeMarker - Индикатор Демарка (Demarker)
iEnvelopes - Каналы изменения цен (Envelopes)
iEnvelopesOnArray - Каналы изменения цен (Envelopes), построенные по данным, хранящимся в массиве
iForce - Индекс Силы (Force Index)
iFractals - Фракталы (Fractals) Б.Вильямса
iGator - Gator Oscillator
iIchimoku - Ишимоку Кинко Хайо (Ichimoku Kinko Hyo)
iBWMFI - Индекс Облегчения Рынка (Market Facilitation Index, BW MFI)
iMomentum - Индикатор Momentum
iMomentumOnArray - Индикатор Momentum, построенный по данным, хранящимся в массиве
iMFI - Индекс денежного потока (Money Flow Index - MFI)
iMA - скользящая средния
iMAOnArray - скользящая средния, построенная по данным, хранящимся в массиве
iOsMA - Индикатор Скользящая Средняя Осциллятора (Moving Average of Oscillator, OsMA)
iMACD - MACD-гистограмма (метод конвергенции-дивергенции)
iOBV - Индикатор равновесного объема (On Balance Volume - OBV)
iSAR - Индикатор Параболик
iRSI - Индекс относительной силы (Relative Strength Index, RSI)
iRSIOnArray - Индекс относительной силы (Relative Strength Index, RSI), построенный по данным, хранящимся в массиве
iRVI - Индекс Относительной Бодрости (Relative Vigor Index, RVI)
iStdDev - индикатор Standard Deviation
iStdDevOnArray - индикатор Standard Deviation, построенный по данным, хранящимся в массиве
iStochastic - Стохастик (Stochastic Oscillator)
iWPR - Индикатор Процентный Диапазон Вильямса (Williams’ Percent Range, %R)
iAlligator() - Аллигатор Билла Вильямса (Alligator)
Рассмотрение функций языка MQL4, с помощью которых Вы можете использовать встроенные индикаторы технического анализа в своих экспертах, я начну с функции iAlligator().
С помощью этой функции можно получить значения Аллигатора Билла Вильямса (Alligator).
Думаю, будет нелишним сначала рассказать о самом идикаторе.
Аллигатор Билла Вильямса (Alligator) – это комбинация трех линий баланса (рис. 1):
Челюсть Аллигатора (синяя линия) – это 13-периодная скользящая средняя по центральной цене (High+Low)/2, смещенная на 8 баров в будущее;
Зубы Аллигатора (красная линия) – это 8-периодная скользящая средняя по центральной цене (High+Low)/2, смещенная на 5 баров в будущее;
Губы Аллигатора (зеленая линия) - это 5-периодная скользящая средняя по центральной цене (High+Low)/2, смещенная на 2 бара в будущее.
Для добавления Аллигатора (Alligator) на график платформы MetaTrader 4 выберите пункт меню "Вставка -> Индикаторы -> Билла Вильямса - Alligator".
Рис.
1. Аллигатор Билла Вильямса (Alligator)
С помощью Аллигатора можно определить направление существующего тренда или его отсутствие.
Если все три линии переплетены, то Аллигатор "спит". В это время рынок торгуется в небольшом ценовом диапазоне (во флэте), отбирая у трейдера заработанное на прошлом движении цены. Чем дольше спит Аллигатор, тем более голодным он становится, и тем более сильным будет последующее движение цены. Пока Аллигатор спит, оставайтесь квадратными. Проснувшись, Аллигатор раскрывает пасть (Линии Баланса расходятся) и начинает охотиться за добычей. Наевшись, Аллигатор снова засыпает (Линии Баланса сходятся).
Если Аллигатор не спит, на рынке существует повышательный или понижательный тренд (добыча убегает от Аллигатора):
если цена находится выше пасти Аллигатора, то тренд повышательный;
если цена ниже пасти Аллигатора, то тренд понижательный.
Еще одна полезная функция Аллигатора – помощь в определении разметки волн Эллиотта. Если цена находится за пределами пасти Аллигатора, на рынке формируется импульсная волна, а если внутри пасти, то корректирующая.
Формула расчета Аллигатора:
MEDIAN PRICE = (HIGH + LOW) / 2 ALLIGATORS JAW = SMMA (MEDIAN PRICE, 13, 8) ALLIGATORS TEETH = SMMA (MEDIAN PRICE, 8, 5) ALLIGATORS LIPS = SMMA (MEDIAN PRICE, 5, 3)
Где: MEDIAN PRICE - центральная цена; HIGH - максимальная цена бара; LOW - минимальная цена бара; SMMA (A, B, C) — сглаженное скользящее среднее (А — сглаживаемые данные, В — период сглаживания, С — сдвиг в будущее). ALLIGATORS JAW — Челюсти Аллигатора (синяя линия); ALLIGATORS TEETH — Зубы Аллигатора (красная линия); ALLIGATORS LIPS — Губы Аллигатора (зеленая линия).
Для того, чтобы получить значения Аллигатора в эксперте, мы можем использовать функцию iAlligator().
