Клиринг в тестере - страница 6

 
Roman Shiredchenko #:

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

в общем, как понять, что цикл ордеров, новая позиция - ПРОФИТНАЯ началась НОВАЯ - для учета средней цены открытия позиции (клиринг ее меняет значение):

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

В общем нужна точка отчета - для расчета средней цены входа в позицию.

Можно, исп-ть данные отсюда + например, время считывать, когда предыдущая позиция закрылась в профит и уже оттуда брать разность с настоящим временем сервера, типа если я сам цикл начну с терминала - без магика:

ну то есть типа этого:

типа прошлая позиция в плюс - то уже учет актуальный цикла начался. и ордера - надо уже считать и цену входа и объем для расчета средней цены входа в совокупную позицию...

https://www.mql5.com/ru/articles/211


--------------------------------------------------------------

конечно, в идеале - надо сделать, чтобы вне зависимости от исхода предыдущего цикла - в плюс или в минус он закрыт.

Начало - нового было обозначено для расчета в коде - средней цены нового актуального цикла усреднений, например, или доливок - не важно...

Нет ни кого готовой конструкции расчета средней цены итоговой позиции? Что то уже подустал считать и код править - не выходит каменный цветок....:-)

разными способами пытался в OnTrade Transaction () - много лишнего лезет в учет, в итоге лоты удваиваются в расчете - что не верно:

События

"Например, при отсылке рыночного ордера на покупку, он обрабатывается, для счета создается соответствующий ордер на покупку, происходит исполнение ордера, его удаление из списка открытых, добавление в историю ордеров, далее добавляется соответствующая сделка в историю и создается новая позиция. Все эти действия являются торговыми транзакциями

"

Это через On Trade Transaction ()

//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction& trans,
                        const MqlTradeRequest& request,
                        const MqlTradeResult& result)
  {


 if ((Hour() <= 13 && Minute() < 44) || (Hour() >=14 && Minute() > 5) || 
          (Hour() <= 18 && Minute() < 44) || (Hour() >=19 && Minute() > 5)) 
   if(trans.type == TRADE_TRANSACTION_DEAL_ADD)   //TRADE_TRANSACTION_DEAL_ADD)
   
     {
      long deal_type = -1;
      long deal_entry = -1;
      long deal_magic = 0;

      double deal_volume = 0;
      double deal_price  = 0;
      string deal_symbol = "";

      if(HistoryDealSelect(trans.deal))
        {
         // Print(" deal_entry == DEAL_ENTRY_IN, last_price = ",last_price, " last_lots = ",last_lots);

         deal_type    = HistoryDealGetInteger(trans.deal, DEAL_TYPE);
         deal_entry   = HistoryDealGetInteger(trans.deal, DEAL_ENTRY);
         deal_magic   = HistoryDealGetInteger(trans.deal, DEAL_MAGIC);

         deal_volume  = HistoryDealGetDouble(trans.deal, DEAL_VOLUME);
         deal_price   = HistoryDealGetDouble(trans.deal, DEAL_PRICE);
         deal_symbol  = HistoryDealGetString(trans.deal, DEAL_SYMBOL);
         Print(" deal_entry == DEAL_ENTRY_IN, deal_price = ", deal_price, " deal_volume = ", deal_volume);
        }
      else
         return;

      if(deal_symbol == _Symbol) // && deal_magic == MagicNumber)

         if(deal_entry == DEAL_ENTRY_IN && (deal_type == DEAL_TYPE_BUY || deal_type == DEAL_TYPE_SELL))
           {
            // last_price    = deal_price;
            last_pos_type = (deal_type == DEAL_TYPE_BUY) ? POSITION_TYPE_BUY : POSITION_TYPE_SELL;
            // last_lots     = deal_volume;


          
            if (deal_type == DEAL_TYPE_BUY)
             {
              if(deal_volume > 0)  
              if (!PositionSelect(_Symbol) ||
                 (PositionSelect(_Symbol) && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY   && 
                 NormalizeDouble(PositionGetDouble(POSITION_SL),_Digits) < last_price))
                        
             
              {
               // расчет средней цены СОВОКУПНОЙ ПОЗИЦИИ для общего случая - входа, как руками, так и роботом 
               last_price = (last_price * last_lots + NormalizeDouble(deal_price,_Digits) *
                             NormalizeDouble(deal_volume,0)) / (last_lots +  NormalizeDouble(deal_volume,0));
               last_price = NormalizeDouble(last_price,_Digits);
               
               last_lots = last_lots + NormalizeDouble(deal_volume,0); // накапливаем совокупный объем
              }
            Print(" OnTradeTransaction_BUY: last_price_BUY = ",last_price, " last_lots_BUY = ",last_lots, " N_max_B = ", N_max_B);
           }
           
         if (deal_type == DEAL_TYPE_SELL)
             {
              if(deal_volume > 0)  
              if (!PositionSelect(_Symbol) ||                
                 (PositionSelect(_Symbol) && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL &&
                   (NormalizeDouble(PositionGetDouble(POSITION_SL),_Digits) == 0 ||
                    NormalizeDouble(PositionGetDouble(POSITION_SL),_Digits) > last_price ))) 
                        
             
              {
               // расчет средней цены СОВОКУПНОЙ ПОЗИЦИИ для общего случая - входа, как руками, так и роботом 
               last_price = (last_price * last_lots + NormalizeDouble(deal_price,_Digits) *
                             NormalizeDouble(deal_volume,0)) / (last_lots +  NormalizeDouble(deal_volume,0));
               last_price = NormalizeDouble(last_price,_Digits);
               
               last_lots = last_lots + NormalizeDouble(deal_volume,0); // накапливаем совокупный объем
              }
            Print(" OnTradeTransaction_SELL: last_price_SELL = ",last_price, " last_lots_SELL = ",last_lots, " N_max_S = ", N_max_S);
           }   
           
         } // к if(deal_entry == DEAL_ENTRY_IN && (deal_type == DEAL_TYPE_BUY || deal_type == DEAL_TYPE_SELL))
     }
  }

