Найден баг в работе "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. Можете не отвечать на данное сообщение. Только, прошу: не надо меня отправлять открывать счёт, чтобы команда техподдержки чего-то тут увидела. Я достаточно полазил по гитхабу, чтобы понять кто правит баги и делает основную работу. И данный человек читает сей форум. Считайте что я это всё написал как-бы на гитхабе. Я пока не умею им пользоваться - времени пока нет разбираться, но в будущем разберусь. В общем, данный баг надо чинить. Успехов!