PDA

View Full Version : ТААЧ



Scriptong
20-01-2010, 11:20
Продолжая рассмотрение методик Станислава Чувашова, перейдем к более обширной его разработке - ТААЧ (Торгово-аналитический алгоритм Чувашова). Система ТААЧ, по сути, не является абсолютно законченной и строго оговоренной. Например, вообще не указано, где необходимо устанавливать уровень стопа при открытии сделки. Тем не менее, в отличие от большинства теорий (например, волны Эллиотта или Тактика Адверса) ТААЧ обладает рядом четко формализованных критериев, которые трудно истолковать двояко.

Перейдем же непосредственно к рассмотрению системы. ТААЧ вновь оперирует двумя линиями, но, в отличие от стратегии "Вилка Чувашова", базируется на образовании каналов. Одна из методик построения каналов уже была рассмотрена в прошлогодней статье Откат в тренде. ТААЧ отличается и от нее. Согласно ТААЧ, каналы существуют в любом месте графика, а не только при выполнении определенных условий. В качестве опорных точек канала используются три последних фрактала. Единственное условие - один из трех фракталов должен отличаться по типу от других двух. Например, два верхних фрактала и один нижний или два нижних фрактала и один верхний. Если подряд следует три одинаковых по типу фрактала, то из них берутся только первые два, и поиск продолжается до нахождения первого фрактала другого типа.

Три фрактала - это три точки, по которым можно построить две параллельные линии. Одну линию строим по двум фракталам, а вторую по третьему фракталу и углу наклона первой линии так, чтобы вторая линия была параллельная первой. В результате выходит, что можно построить только четыре типа каналов:
восходящий канал, который в качестве первых двух опорных точек использует верхние фракталы (рис. 1) восходящий канал, который в качестве первых двух опорных точек использует нижние фракталы (рис. 2) нисходящий канал, который в качестве первых двух опорных точек использует верхние фракталы (рис. 3) нисходящий канал, который в качестве первых двух опорных точек использует нижние фракталы (рис. 4)

http://www.forextrade.ru/media/Image/MQLabs/49_ag/figure_11.gif
Рис. 1. - Восходящий канал, построенный по двум верхним фракталам. http://www.forextrade.ru/media/Image/MQLabs/49_ag/figure_12.gif
Рис. 2. - Восходящий канал, построенный по двум нижним фракталам
http://www.forextrade.ru/media/Image/MQLabs/49_ag/figure_13.gif
Рис. 3. - Нисходящий канал, построенный по двум верхним фракталам.http://www.forextrade.ru/media/Image/MQLabs/49_ag/figure_14.gif
Рис. 4. - Нисходящий канал, построенный по двум нижним фракталам

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

Дальше следует довольно важный момент - что считать пробитием или отбоем от линии? В стратегии ТААЧ специально для четкого определения этих понятий вводится термин Зона Условного Касания (ЗУК). Границы ЗУК располагаются по обе стороны от каждой линии канала на расстоянии 10%, взятой от ширины канала. В результате отбоем (см. рис. 5) считается нахождение максимума или минимума свечи в ЗУК, а закрытие свечи вне ЗУК, но внутри канала.
http://www.forextrade.ru/media/Image/MQLabs/49_ag/figure_15.gif
Рис. 5. - Отбой от линии поддержки

По аналогии, пробой линии - нахождение одного из экстремумов свечи внутри канала (или в ЗУК), а закрытие свечи вне пределов ЗУК (см. рис. 6)
http://www.forextrade.ru/media/Image/MQLabs/49_ag/figure_16.gif
Рис. 6. - Пробой линии поддержки

Описанные правила помогают всего лишь определиться с сигнальной свечей. А вот пробой сигнальной свечи в направлении отбоя или пробоя уже является сигналом для открытия позиции. Поэтому после идентификации сигнальной свечи будем откладывать ордер на максимум (минимум) свечи.
С ценой входа в рынок мы определились. А вот с целями - нет. ТААЧ имеет ответ и на этот вопрос. При отбое от линии возможно два типа целей:
Если направление отбоя совпадает с направлением канала (отбой от нижней границы восходящего канала или отбой от верхней границы нисходящего канала), то целью является противоположная граница ЗУК. Если направление отбоя не совпадает с направлением канала (отбой от верхней границы восходящего канала или отбой от нижней границы нисходящего канала), то целью является середина канала.
Цель при пробое канала не разделяется на варианты. Это всегда будет граница двойного канала. Например, при пробое линии поддержки нужно от нижней границы канала отложить ширину имеющегося канала вниз.

А вот насчет стопов для позиции стратегия ТААЧ молчит. Поэтому сегодняшняя реализация стратегии не будет устанавливать уровни стопа, так как на данный момент круг ее применения будет ограничен тестером стратегий.

Приступая к реализации, по обыкновению начнем с функции GetSignal. Но так как она получилась очень объемной (более 100 строк), рассмотрим ее поблочно:

// - 1 - =========================== Инициализация значений =============================
BuyLevel = 0; SellLevel = 0; // Уровни входа не определены, значит, вилки нет
double VUp[2], VDn[2]; // Значения верхних и нижних фракталов
int NUp[2], NDn[2]; // Соответствующие номера баров, на которых найдены фракталы
int UpCnt = 0, DnCnt = 0; // Счетчики количества верхних и нижних фракталов
ArrayInitialize(VUp, 0);
ArrayInitialize(VDn, 0);
// - 1 - ============================== Окончание блока =================================

// - 2 - ====== Поиск трех последовательно понижающихся или повышающихся фракталов ======
for (int i = Bar+3; i < Bars && UpCnt+DnCnt < 3; i++)
{
double Fup = iFractals(Symbol(), 0, MODE_UPPER, i);
double Fdn = iFractals(Symbol(), 0, MODE_LOWER, i);
// - 2.1 - ================== Сохранение верхних фракталов ==========================
if (Fup != 0 && UpCnt != 2)
{
VUp[UpCnt] = Fup; // Сохраняем значение фрактала
NUp[UpCnt] = i; // Сохраняем номер бара, на котором найден фрактал
UpCnt++; // Увеличение счетчика верхних фракталов
}
// - 2.1 - ========================== Окончание блока ===============================

// - 2.2 - ================== Сохранение нижних фракталов ===========================
if (Fdn != 0 && DnCnt != 2)
{
VDn[DnCnt] = Fdn; // Сохраняем значение фрактала
NDn[DnCnt] = i; // Сохраняем номер бара, на котором найден фрактал
DnCnt++; // Увеличение счетчика нижних фракталов
}
// - 2.2 - ========================== Окончание блока ===============================
}
// - 2 - ============================== Окончание блока =================================
if (i == Bars) return;
Первый блок затруднений не вызывает, обычная инициализация значений переменных. Как и в прошлом эксперте по стратегии "Вилка Чувашова", используются переменные BuyLevel и SellLevel, ненулевое значение которых свидетельствует о наличии сигнала для установки отложенного ордера и указывает цену Bid для входа. Точно также как и в "Вилке Чувашова", используются массивы VUp, VDn, NUp и NDn. Только на этот раз они двумерные, так как нам всего потребуется три фрактала, а не три фрактала каждого типа.

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