При таком виде ф-ии - лоты в расчете цены средней входа в позицию (неттинговый учет) считаются не правильно.


Возможно проще сделать через On Trade.

Здесь это через on Trade ()  сейчас смотрю: тут все расписано, просто в код вставить расчет надо и все... по сути.

https://www.mql5.com/ru/articles/40


По сути вот конструкция - если наращена поза - то считать среднюю цену. При закрытии позиции - все промежуточные переменные - занулять и все. Там по сути все элементарно.

Задача исключить изменение цены открытия позиции во время клиринга (когда она становится равной цене символа на время клиринга).

Т.е. считать ее в коде.

Обработка торговых событий в эксперте при помощи функции OnTrade()
Обработка торговых событий в эксперте при помощи функции OnTrade()
  • www.mql5.com
В 5-ой версии языка MQL появилась масса нововведений, в том числе работа с событиями различных типов (события таймера, торговые события, пользовательские и т.д.). Возможность обработки событий позволяет создавать совершенно новый тип программ для автоматического и полуавтоматического трейдинга. В этой статье мы рассмотрим торговые события и напишем для функции OnTrade() код, который будет обрабатывать событие Trade.
 
Roman Shiredchenko #:

Нет ни кого готовой конструкции расчета средней цены итоговой позиции? Что то уже подустал считать и код править - не выходит каменный цветок....:-)

