[АРХИВ!] Любой вопрос новичка, чтоб не захламлять форум. Профи, не проходите мимо. Без вас никуда - 4. - страница 566

 
delf:

Наверное я не правильно сформулировал, что нужно :(

Есть есть алгоритм открытия ордеров.

Нужно, чтобы при любом варианте закрытия последнего ордера, следующий открывался в другом направлении ( при появлении условий соответственно). 

Все работает, но если закрылся по стоп лосс, например по sell,  а условия на открытие по sell в данном направлении есть, то  открытия продолжаются. А надо, что бы ждал условий на buy.

То есть, нужна проверка последнего закрытого ордера, что бы он не совпадал с открывающимся (чередование  buy-sell-buy-sell). В работе только один ордер или ожидание сигнала.  

 Понимаю, что скорее всего надо через   OrdersHistoryTotal(), но как это может  выглядеть в работающем советнике ?

Спасибо.


Наверно где то так. Но если ордеров в истории много лучше использовать свой учет ордеров.https://www.mql5.com/ru/articles/1404   https://www.mql5.com/ru/articles/1390
//+------------------------------------------------------------------+
//|                                                         0000.mq4 |
//+------------------------------------------------------------------+
#property copyright ""
#property link      ""
void CloseOrder(string signal)
   {
   int      i,Ticket=-1,error; 
   double   Price;
   datetime time=0;
   for (i=0;i<OrdersHistoryTotal();i++)  
      {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_HISTORY));
         {
         error=GetLastError();Print("Ошибка OrderSelect() = ", error);
      }
      if(OrderSymbol()==Symbol()&&(OrderMagicNumber()==magic
      ||OrderClosePrice()==OrderStopLoss())
         {
         if(OrderCloseTime()>time)
            {
            time=OrderCloseTime();Ticket=OrderTicket();
         }
      }
   }
   if(!OrderSelect(Ticket,SELECT_BY_TICKET,MODE_HISTORY))
      {
      error=GetLastError();Print("Ошибка OrderSelect() = ",error);
   }
   if(OrderType()==OP_BUY&&signal=="CloseBUY"||OrderType()==OP_SELL&&signal=="CloseSELL")return;
   if(signal=="CloseBUY")Price=NormalizeDouble(Bid,Digits);
   if(signal=="CloseSELL")Price=NormalizeDouble(Ask,Digits);
   for (i=0;i<OrdersTotal();i++)  
      {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES));
         {
         error=GetLastError();Print("Ошибка OrderSelect() = ",error);
      }
      if(OrderSymbol()==Symbol()&&(OrderMagicNumber()==magic)
         {
         if(OrderType()==OP_BUY&&signal=="CloseBUY"||OrderType()==OP_SELL||signal=="CloseSELL")
            {
            Ticket=OrderClose(OrderTicket(),OrderLots(),Price,0,CLR_NONE);
         }
      }
      if(Ticket<0)
         {
         error=GetLastError();Print("Ошибка = ",error);
      }
   }
   return;
}
       
 
peshihod:

Более строгий вариант

Огромное спасибо всем откликнувшимся, результат достигнут, то что нужно.  
 
delf:

Наверное я не правильно сформулировал, что нужно :(

Есть есть алгоритм открытия ордеров.

Нужно, чтобы при любом варианте закрытия последнего ордера, следующий открывался в другом направлении ( при появлении условий соответственно). 

Все работает, но если закрылся по стоп лосс, например по sell,  а условия на открытие по sell в данном направлении есть, то  открытия продолжаются. А надо, что бы ждал условий на buy.

То есть, нужна проверка последнего закрытого ордера, что бы он не совпадал с открывающимся (чередование  buy-sell-buy-sell). В работе только один ордер или ожидание сигнала.  

 Понимаю, что скорее всего надо через   OrdersHistoryTotal(), но как это может  выглядеть в работающем советнике ?

Спасибо. 

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

Алгоритм решения Вашей задачи может быть таким. Сначала убеждаетесь в отсутствии "своих" ордеров. Эта задача, если не для тестера (где можно ограничится условием if (OrdersTotal() == 0)), решается перебором ордеров с использованием фильтров на соответствие OrderMagicNumber() и Symbol(). Затем проверяете условие (по своей стратегии) на открытие ордера. Если есть сигнал, то по перебору OrdersHistoryTotal() (обычно это последний в списке) вычисляете OrderType() последнего закрытого ордера. Если сигнал на открытие и тип последнего закрытого ордера не совпадают, открываете по сигналу ордер.

Такой подход содержит минимум расчётов и значительно уменьшает время оптимизации советника в тестере.

 
TarasBY:
Какое-то время назад я Вам давал алгоритм решения поиска последних позиций. А что потом с ними делать НЕ ВАЖНО: считать, удалять, модифицировать СТОПы. Если Вы не в состоянии писать код хотя бы "по образу и подобию", то это не Ваше (программировать)...


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

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

double profits_buy_2pos()
{
    int ordercount = 0, OpenOrders = OrdersTotal();
    double pr_buy = 0;
    for (int cnt = OpenOrders - 1; cnt >= 0; cnt--)   // scan all orders and positions. ..
    {
        if (!OrderSelect (cnt, SELECT_BY_POS)) return (0.0);
        if (OrderSymbol() != Symbol()) continue;
        if (OrderMagicNumber() != magic) continue;
        if (OrderType() != OP_BUY) continue;
        pr_buy += OrderProfit();
        ordercount++;
        if (ordercount == 2) break;
    } 
    Print ("::::::::::::::::::::::::: pr_buy2 = ", pr_buy);   
    Print ("::::::::::::::::::::::::: ordercount = ", ordercount);    
    return (pr_buy);   
}

 
TarasBY:

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

Полностью с Вами согласен. Вы правы на 100%. Это правильный путь и я честно  пытался по нему идти. Но изучение MQL4 на уровне учебников и чтения без цели ни к чему не привело. По любому приходилось разбирать чужие коды, т. к.  свои безумные идеи засунуть в рамки программы большей частью не получалось. Начал строить стратегию в ....excel (он мне ближе и понятнее). По отбивке основы стратегии очень даже удачно и наглядно (на истории разумеется).  Честная  математика показывает прибыль или убыток как есть.  А вот дальше надо все таки принимать во внимание особенности торговли: спред плавающий, своп, особенности ДЦ, все это  засунуть в формулы  exel уже сложно. Вот и захотелось посмотреть какова разница между прибылью в excel  и MQL. Честно -  разница боольшая, не в мою пользу. Почему, пока не знаю, буду разбирать каждую позицию, может в советнике ошибка, но это уже я сам.

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

 
Ekburg:

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

Ошибка 1 выдается только если все параметры, передаваемые в функцию OrderModify( ), равны всем параметрам модифицируемого ордера, выбранного вами( по номеру тикета) или функцией OrderSelect() для модификации. Пример использования проверки: 

Только "Полезные функции от KimIV".

Функция ModifyOrder() https://www.mql5.com/ru/forum/131859

 

 
rigonich:

Ошибка 1 выдается только если все параметры, передаваемые в функцию OrderModify( ), равны всем параметрам модифицируемого ордера, выбранного вами( по номеру тикета) или функцией OrderSelect() для модификации. 

1 (ERR_NO_RESULT) - если ни один из параметров не был изменен или Нет ошибки, но результат неизвестен, скорее всего просто, по какой то причине ордер не модифицируется...
 
abeiks:

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

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

int Slippage = 3;
int Close_buy_2pos()
{
    int ordercount = 0, OpenOrders = OrdersTotal();
    for (int cnt = OpenOrders - 1; cnt >= 0; cnt--)   // scan all orders and positions. ..
    {
        if (!OrderSelect (cnt, SELECT_BY_POS)) return (ordercount);
        if (OrderSymbol() != Symbol()) continue;
        if (OrderMagicNumber() != magic) continue;
        if (OrderType() != OP_BUY) continue;
        if (OrderClose (OrderTicket(), OrderLots(), Bid, Slippage)) ordercount++;
        else return (ordercount);
        if (ordercount == 2) break;
    } 
    Print ("::::::::::::::::::::::::: ordercount = ", ordercount);    
    return (ordercount);   
}

В общем случае так. Если же использовать "маразматический" вариант (я пользую именно его), то нужно запускать цикл: сначала отыскать последнюю открытую позицию BUY, затем её по тикету удалить и так повторить столько раз, сколько нужно.

P.S. Писать отдельно функции для BUY и SELL - это изначально криворукий вариант (ИМХО).

И функция, в таком случае, будет выглядеть не на много сложнее: 

int Slippage = 3;
int Close_LastPos (string fs_Symbol,
                   int fi_Magic,
                   int fi_Type = -1,   // тип закрываемых позиций
                   int fi_cnt = 1)     // количсетво закрываемых позиций
{
    int ordercount = 0, OpenOrders = OrdersTotal();
    double ld_PriceClose;
    for (int cnt = OpenOrders - 1; cnt >= 0; cnt--)   // scan all orders and positions. ..
    {
        if (!OrderSelect (cnt, SELECT_BY_POS)) return (ordercount);
        if (OrderSymbol() != fs_Symbol) continue;
        if (OrderMagicNumber() != fi_Magic) continue;
        if (OrderType() != fi_Type) if (fi_Type != -1) continue;
        if (OrderType() > 1) continue;
        if (OrderType() == OP_BUY) ld_PriceClose = NormalizeDouble (Bid, Digits);
        else ld_PriceClose = NormalizeDouble (Ask, Digits);
        if (OrderClose (OrderTicket(), OrderLots(), ld_PriceClose, Slippage)) ordercount++;
        else return (ordercount);
        if (ordercount == fi_cnt) break;
    } 
    Print ("::::::::::::::::::::::::: ordercount = ", ordercount);    
    return (ordercount);   
}
 
Ekburg:

1 (ERR_NO_RESULT) - если ни один из параметров не был изменен или Нет ошибки, но результат неизвестен, скорее всего просто, по какой то причине ордер не модифицируется...
ERR_NO_RESULT это не или, а именно  Нет ошибки, но результат неизвестен . В каких случаях возвращается эта ошибка указано выше. Если после функции OrderModify() вызывается функция GetLastError(), она обязательно вернет код ошибки (то есть причину, по которой  ордер не модифицирован) или 0 (в случае успешной модификации).Успешной модификацией считается отправка на торговый сервер торгового приказа на модификацию ордера и получение от севера ответа что торговый приказ исполнен.  

 
TarasBY:

В общем случае так. Если же использовать "маразматический" вариант (я пользую именно его), то нужно запускать цикл: сначала отыскать последнюю открытую позицию BUY, затем её по тикету удалить и так повторить столько раз, сколько нужно.

P.S. Писать отдельно функции для BUY и SELL - это изначально криворукий вариант (ИМХО).

И функция, в таком случае, будет выглядеть не на много сложнее: 


Спасибо, буду разбираться.

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