Проблема в RealTimeEmulationTrader
Atom
05.03.2013
AASorokovoy


Наблюдаю на 4.1.8

Проявляет себя как не вызывание события NewMyTrades у объекта EmulationTrader as ITrader (существует и такой по мимо RealTimeEmulationTrader).

Схема такая: ( прошу не задавать вопросы зачем это нужно :) )

  1. создаем объект EmulationTrader, нацеленный на некоторую базу гидры.
  2. создаем объект new RealTimeEmulationTrader (EmulationTrader as ITrader)
  3. Создаем стратегию new MyStrategy(EmulationTrader as ITrader) с примерно следующим конструктором.

MyStrategy(ITrader iDataSource)
{
iDataSource.NewMyTrades += (obj) => { MessageBox.Show("Приехали сделки"); };
}

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

Дальше веселее. Если поменять пункт 2 и 3 по порядку то есть сделать так:

  1. создаем объект EmulationTrader, нацеленный на некоторую базу гидры.
  2. Создаем стратегию new MyStrategy(EmulationTrader as ITrader)
  3. создаем объект new RealTimeEmulationTrader (EmulationTrader as ITrader). Сделки приедут.

В логах можно обнаружить следующее.

2012/02/24 10:06:10.000|Error |EmulationTrader|System.InvalidOperationException: Ордер с transactionId=101 не найден at StockSharp.Algo.Testing.RealTimeEmulationTrader1.#=qoYen7SIGXXIHC5yDoBmtakvI8ajVk$YMRTG2hIXiflw=(Int64 #=qO9iU2Mv29dcXgUc$4EMffw==) at StockSharp.Algo.Testing.RealTimeEmulationTrader1.#=qW_NOGPO8hUy5l8I2xNZCL$oRPjjivnoDpJ2KizA3TPo=(IEnumerable1 #=qA0Q6xXtG5Oyta7t6dDl7yg==) at System.Action1.Invoke(T obj) at Ecng.Common.DelegateHelper.SafeInvoke(Action1 handler, T arg) at Ecng.ComponentModel.EventsContainer1.Raise(IEnumerable1 items) 2012/02/24 10:06:10.000| |EmulationTrader|New order: 102/2 Покупка Цена=7025,00000 Объем=1 Сост=Active Бал=1 2012/02/24 10:06:10.000|Error |EmulationTrader|System.InvalidOperationException: Ордер с transactionId=102 не найден at StockSharp.Algo.Testing.RealTimeEmulationTrader1.#=qoYen7SIGXXIHC5yDoBmtakvI8ajVk$YMRTG2hIXiflw=(Int64 #=qO9iU2Mv29dcXgUc$4EMffw==) at StockSharp.Algo.Testing.RealTimeEmulationTrader1.#=qW_NOGPO8hUy5l8I2xNZCL$oRPjjivnoDpJ2KizA3TPo=(IEnumerable1 #=qA0Q6xXtG5Oyta7t6dDl7yg==) at System.Action1.Invoke(T obj) at Ecng.Common.DelegateHelper.SafeInvoke(Action1 handler, T arg) at Ecng.ComponentModel.EventsContainer1.Raise(IEnumerable1 items)

Что наводит нас на мысли о том, что мы отправляем заявки через EmulationTrader он их обрабатывает и генерирует MyTrade которые выдает ее через событие NewMyTrades. Данные MyTrades перехватываются RealTimeEmulationTrader и обрабатываются в методе.


		private void NewMyTradesHandler(IEnumerable<MyTrade> trades)
		{
			foreach(var trade in trades)
			{
				trade.Order = GetOrderByTransaction(trade.Order.TransactionId);
			}
			NewMyTrades.SafeInvoke(trades);
		}

и далее 
		private Order GetOrderByTransaction(long transactionId)
		{
			var order = _byTransactionOrders.TryGetValue(transactionId);

			if(order == null)
				throw new InvalidOperationException("Ордер с transactionId="+transactionId+" не найден");

			return order;
		}


Который выбрасывает исключение (потому что заявка подавалась не через эмулятор).

На событие NewMyTrades есть два подписчика. Подписчики лежат в чем то типо List<Action<IEnumerable>> и при NewMyTrades.Invoke начинают вызываться в порядке в котором на событие были подписаны (ITrader.NewMyTrades += ... ) и соответственно при порядке исполнения 1),3),2) вначале вызывается обработчик стратегии а потом обработчик RealTimeEmulationTrader и вроде все хорошо. При порядке 1), 2), 3) выброшенное, необработанное исключение RealTimeEmulationTrader'ом прерывает перечисление обработчиков в List<Action<IEnumerable>> и соответственно до обработчика стратегии действие не доходит и он не вызывается и получаем то, что имеем. (По крайней мере так я вижу проблему)