Назначением второго блока является поиск фракталов. Как уже замечалось выше, требуется именно три фрактала, но такие, чтобы среди них было два типа фракталов. Блок устроен таким образом, что если после нахождения двух фракталов одинакового типа находится еще один такой же, то он игнорируется. Это достигается запретом приращения счетчиков UpCnt и DnCnt, если они достигли 2.

Последняя строка, не относящаяся ни к одному из блоков, страхует эксперт от слишком короткой истории котировок, доступной терминалу.

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

// - 3 - ====================== Строим канал по верхним фракталам =======================
if (UpCnt == 2)
{
// Параметры отображение канала
datetime Time1 = Time[NUp[1]];
datetime Time2 = Time[NUp[0]];
datetime Time3 = Time[NDn[0]];
double Price1 = VUp[1];
double Price2 = VUp[0];
double Price3 = VDn[0];
// Расчет верхней границы канала по двум верхним фракталам
double BUp = (VUp[0]*NUp[1] - VUp[1]*NUp[0])/(NUp[1] - NUp[0]); // Коэф. B для прямой
double K = (VUp[1] - BUp)/NUp[1]; // Коэффициент K из уравнения прямой Y = K*X + B
// Расчет коэффициента B для нижней границы канала (B = Y - K*X, Y = VDn, X = NDn)
double BDn = (VDn[0] - K*NDn[0]);
}
// - 3 - ============================== Окончание блока =================================

// - 4 - ========================= Строим канал по нижним фракталам =====================
if (DnCnt == 2)
{
// Параметры отображение канала
Time1 = Time[NDn[1]];
Time2 = Time[NDn[0]];
Time3 = Time[NUp[0]];
Price1 = VDn[1];
Price2 = VDn[0];
Price3 = VUp[0];
// Расчет нижней границы канала по двум нижним фракталам
BDn = (VDn[0]*NDn[1] - VDn[1]*NDn[0])/(NDn[1] - NDn[0]); // Коэффициент B для прямой
K = (VDn[1] - BDn)/NDn[1]; // Коэффициент K из уравнения прямой Y = K*X + B
// Расчет коэффициента B для верхней границы канала (B = Y - K*X, Y = VUp, X = NUp)
BUp = (VUp[0] - K*NUp[0]);
}
// - 4 - ============================== Окончание блока =================================
В данном случае каналы разделяются не на восходящие и нисходящие, а на каналы, построенные по верхним и нижним фракталам. Блок 3 как раз занимается каналами, у которых две опорные точки являются верхними фракталами. Это определяется по значению счетчика верхних фракталов UpCnt. Он должен быть равен 2, что автоматически означает равенство DnCnt единице. Переменные Time1-Time3 и Price1-Price3 подготавливаются для последующего использования в функции ShowChannel, которая отображает сам канал и границы ЗУК. В качестве первых двух координат берутся время и значения верхних фракталов, а в качестве третьей координаты используется единственный найденный нижний фрактал.

Следующим шагом блока 3 является расчет коэффициентов К и B, участвующих в уравнении прямой. Так как все шесть интересующих нас линий (верхняя и нижняя границы канала, плюс четыре линии ЗУК) параллельны друг другу, то коэффициент К у них одинаковый. Разница будет лишь в коэффициентах B. Сначала рассчитывается коэффициент B для верхней границы канала - BUp. Зная ее значение, уже можно будет рассчитать К. А затем по значению К находится коэффициент B нижней границы канала - BDn.

Четвертый блок идентичен третьему. В нем производятся расчеты, если две опорные точки канала являются нижними фракталами (DnCnt равен 2). Поэтому в качестве первых двух координат канала (Time1, Price1, Tim2, Price2) используются значения двух нижних фракталов. В качестве третьей координаты выступает значение единственного верхнего фрактала. Далее рассчитывается коэффициент B для нижней границы канала, по которому впоследствии рассчитывается угол наклона прямой К. Зная значение К, становится возможным рассчитать коэффициент B для верхней границы канала, чем и заканчивается четвертый блок.

Последние два блока функции GetSignal отображают канал и ЗУК, а также генерируют сигналы установки отложенных ордеров:

double CW = (BUp - BDn)*(ZUK/100.0); // Ширина ЗУК в процентах канала

// - 5 - ================== Расчет коэффициентов для ЗУК ================================
// Расчет коэффициентов B для четырех линий: 1) ЗУК выше верхней границы канала;
// 2) ЗУК ниже верхней границы канала; 3) ЗУК выше нижней границы канала; 4) ЗУК ниже
// нижней границы канала
double BZUKUpUp = BUp + CW; // Коэф. B для линии выше верхней границы канала
double BZUKUpDn = BUp - CW; // Коэф. B для линии ниже верхней границы канала
double BZUKDnUp = BDn + CW; // Коэф. B для линии выше нижней границы канала
double BZUKDnDn = BDn - CW; // Коэф. B для линии ниже нижней границы канала
ShowChannel(Time1, Price1, Time2, Price2, Time3, Price3, Price1 + CW, Price2 + CW,
Price3 - CW, Price1 - CW, Price2 - CW, Price3 + CW, IFc(K < 0, Blue, Red));
// - 5 - ============================== Окончание блока =================================

// - 6 - ============================= Генерация сигналов ===============================
// Пробой линии сопротивления - сигнал BUY
if (Close > (Bar+1)*K+BZUKUpUp &&//закрытие бара выше точки UpUp на этой же свече
Close[Bar+2] <= (Bar+2)*K + BZUKUpUp) // а предыдущая свеча закрылась ниже
{
BuyLevel = High[Bar+1]; // уровень входа - максимум первой свечи
SellLevel = 0;
Target = (Bar+1)*K+BUp + (BUp - BDn); // при любом канале цель - двойной канал
Signal = 1;
}

// Отбой от линии поддержки - сигнал BUY
if (Close[Bar+1] > (Bar+1)*K+BZUKDnUp &&//закрытие бара выше точки DnUp на этой же свече
Low[Bar+1] >= (Bar+1)*K + BZUKDnDn && Low[Bar+1] < (Bar+1)*K + BZUKDnUp &&
Close[Bar+1] < (Bar+1)*K+BZUKUpDn) // а минимум находится в нижнем ЗУКе
{
BuyLevel = High[Bar+1]; // уровень входа - максимум первой свечи
SellLevel = 0;
if (K < 0) //при трендовом сигнале цель - нижняя граница верхнего ЗУК
Target = (Bar+1)*K+BZUKUpDn;
else // если сигнал противотрендовый, то цель - середина канала
Target = (Bar+1)*K+BDn + (BUp - BDn)/2;
Signal = 2;
}

