Хотелось бы понять, как матчить ордера и их исполнение (трэйды), чтобы отследить полное исполнение заявки.
Допустим, один из режимов работы будущего робота будет "синхронный", то есть выбрасывается несколько ордеров по маркету (допустим), и затем ожидание их исполнения, и только после этого пойдет последующая расстановка ордеров и т.д. Проблема усложняется тем, что на том же счету будет работать несколько роботов (в будущем) с теми же инструментами, и следовательно MyTrades и Orders будут сыпаться во все роботы синхронно, и их нужно как-то разделять. Так как объект Strategy не удалось для этого прикрутить, после недолгого размышления пришла мысль использовать коментарии (Order.Comment).
Все выглядит примерно так.
1. В методе Connect
trader.NewOrders += orders => { ProcessNewOrder(orders) };
trader.OrderChanged += orders => {ProcessNewOrders(orders) };
trader.OrderRegisterFailed += ....
trader.OrderCancelFailed += ....
trader.NewMyTrades += trades => { ProcessMyTrades(trades) };
2. В методе запуска ордеров
а. Создаем потокобезопасную коллекцию, в которой храним Comment + нужные нам данные.
_collection = new ThreadSafeObservableCollection<MyCollection>();
б. Создаем ордер.
o = new Order {
Market, Price, Volume, Direction,
Comment = StrategyID.ToString() + Type.ToString() + Portfolio.Name + Security.ID + Direction.ToString() + RND.Next().ToString()
};
в. Регистрируем его в коллекции.
MyCollection col = new MyCollection();
MyCollection.Comment = o.Comment;
_collection.Add(col);
г. запускаем Order.
trader.RegisterOrder(o);
и далее последовательно несколько ордеров в том же цикле. На этом выставление завершается, ждем подтверждений.
Теперь в методе
private void ProcessNewOrder(orders)
{
foreach (Order o in orders)
{
String Comment = o.Comment;
var c = _collection.FirstOrDefault( cc => cc.Comment == Comment);
if (var != null)
нашли наш ордер, который мы запускали.
}
}
и далее по шагам:
- когда order.State != Done - в коллекции отмечаем, что он не выполнен, следовательно весь цикл не имеет смысла, отыгрываем позицию назад (логика исключительно для примера).
- когда Order.State == Done - отмечаем это, и ждем прихода MyTrades по этому ордеру.
- если в процессе ожидания исполнения лимитных заявок рынок ушел, то убить все неисполненные ордера, запустить ордера для возврата позиции в исходное состояние (где отрботал sell туда дать Buy), и войти заново по новым уровням....
- в событии ProcessMyTrades(trades) через вложенный Order по комментарию находим элемент коллекции и ждем, когда в трэйдах придет все то количество, которое мы размещали в Order.Volume.
- и так далее с очень разветвленным алгоритмом.
Собственно вопрос: есть ли более элегантный метод матчинга, чем генерация комментариев через SID и rnd, чтобы не сравнивать строки? Я надеялся (казалось, логично) на TransactionID, но он всегда нулевой.
P.S. Не знаю, баг это или специфическое поведение, но согласно документации Объект MyTrade фактически содержит в себе два объекта Trade и Order. В процессе матчинга я пытался проверять, одинаковые ли MyTrade.Trade.OrderDirection и MyTrade.Order.Direction (мало ли :-) ). Оказалось, что MyTrade.Trade.OrderDirection всегда есть null, и следовательно, когда получаешь новый MyTrade по событию trader.NewMyTrades +>, то направление трэйда можно получить только из вложенного ордера. Версия 4.0.20.