Михаил, у меня сложилось ощущение что ассинхронный режим работает иногда некорректно. поппытаюсь сейчас объяснить. Я пишу арбитражера, сут ье го работы - выставить заявку при появлении определенного сигнала и дальше 2 варианта - либо по исполнении ее выброзить еще одну заявку, либо , если сигнал ушел - снять первую заявку.
Это преамбула. (бага на версии 2.0.1, т.к. с 2.1 у меня известные вам траблы)
Амбула - т.к. режим асинхронный, когда уходит сигнал, успевает пройти запрос на снятие раз 15, прежде чем заявка снимется и поменяет статус на Canceled, у меня как только заявка становится Canceled или Matched срабатывает ветка в коде, кторая проверяет Volume-Blance и на эту разницу выкидывает вторую заявку (если Canceled), либо (если Matched) выкидывают вторую заявку на Volume первой.И у меня складывается ощущения, что в какой то момент сбивается или нарушается (не знаю как скзаать) процесс обновления полей в экземпляре заявки. Как эт овыглядит (в прилагаемом скрине, я далее для удобства буду давать только послдение 4 цифры номера заявки)
Сработал сигнал, выставилась заявка 6984, сигнал ушел, я отправляю trader.CancelOrder(order) до тех пор пока order.State != Canceled. как только Canceled, делаю order = null и дальше слушать сигнал.В логах так и написано - заявка стала Canceled, Balance = 2
Сигнал срабатывает второй раз, выставялю снвоа заявку order = new Order () .... (перменная та же самая), trader.RegisterOrder(order). Высталяется заявка (номер у нее 8248) Что происходит далее - на бирже заявка исполняется, но сигнал уходит. Робот честно пытается ее отменить до тех пор, пока статус у нее Active. как только статус заявки меняется на Исполнена(в квике), робот видит изменение статуса, но! в логах пишет мне что заявка Canceled, и Balance у нее 2. (то есть данные из заявки 6984). ну и соответсвенно не выкидаывает правую часть. и другая бага (наверно изза тгого, что уходит 10-15 запросов на снятие заявки до тех пора пока она станет Canceled - были случаи ,когда аявки часто тсавилис снимались, что например идут заявки 1,2,3,4,5,6 , они выставляются- снимают, но по логам заявка под номером например 4 вообще не снималась.То есть робот ее не снимал.Может быть это изза тго, что между первым запросом на снятие и реальным изменением ее статуса на Canceled на сервер уходит штук 15 транзакций на снятие?
скрин списка заявок - файл 07.07.png
Kommentare (34)
Anmelden oder Konto erstellen, Melden Sie sich an oder registrieren Sie sich, um einen Kommentar zu hinterlassen
По скрину. Пустые номера транзакций - это ручками? Номера транзакций уникальны? А то я смотрю у Вас с 1 начинается. До этого 1 не встречался? Уникальность должна быть в пределах всей таблицы (тоесть, робот запускали несколько раз и между запусками должна сохраняться уникальность). Заявки никак не меняются в коде? Если выставили заявку, то ее уже никак нельзя менять. Это иногда вводит в путаницу, когда используют ФОРЦ мув. Даже при нем нельзя менять заявку.
Путсые - да, руками закрывал позы.ну каждый запуск робота - это с 1 начинается генерация. генератор - ваш, кторый не тики берет, а инкрементальный. Уникальность транзакций попробуем обеспечить. муваю я просто -
public Order MoveOrder(Order order, decimal price) { var newOrder = makeOrder(order.Direction, order.Security, order.Volume, order.Security.ShrinkPrice((double)price), order.Account); if (order.Price != newOrder.Price) { bool succes = CancelOrder(order); if (succes) {
TradeBasketHelperLogger.Logger.Debug(String.Format("Try moving order ID = {0}", order.Id)); trader.RegisterOrder(newOrder);
TradeBasketHelperLogger.Logger.Debug(String.Format("Moving order succes. New order ID = {0}", newOrder.Id)); return newOrder; } return order; } return order; }
В Вашем случае такое не подойдет (надо в доке отразить). Сделайте свой генератор (по сути там только один метод реализовать). Который такты проца берет. Уж он то точно будет уникью =)
Если затык тока в генераторе - поставлю вам памятник нерукотворный :)
Я не знаю. По картинке выше не видно, были еще заявки с таким номером или нет.
наверняка были - робот несколько раз запускался
IncrementTransactionIdGenerator tranGen = new IncrementTransactionIdGenerator
; trader.TransactionIdGenerator = tranGen;
вот так я думаю прокатывать будет всегда :)
нет, не катит - пишет что превышен размер . щас буду думать. я хрен знает как тики проца взять, и разбираться лень.
Да, дилема... Штука в том, что транзакция не может превышать int.MaxValue. А если брать тики (+такты) то без разрядности long ну никак. Есть обходной маневр. Попробовать в начале инициализировать не количество тиков, а количество секунд с начала дня. Как то так:
{CurrentTransactionId = (DateTime.Now - DateTime.Today).TotalSeconds};
Ну вполне рабочий такой work around.Надеюсь в версии 2.2 будет еще один генератор транзакций, для таких как я :)
... если этот поможет.
Блин опять то же самое :( не помогла генерация транзакций.
Тогда где-то проблема в другом месте. ITrader.OrdersChanged по этим заявкам выводит событие, что в них что-то поменялось?
в сделке кторая пришла по событию баланс - 0, а в переменной - 4.
вот лог из консоли
Done branch, Order Id = 1882934524, Balance = 4 - эт ов основном цикле, ветка Status = Done
а это лог из OrderChanged 15:27:03,968 - OrderId = 1882934524 State = Done Bal = 0 TrId = 55471 Time = 15:27:03 15:27:03,968 - OrderId = 1882934524 State = Done Bal = 0 TrId = 55471 Time = 15:27:03 15:27:03,968 - OrderId = 1882934524 State = Done Bal = 0 TrId = 55471 Time = 15:27:03
Переменная эта используется в Workflow, а воркфолоу работает в своем потоке. может изза этого?
смотрите как интересно - как будто заявка сразу считается снята. это может быть отго, что бросается масса заявок на снятие?
он выполняет ветку кторая if (State == Done), а потом еще приходит 3 события OrderChaged.
15:47:52,656 - OrderId = 1883161388 State = Active Bal = 4 TrId = 56280 Time = 15:47:51 15:47:52,656 - OrderId = 1883161388 State = Active Bal = 4 TrId = 56280 Time = 15:47:51 15:47:52,765 - OrderId = 1883161388 State = Done Bal = 4 TrId = 56280 Time = 15:47:51
в общем щас еще раз поймаю - напишу сюда последовательность.
Забрела ко мне в голову идея - может вы сперва в заявке статус обновляете, а потом баланс?
Поймал. вот что мы имеем
16:59:23,578 - Buy left part spread start. SRU0 BA = 7567, SBER03 BB = 75,4 16:59:23,578 - Buy left part spread end. SRU0 BA = 7567, SBER03 BB = 75,4 Это вставил заявку в результате срабатывания сигнала
16:59:24,093 - Check open long spread order. A = 35,125000, ? = 39,0, (A-?*?) = 41,125000, signal is 0 < 39,0 - 41,125000 <= 2, alpha = 6, sigma = 1 16:59:24,093 - Prices: SRU0 BA = 7570, SBER03 BB = 75,3 16:59:24,093 - Try cancel order 1883929777, State = Active, Status = Done 16:59:24,093 - Canceling succesful это проверка сигнала. в данном случае сигнал ушел, поэтому мы отменяем заявку.Проверяем и отменяем в цикле до тех пор, пока статус не станет Done. Canceling succesful - т.к. режим ассинхронный, и CancelOrder не вызывает исключений
16:59:24,109 - Check open long spread order. A = 35,125000, ? = 39,0, (A-??) = 41,125000, signal is 0 < 39,0 - 41,125000 <= 2, alpha = 6, sigma = 1 16:59:24,109 - Prices: SRU0 BA = 7570, SBER03 BB = 75,3 16:59:24,109 - Try cancel order 1883929777, State = Active, Status = Done 16:59:24,109 - Canceling succesful 16:59:24,125 - Check open long spread order. A = 35,125000, ? = 39,0, (A-??) = 41,125000, signal is 0 < 39,0 - 41,125000 <= 2, alpha = 6, sigma = 1 16:59:24,125 - Prices: SRU0 BA = 7570, SBER03 BB = 75,3 16:59:24,125 - Try cancel order 1883929777, State = Active, Status = Done 16:59:24,125 - Canceling succesful 16:59:24,140 - Check open long spread order. A = 35,125000, ? = 39,0, (A-??) = 41,125000, signal is 0 < 39,0 - 41,125000 <= 2, alpha = 6, sigma = 1 16:59:24,140 - Prices: SRU0 BA = 7570, SBER03 BB = 75,3 16:59:24,140 - Try cancel order 1883929777, State = Active, Status = Done 16:59:24,140 - Canceling succesful 16:59:24,156 - Check open long spread order. A = 35,125000, ? = 39,0, (A-??) = 41,125000, signal is 0 < 39,0 - 41,125000 <= 2, alpha = 6, sigma = 1 16:59:24,156 - Prices: SRU0 BA = 7570, SBER03 BB = 75,3 16:59:24,156 - Try cancel order 1883929777, State = Active, Status = Done 16:59:24,156 - Canceling succesful 16:59:24,171 - Check open long spread order. A = 35,125000, ? = 39,0, (A-??) = 41,125000, signal is 0 < 39,0 - 41,125000 <= 2, alpha = 6, sigma = 1 16:59:24,171 - Prices: SRU0 BA = 7570, SBER03 BB = 75,3 16:59:24,171 - Try cancel order 1883929777, State = Active, Status = Done 16:59:24,171 - Canceling succesful 16:59:24,187 - Check open long spread order. A = 35,125000, ? = 39,0, (A-??) = 41,125000, signal is 0 < 39,0 - 41,125000 <= 2, alpha = 6, sigma = 1 16:59:24,187 - Prices: SRU0 BA = 7570, SBER03 BB = 75,3 16:59:24,187 - Try cancel order 1883929777, State = Active, Status = Done 16:59:24,187 - Canceling succesful 16:59:24,203 - Check open long spread order. A = 35,125000, ? = 39,0, (A-??) = 41,125000, signal is 0 < 39,0 - 41,125000 <= 2, alpha = 6, sigma = 1 16:59:24,203 - Prices: SRU0 BA = 7570, SBER03 BB = 75,3 16:59:24,203 - Try cancel order 1883929777, State = Active, Status = Done 16:59:24,203 - Canceling succesful 16:59:24,218 - Check open long spread order. A = 35,125000, ? = 39,0, (A-??) = 41,125000, signal is 0 < 39,0 - 41,125000 <= 2, alpha = 6, sigma = 1 16:59:24,218 - Prices: SRU0 BA = 7570, SBER03 BB = 75,3 16:59:24,218 - Try cancel order 1883929777, State = Active, Status = Done 16:59:24,218 - Canceling succesful
и вот на этом месте статус меняется, но баланс все равно 4, и робот уходит в ветку, где статус = Done и IsFilledEmpty = true. Хотя на деле баланс = 0.
А дальше идет лог из OrderChaged:
16:59:24,546 - OrderId = 1883929777 State = Done Bal = 0 TrId = 60554 Time = 16:59:23 Now = 16:59:24.5468750 16:59:24,546 - OrderId = 1883929777 State = Done Bal = 0 TrId = 60554 Time = 16:59:23 Now = 16:59:24.5468750 16:59:24,546 - OrderId = 1883929777 State = Done Bal = 0 TrId = 60554 Time = 16:59:23 Now = 16:59:24.5468750
Кажется я начинаю понимать. У Вас случаем не такой код?
while (order.Type != Done) { WriteLog(); }
if (order.Balance > 0) {
Тут дело не в 2.1 и не в асинхронности. Такое бы не прокатило ни на одной вресии. Вы своим кодом предполагаете, что все свойства меняются одновременное. А такое невозможно. Я даже предполжить не могу, на что можно блокироваться. Так просто не делается, и я не знаю подхода, который бы такое делал.
А почему Вы не работаете стандартным путем - через события. У Вас везде вечные циклы. Зачем все так сложно?
потому что робот у меня в WorkFlow нарисован. А там - детерменированый подход. А предполагаю что свойства меняются не одновременно, а что сперва баланс, а потом - состояние заявки.
у Вас sequential?
в 4м дотнете нет такого понятия. там один вид воркфлоу.
а никак нельзя лочить объект во время его апдейта?
Цель же была - сделать хреновину, кторая позволит трейдерам помахав мышкой реализовать стратегию.
On 7 июл, 17:51, Tauler <vladimir_igo...@mail.ru> wrote:
Короче придумал я костыль - класс-репозиторий, кторый подписывается на NewOrder и OrderChanged, и оттуда форкфлоу запрашивает заявку перед ее проверкой.
On 7 июл, 17:54, Tauler <vladimir_igo...@mail.ru> wrote:
Да, я еще вчера посмотрел как идет обновлением. Статус обновляется последним.
On 8 июл, 12:37, Tauler <vladimir_igo...@mail.ru> wrote:
Тогда вообще не понятно, почему у меня был статус Done, но баланс ненулевой на целиком закрытой заявке.
On 8 июл, 12:38, Mikhail Sukhov <msou...@gmail.com> wrote:
OrdersChanged должен был помочь разгадать загадку.
On 8 июл, 13:26, Tauler <vladimir_igo...@mail.ru> wrote:
Не прокатывает мое решение с репозиторием - такая же фигня.
икак не пойму как так получется
вот класс репозитория
public class OrderRepository { private ITrader trader; private List<Order> orders = new List<Order>();
Action<IEnumerable<Order>>(trader_OrdersChanged); trader.NewOrders += new Action<IEnumerable<Order>>(trader_NewOrders); }
id); if (order != null) { orders.RemoveAll(ord => ord.Id == id); orders.Add(order); }
ord.TransactionId == id); if (order != null) { orders.RemoveAll(ord => ord.TransactionId == id); orders.Add(order); Console.WriteLine(String.Format("GetOrderByTransId TRID = {0} St = {1} bal = {2} ID = {3}",
order.TransactionId, order.State, order.Balance, order.Id)); }
воркфлоу перед какждыйм циклом проверки заявки лезет сюда за заявкой
но каким то чудом он получает из репозиторя заявку со стутусом Done, но с целым балансом. И тут же вылетает лог события что заявка изменилась, статус Доне, и баланс 0. Ваще ничего не понимаю :(
On 8 июл, 13:31, Mikhail Sukhov <msou...@gmail.com> wrote:
В событии вы выбрасываете новый экземпляр заявки , или все время один и тот же? кторый сформировался на NewOrder?
On 8 июл, 13:31, Mikhail Sukhov <msou...@gmail.com> wrote:
Всегда один и тот же.
On 8 июл, 17:19, Tauler <vladimir_igo...@mail.ru> wrote:
Интерфес IClonable реализован?
On 8 июл, 17:35, Mikhail Sukhov <msou...@gmail.com> wrote:
Это для ReRegister. В перегруженом методе, где передается не новая заявка, а только новые цена и объем, сначала клонируется текущая заявка, а затем ей заполняются новые параметры.
On 8 июл, 17:44, Tauler <vladimir_igo...@mail.ru> wrote: