← Zurück

Вопрос по обработке сделок

Ситуация такая, стратегия отправляет заявки на биржу метод RegisterOrder(Order) и по таймауту или исполнению некого условия снимает через метод Trader.CancelOrder(Order). Учет закрытых позиций и цены происходит при событии появлении новой сделки order.NewTrades() (нужно для работы робота), По событию снятия заявки .Order.Canceled() или её полного исполнения заявка считается закрытой.

В каждом событии стоит проверка - если статус заявки Done и количество учтенных роботом позиций равно ОбъемЗаявки - БалансЗаявки. То исключаем её из списка робота, и считаем что закрыта, т.е. робот считает что вся информация по заявке получена. Учитывается ситуация если сделки пришли позже, чем заявка была снята/исполнена, так же есть обработка события неудачной отмены заявки. Код основательно перерыт и перепроверен.

Но иногда примерно с одной-двумя из 500 заявок возникает ситуация когда условие проверки выполняется заявка исключается, но Робот учитывает не все сделки прошедшие по заявке. Как вариант может быть такое, что в какой-то момент статус заявки Done, а баланс по ней ещё может изменится? В чем может быть причина, может сталкивался кто-то? Уже просто не знаю что с этим делать. Сейчас все работает на тестовом сервере РТС, Forts Plaza - II.

Kommentare (28)

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

Самунджян Артем

Александр (ПАА): Ситуация такая, стратегия отправляет заявки на биржу метод RegisterOrder(Order) и по таймауту или Но иногда примерно с одной-двумя из 500 заявок возникает ситуация когда условие проверки выполняется заявка исключается, но Робот учитывает не все сделки прошедшие по заявке. Как вариант может быть такое, что в какой-то момент статус заявки Done, а баланс по ней ещё может изменится? В чем может быть причина, может сталкивался кто-то? Уже просто не знаю что с этим делать. Сейчас все работает на тестовом сервере РТС, Forts Plaza - II. Если я всё правильно понял, то могу посоветовать использовать strategyRule и непосредственно опираться на событие изменения самого ордера , то есть переписать полностью алгоритм на событийную модель. Если состояние у заявки Done , то никакое изменение по ней прийти уже не может.Попробуй включить логирование , если неизвестно как , я отпишусь...Не совсем понял , как работает "проверка", может быть её можно как-нибудь доработать.



 this.When(_order.Matched())
                            .Do(o =>
                                    {
                                        //алгоритм работы с ордером
                                    });

Alexander
Alexander

Артём Самунджян: Если состояние у заявки Done , то никакое изменение по ней прийти уже не может.

Может. Мы можем done выставить как ответ на заявку по транзакционному потоку, а затем нам пришло изменение по таблице заявок.

В данном случае, как совершенно верно ответил Артём, лучше пользоваться правилами.

И просьба всегда указывать версию при описании проблем. В случае с плазой изменений в 4.1 было крайне много и если пользуетесь 4.0 - совет переходить на 4.1 как можно скорее.

Александр (ПАА)
Александр (ПАА) Autor

Спасибо за ответы. В принципе я и так использую событийную модель. Может если кусок кода показать понятнее будет, о чем я. Происходит это так, в стратегии объявлена публичная функция RegisterOrder(JointRequest order), JointRequest - это собственный класс, в нем содержится Заявка Order и дополнительная информация. Стратегия занимается только тем что регистрирует/снимает заявки и обрабатывает соответствующие события, остальной частью занимается другой класс, который и вызывает Strategy.RegisterOrder или Strategy.CancelOrder.

 public void RegisterOrder(JointRequest order)
        {
            order.State = StateJointRequest.Sended;
            JointRequests.Add(order);
            try
            {
                base.RegisterOrder(order.Order);
                OnJointRequestChanged(order);
                order.Save();
                this
                   .When(order.Order.Matched())
                   .Do((Action)(() => RequestMatched(order)));
                this
                  .When(order.Order.NewTrades())
                  .Do((Action<IEnumerable<MyTrade>>)((newTrades) => NewTradesRequest(order, newTrades)));
            }
            catch  
            {
                order.State = StateJointRequest.None;
            }
        }

        public void NewTradesRequest(JointRequest order,IEnumerable<MyTrade> MyTrades)
        {
            order.ClosePositions(MyTrades);
            //то самое условие
            if (order.Order.State == OrderStates.Done && (order.Order.Volume - order.Order.Balance == order.ClosedCount))
                order.CloseJR();
        }
  public void RequestMatched(JointRequest order)
        {
            //то самое условие
            if (order.Order.State == OrderStates.Done && (order.Order.Volume - order.Order.Balance == order.ClosedCount))
                order.CloseJR();
        }

аналогично и со снятием заявки. ClosedCount считается в order.ClosePositions(MyTrades) считается правильно.

Использую 4.0.23, а где можно скачать 4.1 чтобы перейти? по ссылке с сайта на скачивание вижу только 4.0 и более ранние версии.

Alexander
Alexander

NewTrades может быть раньше чем order.Matched, а может и нет.

  • выше дал пояснения по тому как баланс может меняться после Done.

4.1 брать с stocksharp.codeplex.com из sources, папка dev\references

Александр (ПАА)
Александр (ПАА) Autor

Спасибо, Александр, а как тогда лучше организовать проверку все ли сделки по заявке учтены? С Matched() то понятно там Order.Balance = 0, а если событие Order.Canceled()?

Alexander
Alexander

Александр (ПАА): Спасибо, Александр, а как тогда лучше организовать проверку все ли сделки по заявке учтены? С Matched() то понятно там Order.Balance = 0, а если событие Order.Canceled()?

давайте немного с другой стороны зайдём. расскажите для чего вам это нужно. мне кажется, подход немного не верный.

Александр (ПАА)
Александр (ПАА) Autor

Давайте попробуем. Суть в том что у меня есть много модулей, каждый из который торгует по некоему алгоритму, часто бывает так, что нужно отправить на биржу одновременно несколько заявок от разных модулей, чтобы сократить количество отправляемых заявок а так же исключить встречные заявки от модулей, я составляю одну - которая и отправляется на биржу через стратегию, но после исполнения или снятия этой объединенной заявки информацию по ней необходимо разобрать и вернуть каждому модулю сколько и как исполнилось по нему.

westtrd
westtrd

Александр (ПАА): Давайте попробуем. Суть в том что у меня есть много модулей, каждый из который торгует по некоему алгоритму, часто бывает так, что нужно отправить на биржу одновременно несколько заявок от разных модулей, чтобы сократить количество отправляемых заявок а так же исключить встречные заявки от модулей, я составляю одну - которая и отправляется на биржу через стратегию, но после исполнения или снятия этой объединенной заявки информацию по ней необходимо разобрать и вернуть каждому модулю сколько и как исполнилось по нему. Вообще то это клиринговая логика, с распределением проторгованного объема по компонентам Такое на западных рынках есть, и проблем тут достаточно.

Есть несколько основных сценариев:

  1. пропорционально
  2. FIFO
  3. нечто производное

Вообще, если размеры счетов позволяют, лучше тупо разводить по разным субсчетам

Alexander
Alexander

тогда не отслеживайте done, а отслеживайте только new trades. приходит новая сделка - сообщили модулую. когда у модуля исполненный объём станет равен посланному - считаем что заявка исполнилась полностью.

Александр (ПАА)
Александр (ПАА) Autor

А как быть если заявка полностью не исполниться? Я же снимаю ее по таймауту, и она может либо быть частично исполнена, либо вообще не исполнена...

Alexander
Alexander

У вас баланс меняется после Done только для снятой заявки?

Александр (ПАА)
Александр (ПАА) Autor

По моим наблюдениям только для снятой.

Alexander
Alexander

Александр (ПАА): По моим наблюдениям только для снятой.

В ветке 4.1 точно сделано следующее:

  • если мы посылаем CancelOrder - то в ответ на эту транзакцию биржа присылает сколько осталось по балансу в заявке - мы это проставляем и заявка больше не может быть изменена
  • если посылаем CancelOrders - групповое снятие - то тут да, может возникнуть что после State = OrderState.Done изменится баланс - я это поправил, будет фикс выложен на codeplex
  • для перерегистрации - см. групповое снятие - тоже поправлено

Вообще после того как стал OrderState.Done баланс меняться не должен. Если у вас не так на 4.1 - пишите ещё раз, будем разбираться.

Сейчас просьба перейти на 4.1 и пока (до выкладывания последнего фикса на codeplex) - пользоваться CancelOrder, а не групповым снятием заявки.

gazrvs_nur
gazrvs_nur

