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


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


Только начинаю использовать библиотеку 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);
            }
        }
    }
}

Теги:


Спасибо:




12 Ответов
Alexander

Фотография
Дата: 19.03.2012
Ответить


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

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

StockSharpUser

Фотография
Дата: 19.03.2012
Ответить


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

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

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

Alexander

Фотография
Дата: 19.03.2012
Ответить


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

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

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


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

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

StockSharpUser

Фотография
Дата: 19.03.2012
Ответить


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

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

Фотография
Дата: 19.03.2012
Ответить


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

Memory

Фотография
Дата: 14.06.2012
Ответить


или не поправили или опять ошибка вернулась. У меня в 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

Фотография
Дата: 14.06.2012
Ответить


LastChangeTime с мс покажите
Спасибо:

Memory

Фотография
Дата: 14.06.2012
Ответить


Вот. Времена даже в секундах разные. Только не понятно что с этим делать?
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

Фотография
Дата: 14.06.2012
Ответить


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

Memory

Фотография
Дата: 14.06.2012
Ответить


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

Alexander

Фотография
Дата: 14.06.2012
Ответить


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

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

Memory

Фотография
Дата: 14.06.2012
Ответить


Под 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

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


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

loading
clippy