SampleRealTimeTesting sample после миграции со SmartCOM на QUIK выдает исключение в недрах S#. API

SampleRealTimeTesting sample после миграции со SmartCOM на QUIK выдает исключение в недрах S#. API
Atom
3/25/2014
nryabkov


Не знаю, насколько тут уместно постить такое. Пытаюсь разобраться с примерами (ну и понять, смогу ли я работать с таким API). В общем пытаюсь перевести SimpleRealTimeTesting со SmartCOM на QUIK. В результате получаю исключение из недр обфусцированного кода:
Quote:
---------------------------
Ошибка обработки данных
---------------------------
System.InvalidCastException: Specified cast is not valid.

at StockSharp.Algo.Testing.MarketEmulator.#=qs6NzRPBUoQ97T6nLH2BXpdtViDMxlBeB2SExFBHpRbs=.#=q7j8EZbErbhHRqBgBllTfPQ==(Message #=qFQNVQcmMx$w5TCZAXAka$w==, ICollection`1 #=qRIzQ1Vh6LxB082hZhWuGCw==)

at StockSharp.Algo.Testing.MarketEmulator.#=qs6NzRPBUoQ97T6nLH2BXpdtViDMxlBeB2SExFBHpRbs=.#=qIoakeHStFXUa2AHCKtSOdeQTtljz6NCiG3BQadYRn1nAyHWoqu4FDXdnHAk7VIwVHhs22v7wgoRTEod9oBwpFg==(Message #=qEU2PbcRHgieaeZXSjz7SIQ==)

at StockSharp.Algo.Testing.MarketEmulator.#=qf8FBDiLuwFV_pI1sqDDhMrxGHa5ZJ9z$AV68KOW7ejSUVtF2Mf18_A0jyIaKkzavqxn_yyIY0YlX$A7mV7dnGg==(Message #=qchosc_KrDpyII45LSsUmJg==)

at StockSharp.Algo.Testing.EmulationMessageAdapter.OnSendInMessage(Message message)

