← Zurück

Проблема: событие OrdersChanged вызывается дважды на состояние OrderState.Active

Только начинаю использовать библиотеку StockSharp. Скопировал пример из Samples и подписался на событие OrdersChanged. Оно почему-то вызывается дважды на одно и то же состояние заявки (Active) и тот же баланс (1). Не понимаю: почему так происходит. Код прикладываю. Помогите, пожалуйста, разобраться.

Иногда это событие вызывается дважды, но с состоянием заявки Done. Active при этом не вызывается


using System;
    using System.Linq;
    using System.Threading;

    using Ecng.Common;

    using StockSharp.BusinessEntities;
    using StockSharp.Quik;
    using StockSharp.Algo;

namespace Test
{
    static class Test
    {
        private static Security _lkoh;
        private static Portfolio _portfolio;
        private static MarketDepth _depth;

        static void Main()
        {
            try
            {
                // для теста выбираем бумагу Лукойл
                const string secCode = "SBER";

                var quikPath = QuikTerminal.GetDefaultPath();

                if (quikPath.IsEmpty())
                {
                    Console.WriteLine("Не найден ни один запущенный Quik");
                    return;
                }

                Console.WriteLine("Запущенный Quik найден по пути " + quikPath);

                Console.Write("Введите код клиента, через который будет выставлена заявка: ");
                var account = "43913";

                using (var waitHandle = new AutoResetEvent(false))
                {
                    // создаем шлюз к Quik-у
                    using (var trader = new QuikTrader(quikPath))
                    {
                        // необходимо раскомментировать, если идет работа с РТС Стандарт
                        //trader.FormatTransaction += builder => builder.RemoveInstruction(TransactionBuilder.ExecutionCondition);

                        // подписываемся на событие успешного подключения
                        // все действия необходимо производить только после подключения
                        trader.Connected += () =>
                        {
                            Console.WriteLine("Подключение было произведено успешно.");

                            // извещаем об успешном соединени
                            waitHandle.Set();
                        };

                        Console.WriteLine("Производим подключение...");

                        trader.Connect();

                        // дожидаемся события об успешном соединении
                        waitHandle.WaitOne();

                        trader.NewPortfolios += portfolios =>
                        {
                            if (_portfolio == null)
                            {
                                // находим нужный портфель и присваиваем его переменной _portfolio
                                _portfolio = portfolios.FirstOrDefault(p => p.Name == account);

                                if (_portfolio != null)
                                {
                                    Console.WriteLine("Портфель {0} появился.", account);

                                    // если инструмент и стакан уже появились,
                                    // то извещаем об этом основной поток для выставления заявки
                                    if (_lkoh != null && _depth != null)
                                        waitHandle.Set();
                                }
                            }
                        };

                        // подписываемся на событие появление инструментов
                        trader.NewSecurities += securities =>
                        {
                            if (_lkoh == null)
                            {
                                // находим Лукойл и присваиваем ее переменной lkoh
                                _lkoh = securities.FirstOrDefault(sec => sec.Code == secCode);

                                if (_lkoh != null)
                                {
                                    Console.WriteLine("Инструмент Лукойл появился.");

                                    // запускаем экспорт стакана
                                    trader.RegisterQuotes(_lkoh);

                                    if (_portfolio != null && _depth != null)
                                        waitHandle.Set();
                                }
                            }
                        };

                        // подписываемся на событие появления моих новых сделок
                        trader.NewMyTrades += myTrades =>
                        {
                            foreach (var myTrade in myTrades)
                            {
                                var trade = myTrade.Trade;
                                Console.WriteLine("Сделка {0} по цене {1} по бумаге {2} по объему {3} в {4}.", trade.Id, trade.Price, trade.Security.Code, trade.Volume, trade.Time);
                            }
                        };

                        // подписываемся на событие обновления стакана
                        trader.QuotesChanged += depths =>
                        {
                            if (_depth == null && _lkoh != null)
                            {
                                _depth = depths.FirstOrDefault(d => d.Security == _lkoh);

                                if (_depth != null)
                                {
                                    Console.WriteLine("Стакан Лукойла появился.");

                                    // если портфель и инструмент уже появился, то извещаем об этом основной поток для выставления заявки
                                    if (_portfolio != null && _lkoh != null)
                                        waitHandle.Set();
                                }
                            }
                        };

                        // subscribing to orders change event:
                        // subscribing to the orders changed event:
                        trader.OrdersChanged += orders =>
                        {
                            Console.WriteLine("Orders change event fired. Count = " + orders.Count());
                            foreach (Order order in orders)
                            {
                                Console.WriteLine(" [" + order.Time + "] Order has changed for Strategy=" + order.Comment + " with id=" + order.Id + ", price=" + order.Price + ", size=" + order.Volume + ", security=" + order.Security.Code + ", new state=" + order.State + ", new balance=" + order.Balance);
                                // saving orders to the database:
                                // TODO
                            }
                        };

                        Console.WriteLine("Дожидаемся появления в программе инструмента Лукойл и портфеля {0}...".Put(account));

                        // запускаем экспорт по DDE
                        trader.StartExport(new[] {trader.SecuritiesTable, trader.MyTradesTable, trader.EquityPositionsTable,
						                   trader.EquityPortfoliosTable, trader.OrdersTable});

                        // дожидаемся появления портфеля и инструмента
                        waitHandle.WaitOne();

                        Order o = new Order
                        {
                            Portfolio = _portfolio,
                            Price = _lkoh.ShrinkPrice(_lkoh.BestAsk.Price),
                            Security = _lkoh,
                            Volume = 1,
                            Direction = OrderDirections.Sell
                        };
                        trader.RegisterOrder(o);
                        Console.WriteLine("Заявка {0} зарегистрирована.", o.Id);

                        // просто зависнуть:
                        waitHandle.WaitOne();

                        // останавливаем экспорт по DDE
                        trader.StopExport(new[] {trader.SecuritiesTable, trader.MyTradesTable, trader.EquityPositionsTable,
						                  trader.EquityPortfoliosTable, trader.OrdersTable});

                        Console.ReadLine();
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }
    }
}

Kommentare (12)

Anmelden oder Konto erstellen, Melden Sie sich an oder registrieren Sie sich, um einen Kommentar zu hinterlassen

Alexander
Alexander

OrdersChanged это изменение любого из поля заявки, не обязательно состояния

с Done - у вас сразу заявка исполняется по рынку, потому без Active обходится. Первый раз с done - информация по ответу на транзакцию Второй раз с done - пришло обновление по одной из таблиц квика

StockSharpUser
StockSharpUser Autor

Спасибо за быстрый ответ!

Пробовал выводить все поля заявки в консоль - они одинаковые в обоих случаях вызова на состояние Active.

По поводу двух Done: то есть StockSharp обновляет заявку не по таблицам QUIK'а? Как тогда по-другому происходит обновление?

Alexander
Alexander

StockSharpUser: Спасибо за быстрый ответ!

Пробовал выводить все поля заявки в консоль - они одинаковые в обоих случаях вызова на состояние Active.

По поводу двух Done: то есть StockSharp обновляет заявку не по таблицам QUIK'а? Как тогда по-другому происходит обновление?

По первому - привидет пример такого вывода. Время везде выводите с милисекундами.

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

StockSharpUser
StockSharpUser Autor

Печатаю следующее:


Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffff") + "\r\n" +
										"balance = " + order.Balance + "\r\n" +
                                        "cancel time = " + order.CancelTime + "\r\n" +
										"comment = " + order.Comment + "\r\n" +
                                        "derived order = " + order.DerivedOrder + "\r\n" +
										"direction = " + order.Direction + "\r\n" +
                                        "execution condition = " + order.ExecutionCondition + "\r\n" +
										"expiry = " + order.ExpiryDate + "\r\n" +
										"id = " + order.Id + "\r\n" +
                                        "isDisposed = " + order.IsDisposed + "\r\n" +
										"latency = " + order.Latency + "\r\n" +
										"messages = " + string.Join(" | ", order.Messages) + "\r\n" +
                                        "portfolio = " + order.Portfolio + "\r\n" +
										"price = " + order.Price + "\r\n" +
                                        "repo info = " + order.RepoInfo + "\r\n" +
                                        "rps info = " + order.RpsInfo + "\r\n" +
										"state = " + order.State + "\r\n" +
										"status = " + order.Status + "\r\n" +
                                        "stop condition = " + order.StopCondition + "\r\n" +
                                        "time = " + order.Time.ToString("yyyy-MM-dd HH:mm:ss.fffff") + "\r\n" +
                                        "trader = " + order.Trader + "\r\n" +
										"transaction id = " + order.TransactionId + "\r\n" +
                                        "type = " + order.Type + "\r\n" +
                                        "volume = " + order.Volume + "\r\n");

Вывод программы:

Заявка 0 зарегистрирована. Orders change event fired. Count = 1 2012-03-20 01:04:37.49263 balance = 1 cancel time = comment = derived order = direction = Sell execution condition = PutInQueue expiry = id = 1658846224 isDisposed = False latency = 00:00:00.1190810 messages = (161) Заявка N 1658846224 зарегистрирована portfolio = 43913 price = 100,72 repo info = rps info = state = Active status = Accepted stop condition = time = 2012-03-19 01:04:38.00000 trader = StockSharp.Quik.QuikTrader transaction id = 3875622 type = Limit volume = 1

Orders change event fired. Count = 1 2012-03-20 01:04:37.50563 balance = 1 cancel time = comment = derived order = direction = Sell execution condition = PutInQueue expiry = id = 1658846224 isDisposed = False latency = 00:00:00.1190810 messages = (161) Заявка N 1658846224 зарегистрирована portfolio = 43913 price = 100,72 repo info = rps info = state = Active status = Accepted stop condition = time = 2012-03-19 01:04:38.00000 trader = StockSharp.Quik.QuikTrader transaction id = 3875622 type = Limit volume = 1

Сделка 1025086613 по цене 100,72 по бумаге SBER по объему 1 в 19.03.2012 1:04:48 . Orders change event fired. Count = 1 2012-03-20 01:04:47.82122 balance = 0 cancel time = comment = derived order = direction = Sell execution condition = PutInQueue expiry = id = 1658846224 isDisposed = False latency = 00:00:00.1190810 messages = (161) Заявка N 1658846224 зарегистрирована portfolio = 43913 price = 100,72 repo info = rps info = state = Done status = Accepted stop condition = time = 2012-03-19 01:04:38.00000 trader = StockSharp.Quik.QuikTrader transaction id = 3875622 type = Limit volume = 1

Alexander
Alexander

Пробуйте из ветки dev (codeplex \ dev), там это исправлено

Memory
Memory

или не поправили или опять ошибка вернулась. У меня в QUIKE иногда дважды приходят отмена ордеров поэтому ловил только его. Версия 4.1.1

Вот код.