Чтобы не плодить одинаковые темы, просьба помочь с простым вопросом по сделкам: в тестовом примере SmaStrategy создал правило на появление новых сделок: this .WhenNewMyTrades() .Do(writecsv) .Apply(this); в обработчике writecsv хочу получить данные по последней сделке: var trade = this.MyTrades. ???? ; но не могу получить не одно из свойств MyTrades, хотя отладчике они все есть в ((StockSharp.BusinessEntities.MyTrade[])(this.MyTrades))

Есть другой способ?

Alexander
Alexander

gazrvs_nur: Чтобы не плодить одинаковые темы, просьба помочь с простым вопросом по сделкам: в тестовом примере SmaStrategy создал правило на появление новых сделок: this .WhenNewMyTrades() .Do(writecsv) .Apply(this); в обработчике writecsv хочу получить данные по последней сделке: var trade = this.MyTrades. ???? ; но не могу получить не одно из свойств MyTrades, хотя отладчике они все есть в ((StockSharp.BusinessEntities.MyTrade[])(this.MyTrades))

Есть другой способ?

this.WhenNewMyTrades().Do<IEnumerable<MyTrade>>(writecsv).Apply(this);

private void writecsv(IEnumerable<MyTrade> newMyTrades)
{
...
}

Таким образом в обработчик сразу передадутся новые сделки.

gazrvs_nur
gazrvs_nur

Компилятор ругается на строку private void writecsv( IEnumerable<MyTrade> newMyTrades)

Ошибка 1 Вместе с аргументами-типами нельзя использовать не универсальный тип "System.Collections.IEnumerable" E:\WIN\Samples\Testing\SampleHistoryTestingParallel\SmaStrategy.cs 92 41 SampleHistoryTestingParallel

Alexander
Alexander

gazrvs_nur: Компилятор ругается на строку private void writecsv( IEnumerable<MyTrade> newMyTrades)

Ошибка 1 Вместе с аргументами-типами нельзя использовать не универсальный тип "System.Collections.IEnumerable" E:\WIN\Samples\Testing\SampleHistoryTestingParallel\SmaStrategy.cs 92 41 SampleHistoryTestingParallel

Сейчас в 4.1 всё даже проще стало


...
this.WhenNewMyTrades().Do(writecsv);
...

private void writecsv(IEnumerable<MyTrade> newMyTrades)
{
...
}
gazrvs_nur
gazrvs_nur

Александр, я аналогично уже пробывал ..

На конструкцию: ".Do(writecsv);" компилятор выдает ошибку: Ошибка 1 Наиболее подходящий перегруженный метод для "StockSharp.Algo.Strategies.StrategyRule<System.Collections.Generic.IEnumerable<StockSharp.BusinessEntities.MyTrade>>.Do(System.Action)" имеет несколько недопустимых аргументов Ошибка 2 Аргумент "1": преобразование типа из "группа методов" в "System.Action" невозможно

А на "private void writecsv(IEnumerable<MyTrade> newMyTrades)" по прежднему: Ошибка 3 Вместе с аргументами-типами нельзя использовать не универсальный тип "System.Collections.IEnumerable"

как бы вообще уйти от этого IEnumerable<MyTrade> в нормальный IEnumerable хотя бы.

Alexander
Alexander

gazrvs_nur: Александр, я аналогично уже пробывал ..

На конструкцию: ".Do(writecsv);" компилятор выдает ошибку: Ошибка 1 Наиболее подходящий перегруженный метод для "StockSharp.Algo.Strategies.StrategyRule<System.Collections.Generic.IEnumerable<StockSharp.BusinessEntities.MyTrade>>.Do(System.Action)" имеет несколько недопустимых аргументов Ошибка 2 Аргумент "1": преобразование типа из "группа методов" в "System.Action" невозможно

А на "private void writecsv(IEnumerable<MyTrade> newMyTrades)" по прежднему: Ошибка 3 Вместе с аргументами-типами нельзя использовать не универсальный тип "System.Collections.IEnumerable"

как бы вообще уйти от этого IEnumerable<MyTrade> в нормальный IEnumerable хотя бы.

У вас точно последняя версия 4.1?

gazrvs_nur
gazrvs_nur

у меня сборка stocksharp-16844 от 10.05.2012г. сейчас скачаю последнюю и проверю

gazrvs_nur
gazrvs_nur

Проблема в stocksharp-17079 (папка dev) та же

private void writecsv(IEnumerable<MyTrade> newMyTrades) Ошибка 3 Вместе с аргументами-типами нельзя использовать не универсальный тип "System.Collections.IEnumerable"

а не проще было бы сделать доступными свойства Strategy.MyTrades. ?

Alexander
Alexander

gazrvs_nur: Проблема в stocksharp-17079 (папка dev) та же

private void writecsv(IEnumerable<MyTrade> newMyTrades) Ошибка 3 Вместе с аргументами-типами нельзя использовать не универсальный тип "System.Collections.IEnumerable"

а не проще было бы сделать доступными свойства Strategy.MyTrades. ?

Они все доступны.

У вас проблема в том, что не подключены либо библиотеки нужные, либо using.

Следующий код без проблем компилируется у меня:

namespace Test
{
	using System.Collections.Generic;
	using StockSharp.Algo.Strategies;
	using StockSharp.BusinessEntities;

	public class MyStategy : Strategy
	{
		protected override void OnStarting()
		{
			base.OnStarting();

			this.WhenNewMyTrades().Do(writecsv);
		}

		void writecsv(IEnumerable<MyTrade> newMyTrades)
		{
		}
	}
}

Собираю под .Net Framework 4.0

gazrvs_nur
gazrvs_nur

Спасибо Александр, вся проблема была в using System.Collections.Generic; я использовал using System.Collections; странно конечно .Generic должен входить в System.Collections по умолчанию, но видимо не обязан.

вот только проблема была не в вызове процедуры с передаче туда MyTrades, а в том, чтобы получить дату, время, цену и направление последней сделки из this.MyTrades.

пока вытащить из IEnumerable<MyTrade> это данные неполучается.

добавить что то вроде this.MyTrades.Last() тоже нельзя.

в цикле foreach (IEnumerable<MyTrade> value in newMyTrades) получить какое либо значение(дату, время) "value." также не идет.

Alexander
Alexander

gazrvs_nur: вот только проблема была не в вызове процедуры с передаче туда MyTrades, а в том, чтобы получить дату, время, цену и направление последней сделки из this.MyTrades.

пока вытащить из IEnumerable<MyTrade> это данные неполучается.

добавить что то вроде this.MyTrades.Last() тоже нельзя.

в цикле foreach (IEnumerable<MyTrade> value in newMyTrades) получить какое либо значение(дату, время) "value." также не идет.

К сожалению, лишь сейчас увидел это добавление к сообщению. На будущее просьба писать новые сообщения, а не редактировать предыдущие :) А то они через RSS не идут. Я уже вроде как прочитал, а потом оказывается что там половина нового была.

Так можно и без ответа остаться :)

Очень странно что не работает через MyTrades.Last()

MyTrades - это обычный IEnumerable<T> Идём в MSDN, ищем метод Last у интерфейса. Видим - необходимо объявить using System.Linq; и подключить reference System.Core.dll

gazrvs_nur
gazrvs_nur

Может кому понадобится. Извернулся в вышеуказанном случае следующим образом: private void writecsv(IEnumerable<MyTrade> newMyTrades) { var Tradeneed = new List<MyTrade>(newMyTrades); decimal ClosedVolumeneed = Tradeneed[0].ClosedVolume; decimal Volumeneed = Tradeneed[0].Trade.Volume; DateTime Timeneed = Tradeneed[0].Trade.Time; string Securityneed = Tradeneed[0].Trade.Security.ToString(); decimal Priceneed = Tradeneed[0].Trade.Price; string Directionneed = Tradeneed[0].Trade.OrderDirection.ToString(); long Idneed = Tradeneed[0].Trade.Id;
}

gazrvs_nur
gazrvs_nur

Да я уже понял, что что не так, System.Linq объявлял, но вот до reference System.Core.dll уже не дошел, будем нарабатывать опыт.

Александр (ПАА)
Александр (ПАА) Autor

Добрый день, после перехода на 4.1 опять та же проблема (с изменением баланса после изменения статуса заявки на Done) возникает, правда намного реже...

Alexander
Alexander

Александр (ПАА): Добрый день, после перехода на 4.1 опять та же проблема (с изменением баланса после изменения статуса заявки на Done) возникает, правда намного реже...

приведите лог, укажите шлюз лучше в соответствующем подфоруме