Баг в WhenAllTrades()
Atom
21.01.2017


Найден баг в работе "WhenAllTrades() - создать правило на событие появления всех сделок по заявке." Правило, помимо своего базового назначения: реакции на появление всех сделок по заявке, когда оно присылает коллекцию со сделками, реагирует ещё и на события появления и изменения ордера, присылая при этом пустую коллекцию. Скрин: http://stocksharp.ru/file/104104









Код стратежки для вопроизведения проблемы
Код

class SmartStrategy4: Strategy 
{
        decimal neededVolume = 10;                                                             
        decimal currentVolume;                   
        bool tradeFullFlag = true;
        bool unRegOrderFlag = true;

        protected override void OnStarted()   
        {
            var sRule = Security.WhenMarketDepthChanged(Connector).Do((srArg, stakanArg) =>
                           {  
                              if(currentVolume >= neededVolume)                                                       
                                 Stop();

                              if(tradeFullFlag || unRegOrderFlag)
                              { 
                                   var openBuyOrder = this.BuyAtLimit(stakanArg.BestBid.Price, 2);                        
                                                                                              
                                   var myTrRule = openBuyOrder.WhenNewTrade(Connector).Do((rArg, myTradeArg) =>        
                                                             {   
                                                                    currentVolume += myTradeArg.Trade.Volume;
                                                             }).Apply(this);       
                           
                                   var myAlltRule = openBuyOrder.WhenAllTrades(Connector).Do((rArg, myTradeCollArg) => 
                                                             {
                                                                    if (myTradeCollArg.Any()) 
                                                                        tradeFullFlag = true;                                                                        
                                                              }).Apply(this);

                                   var regRule = openBuyOrder.WhenRegistered(Connector).Do((rArg, orderArg) =>         
                                                          {                                                                                                                        
                                                                  if(openBuyOrder.State != OrderStates.Done && !openBuyOrder.IsMatchedPartially())
                                                                      CancelOrder(openBuyOrder);                                                                                 
                                                          }).Apply(this);

                                   var unRegRule = openBuyOrder.WhenCanceled(Connector).Do((rArg, orderArg) => { unRegOrderFlag = true; }).Apply(this);
        
                                   RegisterOrder(openBuyOrder);                                                    

                                   tradeFullFlag = false; 
                                   unRegOrderFlag = false; 
                              }                                                                                             
                         }).Apply(this);                                                   
            base.OnStarted();                                                                  
        }
    }


Выше представлена модифицированная стратежка из обучающих уроков. Она выставляет лимитку на покупку по лучшему биду, объёмом 2 коня. И тут же снимает её, если её сразу не скушали. И так до тех пор, пока не наберёт 10 коней. Стратежка конечно убогая, но тут важно другое, что если поставить точку остановки на анонимном методе у правила, которое создаёт метод WhenAllTrades(), то мы увидим как оно будет постоянно срабатывать, оно будет отрабатывать каждое изменение ордера: постановку/отмену, при этом будет присылать пустую коллекцию. Такого быть не должно, правило должно срабатывать лишь единожды - на событие полного исполнения. Не должно быть холостых срабатываний. Сейчас оно отрабатывает в перемешку: холостой-холостой-холостой-боевой-холостой-холостой--холостой- боевой и т.д.

Как поправить проблему
Залезть в исходники, в файл MarketRuleHelper.cs. Найти там класс AllTradesOrderRule и малость подпилить строчку:
Код
 private bool AllTradesReceived => Order.State == OrderStates.Done && (Order.Volume - Order.Balance == _receivedVolume); 

Как нужно правильно - я не знаю, но я бы ввёл проверку на нулевую позицию. В левой части строчки - рыть бесполезно, т.к. статус Done не даёт однозначного ответа: заявка исполнена или снята, поэтому правило реагирует и на отменённую заявку тоже. Поэтому рыть надо правее. Допустим, заявка снята, левая часть нам даст true, но и правая часть тоже даст true, ибо разность объёма и баланса даст ноль, а _receivedVolume у нас тоже ноль, т.к. мы ещё не успели ничего набрать. Поэтому, надо проверить, чтобы _receivedVolume не был ноль. Я бы попробовал именно так:
Код
 private bool AllTradesReceived => Order.State == OrderStates.Done && _receivedVolume != 0  && (Order.Volume - Order.Balance == _receivedVolume); 


P.S. Можете не отвечать на данное сообщение. Только, прошу: не надо меня отправлять открывать счёт, чтобы команда техподдержки чего-то тут увидела. Я достаточно полазил по гитхабу, чтобы понять кто правит баги и делает основную работу. И данный человек читает сей форум. Считайте что я это всё написал как-бы на гитхабе. Я пока не умею им пользоваться - времени пока нет разбираться, но в будущем разберусь. В общем, данный баг надо чинить. Успехов!

Теги:


Спасибо: Mikhail Sukhov




Добавить файлы через драг-н-дроп, , или вставить из буфера обмена.

loading
clippy