Любые вопросы новичков по MQL4 и MQL5, помощь и обсуждение по алгоритмам и кодам - страница 248

 
STARIJ:

Интернет включили! Можно на почту писать?


Да, я на связи. Пишите. 

 

Помогите доработать советник я начинающий программист, описание:

Советник работает по двум валютным парам EURUSD и USDCHF,  открывает две сделки только на покупку в том случае, когда происходит расхождение на 10пп (по сути - это стандартный арбитражёр).

Вот условие:  if ((ind2>ind1+impulse*Point && ind3<ind4-impulse*Point) || (ind2<ind1-impulse*Point && ind3>ind4+impulse*Point)) 

И закрывает, когда общая прибыль/убыток достигает определённого значения:  if ((AccountProfit()>=10)||(AccountProfit()<=-20))


CУТЬ ПРОБЛЕММЫ: Не всегда открывает 2 сделки, а бывает открывает 3. Или открывает две сделки по одной валюте. Нужно чтобы: открывал всегда 2 сделки по разным валютам ( одна - по EURUSD; другая- по USDCHF) 



Вот сам код: 


extern double impulse = 10;  // Глобальные переменные 

extern double Lots = 1;


int start()

{

double ind2=iClose("EURUSD",PERIOD_M1,0);

double ind1=iOpen("EURUSD",PERIOD_M1,0);


double ind3=iClose("USDCHF",PERIOD_M1,0);

double ind4=iOpen("USDCHF",PERIOD_M1,0);


double oper1=ind2-ind1;

double EUR=(int)DoubleToStr(oper1*100000,0);


double oper2=ind3-ind4;

double CHF=(int)DoubleToStr(oper2*100000,0);


Comment(StringFormat("Выводим данные\nEUR = %G\nCHF =%G",EUR,CHF)); 

if ((AccountProfit()>=10)||(AccountProfit()<=-20))  //    Условие закрытие 

Alert3();

if ((ind2>ind1+impulse*Point && ind3<ind4-impulse*Point) || (ind2<ind1-impulse*Point && ind3>ind4+impulse*Point))   // Условие открытия

if (OrdersTotal() == 0)

Alert1();

if (OrdersTotal() == 1)

Alert2();

return(0);

}


int Alert1()

{

if (OrdersTotal() == 0)

int send1=OrderSend("EURUSD",OP_BUY,Lots,Ask,3,0,0); 

return(0);

}


int Alert2()

{

if(OrdersTotal() == 1) 

int send2=OrderSend("USDCHF",OP_BUY,Lots,Ask,3,0,0);

return(0);

}


int Alert3()

while (OrdersTotal()>0)

if (OrderSelect(0, SELECT_BY_POS, MODE_TRADES))     //Закрытие

int cl1=OrderClose (OrderTicket(),OrderLots(),Bid,3);

int cl1=OrderClose (OrderTicket(),OrderLots(),Ask,3);

return(0);

}

 

Alexey Belyakov:  CУТЬ ПРОБЛЕММЫ: Не всегда открывает 2 сделки, а бывает открывает 3. Или открывает две сделки по одной валюте. Нужно чтобы: открывал всегда 2 сделки по разным валютам ( одна - по EURUSD; другая- по USDCHF)

Серверу приказ открыть Евро. Пока дойдет до сервера, пока сервер ... Пока что ордеров 0. На следующем тике опять условие выполняется и вновь приказ открыть Евро. Сервер открыл первый ордер. Раз ордеров 1, посылается команда открыть второй (а он уже третий!) ордер.

Сделал все функции void и убрал return. Вот эту часть программы (для вставки нажал кнопку SRC)

  if((ind2>ind1+impulse*Point && ind3<ind4-impulse*Point) ||
     (ind2<ind1-impulse*Point && ind3>ind4+impulse*Point))   // Условие открытия
     if(OrdersTotal() == 0) Alert1();
     if(OrdersTotal() == 1) Alert2();
}

void Alert1()
{
  if (OrdersTotal() == 0)  // Перед вызовом этой функции уже проверялось количество ордеров
  int send1=OrderSend("EURUSD",OP_BUY,Lots,Ask,3,0,0);
}

void Alert2()
{
  if(OrdersTotal() == 1)  // Перед вызовом этой функции уже проверялось количество ордеров
  int send2=OrderSend("USDCHF",OP_BUY,Lots,Ask,3,0,0);
}