// Пробой линии поддержки - сигнал SELL
if (Close[Bar+1] < (Bar+1)*K+BZUKDnDn &&//закрытие бара ниже точки DnDn на этой же свече
Close[Bar+2] >= (Bar+2)*K + BZUKDnDn) // а предыдущая свеча закрылась выше
{
SellLevel = Low[Bar+1]; // уровень входа - минимум первой свечи
BuyLevel = 0;
Target = (Bar+1)*K+BDn - (BUp - BDn); // при любом канале цель - двойной канал
Signal = -1;
}

// Отбой от линии сопротивления - сигнал SELL
if (Close[Bar+1] < (Bar+1)*K+BZUKUpDn &&//закрытие бара ниже точки UpDn на этой же свече
High[Bar+1]>=(Bar+1)*K + BZUKUpDn && High[Bar+1] < (Bar+1)*K + BZUKUpUp &&
Close[Bar+1] > (Bar+1)*K+BZUKDnUp) // а максимум находится в верхнем ЗУКе
{
SellLevel = Low[Bar+1]; // уровень входа - минимум первой свечи
BuyLevel = 0;
if (K > 0) //при трендовом сигнале цель - верхняя граница нижнего ЗУК
Target = (Bar+1)*K+BZUKDnUp;
else // если сигнал противотрендовый, то цель - середина канала
Target = (Bar+1)*K+BDn + (BUp - BDn)/2;
Signal = -2;
}
// - 6 - ============================== Окончание блока =================================
}
В первой строке, не входящей ни в один из блоков, рассчитывается ширина ЗУК (переменная CW), выраженная в процентах от ширины канала. В расчете участвует входной параметр эксперта ZUK, при помощи которого пользователь имеет возможность изменять ширину ЗУК.

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

Шестой блок логически состоит из четырех подблоков. Каждый подблок соответствует одному варианту торговли: два варианта торговли на отбой внутрь канала и два варианта торговли на пробой за пределы канала. Первым следует вариант пробития линии сопротивления. Формально он описывается так: последняя свеча закрылась выше ЗУК, а предыдущая ей свеча закрылась ниже или на уровне верхней линии ЗУК. При выполнении этого условия BuyLevel заполняется значением максимума свечи, закрытой выше ЗУК, а Target указывает на уровень двойного канала, отложенного от существующего вверх. Код сигнала пробития линии сопротивления 1.

Следующий подблок имеет код сигнала 2 - отбой от линии поддержки. Его формальное описание: закрытие последней свечи выше верхней линии ЗУК, опоясывающего нижнюю границу канала, но не выше нижней линии ЗУК, относящейся к верхней границе канала, то есть закрытие должно быть внутри канала и вне ЗУК. При этом минимум свечи должен находиться внутри нижнего ЗУК, а именно: выше нижней линии ЗУК, опоясывающей нижнюю границу канала, и ниже верхней линии ЗУК, относящейся к нижней границе канала. Значение цены открытия позиции BuyLevel и в этом случае устанавливается равным максимуму последней свечи. А вот цель Target принимает разные значения, в зависимости от наклона линий канала.

Наклон линий определяется коэффициентом К. Из курса геометрии многим должно быть известно, что если К положительное, то прямая является восходящей, а если отрицательное, то - нисходящей. Но в нашем случае декартовая система координат получилась "перевернутой" по оси абсцисс. Поэтому при положительном К канал будет нисходящим, а при отрицательном К - восходящим. В связи с этим Target принимает значение нижней линии ЗУК, относящейся к верхней границе канала, если К < 0 (то есть сигнал у нас по тренду), и средней линии канала, если К > 0 (сигнал против тренда).

Подобным образом работают подблоки по генерации сигналов пробоя линии поддержки и отбоя от линии сопротивления, которые соответственно используют коды сигнала -1 и -2.

Использование полученных данных производится в функции start. Она хоть и не менее громоздкая, чем GetSignal, но воспринимается проще. Поэтому приводим ее целиком:

//+-------------------------------------------------------------------------------------+
//| Функция START эксперта |
//+-------------------------------------------------------------------------------------+
int start()
{
// - 1 - == Разрешено ли советнику работать? ===========================================
if (!Activate || FatalError) // Отключается работа советника, если функция
return(0); // init завершилась с ошибкой или имела место фатальная ошибка
// - 1 - ============================= Окончание блока ==================================

// - 2 - == Сбор информации об условиях торговли ========================================
Spread = ND(MarketInfo(Symbol(), MODE_SPREAD)*Point); // текущий спрэд
StopLevel = ND(MarketInfo(Symbol(), MODE_STOPLEVEL)*Point); // текущий уровень стопов
FreezeLevel = ND(MarketInfo(Symbol(), MODE_FREEZELEVEL)*Point); // уровень заморозки
// - 2 - ============================= Окончание блока ==================================

// - 3 - =================== Оптимизация вычислений и генерация сигнала =================
if (LastTrans == Time[0]) // Все действия на данной свече выполнены,
return(0); // до следующей бездействуем

if (LastBar != Time[0])
{
GetSignal(0); // Рассчитываем сигнал,
LastBar = Time[0]; // но не чаще одного раза за свечу
}
// - 3 - ============================= Окончание блока ==================================

// - 4 - ============================ Установка ордеров =================================
if (BuyLevel > 0) // активен один из Buy-сигналов
{
GetOrdersInfo(); // Сбор информации о своих ордерах
// - 4.1 - ===================== Расчет цены открытия ордера ======================
if (BuyLevel - Bid <= StopLevel) // Цена открытия ордера не должна быть слишком
double Price = NP(Ask + StopLevel + Tick); // близко к текущей цене
else
Price = NP(BuyLevel + Spread + Tick);
// - 4.1 - ============================ Окончание блока ===========================

// - 4.2 - ============== Проверка противоположного ордера или позиции ============
if (!CheckStopOfPos(SellTicket, Price)) // Установка стопа позиции Sell
return(0);
if (!CheckPresentOrder(SSTicket)) // Удаление ордера Sell Stop
return(0);
// - 4.2 - ============================ Окончание блока ===========================

// - 4.3 - ============== Установка или коррекция ордера Buy Stop =================
if (BuyTicket < 0) // Если позиция Buy не существует
if (!CheckOpenPos(BSTicket, Price)) // и нет ордера Buy Stop (если есть, то
if (Target - Price > StopLevel) // проверяем цену открытия)
if (OpenOrderCorrect(OP_BUYSTOP, Price, 0, Target) != 0)
return(0);
else
// - 4.3.1 - ======= Вывод сигнала с описанием действий советника =========
if (Signal == 1)
{
if (UseAlert)
Alert("Ордер BUYSTOP установлен по пробою линии сопротивления");
Print("Ордер BUYSTOP установлен по пробою линии сопротивления");
}
else
{
if (UseAlert)
Alert("Ордер BUYSTOP установлен по отбою от линии поддержки");
Print("Ордер BUYSTOP установлен по отбою от линии поддержки");
}
// - 4.3.1 - ================= Окончание блока ============================
// - 4.3 - ============================ Окончание блока ===========================
}

if (SellLevel > 0) // Активен один из Sell-сигналов
{
GetOrdersInfo(); // Сбор информации о своих ордерах
// - 4.4 - ===================== Расчет цены открытия ордера ======================
if (Bid - SellLevel <= StopLevel) // Цена открытия ордера не должна быть слишком
Price = NP(Bid - StopLevel - Tick); // близко к текущей цене
else
Price = NP(SellLevel - Tick);
// - 4.4 - ============================ Окончание блока ===========================

// - 4.5 - ============== Проверка противоположного ордера или позиции ============
if (!CheckStopOfPos(BuyTicket, Price)) // Установка уровня стопа для позиции BUY
return(0);
if (!CheckPresentOrder(BSTicket)) // Удаление ордера Buy Stop
return(0);
// - 4.5 - ============================ Окончание блока ===========================

// - 4.6 - ============ Установка или коррекция ордера Sell Stop ==================
if (SellTicket < 0) // Если позиция Sell не существует
if (!CheckOpenPos(SSTicket, Price)) // и нет ордера Sell Stop (если есть, то
if (Price - Target > StopLevel) // проверяем цену открытия)
if (OpenOrderCorrect(OP_SELLSTOP, Price, 0, Target) != 0)
return(0);
else
// - 4.6.1 - ======= Вывод сигнала с описанием действий советника =========
if (Signal == -1)
{
if (UseAlert)
Alert("Ордер SELLSTOP установлен по пробою линии поддержки");
Print("Ордер SELLSTOP установлен по пробою линии поддержки");
}
else
{
if (UseAlert)
Alert("Ордер SELLSTOP установлен по отбою от линии сопротивления");
Print("Ордер SELLSTOP установлен по отбою от линии сопротивления");
}
// - 4.6.1 - ================= Окончание блока ============================
// - 4.6 - ============================ Окончание блока ===========================
}
// - 4 - ============================= Окончание блока ==================================

LastTrans = Time[0];

return(0);
}
Описание начнем с третьего блока. LastTrans используется для сохранения времени последней успешной обработки всех имеющихся ордеров и позиций эксперта. Если это время указывает на время открытия текущей свечи, то до ее закрытия никаких действий эксперт предпринимать не будет. Этот ход позволяет существенно ускорить тестирование эксперта и снижает нагрузку на процессор во время онлайн торговли. Точно такие же функции у переменной LastBar, но они относятся к ограничению вызова GetSignal не более одного раза за свечу.

Все самое интересное происходит в четвертом блоке, который для удобства разделен на подблоки.

Первая часть четвертого блока реагирует на сигнал установки ордера Buy Stop (BuyLevel > 0). В этом случае происходит обращение к функции GetOrdersInfo, которая находит все позиции Buy и Sell эксперта, а также ордера Buy Stop и Sell Stop, записывая номера их тикетов в соответствующие переменные. После этого блок 4.1 проверяет корректность указанной цены открытия ордера BuyLevel, которая может быть слишком близко от текущей цены (в этом случае устанавливается ближайшая возможная цена).

Далее в игру вступает подблок 4.2, обязанностью которого является слежение за противоположными ордерами - Sell и SellStop. В случае присутствия Sell, уровень стопа позиции переносится на цену открытия ордера Buy Stop. Это делает функция CheckStopOfPos. Она выполняется с каждым новым тиком до тех пор, пока стоп все же не будет перенесен на нужный уровень. Далее, если Sell не существует, то проверяется наличие ордера Sell Stop, наличие которого в рынке вовсе не нужно, ведь у нас сигнал BUY. Проверкой и удалением ордера занимается функция CheckPresentOrder, которая тоже разрешает дальнейшее исполнение эксперта только в случае успеха.

Подблок 4.3 непосредственно устанавливает ордер Buy Stop. Но сначала проверяется существование позиции BUY (если существует, то BuyTicket > 0). Если она уже имеется, то никаких действий эксперт не совершает. Если же BUY нет, то проверяется существование ордера Buy Stop и цена его открытия сверяется с необходимой. Это производится в функции CheckOpenPos. Если же и Buy Stop нет, то происходит установка ордера и вывод соответствующих сообщений.

В подобной последовательности работают подблоки 4.4-4.6, обрабатывающие сигнал установки ордера Sell Stop. Только в них устанавливается стоп для позиции BUY и удаляется существующий Buy Stop для того, чтобы установить Sell Stop.

Функции CheckStopOfPos, CheckPresentOrder и CheckOpenPos тривиальны и в особых комментариях не нуждаются. Перейдем к тестированию советника.

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

В "чистом виде", то есть с такими настройками, которые были предложены самим автором стратегии, хороших результатов от эксперта добиться не удалось. А вот при подборе параметра ZUK некоторые тесты выглядят многообещающе. Все приведенные ниже рисунки показывают кривые баланса после тестирования эксперта на таймфрейме H4 и периоде истории 01.01.2009 - 15.01.2010.

Для валютной пары EURUSD наилучшие результаты показаны при ширине ЗУК = 5% (см. рис. 7).
http://www.forextrade.ru/media/Image/MQLabs/49_ag/EURUSD.gif

Рис. 7. - График кривой баланса, получаемый при тестировании советника на валютной паре EURUSD.
В данном случае даже оптимизация эксперта не помогла. Чистая прибыль так и не была достигнута, а кривая баланса уж слишком "кривая".

Валютная пара USDCHF показала себя гораздо лучше. Этот результат зафиксирован при ZUK = 12, совсем недалеко от авторского значения (см. рис. 8).
http://www.forextrade.ru/media/Image/MQLabs/49_ag/USDCHF.gif

Рис. 8. - График кривой баланса, получаемый при тестировании советника на валютной паре USDCHF.

Чистая прибыль составила 1016.38 долларов при максимальной просадке 593.94 доллара. В итоге фактор восстановления почти добрался до двух - 1.71. К тому же, вид кривой баланса довольно стабильный и даже в зоне потенциального убытка (вторая половина графика) убыток не дошел до огромной величины.

Валютная пара GBPUSD дала ростки при ZUK = 23 (см. рис. 9).
http://www.forextrade.ru/media/Image/MQLabs/49_ag/GBPUSD.gif

Рис. 9. - График кривой баланса, получаемый при тестировании советника на валютной паре GBPUSD.

Чистая прибыль 1429.85, вот только максимальная просадка тоже велика - 1283.45. Фактор восстановления чуть больше единицы. Но вновь радует довольно красивый вид кривой баланса, который подпорчен лишь началом. Еще один интересный показатель - в среднем на каждые три подряд прибыльные сделки приходится всего одна убыточная.

Валютная пара USDJPY попыталась что-то показать при ZUK = 11 (см. рис. 10).
http://www.forextrade.ru/media/Image/MQLabs/49_ag/USDJPY.gif