Как вариант, возможно есть смысл, немного подправить обработчик NewOrderHandler RealTimeEmulationTrader


		private void NewOrderHandler(Order state)
		{
			var order = GetOrderByTransaction(state.TransactionId); // (здесь кстати происходит точно такая же ситуация, только с событием NewOrder. Со всеми вытекающими.) 
			using (order.BeginUpdate())
			{
				order.Id = state.Id;
				order.LastChangeTime = state.LastChangeTime;
				order.Time = state.Time;
				order.Balance = state.Balance;
				order.State = state.State;
			}

			if (order.Type == OrderTypes.Conditional)
				NewStopOrdersHandler(new[] { order });
			else
				NewOrdersHandler(new[] { order });
		}

Что бы при выбрасывании исключения


var order = GetOrderByTransaction(state.TransactionId); 

оно обрабатывалось добавление нового ордера в коллекцию RealTimeEmulationTrader'а и что в свою очередь уберет проблему с выбрасыванием исключений при NewMyTrades (так как ордер уже будет в RealTimeEmulationTrader)




Спасибо:


< 1 2 3  >
VassilSanych

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


Творог: Мне кажется, тогда, было бы логичным сделать стандартное правило ожидания, типа:

order
    .WaitFeedback(strategy, timeout) //запрещает проводить любые действия с заявками по стратегии
    .WhenRegistered()
    .Do(() => trader.AddInfoLog("Заявка успешно зарегестрирована"))
    .Once()
    .Apply(this);

// регистрация заявки
trader.RegisterOrder(order);
Оk. Допустим у вас есть такое правило. Ошибка регистрации заявки. Ваши действия?

Спасибо:

Творог

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


VassilSanych:

Творог: Мне кажется, тогда, было бы логичным сделать стандартное правило ожидания, типа:

order
    .WaitFeedback(strategy, timeout) //запрещает проводить любые действия с заявками по стратегии
    .WhenRegistered()
    .Do(() => trader.AddInfoLog("Заявка успешно зарегестрирована"))
    .Once()
    .Apply(this);

// регистрация заявки
trader.RegisterOrder(order);
> Оk. Допустим у вас есть такое правило. Ошибка регистрации заявки. Ваши действия?

Если по таймауту, например 10 сек, никакого ответа, то запускается делегат
.WaitFeedback(strategy, timeout, action)
Это будет означать что косяки либо с интернетом (переход на резервный канал), либо биржей (стоп-торги) или брокером. В общем торговлю вообще надо замораживать и по возможности крыть все позиции.

Если ошибка регистрации, то это уже ответ failed, это уже другая история, например, денег на счёте не хватило.
Спасибо:

esper

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


private void Process(Candle candle)
{
	if (_order != null)
		return;

	_order = this.CreateOrder(OrderDirections.Buy, candle.ClosePrice);

	_order
		.WhenRegistered()
		.Do(() => { _order = null; })
		.Apply(this);

	_order
		.WhenRegisterFailed()
		.Do(() => { _order = null; })
		.Apply(this);

	RegisterOrder(_order);
}

Почему нельзя сделать так?

Спасибо:

Творог

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


esper: Почему нельзя сделать так?

Попробую. Но в таком правиле тоже, думаю, был бы смысл


    _order
        .WaitFeedback(timeout = 10)
        .Do(() => { отправить SMS и email о том, что слишком большая задержка. попытаться перейти на резервный канал. в QUIK перейти на следующий по списку сервер, если такое вообще технически возможно  })
        .Apply(this);

Спасибо:

esper

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


Творог: Но в таком правиле тоже, думаю, был бы смысл

Trader.WhenIntervalElapsed
Спасибо:

Творог

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


esper:

Творог: Но в таком правиле тоже, думаю, был бы смысл

Trader.WhenIntervalElapsed


Но бывают же ситуации, когда просмотровая информация поступает, а с заявками проблема.
А есть ли разница приметь к заявкам null или Dispose?
Спасибо:

esper

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


Творог: Но бывают же ситуации, когда просмотровая информация поступает, а с заявками проблема. Так и смотрите, что таймаут истек, а информация по заявке еще не пришла.

Спасибо:

AASorokovoy

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


Проявляет себя на 4.1.11 Возможно выше написанная диагностика выполнена не достаточно ясно? Может быть, что то не понятно? Может я как то еще могу помочь?

P.S. Прошу очистить ветку от сообщений не по теме.

Спасибо:

esper

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


AASorokovoy: Проявляет себя на 4.1.11 Возможно выше написанная диагностика выполнена не достаточно ясно? Может быть, что то не понятно? Может я как то еще могу помочь? Диагностика отличная, спасибо. Были другие задачи, в следующей версии будет фикс.

Спасибо:

longtrades

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


Прошу проверить:

Версия 4.1.12 , RealTimeEmulationTrader поверх QuikTrader: _trader.CancelOrder(order) не срабатывает, заявки не удяляються и остаются висеть в _trader.Orders со статусом Active , _trader.ReRegisterOrder тоже не удаляет заявки , но при попытке повторного удаления заявок из _trader.Orders.Where(x => x.State == OrderStates.Active) выдает ошибку что заявка не была зарегистрирована или уже удалена , при чем в _trader.Orders все также остаются висеть те же заявки с OrderStates.Active. И при попытке заслать противоположную заявку с ценой ниже выдает сообщение про кросс заявку.

Спасибо.

Спасибо:
< 1 2 3  >

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

loading
clippy