Вот кусок моего старого, но до сих пор "боевого" кода:

               Pr=HistoryDealGetDouble(DealTicket,DEAL_PRICE);
               Vol=HistoryDealGetDouble(DealTicket,DEAL_VOLUME);
               if(st.Pos==0.0)
                  st.Price=Pr;
               if((ENUM_DEAL_TYPE)HistoryDealGetInteger(DealTicket,DEAL_TYPE)==DEAL_TYPE_BUY)
                 {
                  if(st.Pos>=0.0) // Увеличиваем лонг
                     st.PriceAvr=(st.PriceAvr*st.Pos+Pr*Vol)/(st.Pos+Vol);
                  else  // st.Pos<0
                    {
                     if(Vol<=-st.Pos) // Кроемся или сокращаем позу
                        Res=(-Vol)*(Pr-st.PriceAvr);
                     else if(Vol>-st.Pos) // Переворот в лонг
                       {
                        Res=st.Pos*(Pr-st.PriceAvr);
                        ClearClosedPos();
                        st.Price=Pr; st.PriceAvr=Pr;
                       }
                    }
                  st.Pos+=Vol; st.PlanPos-=Vol;
                 }
               else if((ENUM_DEAL_TYPE)HistoryDealGetInteger(DealTicket,DEAL_TYPE)==DEAL_TYPE_SELL)
                 {
                  if(st.Pos<=0.0) // Увеличиваем шорт
                     st.PriceAvr=(st.PriceAvr*(-st.Pos)+Pr*Vol)/(-st.Pos+Vol);
                  else  // st.Pos>0
                    {
                     if(Vol<=st.Pos) // Кроемся или сокращаем позу
                        Res=(Vol)*(Pr-st.PriceAvr);
                     else if(Vol>st.Pos) // Переворот в шорт
                       {
                        Res=st.Pos*(Pr-st.PriceAvr);
                        ClearClosedPos();
                        st.Price=Pr; st.PriceAvr=Pr;
                       }
                    }
                  st.Pos-=Vol; st.PlanPos+=Vol;
                 }
 
JRandomTrader #:

Вот кусок моего старого, но до сих пор "боевого" кода:

О!!! Спс, большое за такое быстрое реагирование - возьму на отсмотр и редактирование.
 
Roman Shiredchenko #:
О!!! Спс, большое за такое быстрое реагирование - возьму на отсмотр и редактирование.

Обращаю внимание - "st" (там довольно большая структура, включающая, в т.ч., трейлы и статистику) - это как раз "состояние" робота - то, что скидывается на диск после изменения(и при деините) и загружается при ините.

И да, тут скорее всего st.Price и st.PriceAvr по сути не нужны, достаточно одной, но код старый, больше 5 лет, и на него завязаны все мои "боевые" роботы, так что "первое правило авиамеханика - не трожь работающий механизм".

 

результат клиринга - перевод всех позиций к текущей, т.е. к средней цене внутрь спреда

сдалась кому то эта биржа? ...

 
JRandomTrader #:

Обращаю внимание - "st" (там довольно большая структура, включающая, в т.ч., трейлы и статистику) - это как раз "состояние" робота - то, что скидывается на диск после изменения(и при деините) и загружается при ините.

И да, тут скорее всего st.Price и st.PriceAvr по сути не нужны, достаточно одной, но код старый, больше 5 лет, и на него завязаны все мои "боевые" роботы, так что "первое правило авиамеханика - не трожь работающий механизм".

Спс за разъяснения, возьму  на базовое исполнение.
 
Renat Akhtyamov #:

результат клиринга - перевод всех позиций к текущей, т.е. к средней цене внутрь спреда

сдалась кому то эта биржа? ...

Я  как сделаю ф-ию - выложу тут.
 
Renat Akhtyamov #:

результат клиринга - перевод всех позиций к текущей, т.е. к средней цене внутрь спреда

сдалась кому то эта биржа? ...

Я только на бирже и торгую.

 
JRandomTrader #:

Я только на бирже и торгую.

а я только на форексе

на бирже не умею

заходил туда, открывался там

не моё - заново изучать

кстати, почему средняя цена по стакану не есть та, которая после клиринга?

// а то я бы торговал там такое ;)

// но по ходу в стакан не все отдают, чуток прячут, т.е. стакан лажа?

 
Roman Shiredchenko #:
Я  как сделаю ф-ию - выложу тут.

Все давным-давно выложено в разделе "Биржевой трейдинг"

https://www.mql5.com/ru/forum/67298/page3#comment_2109451

ФОРТС: В помощь начинающим
ФОРТС: В помощь начинающим
  • 2015.12.08
  • www.mql5.com
Установка отложенного ордера командой OrderSend().