Допустим, мы хотим открыть ордер на покупку (рыночный ордер BUY). При ручном открытии мы устанавливаем валютную пару, размер лота, стоп лосс и тейк профит. Сделаем то же самое программно, с помощью советника. Параметры ордера зададим во внешних переменных(в настройках) советника. Используем текущий график, то есть валютную пару явно указывать не будем. Тип ордера тоже в настройки пока выносить не будем, ( сделаем это в следующем примере ), укажем его непосредственно в функции открытия ордера. Проскальзывание так же менять не будем, укажем фиксированное значение, например 3 пункта.
Зададим размер лота, стоп лосс и тейк профит:
extern double lot=0.01;
extern int stoploss=20;
extern int takeprofit=30;
Стоп лосс и тейк профит удобнее задавать в пунктах, чтобы каждый раз при открытии ордера их не пересчитывать. Но в функции открытия ордера должна быть указана цена, то есть наш советник должен сам посчитать стопы. Для этого нужно определить 2 переменные типа double:
double sl,tp;
Магическое число magic нет смысла задавать в настройках, поэтому просто определим целочисленную переменную.
int magic=12345;
Главная функция советника (функция start () ), в которой мы и будем открывать ордер, запускается с каждым тиком, то есть если просто прописать внутри функции start() нашу функцию открытия ордера, советник будет открывать новые ордера с приходом каждого тика, до тех пор, пока хватит денег на депозите. Значит нужно как то ограничить количество открытых ордеров. Вообще то контроль ордеров должен присутствовать в любом советнике, но эту функцию мы рассмотрим позднее. Пока просто введём ограничение, если есть хотя бы одна открытая позиция, советник не должен открывать ордер. Для этого используем встроенную функцию MQL - OrdersTotal(). Эта функция возвращает общее количество ордеров, то есть если открытых ордеров нет, её значение равно 0. Так и запишем:
int start()
{
if(OrdersTotal()!=0)return;
/* если есть открытые ордера (OrdersTotal()!=0) дальнейшие операторы не выполняем, выходим из функции Start(), Если же открытых позиций нет, продолжаем работу советника*/
return(0);
}
Теперь нужно посчитать значение стоп лосса и тейк профита.
sl=Bid-stoploss*Point;
tp=Ask+takeprofit*Point;
Мы получили значение цен, на которых устанавливаются стопы, хотя в настройках у нас заданы целые числа (значения стопов в пунктах). Но тут есть один момент, а что будет если пользователь задаст в настройках значения стопов равным нулю?
sl=Bid-0*Point;
tp=Ask+0*Point;
то есть sl получится равным Bid, а tp равным Ask. Терминал в таком случае выдаст ошибку: - неправильные стопы. Такие ошибки также будут рассмотрены позднее, а пока просто устраним этот дефект.
if(stoploss!=0) //если стоп лосс не равен нулю
sl=Bid-stoploss*Point; //высчитываем значение цены установки стоп лосс
extern double lot=0.01; extern int stoploss=20; extern int takeprofit=30; double sl,tp; int magic=12345; int start() { if(OrdersTotal()!=0)return; if(stoploss!=0) sl=Bid-stoploss*Point; else sl=0; if(takeprofit!=0) tp=Ask+takeprofit*Point; else tp=0; OrderSend(Symbol(),OP_BUY,lot,Ask,3,sl,tp,"",magic,0,Red); return(0); }
После компиляции можно прогнать этот советник в тестере стратегий и поэкспериментировать изменяя значения стоп лосса и тейк профита. Наверняка вы заметите, что при каких то значениях стопов советник перестанет работать, то есть не будет открывать ордера. Если заглянуть в журнал, можно увидеть ту же самую ошибку, неправильные стопы. Это связано с некоторыми ограничениями на установку стопов. Ведь и вручную вы не сможете поставить стоп лосс или тейк профит ближе определённого расстояния от цены. Это расстояние называется STOPLEVEL, обычно 3-5 пунктов. (зависит от брокера) Узнать это расстояние можно при помощи функции MarketInfo(Symbol(),MODE_STOPLEVEL); Возникает вопрос: что делать в этом случае? Тут есть 2 варианта, совсем не открывать сделку и просто выйти из функции установки ордера ( на мой взгляд более предпочтительный вариант ), либо открыть сделку с минимально допустимыми стопами (stoplevel+1 пункт).