Сопровождение ордеров

 

Привет всем! Понадобилась такая штука: есть допустим пять ордеров селл на разных инструментах, мне нужно при прохождении ордером 20 пунктов закрыть 0.01 лот, при прохождении 40 пунктов - 0.02 лота и т.д. Собственно проблема в том что я не могу сообразить как запоминать ордера уже отработанные? То есть один ордер прошел 20 пунктов и закрылась часть 0.01 лот, дальше ждем прохождения 40 пунктов что бы закрыть 0.02 лота. У меня сейчас при прохождении 20 пунктов постоянно закрывается по 0.01 лоту один и тот же ордер. Не знаю правильно ли объяснил, но надеюсь Вы поймете...

Выглядит это так (прошу не судить строго):

void Closer()
{
   double _Ask=0,_Bid=0;
   for(int i=OrdersTotal()-1;i>=0;i--)
   {
      if(OrderSelect(i,SELECT_BY_POS))
      {
         double point=SymbolInfoDouble(OrderSymbol(),SYMBOL_POINT);
         int digits=(int)SymbolInfoInteger(OrderSymbol(),SYMBOL_DIGITS);
         prof1=NormalizeDouble(prof_1*point,digits);
         prof2=NormalizeDouble(prof_2*point,digits);
         prof3=NormalizeDouble(prof_3*point,digits);
         prof4=NormalizeDouble(prof_4*point,digits);
         prof5=NormalizeDouble(prof_5*point,digits);
         Break=NormalizeDouble(breakeven*point,digits);
         Break_price=NormalizeDouble(breakeven_price*point,digits);
         Stop=NormalizeDouble(stop*point,digits);
         
         _Ask=SymbolInfoDouble(OrderSymbol(),SYMBOL_ASK);
         _Bid=SymbolInfoDouble(OrderSymbol(),SYMBOL_BID);
         if(OrderType()==OP_BUY)
         {
            if(_Bid>=OrderOpenPrice()+Break)
            {
               if(NormalizeDouble(OrderStopLoss(),_Digits)!=NormalizeDouble(OrderOpenPrice()+Break_price,_Digits))
               {
                  if(!OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()+Break_price,OrderTakeProfit(),0))Print("Order #",OrderTicket()," not remove to Breakeven! Error: ",GetLastError());
               }
            }
            if(_Bid<=OrderOpenPrice()-Stop)
            {
               if(!OrderClose(OrderTicket(),OrderLots(),_Bid,Slippage))Print("Order #",OrderTicket()," not close! Error: ",GetLastError());
            }
            if(_Bid>=OrderOpenPrice()+prof1&&ab[i]!=OrderOpenPrice())
            {
               if(!OrderClose(OrderTicket(),lot_1,_Bid,Slippage))Print("Order #",OrderTicket()," not close! Error: ",GetLastError());
               else ab[i]=OrderOpenPrice();
               Print(ab[i]);
            }
            if(_Bid>=OrderOpenPrice()+prof2&&bb[i]!=OrderOpenPrice())
            {
               if(!OrderClose(OrderTicket(),lot_2,_Bid,Slippage))Print("Order #",OrderTicket()," not close! Error: ",GetLastError());
               else bb[i]=OrderOpenPrice();
            }
            if(_Bid>=OrderOpenPrice()+prof3&&cb[i]!=OrderOpenPrice())
            {
               if(!OrderClose(OrderTicket(),lot_3,_Bid,Slippage))Print("Order #",OrderTicket()," not close! Error: ",GetLastError());
               else cb[i]=OrderOpenPrice();
            }
            if(_Bid>=OrderOpenPrice()+prof4&&db[i]!=OrderOpenPrice())
            {
               if(!OrderClose(OrderTicket(),lot_4,_Bid,Slippage))Print("Order #",OrderTicket()," not close! Error: ",GetLastError());
               else db[i]=OrderOpenPrice();
            }
            if(_Bid>=OrderOpenPrice()+prof5&&eb[i]!=OrderOpenPrice())
            {
               if(!OrderClose(OrderTicket(),lot_5,_Bid,Slippage))Print("Order #",OrderTicket()," not close! Error: ",GetLastError());
               else eb[i]=OrderOpenPrice();
            }
         }
         if(OrderType()==OP_SELL)
         {
            if(_Ask<=OrderOpenPrice()-Break)
            {
               if(NormalizeDouble(OrderStopLoss(),_Digits)!=NormalizeDouble(OrderOpenPrice()-Break_price,_Digits))
               {
                  if(!OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()-Break_price,OrderTakeProfit(),0))Print("Order #",OrderTicket()," not remove to Breakeven! Error: ",GetLastError());
               }
            }
            if(_Ask>=OrderOpenPrice()+Stop)
            {
               if(!OrderClose(OrderTicket(),OrderLots(),_Ask,Slippage))Print("Order #",OrderTicket()," not close! Error: ",GetLastError());
               else Print(_Ask,"   ",OrderOpenPrice()+Stop);
            }
            if(_Ask<=OrderOpenPrice()-prof1&&aS[i]!=OrderOpenPrice())
            {
               if(!OrderClose(OrderTicket(),lot_1,_Ask,Slippage))Print("Order #",OrderTicket()," not close! Error: ",GetLastError());
               else aS[i]=OrderOpenPrice();
               Print(aS[i]);
            }
            if(_Ask<=OrderOpenPrice()-prof2&&bs[i]!=OrderOpenPrice())
            {
               if(!OrderClose(OrderTicket(),lot_2,_Ask,Slippage))Print("Order #",OrderTicket()," not close! Error: ",GetLastError());
               else bs[i]=OrderOpenPrice();
            }
            if(_Ask<=OrderOpenPrice()-prof3&&cs[i]!=OrderOpenPrice())
            {
               if(!OrderClose(OrderTicket(),lot_3,_Ask,Slippage))Print("Order #",OrderTicket()," not close! Error: ",GetLastError());
               else cs[i]=OrderOpenPrice();
            }
            if(_Ask<=OrderOpenPrice()-prof4&&ds[i]!=OrderOpenPrice())
            {
               if(!OrderClose(OrderTicket(),lot_4,_Ask,Slippage))Print("Order #",OrderTicket()," not close! Error: ",GetLastError());
               else ds[i]=OrderOpenPrice();
            }
            if(_Ask<=OrderOpenPrice()-prof5&&es[i]!=OrderOpenPrice())
            {
               if(!OrderClose(OrderTicket(),lot_5,_Ask,Slippage))Print("Order #",OrderTicket()," not close! Error: ",GetLastError());
               else es[i]=OrderOpenPrice();
            }
         }
      }
   }
}
 

ваши темы можно обнулить и отписаться ?

это были заезды на наёмниках ?? включая продукты

 
Maxim Kuznetsov:

ваши темы можно обнулить и отписаться ?

это были заезды на наёмниках ?? включая продукты

Будьте добры - объясните что Вы написали...

 
Maksim Neimerik:

Выглядит это так (прошу не судить строго):

Этот код выглядит как несколько разных способов сопровождения ордера, а в своем сообщении Вы ищете способ частично закрывать ордера на разных символах

Задача частичного закрытия ордера, довольно сложна, т.к. после удачного частичного закрытия ордера у оставшейся части ордера будет новый тикет, и как было ранее обсуждение с однозначным выводом (не могу утверждать с уверенностью, мало проверял), что у этого ордера будет комментарий ордера OrderComment()  "подписанный сервером" что то про partial close ? - если поиском пройдетесь по форуму должны найти решения как проанализировать комментарий ордера на предмет частичного закрытия - мне не нравится это решение

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


ЗЫ: для себя я делал через динамические списки, если нужно было закрыть ордер частично - запоминал все тикеты и искал новый тикет , для серии ордеров до 5-ти штук работает шустро, но там другая проблема - сохранять все после перезагрузки  терминала, в общем тоже не самый простой вариант

 
Igor Makanu:

Этот код выглядит как несколько разных способов сопровождения ордера, а в своем сообщении Вы ищете способ частично закрывать ордера на разных символах

Задача частичного закрытия ордера, довольно сложна, т.к. после удачного частичного закрытия ордера у оставшейся части ордера будет новый тикет, и как было ранее обсуждение с однозначным выводом (не могу утверждать с уверенностью, мало проверял), что у этого ордера будет комментарий ордера OrderComment()  "подписанный сервером" что то про partial close ? - если поиском пройдетесь по форуму должны найти решения как проанализировать комментарий ордера на предмет частичного закрытия - мне не нравится это решение

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


ЗЫ: для себя я делал через динамические списки, если нужно было закрыть ордер частично - запоминал все тикеты и искал новый тикет , для серии ордеров до 5-ти штук работает шустро, но там другая проблема - сохранять все после перезагрузки  терминала, в общем тоже не самый простой вариант

Спасибо за развернутый ответ! Буду дальше искать истину)) Можете по поводу лишнего больше сказать? Дело в том что я не программист по образованию и многое мне дается с большим трудом, я и так уже многое научился благодаря интернету и Вам (всем), но самоучение не всегда позволяет достичь уровня профи)) Еще раз спасибо!

 

лишнее в Вашем коде - по крайней мере не имеющее отношение к поставленной задаче это модификации ордеров

ладно, упростим задачу, покажите код частичного закрытия 2-х ордеров - даже там не все так просто, как в логике Вашего примера

у Вас в коде "все по полочкам" - выбрали ордер OrderSelect()  и начали работу с ним, затем следующий ордер - при частичном закрытии так не получится

после выполнения OrderClose() сервер закроет ордер с выбранным тикетом и даст новый ордер с новым тикетом и с заполненным комментарием к ордеру , а какой ордер будет выбран следующим в  OrderSelect() ? - у нас же в окружении терминала произошли изменения? - в справке нет разъяснений, но есть указание:

Функция OrderSelect() копирует данные об ордере в программное окружение, и последующие вызовы OrderClosePrice(), OrderCloseTime(), OrderComment(), OrderCommission(), OrderExpiration(), OrderLots(), OrderMagicNumber(), OrderOpenPrice(), OrderOpenTime(), OrderPrint(), OrderProfit(), OrderStopLoss(), OrderSwap(), OrderSymbol(), OrderTakeProfit(), OrderTicket(), OrderType() возвращают ранее скопированные данные. Это означает, что самого ордера может уже и не быть (или же в нем изменились цена открытия, уровни Stop Loss / Take Profit или момент истечения), а данные этому ордеру можно еще получать. Для гарантированного получения свежих данных об ордере рекомендуется вызывать функцию OrderSelect() непосредственно перед обращением за ними.

При последовательном выборе ордеров с помощью параметра SELECT_BY_POS информация отдаётся в том порядке, в котором она поступила с торгового сервера. Никакая сортировка полученного списка ордеров не гарантируется.



поэтому я и предлагаю Вашу задачу решать частями, я в прошлом году искал решение на форумах, а вот и нет в открытом доступе хорошего кода! - я написал свою версию, но мне она не нравится, по моему лишние циклы делаю

в общем подожду, может кто то появится с вариантами решения, нет так сам опять напишу )))

 
Maksim Neimerik:

Будьте добры - объясните что Вы написали...

у вас тьма продуктов в маркете, свой сигнал

и вы тут не первый вовсе год..

всё, наймиты разбежались ?

 
Maxim Kuznetsov:

у вас тьма продуктов в маркете, свой сигнал

и вы тут не первый вовсе год..

всё, наймиты разбежались ?

Ну зачем вы так?! Вы никогда в помощи не нуждались?..

 
Maksim Neimerik:

Вы никогда в помощи не нуждались?..

В MQL4 при частичном закрытии на, например 0.7 лота, позиции с тикетом, например #1 и объёмом, например 1.0, произойдёт следующее:

  • будет частично закрыта позиция с тикетом #1
  • появится новая позиция с тикетом, например #2 и объёмом 0.3. В её комментарии будет прописана строка "from #1"
  • в истории счёта появится ордер с лотом 0.7 и тикетом #1. В его комментарии будет прописана строка "to #2"
Исходя из всего этого очень несложно проследить цепочку из любого множества частичных закрытий изначальной позиции - вся цепочка будет прописана в комментариях.
 
Artyom Trishkin:

В MQL4 при частичном закрытии на, например 0.7 лота, позиции с тикетом, например #1 и объёмом, например 1.0, произойдёт следующее:

  • будет частично закрыта позиция с тикетом #1
  • появится новая позиция с тикетом, например #2 и объёмом 0.3. В её комментарии будет прописана строка "from #1"
  • в истории счёта появится ордер с лотом 0.7 и тикетом #1. В его комментарии будет прописана строка "to #2"
Исходя из всего этого очень несложно проследить цепочку из любого множества частичных закрытий изначальной позиции - вся цепочка будет прописана в комментариях.

Вот это мне и нужно было! Большое спасибо! Дальше я думаю справлюсь...

 
Еще по поводу того что в OrdersTotal() могут быть устарелые данные: если эту функцию использовать как переменную 
int t=OrdersTotal();
for(int i=t-1;i>=0;i--)
{

}

тогда да, я согласен, но если вызывать ее перед каждой итерацией то и инфа должна быть свежей... правильно?

for(int i=OrdersTotal()-1;i>=0;i--)
{

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