заменил (грубовато, но IMHO лучше исходного) на

  if((ind2>ind1+impulse*Point && ind3<ind4-impulse*Point) ||
     (ind2<ind1-impulse*Point && ind3>ind4+impulse*Point))   // Условие открытия
     if(OrdersTotal() == 0)
  {
    int send1=OrderSend("EURUSD",OP_BUY,Lots,Ask,3,0,0); 
    int send2=OrderSend("USDCHF",OP_BUY,Lots,Ask,3,0,0);
    Sleep(60); // Дождаться следующего бара, а то еще пооткрывает
  }
}

В функции Alert3 лишняя строка

  int cl1=OrderClose (OrderTicket(),OrderLots(),Ask,3);
Вместо double CHF=(int)DoubleToStr(oper2*100000,0);  попробуйте   int CHF=oper2/_Point;
 
STARIJ:

заменил (грубовато, но IMHO лучше исходного) на

Не грубовато, а работать будет с ошибками. Хотя бы потому, что оба ордера идут по Ask одного символа.
 
Alexey Kozitsyn:   Не грубовато, а работать будет с ошибками. Хотя бы потому, что оба ордера идут по Ask одного символа.

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

 
STARIJ:

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

Да. Если, конечно, условия открытия будут выполнены. Ask для второго символа нужно получить отдельно.
 
Привет всем. Вопрос наивный, касается функции OrdersTotal().  Понятно, что она возвращает количество ордеров, а нумерация ордеров происходит от 0 к N. Но если бары нумеруются от нового открытого в историю ,т.е. "свеженький" бар нумеруется как 0, древний N. А в функции OrdersTotal(), как я понял, происходит все наоборот - древний открытый ордер нумеруется как 0, "свеженький" как N. Я правильно понял?  
 
Youri Lazurenko:
Привет всем. Вопрос наивный, касается функции OrdersTotal().  Понятно, что она возвращает количество ордеров, а нумерация ордеров происходит от 0 к N. Но если бары нумеруются от нового открытого в историю ,т.е. "свеженький" бар нумеруется как 0, древний N. А в функции OrdersTotal(), как я понял, происходит все наоборот - древний открытый ордер нумеруется как 0, "свеженький" как N. Я правильно понял?  

Вполне, но есть нюансы.

Было время когда сортировка зависела от сортировки в терминале. Никто точно из пользователей сказать не может - вернётся ли "вдруг" то самое время когда сортировка опять станет зависеть от сортировки в терминале. Поэтому надёжней собирать ордера в массив и сортировать его по времени открытия/закрытия - тогда вы точно будете знать что ваша сортировка зависит от времени, а не "вдруг" от сортировки в терминале.

 
Artyom Trishkin:

Вполне, но есть нюансы.

Было время когда сортировка зависела от сортировки в терминале. Никто точно из пользователей сказать не может - вернётся ли "вдруг" то самое время когда сортировка опять станет зависеть от сортировки в терминале. Поэтому надёжней собирать ордера в массив и сортировать его по времени открытия/закрытия - тогда вы точно будете знать что ваша сортировка зависит от времени, а не "вдруг" от сортировки в терминале.


Здравствуйте. Спасибо за ответ. В начале хочу вернуться к предыдущему вашему ответу на мой вопрос, на счет обратного цикла. Вчера, перед уходом на работу, я написал ответ, а сегодня, не нашел вообще своих (и ваших) постов. Как я понял задал не в той ветке. Обратный цикл это  i--?

"Поэтому надёжней собирать ордера в массив и сортировать его по времени открытия/закрытия" - очень интересно и, как мне кажется надежно и более правильно (и мне показалось, при определении последнего ордера, не всегда получается то что нужно). Если не трудно, в ощих чертах, как это сделать (создать массив и по времени открытия)?

И еще. Пока мысль и см еще не пробовал ее осуществить. Есть профитные и убыточные (локирующие) ордера. Профитные ордера закрываются по тралящему стопу. Как записать, что  ордера закрылись, чтобы потом сравнить их общий профит с профитом убыточных и, при положительном балансе, закрыть и убыточные. Меня интересует именно, что ордера закрылись. 

 
STARIJ:

 Полагаю, позиции будут открываться лишь по символу, на графике которого расположен советник. Так?

Если эксперт работает на EURUSD, а хотите вставить ордер BUY по  USDCHF

тогда в OrderSend нужно использовать MarketInfo("USDCHF",MODE_ASK); вместо Ask (он будет по EURUSD)

Причина обращения: