КАК ЗАРАБОТАТЬ НА ФОРЕКСЕ
Пятница, 03.05.2024, 16:26
Приветствую Вас Гость | RSS
 
Главная Учимся программировать на языке MQL4-Урок 17 - Ваш первый советник (часть 4)РегистрацияВход
<a href="http://instaforex.com/ru/">Форекс портал</a>
Меню сайта
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0
Форма входа
Урок 17 - Ваш первый советник (часть 4)

Мы дошли до края света в поисках истины! Нет, сегодня я не пил. Я просто счастлив, что наконец-то мы дошли до последней части серии уроков, посвящённых нашему первому эксперту!
Итак, начнём.

Код, который мы уже имеем:

Код:
//+------------------------------------------------------------------+
//| My_First_EA.mq4 |
//| Kirill |
//| StockProgrammer@mail.ru |
//+------------------------------------------------------------------+
#property copyright "Kirill"
#property link "StockProgrammer@mail.ru"

//---- input parameters
extern double TakeProfit=350.0;
extern double Lots=0.1;
extern double TrailingStop=35.0;
//+------------------------------------------------------------------+
//| expert initialization function |
//+------------------------------------------------------------------+
int init()
{
//----

//----
return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----

//----
return(0);
}

int Crossed (double line1 , double line2)
{
static int last_direction = 0;
static int current_dirction = 0;

if(line1>line2)current_dirction = 1; //up
if(line1<line2)current_dirction = 2; //down

if(current_dirction != last_direction) //changed
{
last_direction = current_dirction;
return (last_direction);
}

else
{
return (0);
}

}

//+------------------------------------------------------------------+
//| expert start function |
//+------------------------------------------------------------------+

int start()
{
//----
int cnt, ticket, total;
double shortEma, longEma;

if(Bars<100)
{
Print("bars less than 100");
return(0);
}

if(TakeProfit<10)
{
Print("TakeProfit less than 10");
return(0); // check TakeProfit
}

shortEma = iMA(NULL,0,8,0,MODE_EMA,PRICE_CLOSE,0);
longEma = iMA(NULL,0,13,0,MODE_EMA,PRICE_CLOSE,0);

int isCrossed = Crossed (shortEma,longEma);

total = OrdersTotal();
if(total < 1)
{
if(isCrossed == 1)
{
ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,Ask+TakeProfit*Point, "My EA",12345,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);
}

if(isCrossed == 2)
{
ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,3,0,
Bid-TakeProfit*Point,"My EA",12345,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 && OrderSymbol()==Symbol())
{
if(OrderType()==OP_BUY) // long position is opened
{
// should it be closed?
if(isCrossed == 2)
{
OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); // close position
return(0); // exit
}

// check for trailing stop
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 // go to short position
{
// should it be closed?
if(isCrossed == 1)
{
OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet); // close position
return(0); // exit
}

// check for trailing stop
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);
}

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

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

Мы исполльзовали след. код:

Код:
 if(total < 1)
{
if(isCrossed == 1)
{

...

}

if(isCrossed == 2)
{

...

}

return(0);
}

Это был алгоритм открытия новых сделок. Сегодня мы изучим алгоритм закрытия и модификации уже открытых сделок.

Код:
 for(cnt=0;cnt<total;cnt++)
{

...

}

В вышеуказанном блоке мы используем цикл for для перебора всех открытых ордеров.
Мы начинаем цикл с cnt=0, потому что индексация (не тикеты, а именно их индексы в массиве, где они храняться) ордеров начинается с 0. На каждом щаге цикла мы увеличиваем cnt на 1 (cnt++).
Наша сегодняшняя задача заключается в изучении тела данного цикла.

Код:
 OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
if(OrderType()<=OP_SELL && OrderSymbol()==Symbol())
{

...

}
Функция OrderSelect() используется для выбора открытого или отложенного ордера по его тикету или индексу. В этом цикле мы вызвали функцию OrderSelect() перед функциями OrderType() и OrderSymbol(), потому что если бы мы не вызвали её, то вторые две функции просто напросто не сработали бы.

Замечание: Функцию OrderSelect() необходимо вызывать перед следующими функциями, не принимающими никаких параметров:

OrderMagicNumber, OrderClosePrice, OrderCloseTime, OrderOpenPrice,

OrderOpenTime, OrderComment, OrderCommission, OrderExpiration, OrderLots,

OrderPrint, OrderProfit, OrderStopLoss, OrderSwap, OrderSymbol, OrderTakeProfit,

OrderTicket и OrderType


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

Замечание: Индекс первого оредра: 0, второго: 1 и т.д.

Мы использовали режим MODE_TRADES, который означает, что мы будем выбирать ордер из открытых (или отложенных) на данный момент ордеров. Т.е. - не из истории.