Рис. 10. - График кривой баланса, получаемый при тестировании советника на валютной паре USDJPY.

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

Итак, до приемлемых результатов мы пока не добрались. Но это лишь начало пути, все "полезные нововведения", еще впереди.


[B]Доработка стратегии для использования в AutoGraf 4.0

Для возможности запуска стратегии в AutoGraf 4.0 эксперт переделывается довольно просто. Ведь у него имеется всего один значимый параметр - ZUK. Чтобы не отягощать пользователя поиском нужно параметра AT_1 для установки нужной ширины ZUK, вынесем его настройку непосредственно на панель управления AG. Это будет значение параметра Ds (дистанция). В результате, трейдер сможет менять ширину ЗУК "на ходу". Правда, с некоторой оговоркой. Реакция стратегии на новое значение наступит только на следующей свече.

Для запуска советника из-под AutoGraf 4.0 совершите такие шаги:
Воспользуйтесь ссылкой Файлы стратегий для Autograf 4.0 (http://www.forextrade.ru/media/Image/MQLabs/49_ag/AG_Chuvashovs_Channels.zip) и полученный архив распакуйте в папку MT4\experts\libraries. Запустите AutoGraf. Для получения похожих с тестами результатов работы выставьте объем открываемой позиции (Lots) 0.1, а Ds 5, 12, 23 или 11 соответственно для EURUSD, USDHF, GBPUSD или USDJPY. Выберите стратегию №3. Для этого передвиньте вверх значок So и среди названий стратегий найдите значок S3, который также потяните вверх. Запустите функцию автоматической торговли, передвинув значок AT в верхнее положение.

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

Советник ChuvashovsChannels_Expert (http://www.forextrade.ru/media/Image/MQLabs/49_ag/ChuvashovsChannels_Expert.mq4)

Файлы стратегии для AutoGraf 4.0 (http://www.forextrade.ru/media/Image/MQLabs/49_ag/AG_Chuvashovs_Channels.zip)

Развернутые результаты тестирования эксперта (http://www.forextrade.ru/media/Image/MQLabs/49_ag/Test.zip)

Scriptong
26-01-2010, 09:27
Первый опыт реализации стратегии ТААЧ, начатый в первой части (http://fxtrade.ru/mqlabs/19.01.2010-kanaly-chuvashova-chast-1), обладает таким большим недостатком, как отсутствие уровня стопа у отложенных ордеров. На устранение этого недостатка будут направлены сегодняшние изыскания, но, как было выявлено после более тщательного рассмотрения работы стратегии, наибольшим недостатком все же является не отсутствие стопов.

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

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

http://www.forextrade.ru/media/Image/MQLabs/50_ag/figure_1.gif Рис. 1. - "Узкий" канал, формирующийся после флэта.
Рассмотрим один из таких "узких" каналов (см. рис. 1). На первый взгляд 90 пунктов ширины канала это не так уж и мало. Но давайте посчитаем, что получится при получении трендового сигнала на отбой от линии поддержки. Во-первых, 18 пунктов сразу же отбросим на зону условного касания (ЗУК). Это число получается очень просто: 10% от ширины канала - 9 пунктов. Учитывая, что ЗУК присутствует с двух сторон канала, умножаем 9 на 2. Во-вторых, отложенный ордер для входа в рынок должен располагаться за одним из экстремумов свечи, которая собственно и дала сигнал отскока. В итоге, для тела свечи нужно по самым скромным оценкам добавить еще пунктов 10. Уже 28 пунктов. В-третьих, не забываем такую непреложную сущность трейдинга как спрэд. Это еще минимум 3 пункта. Уже 31. То есть в самом лучшем случае из 90 пунктов канала мы получим только 59 пунктов прибыли. А вот риск сделки установить ниже 50 пунктов никак не получится. На рынке стоп меньше 50 пунктов считается благотворительностью в пользу третьих лиц.

Если взять расчеты для противотрендового сигнала отскока, то там все еще грустнее. Целью сделки будет уже не противоположная линия ЗУК, а середина канала, что уменьшает максимальный профит до 14 пунктов. Такая торговля называется скальпингом и чаще всего не дает хороших результатов.

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

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

Более широкий канал получится, если в качестве опорных точек взять экстремумы индикатора ZigZag (см. рис. 2)

http://www.forextrade.ru/media/Image/MQLabs/50_ag/figure_2.gifРис. 2. - Экстремумы Зиг-Зага в качестве опорных точек канала.
Из рисунка очень хорошо видно, что последний экстремум Зиг-Зага не участвует в построении канала. Это связано с тем, что последний экстремум еще не является зафиксированным и может изменять свое положение с каждой новой свечей. Поэтому первой опорной точкой выступает второй экстремум, который уже не изменит свое значение. Зиг-Заг отмечает наиболее важные пики в развитии волновой структуры рынка, пропуская многие незначимые локальные экстремумы, к которым фракталы Билла Вильямса не могли остаться равнодушными.

От проблемы "узких" каналов вернемся ко второй, не менее важной, проблеме - установка уровня первоначального стопа. Решение, как оказалось, лежит на поверхности. В каждом построенном канале присутствует противоположная направлению открытия сделки опорная точка. Если таких точек две, то требуется выбрать самую дальнюю точку от текущей цены. Это и будет уровень первоначального стопа. Например, на рис. 2 для короткой позиции стопом будет максимум Зиг-Зага, расположенный около цены 1.3790, а для длинной позиции - единственный минимум Зиг-Зага около цены 1.3340.

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

// - 2 - ====== Поиск трех последовательно понижающихся или повышающихся фракталов ======
for (int i = Bar; i < Bars && UpCnt+DnCnt < 3; i++)
{
double ZZ = iCustom(Symbol(), 0, "ZigZag", ZZDepth, ZZDev, ZZBackStep, 0, i);
if (ZZ != 0)
{
if (FirstExt == 0)
{
FirstExt = ZZ;
continue;
}
}
else
continue;
// - 2.1 - ================== Сохранение верхних фракталов ==========================
if (ZZ == High[i] && UpCnt != 2)
{
VUp[UpCnt] = ZZ; // Сохраняем значение фрактала
NUp[UpCnt] = i; // Сохраняем номер бара, на котором найден фрактал
UpCnt++; // Увеличение счетчика верхних фракталов
}
// - 2.1 - ========================== Окончание блока ===============================

// - 2.2 - ================== Сохранение нижних фракталов ===========================
if (ZZ == Low[i] && DnCnt != 2)
{
VDn[DnCnt] = ZZ; // Сохраняем значение фрактала
NDn[DnCnt] = i; // Сохраняем номер бара, на котором найден фрактал
DnCnt++; // Увеличение счетчика нижних фракталов
}
// - 2.2 - ========================== Окончание блока ===============================
}
// - 2 - ============================== Окончание блока =================================
Вместо расчета фракталов вставлен вызов функции iCustom, при помощи которой рассчитывается значение индикатора ZigZag. Расчет значения ZigZag во многом похож на расчет значения фракталов. Разница лежит лишь в том, что в одном массиве Зиг-Зага хранятся как максимумы, так и минимумы. Поэтому в блоках 2.1 и 2.2 для сортировки экстремумов на максимумы и минимумы полученное значение сравнивается соответственно с максимумом или минимумом свечи, где был найден экстремум.

Других изменений в блоке 2 не было. Перейдем к рассмотрению еще одного блока, которого коснулись изменения:

// - 6 - ============ Генерация одного из четырех сигналов ==============================
// - 6.1 - ================== Пробой линии сопротивления - сигнал BUY ==================
if (Close > (Bar+1)*K+BZUKUpUp &&//закрытие бара выше точки UpUp на этой же свече
Close[Bar+2] <= (Bar+2)*K + BZUKUpUp) // а предыдущая свеча закрылась ниже
{
BuyLevel = High[Bar+1]; // уровень входа - максимум первой свечи
SellLevel = 0;
Target = (Bar+1)*K+BUp + (BUp - BDn); // при любом канале цель - двойной канал
LossLevel = NP(Low[iLowest(Symbol(), 0, MODE_LOW, IF(DnCnt == 1, NDn[0], NDn[1])+1)]-
Delta*Tick); // Стоп - минимум цены до последнего нижнего фрактала
Signal = 1;
}
// - 6.1 - ================== Окончание блока ==========================================

// - 6.2 - =================== Отбой от линии поддержки - сигнал BUY ===================
if (Close[Bar+1] > (Bar+1)*K+BZUKDnUp &&//закрытие бара выше точки DnUp на этой же свече
Low[Bar+1] >= (Bar+1)*K + BZUKDnDn && Low[Bar+1] < (Bar+1)*K + BZUKDnUp &&
Close[Bar+1] < (Bar+1)*K+BZUKUpDn && // а минимум находится в нижнем ЗУКе
High[Bar+1] < (Bar+1)*K+BZUKUpDn-Spread-StopLevel)//а максимум далек от будущей цели
{
BuyLevel = High[Bar+1]; // уровень входа - максимум первой свечи
SellLevel = 0;
if (K < 0) //при трендовом сигнале цель - нижняя граница верхнего ЗУК
Target = (Bar+1)*K+BZUKUpDn;
else // если сигнал противотрендовый, то цель - середина канала
Target = (Bar+1)*K+BDn + (BUp - BDn)/2;
LossLevel = NP(Low[iLowest(Symbol(), 0, MODE_LOW, IF(DnCnt == 1, NDn[0], NDn[1])+1)]-
Delta*Tick); // Стоп - минимум цены до последнего нижнего фрактала
Signal = 2;
}
// - 6.2 - ================== Окончание блока ==========================================

// - 6.3 - ================== Пробой линии поддержки - сигнал SELL =====================
if (Close[Bar+1] < (Bar+1)*K+BZUKDnDn &&//закрытие бара ниже точки DnDn на этой же свече
Close[Bar+2] >= (Bar+2)*K + BZUKDnDn) // а предыдущая свеча закрылась выше
{
SellLevel = Low[Bar+1]; // уровень входа - минимум первой свечи
BuyLevel = 0;
Target = (Bar+1)*K+BDn - (BUp - BDn); // при любом канале цель - двойной канал
LossLevel = NP(High[iHighest(Symbol(), 0, MODE_HIGH, // Стоп - максимум до последнего
IF(UpCnt == 1,NUp[0],NUp[1])+1)]+Spread+Delta*Tick);//верхнего фрактала
Signal = -1;
}
// - 6.3 - ================== Окончание блока ==========================================

// - 6.4 - ================== Отбой от линии сопротивления - сигнал SELL ===============
if (Close[Bar+1] < (Bar+1)*K+BZUKUpDn &&//закрытие бара ниже точки UpDn на этой же свече
High[Bar+1]>=(Bar+1)*K + BZUKUpDn && High[Bar+1] < (Bar+1)*K + BZUKUpUp &&
Close[Bar+1] > (Bar+1)*K+BZUKDnUp && // а максимум находится в верхнем ЗУКе
Low[Bar+1] > (Bar+1)*K+BZUKDnUp+Spread+StopLevel) // а минимум далек от будущей цели
{
SellLevel = Low[Bar+1]; // уровень входа - минимум первой свечи
BuyLevel = 0;
if (K > 0) //при трендовом сигнале цель - верхняя граница нижнего ЗУК
Target = (Bar+1)*K+BZUKDnUp;
else // если сигнал противотрендовый, то цель - середина канала
Target = (Bar+1)*K+BDn + (BUp - BDn)/2;
LossLevel = NP(High[iHighest(Symbol(), 0, MODE_HIGH, // Стоп - максимум до последнего
IF(UpCnt == 1,NUp[0],NUp[1])+1)]+Spread+Delta*Tick);//верхнего фрактала
Signal = -2;
}
// - 6.4 - ================== Окончание блока ==========================================
// - 6 - ============================== Окончание блока =================================
}
Здесь изменений тоже немного - всего два.

Первое носит, так сказать, "косметический характер". Это небольшое исправление в условиях генерации сигналов отбоя от линий поддержки и сопротивления (блоки 6.2 и 6.4, четвертое условие). Заключается оно в дополнительном условии проверки одного из экстремумов свечи по отношению к ЗУК. Отсутствие этого условия в первой версии эксперта иногда приводило к генерации сигнала открытия позиции в случаях, когда цель была слишком близка к текущему уровню цены.

Второе изменение касается как раз проблемы стопа. Как отмечалось выше, стоп теперь устанавливается сразу при установке отложенного ордера. В качестве уровня стопа используется одна из противоположных сделке опорных точек канала. Для сохранения рассчитанного уровня была введена переменная LossLevel. Когда генерируется сигнал открытия длинной позиции, LossLevel рассчитывается как минимальное значение цены в диапазоне от текущего бара до наиболее раннего минимума Зиг-Зага, использующегося в качестве опорной точки канала. Из полученного значения вычитается Delta пунктов (Delta - внешний параметр эксперта, доступный пользователю для изменения). При помощи параметры Delta можно скорректировать уровень стопа, чтобы он не указывал с точностью до пункта на один из локальных экстремумов цены.

Если же генерируется сигнал на открытие короткой позиции, то LossLevel рассчитывается как максимальное значение цены в диапазоне от текущего бара до наиболее раннего из двух последних экстремумов Зиг-Зага. Затем к LossLevel прибавляется спрэд и Delta пунктов.

Появление уровня стопа при установке отложенного ордера заставляет внести изменения в блоки 4.3 и 4.6 функции start:

// - 4.3 - ============== Установка или коррекция ордера Buy Stop =================
if (BuyTicket < 0) // Если позиция Buy не существует
if (!CheckOpenPos(BSTicket, Price)) // и нет ордера Buy Stop (если есть, то
if (Target - Price > StopLevel && // проверяем цену открытия)
Price - LossLevel > StopLevel)
if (OpenOrderCorrect(OP_BUYSTOP, Price, LossLevel, Target) != 0)
return(0);
else
// - 4.3.1 - ======= Вывод сигнала с описанием действий советника =========
if (Signal == 1)
{
if (UseAlert)
Alert("Ордер BUYSTOP установлен по пробою линии сопротивления");
Print("Ордер BUYSTOP установлен по пробою линии сопротивления");
}
else
{
if (UseAlert)
Alert("Ордер BUYSTOP установлен по отбою от линии поддержки");
Print("Ордер BUYSTOP установлен по отбою от линии поддержки");
}
// - 4.3.1 - ================= Окончание блока ============================
// - 4.3 - ============================ Окончание блока ===========================
}

...
// - 4.6 - ============ Установка или коррекция ордера Sell Stop ==================
if (SellTicket < 0) // Если позиция Sell не существует
if (!CheckOpenPos(SSTicket, Price)) // и нет ордера Sell Stop (если есть, то
if (Price - Target > StopLevel && // проверяем цену открытия)
LossLevel - Price > StopLevel)
if (OpenOrderCorrect(OP_SELLSTOP, Price, LossLevel, Target) != 0)
return(0);
else
// - 4.6.1 - ======= Вывод сигнала с описанием действий советника =========
if (Signal == -1)
{
if (UseAlert)
Alert("Ордер SELLSTOP установлен по пробою линии поддержки");
Print("Ордер SELLSTOP установлен по пробою линии поддержки");
}
else
{
if (UseAlert)
Alert("Ордер SELLSTOP установлен по отбою от линии сопротивления");
Print("Ордер SELLSTOP установлен по отбою от линии сопротивления");
}
// - 4.6.1 - ================= Окончание блока ============================
// - 4.6 - ============================ Окончание блока ===========================
}
Изменения затронули условие, проверяющее корректность параметров при установке ордера (добавлено сравнение разницы между ценой открытия и уровнем стопа с минимальным размером стопа StopLevel), а непосредственно в вызов функции открытия ордера добавлен параметр LossLevel.

Последнее изменение в коде эксперта затронуло функцию CheckOpenPos, которая проверяет равенство цены открытия отложенного ордера требуемому уровню:

//+-------------------------------------------------------------------------------------+
//| Проверка цены открытия отложенного ордера |
//+-------------------------------------------------------------------------------------+
bool CheckOpenPos(int Ticket, double Price)
{
if (Ticket > 0)
if (OrderSelect(Ticket, SELECT_BY_TICKET))
{
if (MathAbs(Price - OrderOpenPrice()) >= Tick)
if ((OrderType() == OP_BUYSTOP && Target - Price > StopLevel && // Проверка
Price - LossLevel > StopLevel) || // корректности новых стопов и профитов
(OrderType() == OP_SELLSTOP && Price - Target > StopLevel && // по отношению
LossLevel - Price > StopLevel)) // к новой цене
OrderModify(Ticket, Price, LossLevel, Target, 0);
return(True); // В любом случае вернем True, так как ордер присутствует и нет нужды
// открывать еще один
}
return(False); // Ордера нет - вернем False
}
Если текущая цена открытия ордера не равна требуемой цене, то происходит проверка корректности новых уровней профита и стопа ордера. В первой версии советника этой проверки не было, что приводило к получению ошибки 130 от терминала - неправильные стопы.

Проведем проверку второй версии советника, где нашли отображение изменения в построении каналов и установке уровней стопа. Как отмечалось выше, целью изменений было достижение приемлемых результатов торговли не только на таймфрейме Н4, но и, прежде всего, на таймфрейме Н1. Поэтому в качестве рабочего периода графика принимаем Н1. Диапазон тестирования расширим до двух лет (01.01.2008 - 22.01.2010), чтобы получить как можно большее количество сделок для анализа. Во всех приведенных случаях входные параметры эксперта принимались по умолчанию (рис. 3 - 6)
http://www.forextrade.ru/media/Image/MQLabs/50_ag/EURUSD.gif

Рис. 3. - График кривой баланса, получаемый при тестировании второй версии советника на валютной паре EURUSD.
Наилучшим образом советник проявил себя на валютной паре EURUSD. Чистая прибыль 2519.36 доллара при максимальной просадке 924.72 доллара, что дает фактор восстановления 2.72. Довольно неплохой результат. Ко всему прочему, вид кривой баланса имеет четкую восходящую структуру, хотя и не очень плавную. Но оправданием здесь может служить тот факт, что резкие скачки, в основном, наблюдаются в сторону повышения.
http://www.forextrade.ru/media/Image/MQLabs/50_ag/USDCHF.gif

Рис. 4. - График кривой баланса, получаемый при тестировании второй версии советника на валютной паре USDCHF.
Валютная пара USDCHF показала себя гораздо хуже. Полученная в начале интервала прибыль была плавно растрачена в течение пятидесяти сделок, а затем кривая баланса и вовсе прочно зацепилась за отрицательную зону, из которой уже не показывалась до конца тестирования. Приводить какие-то цифры в данном случае не имеет смысла.
http://www.forextrade.ru/media/Image/MQLabs/50_ag/GBPUSD.gif

Рис. 5. - График кривой баланса, получаемый при тестировании второй версии советника на валютной паре GBPUSD.
Валютная пара GBPUSD отметилась непостоянством. Направление кривой баланса определить очень трудно. Видимо, его действительно нет. То, что баланс в какое-то время достигал отметки 11 634 доллара, является слабым оправданием отрицательного значения конечного баланса.
http://www.forextrade.ru/media/Image/MQLabs/50_ag/USDJPY.gif

Рис. 6. - График кривой баланса, получаемый при тестировании второй версии советника на валютной паре USDJPY.
Подобно франку, валютная пара USDJPY сначала попыталась взвиться к вершинам, но надолго энтузиазма не хватило. Единственным интересным моментом представленной кривой баланса является классическая нисходящая пятиволновка, приведшая баланс из положительной области в отрицательную.

Подводя итоги исследования ТААЧ, приходим к выводу, что универсальной стратегию назвать нельзя. Нужно специально подбирать параметры под каждую валютную пару. Но даже подбор параметров не всегда спасает. Хотя, на примере EURUSD наглядно продемонстрировано, что если параметры уже подобраны, то стратегия приносит приемлемую прибыль.


[B]Доработка стратегии для использования в AutoGraf 4.0

Доработка стратегии для работы в среде AutoGraf 4.0 основывается на доработке предыдущей версии эксперта. Как и раньше, ширину ЗУК в процентах от канала можно будет задавать при помощи параметра Ds (дистанция). К нему добавился еще один внешний параметр - Delta. Он будет ассоциирован с шагом модификации St. В функции GetSignal, CheckOpenPos и start внесены соответствующие изменения.

Для запуска советника из-под AutoGraf 4.0 совершите такие шаги:
Воспользуйтесь ссылкой Файлы стратегий для Autograf 4.0 (http://www.forextrade.ru/media/Image/MQLabs/50_ag/AG_Chuvashovs_ChannelsZZ.zip) и полученный архив распакуйте в папку MT4\experts\libraries. Запустите AutoGraf. Для получения похожих с тестами результатов работы выставьте объем открываемой позиции (Lots) 0.1, ширину ЗУК 10 (Ds = 10) и коррекцию для стопа 5 (St = 5). Выберите стратегию №3. Для этого передвиньте вверх значок So и среди названий стратегий найдите значок S3, который также потяните вверх. Запустите функцию автоматической торговли, передвинув значок AT в верхнее положение.


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

Советник ChuvashovsChannels_Expert_ZZ (http://www.forextrade.ru/media/Image/MQLabs/50_ag/ChuvashovsChannels_Expert_ZZ.mq4)

Файлы стратегий для Autograf 4.0 (http://www.forextrade.ru/media/Image/MQLabs/50_ag/AG_Chuvashovs_ChannelsZZ.zip)

Развернутые результаты тестирования эксперта (http://www.forextrade.ru/media/Image/MQLabs/50_ag/Test.zip)

VladimirK
25-03-2010, 13:14
Вы сделали замечательную программу. (ТААЧ 1) К сожалению в ней нет StopLoss.
TrelingStop отслеживает по фракталам. Хотелось бы, что бы было два варианта
1- перевод в безубыток
2 - обычный регулируемый TrelingStop
Я Вас очень прошу дополнить программу.

Scriptong
25-03-2010, 19:24
Оба пункта я могу решить при помощи двухуровневого трейлинг-стопа, который реализован в Комплексном советнике (http://forum.fxservice.com/showthread.php?t=3724). Посмотрите, подойдет ли вам такой механизм.

VladimirK
26-03-2010, 13:42
Большое Вам спасибо за мастерски выполненную программу. Вы наверное еще не знаете, что доработанная Ваша прграмма уже существует. Мне вчера вечером ее дали. Пользуясь случаем,что Вы отзвались прошу Вас капельку изменить программу и несколько усложнить TrailingStop. Попытаюсь объяснить.
В Вашей статье ТС называется каналы Чувашова а я раньше читал оТС каналы Бариштольца системы практически близнецы. Немного отличаются лиш построением каналов. У Бариштольца не предполагается TakeProfit. Он описывает сопровождение удачного прфита так: на расстоянии 200-300п выставляет безубыток. Далее сопровождает цену на расстоянии 570п через каждые 100п.
Когда цена становиться значительной более 1000п терять 570 пунктов в случае поворота уже жаль. Поджимает цену на расстоян6ии вдвое меньшим и т.д до закрытия ордера. С такими изменениями система на много прбыльнее. Если можно
сделайте пожалуйста. Вы же Мастер. С благодарностью Владимир.

Scriptong
26-03-2010, 14:27
Вы наверное еще не знаете, что доработанная Ваша прграмма уже существует. Мне вчера вечером ее дали.

Ну как же я могу не знать о ее существовании, если сам ее написал?:)



Пользуясь случаем,что Вы отзвались прошу Вас капельку изменить программу и несколько усложнить TrailingStop. Попытаюсь объяснить.
В Вашей статье ТС называется каналы Чувашова а я раньше читал оТС каналы Бариштольца системы практически близнецы. Немного отличаются лиш построением каналов. У Бариштольца не предполагается TakeProfit. Он описывает сопровождение удачного прфита так: на расстоянии 200-300п выставляет безубыток. Далее сопровождает цену на расстоянии 570п через каждые 100п.
Когда цена становиться значительной более 1000п терять 570 пунктов в случае поворота уже жаль. Поджимает цену на расстоян6ии вдвое меньшим и т.д до закрытия ордера. С такими изменениями система на много прбыльнее.
Можно, конечно, и так. Но система редко оперирует такими значениями. До подхода к 100-200 пунктам, чаще всего, будет следовать противоположный сигнал. Так что трейлинг с предложенными значениями практически ничего не даст.
Но сделать - сделаю, мое дело малое.

VladimirK
28-03-2010, 10:39
Игорь ты уж извини пожалуйста за назойливость, но это в системе Чувашова прибыль не првышает 200п т.к. с одной стороны ограничена стенками канала ( тут уж ничего не пделаешь- это природа изменения цены) с другой TakeProfit хотя цена продолжает движение в том же направлении. На тестере и на демо довольно часто встречается трент 1500 и 2000п. вот его и поймаем. Кстати заметил один минус программы. Я заметил, что внутри канала ордера открываются реже. Стал наблюдать и увидел следующее: к примеру цена движется вверх. Достигает верхней границы канала. При пробое канала без вопросов открываются ордера. а там как уж получиться. А вот при отбое, формируется бар в противоположном направлении, далее должен открыться ордер. Но в это время на предыдущем баре где изменение тренда формируется новый фрактал. Перестраиается система канала и ордер не открывается т.к. в новой системе уже нет критерия для открытия ордера. Хотя цена движется в нужном направлении. Это ведет к упущеной выгоде. Может быть было бы целсообразно, как только цена подойдет к границе канала выставлять отложенный ордер в расчете на отбой хотя мы об этом еще не знаем. Или может быть на оди или два бара задержать перестройку канала. Я не знаю пока что лучше. На первый взгляд кажется прще выставить оложенный ордер на случай отбоя. Если призойдет прбой то мы вроде бы ничего не теряем.

Scriptong
29-03-2010, 08:14
Описанная проблема касается не только этой системы, а многих других. Задним числом мы всегда хорошо видим "правильные" сигналы и сигналы, которых лучше бы не видеть. Но в том то и дело, что во время формирования реакции на сигнал, еще невозможно определить, как отработает тот или иной критерий.

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

VladimirK
29-03-2010, 11:58
Ты совершенно прав. Детально проработанной системы у меня нет. Есть видение отдельной доработки отдельных моментов, которые позволят увеличить прибыльность. Но и в таком виде с 9.03.10 по 260310 программ принесла 440 д. Т.ч. большое тебе спасибо за программу. Когда у меня сформируются более конкретные предложения ты уж разреши к тебе обратиться за помощью.

Scriptong
30-03-2010, 17:42
Ты совершенно прав. Детально проработанной системы у меня нет. Есть видение отдельной доработки отдельных моментов, которые позволят увеличить прибыльность. Но и в таком виде с 9.03.10 по 260310 программ принесла 440 д. Т.ч. большое тебе спасибо за программу. Когда у меня сформируются более конкретные предложения ты уж разреши к тебе обратиться за помощью.

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

По стратегиям обращайтесь без стеснения, но только не в частном порядке, а в рамках форума.