Beispiel #1
0
        /// <inheritdoc />
        public void LookupSecurities(Security criteria, IMessageAdapter adapter = null, MessageOfflineModes offlineMode = MessageOfflineModes.None)
        {
            if (criteria == null)
            {
                throw new ArgumentNullException(nameof(criteria));
            }

            var boardCode    = criteria.Board?.Code;
            var securityCode = criteria.Code;

            if (!criteria.Id.IsEmpty())
            {
                var id = SecurityIdGenerator.Split(criteria.Id);

                if (boardCode.IsEmpty())
                {
                    boardCode = GetBoardCode(id.BoardCode);
                }

                if (securityCode.IsEmpty())
                {
                    securityCode = id.SecurityCode;
                }
            }

            var msg = criteria.ToLookupMessage(criteria.ExternalId.ToSecurityId(securityCode, boardCode));

            msg.Adapter     = adapter;
            msg.OfflineMode = offlineMode;

            LookupSecurities(msg);
        }
        private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
        {
            Year.ItemsSource = Competition.AllYears;
            Year.SelectedItem = Competition.AllYears.Last();

            var ns = typeof(IIndicator).Namespace;

            var rendererTypes = typeof(Chart).Assembly
                .GetTypes()
                .Where(t => !t.IsAbstract && typeof(BaseChartIndicatorPainter).IsAssignableFrom(t))
                .ToDictionary(t => t.Name);

            var indicators = typeof(IIndicator).Assembly
                .GetTypes()
                .Where(t => t.Namespace == ns && !t.IsAbstract && typeof(IIndicator).IsAssignableFrom(t))
                .Select(t => new IndicatorType(t, rendererTypes.TryGetValue(t.Name + "Painter")));

            Chart.IndicatorTypes.AddRange(indicators);

            const string finamSecurities = "finam.csv";

            if (File.Exists(finamSecurities))
            {
                var idGen = new SecurityIdGenerator();

                var securities = File.ReadAllLines(finamSecurities).Select(line =>
                {
                    var cells = line.SplitByComma();
                    var idParts = idGen.Split(cells[0]);

                    return new Security
                    {
                        Id = cells[0],
                        Code = idParts.Item1,
                        Board = ExchangeBoard.GetOrCreateBoard(idParts.Item2),
                        ExtensionInfo = new Dictionary<object, object>
                        {
                            { FinamHistorySource.MarketIdField, cells[1].To<long>() },
                            { FinamHistorySource.SecurityIdField, cells[2].To<long>() },
                        }
                    };
                });

                foreach (var security in securities)
                {
                    _securityProvider.Securities.Add(security);
                    _securityStorage.Save(security);
                }
            }
            else
            {
                _finamHistorySource.Refresh(_securityStorage, new Security(), s => { }, () => false);

                var securities = _securityStorage.LookupAll().ToArray();

                foreach (var security in securities)
                    _securityProvider.Securities.Add(security);

                File.WriteAllLines(finamSecurities, securities.Where(s => !s.Id.Contains(',')).Select(s => "{0},{1},{2}"
                    .Put(s.Id, s.ExtensionInfo[FinamHistorySource.MarketIdField], s.ExtensionInfo[FinamHistorySource.SecurityIdField])));
            }

            if (File.Exists(_settingsFile))
            {
                var settings = CultureInfo.InvariantCulture.DoInCulture(() => new XmlSerializer<SettingsStorage>().Deserialize(_settingsFile).Load<Settings>());

                Year.SelectedItem = settings.Year;
                Trader.Text = settings.Trader;
                From.Value = settings.From;
                To.Value = settings.To;
                Security1.Text = settings.Security1;
                Security2.Text = settings.Security2;
                Security3.Text = settings.Security3;
                Security4.Text = settings.Security4;
                TimeFrame.SelectedItem = settings.TimeFrame;
            }
            else
            {
                Trader.Text = "Vasya";
                Security1.Text = "RIZ5@FORTS";
                //Trader.Text = "iZotov";
                //Security1.Text = "SPZ5@FORTS";
                //Security2.Text = "SIZ5@FORTS";
                //From.Value = new DateTime(2014, 09, 16);
            }
        }
		private void Sync_Click(object sender, RoutedEventArgs e)
		{
			if (_token != null)
			{
				StopSync();
				return;
			}

			Sync.Content = LocalizedStrings.Str2890;

			_token = new CancellationTokenSource();

			Task.Factory.StartNew(() =>
			{
				var securityPaths = new List<string>();

				foreach (var dir in DriveCache.Instance.AllDrives
					.OfType<LocalMarketDataDrive>()
					.Select(drive => drive.Path)
					.Distinct())
				{
					foreach (var letterDir in InteropHelper.GetDirectories(dir))
					{
						if (_token.IsCancellationRequested)
							break;

						var name = Path.GetFileName(letterDir);

						if (name == null || name.Length != 1)
							continue;

						securityPaths.AddRange(InteropHelper.GetDirectories(letterDir));
					}

					if (_token.IsCancellationRequested)
						break;
				}

				if (_token.IsCancellationRequested)
					return;

				var iterCount = 
					securityPaths.Count + // кол-во проходов по директории для создания инструмента
					DriveCache.Instance.AllDrives.Count() * (EntityRegistry.Securities.Count + securityPaths.Count); // кол-во сбросов кэша дат

				this.GuiSync(() => Progress.Maximum = iterCount);

				var logSource = ConfigManager.GetService<LogManager>().Application;

				var securityIdGenerator = new SecurityIdGenerator();

				var securities = EntityRegistry.Securities.ToDictionary(s => s.Id, s => new KeyValuePair<Security, bool>(s, true), StringComparer.InvariantCultureIgnoreCase);

				foreach (var securityPath in securityPaths)
				{
					if (_token.IsCancellationRequested)
						break;

					var securityId = Path.GetFileName(securityPath).FolderNameToSecurityId();

					var isNew = false;

					var security = securities.TryGetValue(securityId).Key;
					if (security == null)
					{
						var firstDataFile =
							Directory.EnumerateDirectories(securityPath)
								.SelectMany(d => Directory.EnumerateFiles(d, "*.bin")
									.Concat(Directory.EnumerateFiles(d, "*.csv"))
									.OrderBy(f => Path.GetExtension(f).CompareIgnoreCase(".bin") ? 0 : 1))
								.FirstOrDefault();

						if (firstDataFile != null)
						{
							var info = securityIdGenerator.Split(securityId);

							decimal priceStep;

							if (Path.GetExtension(firstDataFile).CompareIgnoreCase(".bin"))
							{
								try
								{
									priceStep = File.ReadAllBytes(firstDataFile).Range(6, 16).To<decimal>();
								}
								catch (Exception ex)
								{
									throw new InvalidOperationException(LocalizedStrings.Str2929Params.Put(firstDataFile), ex);
								}
							}
							else
								priceStep = 0.01m;

							security = new Security
							{
								Id = securityId,
								PriceStep = priceStep,
								Name = info.Item1,
								Code = info.Item1,
								Board = ExchangeBoard.GetOrCreateBoard(info.Item2),
								ExtensionInfo = new Dictionary<object, object>()
							};

							securities.Add(securityId, new KeyValuePair<Security, bool>(security, false));

							isNew = true;
						}
					}

					this.GuiSync(() =>
					{
						Progress.Value++;

						if (isNew)
							Logs.Messages.Add(new LogMessage(logSource, TimeHelper.Now, LogLevels.Info, LocalizedStrings.Str2930Params.Put(security)));
					});
				}

				EntityRegistry.Securities.AddRange(securities.Values.Where(p => !p.Value).Select(p => p.Key));

				if (_token.IsCancellationRequested)
					return;

				var dataTypes = new[]
				{
					Tuple.Create(typeof(ExecutionMessage), (object)ExecutionTypes.Tick),
					Tuple.Create(typeof(ExecutionMessage), (object)ExecutionTypes.OrderLog),
					Tuple.Create(typeof(ExecutionMessage), (object)ExecutionTypes.Order),
					Tuple.Create(typeof(ExecutionMessage), (object)ExecutionTypes.Trade),
					Tuple.Create(typeof(QuoteChangeMessage), (object)null),
					Tuple.Create(typeof(Level1ChangeMessage), (object)null),
					Tuple.Create(typeof(NewsMessage), (object)null)
				};

				var formats = Enumerator.GetValues<StorageFormats>().ToArray();

				foreach (var drive in DriveCache.Instance.AllDrives)
				{
					foreach (var security in EntityRegistry.Securities)
					{
						foreach (var dataType in dataTypes)
						{
							foreach (var format in formats)
							{
								if (_token.IsCancellationRequested)
									break;

								var secId = security.ToSecurityId();

								drive
									.GetStorageDrive(secId, dataType.Item1, dataType.Item2, format)
									.ClearDatesCache();

								foreach (var candleType in drive.GetCandleTypes(security.ToSecurityId(), format))
								{
									drive
										.GetStorageDrive(secId, candleType.Item1, candleType.Item2, format)
										.ClearDatesCache();
								}
							}
						}

						if (_token.IsCancellationRequested)
							break;

						this.GuiSync(() =>
						{
							Progress.Value++;
							Logs.Messages.Add(new LogMessage(logSource, TimeHelper.Now, LogLevels.Info,
								LocalizedStrings.Str2931Params.Put(security, drive.Path)));
						});
					}

					if (_token.IsCancellationRequested)
						break;
				}
			}, _token.Token)
			.ContinueWithExceptionHandling(this, res =>
			{
				Sync.Content = LocalizedStrings.Str2932;
				Sync.IsEnabled = true;

				Progress.Value = 0;

				_token = null;
			});
		}
		private void StartEmulation()
		{
			if (_connector != null && _connector.State != EmulationStates.Stopped)
				throw new InvalidOperationException(LocalizedStrings.Str3015);

			if (Strategy == null)
				throw new InvalidOperationException("Strategy not selected.");

			var strategy = (EmulationDiagramStrategy)Strategy;

			if (strategy.DataPath.IsEmpty() || !Directory.Exists(strategy.DataPath))
				throw new InvalidOperationException(LocalizedStrings.Str3014);

			strategy
				.Composition
				.Parameters
				.ForEach(p =>
				{
					if (p.Type == typeof(Security) && p.Value == null)
						throw new InvalidOperationException(LocalizedStrings.Str1380);
				});

			strategy.Reset();
			Reset();

			var securityId = "empty@empty";
			var secGen = new SecurityIdGenerator();
			var secIdParts = secGen.Split(securityId);
			var secCode = secIdParts.SecurityCode;
			var board = ExchangeBoard.GetOrCreateBoard(secIdParts.BoardCode);
			var timeFrame = strategy.CandlesTimeFrame;
			var useCandles = strategy.MarketDataSource == MarketDataSource.Candles;

			// create test security
			var security = new Security
			{
				Id = securityId, // sec id has the same name as folder with historical data
				Code = secCode,
				Board = board,
			};

			// storage to historical data
			var storageRegistry = new StorageRegistry
			{
				// set historical path
				DefaultDrive = new LocalMarketDataDrive(strategy.DataPath)
			};

			var startTime = strategy.StartDate.ChangeKind(DateTimeKind.Utc);
			var stopTime = strategy.StopDate.ChangeKind(DateTimeKind.Utc);

			// ProgressBar refresh step
			var progressStep = ((stopTime - startTime).Ticks / 100).To<TimeSpan>();

			// set ProgressBar bounds
			TicksAndDepthsProgress.Value = 0;
			TicksAndDepthsProgress.Maximum = 100;

			// test portfolio
			var portfolio = new Portfolio
			{
				Name = "test account",
				BeginValue = 1000000,
			};

			var securityProvider = ConfigManager.GetService<ISecurityProvider>();

			// create backtesting connector
			_connector = new HistoryEmulationConnector(securityProvider, new[] { portfolio }, new StorageRegistry())
			{
				EmulationAdapter =
				{
					Emulator =
					{
						Settings =
						{
							// match order if historical price touched our limit order price. 
							// It is terned off, and price should go through limit order price level
							// (more "severe" test mode)
							MatchOnTouch = false,
						}
					}
				},

				UseExternalCandleSource = useCandles,

				HistoryMessageAdapter =
				{
					StorageRegistry = storageRegistry,

					// set history range
					StartDate = startTime,
					StopDate = stopTime,
				},

				// set market time freq as time frame
				MarketTimeChangedInterval = timeFrame,
			};

			//((ILogSource)_connector).LogLevel = DebugLogCheckBox.IsChecked == true ? LogLevels.Debug : LogLevels.Info;

			ConfigManager.GetService<LogManager>().Sources.Add(_connector);

			var candleManager = new CandleManager(_connector);

			strategy.Volume = 1;
			strategy.Portfolio = portfolio;
			strategy.Security = security;
			strategy.Connector = _connector;
			//LogLevel = DebugLogCheckBox.IsChecked == true ? LogLevels.Debug : LogLevels.Info,

			// by default interval is 1 min,
			// it is excessively for time range with several months
			strategy.UnrealizedPnLInterval = ((stopTime - startTime).Ticks / 1000).To<TimeSpan>();

			strategy.SetCandleManager(candleManager);

			_connector.NewSecurity += s =>
			{
				var level1Info = new Level1ChangeMessage
				{
					SecurityId = s.ToSecurityId(),
					ServerTime = startTime,
				}
					.TryAdd(Level1Fields.PriceStep, secIdParts.SecurityCode == "RIZ2" ? 10m : 1)
					.TryAdd(Level1Fields.StepPrice, 6m)
					.TryAdd(Level1Fields.MinPrice, 10m)
					.TryAdd(Level1Fields.MaxPrice, 1000000m)
					.TryAdd(Level1Fields.MarginBuy, 10000m)
					.TryAdd(Level1Fields.MarginSell, 10000m);

				// fill level1 values
				_connector.SendInMessage(level1Info);

				//_connector.RegisterMarketDepth(security);

				//if (!useCandles)
				//	_connector.RegisterTrades(s);
			};

			var nextTime = startTime + progressStep;

			// handle historical time for update ProgressBar
			_connector.MarketTimeChanged += d =>
			{
				if (_connector.CurrentTime < nextTime && _connector.CurrentTime < stopTime)
					return;

				var steps = (_connector.CurrentTime - startTime).Ticks / progressStep.Ticks + 1;
				nextTime = startTime + (steps * progressStep.Ticks).To<TimeSpan>();
				this.GuiAsync(() => TicksAndDepthsProgress.Value = steps);
			};

			_connector.LookupSecuritiesResult += (ss) =>
			{
				if (strategy.ProcessState != ProcessStates.Stopped)
					return;

				// start strategy before emulation started
				strategy.Start();

				// start historical data loading when connection established successfully and all data subscribed
				_connector.Start();
			};

			_connector.StateChanged += () =>
			{
				switch (_connector.State)
				{
					case EmulationStates.Stopped:
						strategy.Stop();

						this.GuiAsync(() =>
						{
							if (_connector.IsFinished)
								TicksAndDepthsProgress.Value = TicksAndDepthsProgress.Maximum;
						});
						break;
					case EmulationStates.Started:
						break;
				}
			};

			TicksAndDepthsProgress.Value = 0;

			DiagramDebuggerControl.Debugger.IsEnabled = true;

			// raise NewSecurities and NewPortfolio for full fill strategy properties
			_connector.Connect();

			// 1 cent commission for trade
			_connector.SendInMessage(new CommissionRuleMessage
			{
				Rule = new CommissionPerTradeRule
				{
					Value = 0.01m
				}
			});
		}
		private void OkClick(object sender, RoutedEventArgs e)
		{
			var volumeStep = VolumeStep.Value;
			var priceStep = PriceStep.Value;
			var decimals = Decimals.Value;
			var type = TypeCtrl.SelectedType;

			if (Securities == null)
			{
				if (Code.Text.IsEmpty())
				{
					ShowError(LocalizedStrings.Str2923);
					return;
				}

				if (decimals == null)
				{
					ShowError(LocalizedStrings.DecimalsNotFilled);
					return;
				}

				if (priceStep == null || priceStep == 0)
				{
					ShowError(LocalizedStrings.Str2925);
					return;
				}

				if (volumeStep == null || volumeStep == 0)
				{
					ShowError(LocalizedStrings.Str2924);
					return;
				}

				if (ExchangeCtrl.SelectedBoard == null)
				{
					ShowError(LocalizedStrings.Str2926);
					return;
				}

				var security = Security;

				security.Code = Code.Text;

				if (!SecName.Text.IsEmpty())
					security.Name = SecName.Text;

				security.VolumeStep = volumeStep;
				security.PriceStep = priceStep;
				security.Decimals = decimals;
				security.Board = ExchangeCtrl.SelectedBoard;
				security.Type = TypeCtrl.SelectedType;

				if (security.Id.IsEmpty())
				{
					var id = new SecurityIdGenerator().GenerateId(security.Code, security.Board);

					var isExist = _entityRegistry.Securities.ReadById(id) != null;

					if (isExist)
					{
						new MessageBoxBuilder()
							.Text(LocalizedStrings.Str2927Params.Put(id))
							.Owner(this)
							.Warning()
							.Show();

						return;
					}

					security.Id = id;
					security.ExtensionInfo = new Dictionary<object, object>();
				}

				_entityRegistry.Securities.Save(security);
			}
			else
			{
				if (priceStep == 0)
				{
					ShowError(LocalizedStrings.Str2925);
					return;
				}

				if (volumeStep == 0)
				{
					ShowError(LocalizedStrings.Str2924);
					return;
				}

				foreach (var security in Securities)
				{
					if (volumeStep != null)
						security.VolumeStep = volumeStep.Value;

					if (priceStep != null)
						security.PriceStep = priceStep.Value;

					if (decimals != null)
						security.Decimals = decimals.Value;

					if (type != null)
						security.Type = type.Value;

					_entityRegistry.Securities.Save(security);
				}
			}

			DialogResult = true;
		}
		private void ExecutedSaveSecurityCommand(object sender, ExecutedRoutedEventArgs e)
		{
			var entityRegistry = ConfigManager.GetService<IEntityRegistry>();
			var security = (Security)PropertyGrid.SelectedObject;

			if (_isNew)
			{
				var mbBuilder = new MessageBoxBuilder()
					.Owner(this)
					.Error();

				if (security.Code.IsEmpty())
				{
					mbBuilder.Text(LocalizedStrings.Str2923).Show();
					return;
				}

				if (security.Board == null)
				{
					mbBuilder.Text(LocalizedStrings.Str2926).Show();
					return;
				}

				if (security.PriceStep == null || security.PriceStep == 0)
				{
					mbBuilder.Text(LocalizedStrings.Str2925).Show();
					return;
				}

				if (security.VolumeStep == null || security.VolumeStep == 0)
				{
					mbBuilder.Text(LocalizedStrings.Str2924).Show();
					return;
				}

				var id = new SecurityIdGenerator().GenerateId(security.Code, security.Board);

				if (entityRegistry.Securities.ReadById(id) != null)
				{
					mbBuilder.Text(LocalizedStrings.Str2927Params.Put(id)).Show();
					return;
				}

				security.Id = id;
			}
			else
			{
				security.CopyTo(SecurityPicker.SelectedSecurity);
				security = SecurityPicker.SelectedSecurity;
			}

			entityRegistry.Securities.Save(security);

			_isNew = false;
			_changed = false;
		}
		private void StartBtnClick(object sender, RoutedEventArgs e)
		{
			InitChart();

			if (HistoryPath.Folder.IsEmpty() || !Directory.Exists(HistoryPath.Folder))
			{
				MessageBox.Show(this, LocalizedStrings.Str3014);
				return;
			}

			if (_connectors.Any(t => t.State != EmulationStates.Stopped))
			{
				MessageBox.Show(this, LocalizedStrings.Str3015);
				return;
			}

			var secGen = new SecurityIdGenerator();
			var id = secGen.Split(SecId.Text);

			//if (secIdParts.Length != 2)
			//{
			//	MessageBox.Show(this, LocalizedStrings.Str3016);
			//	return;
			//}

			var timeFrame = TimeSpan.FromMinutes(TimeFrame.SelectedIndex == 0 ? 1 : 5);

			var secCode = id.SecurityCode;
			var board = ExchangeBoard.GetOrCreateBoard(id.BoardCode);

			// create test security
			var security = new Security
			{
				Id = SecId.Text, // sec id has the same name as folder with historical data
				Code = secCode,
				Board = board,
			};

			if (FinamCandlesCheckBox.IsChecked == true)
			{
				_finamHistorySource.Refresh(new FinamSecurityStorage(security), security, s => {}, () => false);
			}

			// create backtesting modes
			var settings = new[]
			{
				Tuple.Create(
					TicksCheckBox,
					TicksProgress,
					TicksParameterGrid,
					// ticks
					new EmulationInfo {UseTicks = true, CurveColor = Colors.DarkGreen, StrategyName = LocalizedStrings.Ticks}),

				Tuple.Create(
					TicksAndDepthsCheckBox,
					TicksAndDepthsProgress,
					TicksAndDepthsParameterGrid,
					// ticks + order book
					new EmulationInfo {UseTicks = true, UseMarketDepth = true, CurveColor = Colors.Red, StrategyName = LocalizedStrings.XamlStr757}),

				Tuple.Create(
					DepthsCheckBox,
					DepthsProgress,
					DepthsParameterGrid,
					// order book
					new EmulationInfo {UseMarketDepth = true, CurveColor = Colors.OrangeRed, StrategyName = LocalizedStrings.MarketDepths}),

				Tuple.Create(
					CandlesCheckBox,
					CandlesProgress,
					CandlesParameterGrid,
					// candles
					new EmulationInfo {UseCandleTimeFrame = timeFrame, CurveColor = Colors.DarkBlue, StrategyName = LocalizedStrings.Candles}),
				
				Tuple.Create(
					CandlesAndDepthsCheckBox,
					CandlesAndDepthsProgress,
					CandlesAndDepthsParameterGrid,
					// candles + orderbook
					new EmulationInfo {UseMarketDepth = true, UseCandleTimeFrame = timeFrame, CurveColor = Colors.Cyan, StrategyName = LocalizedStrings.XamlStr635}),
			
				Tuple.Create(
					OrderLogCheckBox,
					OrderLogProgress,
					OrderLogParameterGrid,
					// order log
					new EmulationInfo {UseOrderLog = true, CurveColor = Colors.CornflowerBlue, StrategyName = LocalizedStrings.OrderLog}),

				Tuple.Create(
					Level1CheckBox,
					Level1Progress,
					Level1ParameterGrid,
					// order log
					new EmulationInfo {UseLevel1 = true, CurveColor = Colors.Aquamarine, StrategyName = LocalizedStrings.Level1}),

				Tuple.Create(
					FinamCandlesCheckBox,
					FinamCandlesProgress,
					FinamCandlesParameterGrid,
					// candles
					new EmulationInfo {UseCandleTimeFrame = timeFrame, HistorySource = d => _finamHistorySource.GetCandles(security, timeFrame, d.Date, d.Date), CurveColor = Colors.DarkBlue, StrategyName = LocalizedStrings.FinamCandles}),

				Tuple.Create(
					YahooCandlesCheckBox,
					YahooCandlesProgress,
					YahooCandlesParameterGrid,
					// candles
					new EmulationInfo {UseCandleTimeFrame = timeFrame, HistorySource = d => new YahooHistorySource().GetCandles(security, timeFrame, d.Date, d.Date), CurveColor = Colors.DarkBlue, StrategyName = LocalizedStrings.YahooCandles}),
			};

			// storage to historical data
			var storageRegistry = new StorageRegistry
			{
				// set historical path
				DefaultDrive = new LocalMarketDataDrive(HistoryPath.Folder)
			};

			var startTime = ((DateTime)From.Value).ChangeKind(DateTimeKind.Utc);
			var stopTime = ((DateTime)To.Value).ChangeKind(DateTimeKind.Utc);

			// (ru only) ОЛ необходимо загружать с 18.45 пред дня, чтобы стаканы строились правильно
			if (OrderLogCheckBox.IsChecked == true)
				startTime = startTime.Subtract(TimeSpan.FromDays(1)).AddHours(18).AddMinutes(45).AddTicks(1).ApplyTimeZone(TimeHelper.Moscow).UtcDateTime;

			// ProgressBar refresh step
			var progressStep = ((stopTime - startTime).Ticks / 100).To<TimeSpan>();

			// set ProgressBar bounds
			_progressBars.ForEach(p =>
			{
				p.Value = 0;
				p.Maximum = 100;
			});
			
			var logManager = new LogManager();
			var fileLogListener = new FileLogListener("sample.log");
			logManager.Listeners.Add(fileLogListener);
			//logManager.Listeners.Add(new DebugLogListener());	// for track logs in output window in Vusial Studio (poor performance).

			var generateDepths = GenDepthsCheckBox.IsChecked == true;
			var maxDepth = MaxDepth.Text.To<int>();
			var maxVolume = MaxVolume.Text.To<int>();
			var secId = security.ToSecurityId();

			foreach (var set in settings)
			{
				if (set.Item1.IsChecked == false)
					continue;

				var progressBar = set.Item2;
				var statistic = set.Item3;
				var emulationInfo = set.Item4;

				var level1Info = new Level1ChangeMessage
				{
					SecurityId = secId,
					ServerTime = startTime,
				}
				.TryAdd(Level1Fields.PriceStep, secCode == "RIZ2" ? 10m : 1)
				.TryAdd(Level1Fields.StepPrice, 6m)
				.TryAdd(Level1Fields.MinPrice, 10m)
				.TryAdd(Level1Fields.MaxPrice, 1000000m)
				.TryAdd(Level1Fields.MarginBuy, 10000m)
				.TryAdd(Level1Fields.MarginSell, 10000m);

				// test portfolio
				var portfolio = new Portfolio
				{
					Name = "test account",
					BeginValue = 1000000,
				};

				// create backtesting connector
				var connector = new HistoryEmulationConnector(
					new[] { security },
					new[] { portfolio })
				{
					EmulationAdapter =
					{
						Emulator =
						{
							Settings =
							{
								// match order if historical price touched our limit order price. 
								// It is terned off, and price should go through limit order price level
								// (more "severe" test mode)
								MatchOnTouch = false,
							}
						}
					},

					UseExternalCandleSource = emulationInfo.UseCandleTimeFrame != null,

					CreateDepthFromOrdersLog = emulationInfo.UseOrderLog,
					CreateTradesFromOrdersLog = emulationInfo.UseOrderLog,

					HistoryMessageAdapter =
					{
						StorageRegistry = storageRegistry,

						// set history range
						StartDate = startTime,
						StopDate = stopTime,

						OrderLogMarketDepthBuilders =
						{
							{
								secId,
								LocalizedStrings.ActiveLanguage == Languages.Russian
									? (IOrderLogMarketDepthBuilder)new PlazaOrderLogMarketDepthBuilder(secId)
									: new ItchOrderLogMarketDepthBuilder(secId)
							}
						}
					},

					// set market time freq as time frame
					MarketTimeChangedInterval = timeFrame,
				};

				((ILogSource)connector).LogLevel = DebugLogCheckBox.IsChecked == true ? LogLevels.Debug : LogLevels.Info;

				logManager.Sources.Add(connector);

				var candleManager = emulationInfo.UseCandleTimeFrame == null
					? new CandleManager(new TradeCandleBuilderSourceEx(connector))
					: new CandleManager(connector);

				var series = new CandleSeries(typeof(TimeFrameCandle), security, timeFrame);

				_shortMa = new SimpleMovingAverage { Length = 10 };
				_shortElem = new ChartIndicatorElement
				{
					Color = Colors.Coral,
					ShowAxisMarker = false,
					FullTitle = _shortMa.ToString()
				};
				_bufferedChart.AddElement(_area, _shortElem);

				_longMa = new SimpleMovingAverage { Length = 80 };
				_longElem = new ChartIndicatorElement
				{
					ShowAxisMarker = false,
					FullTitle = _longMa.ToString()
				};
				_bufferedChart.AddElement(_area, _longElem);

				// create strategy based on 80 5-min и 10 5-min
				var strategy = new SmaStrategy(_bufferedChart, _candlesElem, _tradesElem, _shortMa, _shortElem, _longMa, _longElem, candleManager, series)
				{
					Volume = 1,
					Portfolio = portfolio,
					Security = security,
					Connector = connector,
					LogLevel = DebugLogCheckBox.IsChecked == true ? LogLevels.Debug : LogLevels.Info,

					// by default interval is 1 min,
					// it is excessively for time range with several months
					UnrealizedPnLInterval = ((stopTime - startTime).Ticks / 1000).To<TimeSpan>()
				};

				logManager.Sources.Add(strategy);

				connector.NewSecurities += securities =>
				{
					if (securities.All(s => s != security))
						return;

					// fill level1 values
					connector.SendInMessage(level1Info);

					if (emulationInfo.HistorySource != null)
					{
						if (emulationInfo.UseCandleTimeFrame != null)
						{
							connector.RegisterHistorySource(security, MarketDataTypes.CandleTimeFrame, emulationInfo.UseCandleTimeFrame.Value, emulationInfo.HistorySource);
						}

						if (emulationInfo.UseTicks)
						{
							connector.RegisterHistorySource(security, MarketDataTypes.Trades, null, emulationInfo.HistorySource);
						}

						if (emulationInfo.UseLevel1)
						{
							connector.RegisterHistorySource(security, MarketDataTypes.Level1, null, emulationInfo.HistorySource);
						}

						if (emulationInfo.UseMarketDepth)
						{
							connector.RegisterHistorySource(security, MarketDataTypes.MarketDepth, null, emulationInfo.HistorySource);
						}
					}
					else
					{
						if (emulationInfo.UseMarketDepth)
						{
							connector.RegisterMarketDepth(security);

							if (
								// if order book will be generated
									generateDepths ||
								// of backtesting will be on candles
									emulationInfo.UseCandleTimeFrame != TimeSpan.Zero
								)
							{
								// if no have order book historical data, but strategy is required,
								// use generator based on last prices
								connector.RegisterMarketDepth(new TrendMarketDepthGenerator(connector.GetSecurityId(security))
								{
									Interval = TimeSpan.FromSeconds(1), // order book freq refresh is 1 sec
									MaxAsksDepth = maxDepth,
									MaxBidsDepth = maxDepth,
									UseTradeVolume = true,
									MaxVolume = maxVolume,
									MinSpreadStepCount = 2,	// min spread generation is 2 pips
									MaxSpreadStepCount = 5,	// max spread generation size (prevent extremely size)
									MaxPriceStepCount = 3	// pips size,
								});
							}
						}

						if (emulationInfo.UseOrderLog)
						{
							connector.RegisterOrderLog(security);
						}

						if (emulationInfo.UseTicks)
						{
							connector.RegisterTrades(security);
						}

						if (emulationInfo.UseLevel1)
						{
							connector.RegisterSecurity(security);
						}
					}

					// start strategy before emulation started
					strategy.Start();
					candleManager.Start(series);

					// start historical data loading when connection established successfully and all data subscribed
					connector.Start();
				};

				// fill parameters panel
				statistic.Parameters.Clear();
				statistic.Parameters.AddRange(strategy.StatisticManager.Parameters);

				var pnlCurve = Curve.CreateCurve(LocalizedStrings.PnL + " " + emulationInfo.StrategyName, emulationInfo.CurveColor, EquityCurveChartStyles.Area);
				var unrealizedPnLCurve = Curve.CreateCurve(LocalizedStrings.PnLUnreal + emulationInfo.StrategyName, Colors.Black);
				var commissionCurve = Curve.CreateCurve(LocalizedStrings.Str159 + " " + emulationInfo.StrategyName, Colors.Red, EquityCurveChartStyles.DashedLine);
				var posItems = PositionCurve.CreateCurve(emulationInfo.StrategyName, emulationInfo.CurveColor);
				strategy.PnLChanged += () =>
				{
					var pnl = new EquityData
					{
						Time = strategy.CurrentTime,
						Value = strategy.PnL - strategy.Commission ?? 0
					};

					var unrealizedPnL = new EquityData
					{
						Time = strategy.CurrentTime,
						Value = strategy.PnLManager.UnrealizedPnL
					};

					var commission = new EquityData
					{
						Time = strategy.CurrentTime,
						Value = strategy.Commission ?? 0
					};

					pnlCurve.Add(pnl);
					unrealizedPnLCurve.Add(unrealizedPnL);
					commissionCurve.Add(commission);
				};

				strategy.PositionChanged += () => posItems.Add(new EquityData { Time = strategy.CurrentTime, Value = strategy.Position });

				var nextTime = startTime + progressStep;

				// handle historical time for update ProgressBar
				connector.MarketTimeChanged += d =>
				{
					if (connector.CurrentTime < nextTime && connector.CurrentTime < stopTime)
						return;

					var steps = (connector.CurrentTime - startTime).Ticks / progressStep.Ticks + 1;
					nextTime = startTime + (steps * progressStep.Ticks).To<TimeSpan>();
					this.GuiAsync(() => progressBar.Value = steps);
				};

				connector.StateChanged += () =>
				{
					if (connector.State == EmulationStates.Stopped)
					{
						candleManager.Stop(series);
						strategy.Stop();

						logManager.Dispose();
						_connectors.Clear();

						SetIsEnabled(false);

						this.GuiAsync(() =>
						{
							if (connector.IsFinished)
							{
								progressBar.Value = progressBar.Maximum;
								MessageBox.Show(this, LocalizedStrings.Str3024.Put(DateTime.Now - _startEmulationTime));
							}
							else
								MessageBox.Show(this, LocalizedStrings.cancelled);
						});
					}
					else if (connector.State == EmulationStates.Started)
					{
						SetIsEnabled(true);
					}
				};

				if (ShowDepth.IsChecked == true)
				{
					MarketDepth.UpdateFormat(security);

					connector.NewMessage += message =>
					{
						var quoteMsg = message as QuoteChangeMessage;

						if (quoteMsg != null)
							MarketDepth.UpdateDepth(quoteMsg);
					};
				}

				_connectors.Add(connector);

				progressBar.Value = 0;
			}

			_startEmulationTime = DateTime.Now;

			// start emulation
			foreach (var connector in _connectors)
			{
				// raise NewSecurities and NewPortfolio for full fill strategy properties
				connector.Connect();

				// 1 cent commission for trade
				connector.SendInMessage(new CommissionRuleMessage
				{
					Rule = new CommissionPerTradeRule { Value = 0.01m }
				});
			}

			TabControl.Items.Cast<TabItem>().First(i => i.Visibility == Visibility.Visible).IsSelected = true;
		}
		private void StartEmulation()
		{
			if (_connector != null && _connector.State != EmulationStates.Stopped)
				throw new InvalidOperationException(LocalizedStrings.Str3015);

			if (Strategy == null)
				throw new InvalidOperationException("Strategy not selected.");

			var strategy = (EmulationDiagramStrategy)Strategy;
			var settings = strategy.EmulationSettings;

			if (settings.MarketDataSettings == null)
				throw new InvalidOperationException(LocalizedStrings.Str3014);

			new SetDefaultEmulationSettingsCommand(settings).Process(this);

			strategy
				.Composition
				.Parameters
				.ForEach(p =>
				{
					if (p.Type == typeof(Security) && p.Value == null)
						throw new InvalidOperationException(LocalizedStrings.Str1380);
				});

			strategy.Reset();
			Reset();

			var securityId = "empty@empty";
			var secGen = new SecurityIdGenerator();
			var secIdParts = secGen.Split(securityId);
			var secCode = secIdParts.SecurityCode;
			var board = ExchangeBoard.GetOrCreateBoard(secIdParts.BoardCode);
			var timeFrame = settings.CandlesTimeFrame;
			var useCandles = settings.MarketDataSource == MarketDataSource.Candles;

			// create test security
			var security = new Security
			{
				Id = securityId, // sec id has the same name as folder with historical data
				Code = secCode,
				Board = board,
			};

			// storage to historical data
			var storageRegistry = new StudioStorageRegistry
			{
				MarketDataSettings = settings.MarketDataSettings
			};

			var startTime = settings.StartDate.ChangeKind(DateTimeKind.Utc);
			var stopTime = settings.StopDate.ChangeKind(DateTimeKind.Utc);

			// ProgressBar refresh step
			var progressStep = ((stopTime - startTime).Ticks / 100).To<TimeSpan>();

			// set ProgressBar bounds
			TicksAndDepthsProgress.Value = 0;
			TicksAndDepthsProgress.Maximum = 100;

			// test portfolio
			var portfolio = new Portfolio
			{
				Name = "test account",
				BeginValue = 1000000,
			};

			var securityProvider = ConfigManager.GetService<ISecurityProvider>();

			// create backtesting connector
			_connector = new HistoryEmulationConnector(securityProvider, new[] { portfolio }, new StorageRegistry())
			{
				EmulationAdapter =
				{
					Emulator =
					{
						Settings =
						{
							// match order if historical price touched our limit order price. 
							// It is terned off, and price should go through limit order price level
							// (more "severe" test mode)
							MatchOnTouch = settings.MatchOnTouch, 
							IsSupportAtomicReRegister = settings.IsSupportAtomicReRegister,
							Latency = settings.EmulatoinLatency,
						}
					}
				},

				UseExternalCandleSource = useCandles,

				HistoryMessageAdapter =
				{
					StorageRegistry = storageRegistry,
					StorageFormat = settings.StorageFormat,

					// set history range
					StartDate = startTime,
					StopDate = stopTime,
				},

				// set market time freq as time frame
				MarketTimeChangedInterval = timeFrame,
			};

			((ILogSource)_connector).LogLevel = settings.DebugLog ? LogLevels.Debug : LogLevels.Info;

			ConfigManager.GetService<LogManager>().Sources.Add(_connector);

			strategy.Volume = 1;
			strategy.Portfolio = portfolio;
			strategy.Security = security;
			strategy.Connector = _connector;
			strategy.LogLevel = settings.DebugLog ? LogLevels.Debug : LogLevels.Info;

			// by default interval is 1 min,
			// it is excessively for time range with several months
			strategy.UnrealizedPnLInterval = ((stopTime - startTime).Ticks / 1000).To<TimeSpan>();

			strategy.SetCandleManager(new CandleManager(_connector));

			_connector.NewSecurity += s =>
			{
				//TODO send real level1 message
				var level1Info = new Level1ChangeMessage
				{
					SecurityId = s.ToSecurityId(),
					ServerTime = startTime,
				}
					.TryAdd(Level1Fields.PriceStep, secIdParts.SecurityCode == "RIZ2" ? 10m : 1)
					.TryAdd(Level1Fields.StepPrice, 6m)
					.TryAdd(Level1Fields.MinPrice, 10m)
					.TryAdd(Level1Fields.MaxPrice, 1000000m)
					.TryAdd(Level1Fields.MarginBuy, 10000m)
					.TryAdd(Level1Fields.MarginSell, 10000m);

				// fill level1 values
				_connector.SendInMessage(level1Info);

				if (settings.UseMarketDepths)
				{
					_connector.RegisterMarketDepth(security);

					if (
							// if order book will be generated
							settings.GenerateDepths ||
							// of backtesting will be on candles
							useCandles
						)
					{
						// if no have order book historical data, but strategy is required,
						// use generator based on last prices
						_connector.RegisterMarketDepth(new TrendMarketDepthGenerator(_connector.GetSecurityId(s))
						{
							Interval = TimeSpan.FromSeconds(1), // order book freq refresh is 1 sec
							MaxAsksDepth = settings.MaxDepths,
							MaxBidsDepth = settings.MaxDepths,
							UseTradeVolume = true,
							MaxVolume = settings.MaxVolume,
							MinSpreadStepCount = 2, // min spread generation is 2 pips
							MaxSpreadStepCount = 5, // max spread generation size (prevent extremely size)
							MaxPriceStepCount = 3   // pips size,
						});
					}
				}
			};

			var nextTime = startTime + progressStep;

			// handle historical time for update ProgressBar
			_connector.MarketTimeChanged += d =>
			{
				if (_connector.CurrentTime < nextTime && _connector.CurrentTime < stopTime)
					return;

				var steps = (_connector.CurrentTime - startTime).Ticks / progressStep.Ticks + 1;
				nextTime = startTime + (steps * progressStep.Ticks).To<TimeSpan>();
				this.GuiAsync(() => TicksAndDepthsProgress.Value = steps);
			};

			_connector.LookupSecuritiesResult += (ss) =>
			{
				if (strategy.ProcessState != ProcessStates.Stopped)
					return;

				// start strategy before emulation started
				strategy.Start();

				// start historical data loading when connection established successfully and all data subscribed
				_connector.Start();
			};

			_connector.StateChanged += () =>
			{
				switch (_connector.State)
				{
					case EmulationStates.Stopped:
						strategy.Stop();

						this.GuiAsync(() =>
						{
							if (_connector.IsFinished)
								TicksAndDepthsProgress.Value = TicksAndDepthsProgress.Maximum;
						});
						break;
					case EmulationStates.Started:
						break;
				}
			};

			_connector.Disconnected += () =>
			{
				this.GuiAsync(() => _connector.Dispose());
			};

			TicksAndDepthsProgress.Value = 0;

			DiagramDebuggerControl.Debugger.IsEnabled = true;

			// raise NewSecurities and NewPortfolio for full fill strategy properties
			_connector.Connect();

			// 1 cent commission for trade
			_connector.SendInMessage(new CommissionRuleMessage
			{
				Rule = new CommissionPerTradeRule
				{
					Value = 0.01m
				}
			});
		}
		private void LoadData()
		{
			_candle = null;
			_lastPrice = 0m;
			_allCandles.Clear();

			var id = new SecurityIdGenerator().Split(SecurityId.Text);

			_security = new Security
			{
				Id = SecurityId.Text,
				PriceStep = 5,
				Board = ExchangeBoard.GetBoard(id.BoardCode)
			};

			Chart.Reset(new IChartElement[] { _candleElement1 });

			var storage = new StorageRegistry();

			var maxDays = 2;

			BusyIndicator.IsBusy = true;

			var path = HistoryPath.Folder;

			Task.Factory.StartNew(() =>
			{
				var date = DateTime.MinValue;

				foreach (var tick in storage.GetTickMessageStorage(_security, new LocalMarketDataDrive(path)).Load())
				{
					AppendTick(_security, tick);
					_lastTime = tick.ServerTime;

					if (date != tick.ServerTime.Date)
					{
						date = tick.ServerTime.Date;

						this.GuiAsync(() =>
						{
							BusyIndicator.BusyContent = date.ToString();
						});

						maxDays--;

						if (maxDays == 0)
							break;
					}
				}
			})
			.ContinueWith(t =>
			{
				if (t.Exception != null)
					Error(t.Exception.Message);

				BusyIndicator.IsBusy = false;
			}, TaskScheduler.FromCurrentSynchronizationContext());
		}
		private void StartButtonOnClick(object sender, RoutedEventArgs e)
		{
			_logManager.Sources.Clear();
			_bufferedChart.ClearAreas();

			Curve.Clear();
			PositionCurve.Clear();

			if (HistoryPathTextBox.Text.IsEmpty() || !Directory.Exists(HistoryPathTextBox.Text))
			{
				MessageBox.Show("Wrong path.");
				return;
			}

			if (_connector != null && _connector.State != EmulationStates.Stopped)
			{
				MessageBox.Show("Already launched.");
				return;
			}

			if (Composition == null)
			{
				MessageBox.Show("No strategy selected.");
				return;
			}

			var secGen = new SecurityIdGenerator();
			var secIdParts = secGen.Split(SecusityTextBox.Text);
			var secCode = secIdParts.SecurityCode;
			var board = ExchangeBoard.GetOrCreateBoard(secIdParts.BoardCode);
			var timeFrame = (TimeSpan)TimeFrameComboBox.SelectedItem;
			var useCandles = (string)MarketDataTypeComboBox.SelectedItem != "Ticks";

			// create test security
			var security = new Security
			{
				Id = SecusityTextBox.Text, // sec id has the same name as folder with historical data
				Code = secCode,
				Board = board,
			};

			// storage to historical data
			var storageRegistry = new StorageRegistry
			{
				// set historical path
				DefaultDrive = new LocalMarketDataDrive(HistoryPathTextBox.Text)
			};

			var startTime = ((DateTime)FromDatePicker.Value).ChangeKind(DateTimeKind.Utc);
			var stopTime = ((DateTime)ToDatePicke.Value).ChangeKind(DateTimeKind.Utc);

			// ProgressBar refresh step
			var progressStep = ((stopTime - startTime).Ticks / 100).To<TimeSpan>();

			// set ProgressBar bounds
			TicksAndDepthsProgress.Value = 0;
			TicksAndDepthsProgress.Maximum = 100;

			var level1Info = new Level1ChangeMessage
			{
				SecurityId = security.ToSecurityId(),
				ServerTime = startTime,
			}
			.TryAdd(Level1Fields.PriceStep, secIdParts.SecurityCode == "RIZ2" ? 10m : 1)
			.TryAdd(Level1Fields.StepPrice, 6m)
			.TryAdd(Level1Fields.MinPrice, 10m)
			.TryAdd(Level1Fields.MaxPrice, 1000000m)
			.TryAdd(Level1Fields.MarginBuy, 10000m)
			.TryAdd(Level1Fields.MarginSell, 10000m);

			// test portfolio
			var portfolio = new Portfolio
			{
				Name = "test account",
				BeginValue = 1000000,
			};

			// create backtesting connector
			_connector = new HistoryEmulationConnector(
				new[] { security },
				new[] { portfolio })
			{
				EmulationAdapter =
				{
					Emulator =
					{
						Settings =
						{
							// match order if historical price touched our limit order price. 
							// It is terned off, and price should go through limit order price level
							// (more "severe" test mode)
							MatchOnTouch = false,
						}
					}
				},

				UseExternalCandleSource = useCandles,

				HistoryMessageAdapter =
				{
					StorageRegistry = storageRegistry,

					// set history range
					StartDate = startTime,
					StopDate = stopTime,
				},

				// set market time freq as time frame
				MarketTimeChangedInterval = timeFrame,
			};

			//((ILogSource)_connector).LogLevel = DebugLogCheckBox.IsChecked == true ? LogLevels.Debug : LogLevels.Info;

			_logManager.Sources.Add(_connector);

			var candleManager = !useCandles
					? new CandleManager(new TradeCandleBuilderSourceEx(_connector))
					: new CandleManager(_connector);

			// create strategy based on 80 5-min и 10 5-min
			var strategy = new DiagramStrategy
			{
				Volume = 1,
				Portfolio = portfolio,
				Security = security,
				Connector = _connector,
				//LogLevel = DebugLogCheckBox.IsChecked == true ? LogLevels.Debug : LogLevels.Info,

				Composition = Composition,

				// by default interval is 1 min,
				// it is excessively for time range with several months
				UnrealizedPnLInterval = ((stopTime - startTime).Ticks / 1000).To<TimeSpan>()
			};

			strategy.SetChart(_bufferedChart);
			strategy.SetCandleManager(candleManager);

			_logManager.Sources.Add(strategy);

			strategy.OrderRegistering += OnStrategyOrderRegistering;
			strategy.OrderReRegistering += OnStrategyOrderReRegistering;
			strategy.OrderRegisterFailed += OnStrategyOrderRegisterFailed;
			
			strategy.StopOrderRegistering += OnStrategyOrderRegistering;
			strategy.StopOrderReRegistering += OnStrategyOrderReRegistering;
			strategy.StopOrderRegisterFailed += OnStrategyOrderRegisterFailed;

			strategy.NewMyTrades += OnStrategyNewMyTrade;

			var pnlCurve = Curve.CreateCurve(LocalizedStrings.PnL + " " + strategy.Name, Colors.DarkGreen, EquityCurveChartStyles.Area);
			var unrealizedPnLCurve = Curve.CreateCurve(LocalizedStrings.PnLUnreal + strategy.Name, Colors.Black);
			var commissionCurve = Curve.CreateCurve(LocalizedStrings.Str159 + " " + strategy.Name, Colors.Red, EquityCurveChartStyles.DashedLine);
			
			strategy.PnLChanged += () =>
			{
				var pnl = new EquityData
				{
					Time = strategy.CurrentTime,
					Value = strategy.PnL - strategy.Commission ?? 0
				};

				var unrealizedPnL = new EquityData
				{
					Time = strategy.CurrentTime,
					Value = strategy.PnLManager.UnrealizedPnL
				};

				var commission = new EquityData
				{
					Time = strategy.CurrentTime,
					Value = strategy.Commission ?? 0
				};

				pnlCurve.Add(pnl);
				unrealizedPnLCurve.Add(unrealizedPnL);
				commissionCurve.Add(commission);
			};

			var posItems = PositionCurve.CreateCurve(strategy.Name, Colors.DarkGreen);

			strategy.PositionChanged += () => posItems.Add(new EquityData { Time = strategy.CurrentTime, Value = strategy.Position });

			_connector.NewSecurities += securities =>
			{
				if (securities.All(s => s != security))
					return;

				// fill level1 values
				_connector.SendInMessage(level1Info);

				//_connector.RegisterMarketDepth(security);
				if (!useCandles)
					_connector.RegisterTrades(security);

				// start strategy before emulation started
				strategy.Start();

				// start historical data loading when connection established successfully and all data subscribed
				_connector.Start();
			};

			var nextTime = startTime + progressStep;

			// handle historical time for update ProgressBar
			_connector.MarketTimeChanged += d =>
			{
				if (_connector.CurrentTime < nextTime && _connector.CurrentTime < stopTime)
					return;

				var steps = (_connector.CurrentTime - startTime).Ticks / progressStep.Ticks + 1;
				nextTime = startTime + (steps * progressStep.Ticks).To<TimeSpan>();
				this.GuiAsync(() => TicksAndDepthsProgress.Value = steps);
			};

			_connector.StateChanged += () =>
			{
				switch (_connector.State)
				{
					case EmulationStates.Stopped:
						strategy.Stop();
						SetIsEnabled(false);

						this.GuiAsync(() =>
						{
							if (_connector.IsFinished)
							{
								TicksAndDepthsProgress.Value = TicksAndDepthsProgress.Maximum;
								MessageBox.Show("Done.");
							}
							else
								MessageBox.Show("Cancelled.");
						});
						break;
					case EmulationStates.Started:
						SetIsEnabled(true);
						break;
				}
			};

			TicksAndDepthsProgress.Value = 0;

			// raise NewSecurities and NewPortfolio for full fill strategy properties
			_connector.Connect();

			// 1 cent commission for trade
			_connector.SendInMessage(new CommissionRuleMessage
			{
				Rule = new CommissionPerTradeRule { Value = 0.01m }
			});
		}
Beispiel #11
0
		private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
		{
			Year.ItemsSource = Competition.AllYears;
			Year.SelectedItem = Competition.AllYears.Last();

			Directory.CreateDirectory(_settingsDir);

			var ns = typeof(IIndicator).Namespace;

			var rendererTypes = typeof(Chart).Assembly
				.GetTypes()
				.Where(t => !t.IsAbstract && typeof(BaseChartIndicatorPainter).IsAssignableFrom(t))
				.ToDictionary(t => t.Name);

			var indicators = typeof(IIndicator).Assembly
				.GetTypes()
				.Where(t => t.Namespace == ns && !t.IsAbstract && typeof(IIndicator).IsAssignableFrom(t))
				.Select(t => new IndicatorType(t, rendererTypes.TryGetValue(t.Name + "Painter")));

			Chart.IndicatorTypes.AddRange(indicators);

			var finamSecurities = Path.Combine(_settingsDir, "finam2.csv");

			BusyIndicator.BusyContent = "Обновление инструментов...";
			BusyIndicator.IsBusy = true;

			Task.Factory.StartNew(() =>
			{
				File.Delete("finam.csv");

				if (File.Exists(finamSecurities))
				{
					CultureInfo.InvariantCulture.DoInCulture(() =>
					{
						var idGen = new SecurityIdGenerator();

						var securities = File.ReadAllLines(finamSecurities).Select(line =>
						{
							var cells = line.SplitByComma();
							var idParts = idGen.Split(cells[0]);

							return new Security
							{
								Id = cells[0],
								Code = idParts.Item1,
								Board = ExchangeBoard.GetOrCreateBoard(idParts.Item2),
								ExtensionInfo = new Dictionary<object, object>
								{
									{ FinamHistorySource.MarketIdField, cells[1].To<long>() },
									{ FinamHistorySource.SecurityIdField, cells[2].To<long>() },
								},
								PriceStep = cells[3].To<decimal?>(),
								Decimals = cells[4].To<int?>(),
								Currency = cells[5].To<CurrencyTypes?>(),
							};
						});

						foreach (var security in securities)
						{
							_securityProvider.Securities.Add(security);
							_securityStorage.Save(security);
						}
					});
				}
				else
				{
					_finamHistorySource.Refresh(_securityStorage, new Security(), s => { }, () => false);

					var securities = _securityStorage.LookupAll().ToArray();

					foreach (var security in securities)
						_securityProvider.Securities.Add(security);

					File.WriteAllLines(finamSecurities, securities.Where(s => !s.Id.Contains(',')).Select(s => "{0},{1},{2},{3},{4},{5}"
						.Put(s.Id, s.ExtensionInfo[FinamHistorySource.MarketIdField], s.ExtensionInfo[FinamHistorySource.SecurityIdField], s.PriceStep, s.Decimals, s.Currency)));
				}
			})
			.ContinueWith(res =>
			{
				BusyIndicator.IsBusy = false;

				if (res.Exception != null)
				{
					new MessageBoxBuilder()
						.Error()
						.Owner(this)
						.Text(res.Exception.ToString())
						.Show();
				}

				if (File.Exists(_settingsFile))
				{
					var settings = CultureInfo.InvariantCulture.DoInCulture(() => new XmlSerializer<SettingsStorage>().Deserialize(_settingsFile).Load<Settings>());

					Year.SelectedItem = settings.Year;
					Trader.Text = settings.Trader;
					From.Value = settings.From;
					To.Value = settings.To;
					Security1.Text = settings.Security1;
					Security2.Text = settings.Security2;
					Security3.Text = settings.Security3;
					Security4.Text = settings.Security4;
					TimeFrame.SelectedItem = settings.TimeFrame;
					Apart.IsChecked = settings.Apart;
				}
				else
				{
					Trader.Text = "Vasya";
					Security1.Text = "RIZ5@FORTS";
					//Trader.Text = "iZotov";
					//Security1.Text = "SPZ5@FORTS";
					//Security2.Text = "SIZ5@FORTS";
					//From.Value = new DateTime(2014, 09, 16);
					Apart.IsChecked = true;
				}
			}, TaskScheduler.FromCurrentSynchronizationContext());
		}