Функция OrderType() возвращает тип выбранного ордера. Тип может принимать одно из след. значений:

OP_BUY, OP_SELL, OP_BUYLIMIT, OP_BUYSTOP, OP_SELLLIMIT или OP_SELLSTOP

Причём этими названиями закодированы обычные числа:


Мы проверяем, верно ли то, что тип выбранного ордера меньше либо равен значения OP_SELL. Это означает, что возможно лишь два варианта: OP_SELL и OP_BUY. Эта проверка необходима, т.к. мы не хотим трогать чужие отложенные ордра.
Также мы хотим работать только с ордерами, которые были открыты на валютном инструменте, на график которого мы подгрузили эксперта.
Так что весь последующий код будет работать тоолько, если OrderType() равен OP_SELL или OP_BUY, а OrderSymbol() равен Symbol()

Код:
 if(OrderType()==OP_BUY) // long position is opened
{

...

}

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

Код:
 // should it be closed?
if(isCrossed == 2)
{
OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); // close position
return(0); // exit
}

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

Для закрытия сделки мы используем функцию OrderClose(). Подробнее см. урок 15 - торговые функции.
Первым параметром она принимает значение тикета закрываемого ордера. Тикет мы предоставляем, используя функцию OrderTicket().
Вторым параметром функция принимает lots - количество лотов для закрытия (ВАЖНО: т.е. можно неполностью закрывать сделку). В нашем случае мы хотим закрыть весь ордер, поэтому в качестве lots предоставляем значение, возвращаемое функцией OrderLots().
Третим параметром функции OrderClose() является предпочитаемая цена закрытия. Ордер на покупку мы закрываем по тек. цене Bid.
Четвёртым параметром является slippage (допустимое проскальзывание цены исполнения). Здесь мы использовали значение 3.
Пятым параметром является цвет закрывающей стрелки. Мы использовали фиолетовый.

Затем мы не забыли завершить функцию start() оператором return(0);

Код:
 // check for trailing stop
if(TrailingStop>0)
{
if(Bid-OrderOpenPrice()>Point*TrailingStop)
{
if(OrderStopLoss()<Bid-Point*TrailingStop)
{
OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Green);
return(0);
}
}
}

Замечание: мы всё ещё находимся внутри блока if(OrderType()==OP_BUY)

В этом блоке кода мы применим технику треилинг-стопа к нашей открытой Buy позиции.
Для начала, мы проверяем, что предоставленное пользователем значение TrailingStop является пригодным (большим 0).
Затем мы проверяем, что:
1. Разница между тек. ценой Bid и ценой открытия сделки больше, чем величина TrailingStop. Это необходимо для того, чтобы треилинг стоп начинал работать толко при переносе стоп-лосса в безубыток. До этого момента стоп-лосс остаётся фиксированным.
2. Текущий стоп-лосс находится ниже, чем он должен быть. Т.е. ниже той цены, которую мы получим, если из тек. цены Bid вычтем величину TrailingStop.

Для осуществления необходимых модификаций мы применяем функцию OrderModify(). Подробнее см. урок 15 - торговые функции.
Её параметры следующие:
ticket: Тикет предоставляем с помощью функции OrderTicket().
price: У нас есть цена открытия ордера благодаря функции OrderOpenPrice().
stoploss: Вот то, что нам на самом деле нужно. Т.к. у нас сделка на покупку, то мы выставляем новый стоп-лосс на уровне, получаемом при вычитании из тек. цены Bid величины TrailingStop.

Замечание: Для сделки BUY стоп-лосс должен всегда находится НИЖЕ тек. цены bid. А для сделки SELL - ВЫШЕ тек. цены ask.

takeprofit: Без изменений. Тек. значение тейк-профита мы предоставляем функцией OrderTakeProfit().
expiration: Это не отложенный ордер у него нет срока истесения. Поэтому 0.
arrow_color: Оставляем зелёный цвет.

Наконец-то мы завершаем функцию start().

Код:
 else // go to short position
{

...

}

Этот блок выполняется в случае, если рассматриваемый ордер не на покупку, а на продажу. Строение и реализация этого блока (блока обработки ордера SELL) абсолютно аналогичны строению и реализации блоку обработки ордера BUY. Попробуйте разобраться с ним самостоятельно.

И в самом конце у нас есть строчка:

Код:
 return(0);

Эта строчка завершает функцию во всех остальных случаях: когда нет условий для открытия новых ордеров, нет условий для их закрытия или модификаций.

Надеюсь, вам понравился этот урок
Поиск
<a href="http://instaforex.com/ru/">Форекс портал</a>
Copyright MyCorp © 2024
Бесплатный конструктор сайтов - uCoz