Только начинаю использовать библиотеку 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)
登录 或 创建账户, 登录或注册以发表评论
OrdersChanged это изменение любого из поля заявки, не обязательно состояния
с Done - у вас сразу заявка исполняется по рынку, потому без Active обходится. Первый раз с done - информация по ответу на транзакцию Второй раз с done - пришло обновление по одной из таблиц квика
Спасибо за быстрый ответ!
Пробовал выводить все поля заявки в консоль - они одинаковые в обоих случаях вызова на состояние Active.
По поводу двух Done: то есть StockSharp обновляет заявку не по таблицам QUIK'а? Как тогда по-другому происходит обновление?
По первому - привидет пример такого вывода. Время везде выводите с милисекундами.
По второму - заявка может быть обновлена в том числе по ответу на посланную транзакцию.
Печатаю следующее:
Вывод программы:
Заявка 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
Пробуйте из ветки dev (codeplex \ dev), там это исправлено
или не поправили или опять ошибка вернулась. У меня в QUIKE иногда дважды приходят отмена ордеров поэтому ловил только его. Версия 4.1.1
Вот код.
Вот результат.
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
LastChangeTime с мс покажите
Вот. Времена даже в секундах разные. Только не понятно что с этим делать? 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
Первый ответ по заявке пришёл в качестве ответа на транзакцию, второй - по таблице заявок. У вас вышло так, что времена выставления не обновились и совпадают.
Да мне чесно говоря, все равно почему так происходит, хотя и не должно по здравому смыслу. Я никак не придумаю как с этим однозначно бороться. Држать предыдущий ID и отбрасывать следующий если равны? А если через один придет? А если через два? Да, вот еще подумалось, так, для общего развития. А зачем из таблицы гонять если в ответ на транзакцию приходит?
Потому что в таблице инфы на порядок больше по заявке. Надо чем-то инициализировать.
Как бороться - пользоваться правилами и делать Once. Либо хранить сработавшие. Вариантов тысячи, благо программирование позволяет :)
Под 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
За правила - спасибо! Пойду учить мат. часть.