at StockSharp.Messages.MessageAdapter`1.OnInMessageProcessor(Message message, IMessageAdapter adapter)
---------------------------
OK
---------------------------


По идее хорошо бы тут говорить, что именно ожидается в данном случае. Какое сообщение. А то отладка ну совершенно странной становится. :)

Код получился вот такой: (заменил класс трейдера, прописал путь к терминалу и отключил загрузку исторических свечей - может в этом дело?):
Code
using StockSharp.Quik;

namespace SampleRealTimeTesting
{
	using System;
	using System.Collections.Generic;
	using System.ComponentModel;
	using System.Diagnostics;
	using System.Linq;
	using System.Windows;

	using Ecng.Collections;
	using Ecng.Common;
	using Ecng.ComponentModel;
	using Ecng.Xaml;

	using StockSharp.Algo;
	using StockSharp.Algo.Candles;
	using StockSharp.Algo.Indicators;
	using StockSharp.Algo.Indicators.Trend;
	using StockSharp.Algo.Reporting;
	using StockSharp.Algo.Testing;
	using StockSharp.BusinessEntities;
	using StockSharp.Logging;
	using StockSharp.Messages;
	
	using StockSharp.Xaml.Charting;

	public partial class MainWindow
	{
		private bool _isConnected;
        private readonly TimeSpan _timeFrame = TimeSpan.FromMinutes(5);
		private readonly SynchronizedList<TimeFrameCandle> _historyCandles = new SynchronizedList<TimeFrameCandle>();
		private CandleManager _candleManager;
        private RealTimeEmulationTrader<QuikTrader> _trader;
		private SmaStrategy _strategy;
		private DateTime _lastHistoryCandle;
		private Security _lkoh;
		private readonly ChartArea _area;
		private ChartCandleElement _candlesElem;
		private ChartIndicatorElement _longMaElem;
		private ChartIndicatorElement _shortMaElem;

		public MainWindow()
		{
			InitializeComponent();

			_area = new ChartArea();
			_chart.Areas.Add(_area);
		}

		protected override void OnClosing(CancelEventArgs e)
		{
			if (_trader != null)
				_trader.Dispose();

			base.OnClosing(e);
		}

		private void ConnectClick(object sender, RoutedEventArgs e)
		{
			if (!_isConnected)
			{
				if (_trader == null)
				{
                    //if (Login.Text.IsEmpty())
                    //{
                    //    MessageBox.Show(this, "Не указан логин.");
                    //    return;
                    //}
                    //else if (Password.Password.IsEmpty())
                    //{
                    //    MessageBox.Show(this, "Не указан пароль.");
                    //    return;
                    //}

					// тестовый портфель
					var portfolio = new Portfolio
					{
						Name = "test account",
						BeginValue = 1000000,
					};

					// создаем подключение
                    _trader = new RealTimeEmulationTrader<QuikTrader>(new QuikTrader
					(@"C:\Users\nryabkov\Documents\QUIK NetTrader\info.exe"));

					var logManager = new LogManager();
					logManager.MaxMessageCount = -1;			// без этого будет буферизация логов и они будут неактуальны при остановке в дебаггере.
					logManager.Listeners.Add(new FileLogListener("sample.log"));
					logManager.Sources.Add(_trader);

					// очищаем из текстового поля в целях безопасности
					Password.Clear();

					// подписываемся на событие успешного соединения
					_trader.Connected += () =>
					{
						// возводим флаг, что соединение установлено
						_isConnected = true;

						// разблокируем кнопку Экспорт
						this.GuiAsync(() => ChangeConnectStatus(true));

						// передаем первоначальное значение размера портфеля в эмулятор
						_trader.TransactionAdapter.SendInMessage(portfolio.ToMessage());
						_trader.TransactionAdapter.SendInMessage(new PortfolioChangeMessage
						{
							PortfolioName = portfolio.Name
						}.Add(PositionChangeTypes.BeginValue, portfolio.BeginValue));

						_candleManager = new CandleManager(_trader);

                        //_trader.UnderlyingConnector.NewCandles += (series, candles) => _historyCandles.SyncDo(col =>
                        //{
                        //    _historyCandles.AddRange(candles.Cast<TimeFrameCandle>());

                        //    this.GuiAsync(() =>
                        //    {
                        //        foreach (var candle in candles)
                        //            ProcessCandle(candle);
                        //    });
                        //});

						_trader.NewSecurities += securities => this.GuiAsync(() =>
						{
							// находим нужную бумагу
							var lkoh = securities.FirstOrDefault(s => s.Code == "LKOH");

							if (lkoh != null)
							{
								_lkoh = lkoh;

								this.GuiAsync(() =>
								{
									Start.IsEnabled = true;
								});
							}
						});

						_trader.NewMyTrades += trades => this.GuiAsync(() =>
						{
							if (_strategy != null)
							{
								// найти те сделки, которые совершила стратегия скользящей средней
								trades = trades.Where(t => _strategy.Orders.Any(o => o == t.Order));

								_trades.Trades.AddRange(trades);
							}
						});

						// подписываемся на событие о неудачной регистрации заявок
						_trader.OrdersRegisterFailed += OrdersFailed;

						_candleManager.Processing += (s, candle) =>
						{
							// выводим только те свечки, которые не были отрисованы как исторические
							if (candle.OpenTime > _lastHistoryCandle)
								ProcessCandle(candle);
						};

						_trader.StartExport();

						this.GuiAsync(() =>
						{
							ConnectBtn.IsEnabled = false;
						});
					};

					// подписываемся на событие разрыва соединения
					_trader.ConnectionError += error => this.GuiAsync(() =>
					{
						// заблокируем кнопку Экспорт (так как соединение было потеряно)
						ChangeConnectStatus(false);

						MessageBox.Show(this, error.ToString(), "Ошибка соединения");
					});

					_trader.ProcessDataError += error => this.GuiAsync(() => MessageBox.Show(this, error.ToString(), "Ошибка обработки данных"));
				}

				_trader.Connect();
			}
			else
			{
				_trader.Disconnect();
			}
		}

		private void OrdersFailed(IEnumerable<OrderFail> fails)
		{
			this.GuiAsync(() =>
			{
				foreach (var fail in fails)
					MessageBox.Show(this, fail.Error.ToString(), "Ошибка регистрации заявки");
			});
		}

		private void ChangeConnectStatus(bool isConnected)
		{
			_isConnected = isConnected;
			ConnectBtn.Content = isConnected ? "Отключиться" : "Подключиться";
		}

		private void OnLog(LogMessage message)
		{
			// если стратегия вывела не просто сообщение, то вывести на экран.
			if (message.Level != LogLevels.Info && message.Level != LogLevels.Debug)
				this.GuiAsync(() => MessageBox.Show(this, message.Message));
		}

		private void OnStrategyPropertyChanged(object sender, PropertyChangedEventArgs e)
		{
			this.GuiAsync(() =>
			{
				Status.Content = _strategy.ProcessState;
				PnL.Content = _strategy.PnL;
				Slippage.Content = _strategy.Slippage;
				Position.Content = _strategy.Position;
				Latency.Content = _strategy.Latency;
			});
		}

		private void StartClick(object sender, RoutedEventArgs e)
		{
			// если были получены и инструмент, и портфель
			if (_strategy == null)
			{
				// создаем скользящие средние, на 80 5-минуток и 10 5-минуток
				var longSma = new SimpleMovingAverage { Length = 80 };
				var shortSma = new SimpleMovingAverage { Length = 10 };
				
				// регистрируем наш тайм-фрейм
				var series = new CandleSeries(typeof(TimeFrameCandle), _lkoh, _timeFrame);
				// создаем торговую стратегию
				_strategy = new SmaStrategy(series, longSma, shortSma)
				{
					Volume = 1,
					Security = _lkoh,
					Portfolio = _trader.Portfolios.First(),
					Connector = _trader,
				};
				_strategy.Log += OnLog;
				_strategy.PropertyChanged += OnStrategyPropertyChanged;

				_candlesElem = new ChartCandleElement();
				_area.Elements.Add(_candlesElem);

				_longMaElem = new ChartIndicatorElement
				{
					Title = "Длинная",
					Indicator = _strategy.LongSma,
				};
				_area.Elements.Add(_longMaElem);

				_shortMaElem = new ChartIndicatorElement
				{
					Title = "Короткая",
					Indicator = _strategy.ShortSma,
				};
				_area.Elements.Add(_shortMaElem);

				// начинаем получать текущие сделки (для построения свечек реального времени)
				_trader.RegisterTrades(_lkoh);

                //// делаем запрос в SmartCOM для получения исторических данных по 5-минуткам для Лукойла за период в 5 дней
                //_trader.UnderlyingConnector.RequestCandles(_lkoh, SmartComTimeFrames.Minute5,
                //                     new Range<DateTime>(DateTime.Today - TimeSpan.FromDays(5), _lkoh.GetMarketTime()));

				_lastHistoryCandle = _timeFrame.GetCandleBounds(_lkoh).Min;

				Report.IsEnabled = true;
			}

			if (_strategy.ProcessState == ProcessStates.Stopped)
			{
				// запускаем процесс получения стакана, необходимый для работы алгоритма котирования
				_trader.RegisterMarketDepth(_strategy.Security);
				_strategy.Start();
				Start.Content = "Стоп";
			}
			else
			{
				_trader.UnRegisterMarketDepth(_strategy.Security);
				_strategy.Stop();
				Start.Content = "Старт";
			}
		}

		private void ProcessCandle(Candle candle)
		{
			var longValue = candle.State == CandleStates.Finished ? new ChartIndicatorValue(_strategy.LongSma, _strategy.LongSma.Process(candle)) : null;
			var shortValue = candle.State == CandleStates.Finished ? new ChartIndicatorValue(_strategy.ShortSma, _strategy.ShortSma.Process(candle)) : null;

			_chart.ProcessValues(candle.OpenTime, new Dictionary<IChartElement, object>
			{
				{ _candlesElem, candle },
				{ _longMaElem, longValue },
				{ _shortMaElem, shortValue },
			});
		}

		private void ReportClick(object sender, RoutedEventArgs e)
		{
			// сгерерировать отчет по прошедшему тестированию
			new ExcelStrategyReport(_strategy, "sma.xls").Generate();

			// открыть отчет
			Process.Start("sma.xls");
		}
	}
}

Tags:


Thanks:


esper

Avatar
Date: 3/25/2014
Reply


Какая версия?
Thanks:

nryabkov

Avatar
Date: 3/26/2014
Reply


Версия 4.2.2.16
Thanks:

esper

Avatar
Date: 3/26/2014
Reply


Обновитесь до последней версии.
Thanks: nryabkov

nryabkov

Avatar
Date: 3/26/2014
Reply


Да, большое спасибо. Заработало! :)
Thanks:


Attach files by dragging & dropping, , or pasting from the clipboard.

loading
clippy