        string PStr;
        long TId;

        void OnOrderChanged(IEnumerable<StockSharp.BusinessEntities.Order> Orders)
        {
            foreach (Order _Order in Orders)
            {
                if (_Order.IsCanceled())
                {
                    if (_Order.Id == TId)
                    {
                        Console.WriteLine("Prev " + PStr);
                        Console.WriteLine("Now "+DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffff") + "\r\n" +
                                                                    "balance = " + _Order.Balance + "\r\n" +
                                                                    "comment = " + _Order.Comment + "\r\n" +
                                                                    "derived Order = " + _Order.DerivedOrder + "\r\n" +
                                                                    "direction = " + _Order.Direction + "\r\n" +
                                                                    "execution condition = " + _Order.ExecutionCondition + "\r\n" +
                                                                    "expiry = " + _Order.ExpiryDate + "\r\n" +
                                                                    "extension info = " + _Order.ExtensionInfo + "\r\n" +
                                                                    "id = " + _Order.Id + "\r\n" +
                                                                    "isDisposed = " + _Order.IsDisposed + "\r\n" +
                                                                    "isSystem = " + _Order.IsSystem + "\r\n" +
                                                                    "isTrace = " + _Order.IsTrace + "\r\n" +
                                                                    "lastchangetime = " + _Order.LastChangeTime+ "\r\n" +
                                                                    "latency = " + _Order.Latency + "\r\n" +
                                                                    "messages = " + string.Join(" | ", _Order.Messages) + "\r\n" +
                                                                    "portfolio = " + _Order.Portfolio + "\r\n" +
                                                                    "price = " + _Order.Price + "\r\n" +
                                                                    "repo info = " + _Order.RepoInfo + "\r\n" +
                                                                    "rps info = " + _Order.RpsInfo + "\r\n" +
                                                                    "security= " + _Order.Security + "\r\n" +
                                                                    "state = " + _Order.State + "\r\n" +
                                                                    "status = " + _Order.Status + "\r\n" +
                                                                    "stop condition = " + _Order.StopCondition + "\r\n" +
                                                                    "time = " + _Order.Time.ToString("yyyy-MM-dd HH:mm:ss.fffff") + "\r\n" +
                                                                    "trader = " + _Order.Trader + "\r\n" +
                                                                    "transaction id = " + _Order.TransactionId + "\r\n" +
                                                                    "type = " + _Order.Type + "\r\n" +
                                                                    "volume = " + _Order.Volume + "\r\n");

                    }
                                            TId = _Order.Id;

                                                                    PStr=DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffff") + "\r\n" +
                                                                    "balance = " + _Order.Balance + "\r\n" +
                                                                    "comment = " + _Order.Comment + "\r\n" +
                                                                    "derived Order = " + _Order.DerivedOrder + "\r\n" +
                                                                    "direction = " + _Order.Direction + "\r\n" +
                                                                    "execution condition = " + _Order.ExecutionCondition + "\r\n" +
                                                                    "expiry = " + _Order.ExpiryDate + "\r\n" +
                                                                    "extension info = " + _Order.ExtensionInfo + "\r\n" +
                                                                    "id = " + _Order.Id + "\r\n" +
                                                                    "isDisposed = " + _Order.IsDisposed + "\r\n" +
                                                                    "isSystem = " + _Order.IsSystem + "\r\n" +
                                                                    "isTrace = " + _Order.IsTrace + "\r\n" +
                                                                    "lastchangetime = " + _Order.LastChangeTime+ "\r\n" +
                                                                    "latency = " + _Order.Latency + "\r\n" +
                                                                    "messages = " + string.Join(" | ", _Order.Messages) + "\r\n" +
                                                                    "portfolio = " + _Order.Portfolio + "\r\n" +
                                                                    "price = " + _Order.Price + "\r\n" +
                                                                    "repo info = " + _Order.RepoInfo + "\r\n" +
                                                                    "rps info = " + _Order.RpsInfo + "\r\n" +
                                                                    "security= " + _Order.Security + "\r\n" +
                                                                    "state = " + _Order.State + "\r\n" +
                                                                    "status = " + _Order.Status + "\r\n" +
                                                                    "stop condition = " + _Order.StopCondition + "\r\n" +
                                                                    "time = " + _Order.Time.ToString("yyyy-MM-dd HH:mm:ss.fffff") + "\r\n" +
                                                                    "trader = " + _Order.Trader + "\r\n" +
                                                                    "transaction id = " + _Order.TransactionId + "\r\n" +
                                                                    "type = " + _Order.Type + "\r\n" +
                                                                    "volume = " + _Order.Volume + "\r\n";

                }
// Дальше собственно обработчик

Вот результат.

Prev 2012-06-14 17:06:35.71875 balance = 1 comment = derived Order = direction = Buy execution condition = PutInQueue expiry = extension info = System.Collections.Generic.Dictionary`2[System.Object,System.Object] id = 8065253846 isDisposed = False isSystem = True isTrace = False lastchangetime = 14.06.2012 17:06:27 latency = 00:00:00.1752975 messages = Заявка, с биржевым номером 8065253846, успешно зарегистрирована. | Заявка, с номером 8065253846 снята. Снятое количество: 1 portfolio = price = 130315 repo info = rps info = security= RIM2@RTS state = Done status = Accepted stop condition = time = 2012-06-14 17:06:27.00000 trader = StockSharp.Quik.QuikTrader transaction id = 61428467 type = Limit volume = 1

Now 2012-06-14 17:06:35.92187 balance = 1 comment = derived Order = direction = Buy execution condition = PutInQueue expiry = extension info = System.Collections.Generic.Dictionary`2[System.Object,System.Object] id = 8065253846 isDisposed = False isSystem = True isTrace = False lastchangetime = 14.06.2012 17:06:27 latency = 00:00:00.1752975 messages = Заявка, с биржевым номером 8065253846, успешно зарегистрирована. | Заявка, с номером 8065253846 снята. Снятое количество: 1 portfolio = price = 130315 repo info = rps info = security= RIM2@RTS state = Done status = Accepted stop condition = time = 2012-06-14 17:06:27.00000 trader = StockSharp.Quik.QuikTrader transaction id = 61428467 type = Limit volume = 1

Alexander
Alexander

LastChangeTime с мс покажите

Memory
Memory

Вот. Времена даже в секундах разные. Только не понятно что с этим делать? Prev 2012-06-14 17:25:37.35937 balance = 1 comment = derived Order = direction = Buy execution condition = PutInQueue expiry = extension info = System.Collections.Generic.Dictionary`2[System.Object,System.Object] id = 8065738989 isDisposed = False isSystem = True isTrace = False lastchangetime = 2012-06-14 17:25:37.35937 latency = 00:00:00.1377125 messages = Заявка, с биржевым номером 8065738989, успешно зарегистрирована. | Заявка, с номером 8065738989 снята. Снятое количество: 1 portfolio = price = 130150 repo info = rps info = security= RIM2@RTS state = Done status = Accepted stop condition = time = 2012-06-14 17:25:27.00000 trader = StockSharp.Quik.QuikTrader transaction id = 62559431 type = Limit volume = 1

Now 2012-06-14 17:25:37.59375 balance = 1 comment = derived Order = direction = Buy execution condition = PutInQueue expiry = extension info = System.Collections.Generic.Dictionary`2[System.Object,System.Object] id = 8065738989 isDisposed = False isSystem = True isTrace = False lastchangetime = 2012-06-14 17:25:29.00000 latency = 00:00:00.1377125 messages = Заявка, с биржевым номером 8065738989, успешно зарегистрирована. | Заявка, с номером 8065738989 снята. Снятое количество: 1 portfolio = price = 130150 repo info = rps info = security= RIM2@RTS state = Done status = Accepted stop condition = time = 2012-06-14 17:25:27.00000 trader = StockSharp.Quik.QuikTrader transaction id = 62559431 type = Limit volume = 1

Alexander
Alexander

Первый ответ по заявке пришёл в качестве ответа на транзакцию, второй - по таблице заявок. У вас вышло так, что времена выставления не обновились и совпадают.

Memory
Memory

Да мне чесно говоря, все равно почему так происходит, хотя и не должно по здравому смыслу. Я никак не придумаю как с этим однозначно бороться. Држать предыдущий ID и отбрасывать следующий если равны? А если через один придет? А если через два? Да, вот еще подумалось, так, для общего развития. А зачем из таблицы гонять если в ответ на транзакцию приходит?

Alexander
Alexander

Потому что в таблице инфы на порядок больше по заявке. Надо чем-то инициализировать.

Как бороться - пользоваться правилами и делать Once. Либо хранить сработавшие. Вариантов тысячи, благо программирование позволяет :)

Memory
Memory
Memory

Под SmartCom тоже проскакивает. И тоже с разными временами. Здесь как такое возможно? Но это так - риторический вопрос. Я код не удалил.

Prev 2012-06-14 19:52:22.67187 balance = 1 comment = derived Order = direction = Buy execution condition = PutInQueue expiry = extension info = System.Collections.Generic.Dictionary`2[System.Object,System.Object] id = 1629461572 isDisposed = False isSystem = True isTrace = False lastchangetime = 2012-06-14 19:51:44.00000 latency = 00:00:00.1201629 messages = portfolio = price = 130955 repo info = rps info = security= RIM2@RTS state = Done status = Accepted stop condition = time = 2012-06-14 19:51:52.09375 trader = StockSharp.Smart.SmartTrader transaction id = 71102056 type = Limit volume = 1

Now 2012-06-14 19:52:22.73437 balance = 1 comment = derived Order = direction = Buy execution condition = PutInQueue expiry = extension info = System.Collections.Generic.Dictionary`2[System.Object,System.Object] id = 1629461572 isDisposed = False isSystem = True isTrace = False lastchangetime = 2012-06-14 19:52:15.00000 latency = 00:00:00.1201629 messages = portfolio = price = 130955 repo info = rps info = security= RIM2@RTS state = Done status = Accepted stop condition = time = 2012-06-14 19:51:52.09375 trader = StockSharp.Smart.SmartTrader transaction id = 71102056 type = Limit volume = 1

За правила - спасибо! Пойду учить мат. часть.