Table of Contents

График

Для графического отображения свечей можно использовать специальный компонент Chart (см. Компоненты для построения графиков), который отрисовывает свечи следующим образом:

sample candleschart

Базовый подход к отображению свечей

Для отображения свечей на графике можно использовать два подхода. Первый подход - ручная отрисовка свечей при получении данных:

private IChartArea _areaComb;
private IChartCandleElement _candleElement;

// Инициализация графика
private void InitializeChart()
{
	// Создаем область графика
	_areaComb = _chart.CreateArea();
	_chart.AddArea(_areaComb);

	// Создаем элемент для отображения свечей
	_candleElement = _chart.CreateCandleElement();
	_candleElement.FullTitle = "Candles";
	_chart.AddElement(_areaComb, _candleElement);
	
	// Подписываемся на событие получения свечей
	_connector.CandleReceived += OnCandleReceived;
}

// Создаем подписку на 5-минутные свечи
private void SubscribeToCandles()
{
	var subscription = new Subscription(
		TimeSpan.FromMinutes(5).TimeFrame(),
		_security)
	{
		MarketData = 
		{
			// Запрашиваем исторические данные за 5 дней
			From = DateTime.Today.Subtract(TimeSpan.FromDays(5)),
			To = DateTime.Now
		}
	};
	
	// Запускаем подписку
	_connector.Subscribe(subscription);
}

// Обработчик события получения свечи
private void OnCandleReceived(Subscription subscription, ICandleMessage candle)
{
	// Проверяем, завершена ли свеча
	if (candle.State == CandleStates.Finished) 
	{
		// Создаем данные для отрисовки
		var chartData = _chart.CreateData();
		chartData.Group(candle.OpenTime).Add(_candleElement, candle);

		// Отрисовываем на графике в потоке UI
		this.GuiAsync(() => _chart.Draw(chartData));
	}
}

Автоматическая привязка подписки к элементу графика

Второй подход - это использование автоматической привязки подписки к элементу графика. Это позволяет автоматически отображать получаемые данные:

// Инициализация графика с автоматической привязкой
private void InitializeChartWithAutoBinding()
{
	// Создаем область графика
	var area = _chart.CreateArea();
	_chart.AddArea(area);

	// Создаем элемент для отображения свечей
	var candleElement = _chart.CreateCandleElement();
	
	// Создаем подписку на свечи
	var subscription = new Subscription(
		TimeSpan.FromMinutes(5).TimeFrame(),
		_security)
	{
		MarketData = 
		{
			From = DateTime.Today.Subtract(TimeSpan.FromDays(5)),
			To = DateTime.Now
		}
	};
	
	// Привязываем элемент к подписке
	_chart.AddElement(area, candleElement, subscription);
	
	// Запускаем подписку
	_connector.Subscribe(subscription);
}

Работа с индикаторами

Для отображения индикаторов на графике вместе со свечами используются элементы типа ChartIndicatorElement:

// Добавление индикатора на график
private void AddIndicatorToChart()
{
	// Создаем элемент для индикатора
	var smaElement = _chart.CreateIndicatorElement();
	smaElement.FullTitle = "SMA (14)";

	// Добавляем элемент на ту же область, что и свечи
	_chart.AddElement(_areaComb, smaElement);
	
	// Создаем индикатор
	var sma = new SimpleMovingAverage { Length = 14 };
	
	// Подписываемся на событие получения свечей для расчета индикатора
	_connector.CandleReceived += (subscription, candle) =>
	{
		// Вычисляем значение индикатора
		var indicatorValue = sma.Process(candle);
		
		// Отрисовываем значение на графике
		var chartData = _chart.CreateData();
		chartData.Group(candle.OpenTime).Add(smaElement, indicatorValue);

		this.GuiAsync(() => _chart.Draw(chartData));
	};
}

Отображение нескольких индикаторов на разных областях

Можно размещать индикаторы на отдельных областях графика:

// Добавление индикаторов на разные области
private void AddIndicatorsToSeparateAreas()
{
	// Основная область для свечей
	var candleArea = _chart.CreateArea();
	_chart.AddArea(candleArea);

	// Элемент для свечей
	var candleElement = _chart.CreateCandleElement();
	_chart.AddElement(candleArea, candleElement);

	// Элемент для SMA на той же области
	var smaElement = _chart.CreateIndicatorElement();
	smaElement.FullTitle = "SMA (14)";
	_chart.AddElement(candleArea, smaElement);

	// Отдельная область для RSI
	var rsiArea = _chart.CreateArea();
	_chart.AddArea(rsiArea);

	// Элемент для RSI
	var rsiElement = _chart.CreateIndicatorElement();
	rsiElement.FullTitle = "RSI (14)";
	_chart.AddElement(rsiArea, rsiElement);
	
	// Создаем индикаторы
	var sma = new SimpleMovingAverage { Length = 14 };
	var rsi = new RelativeStrengthIndex { Length = 14 };
	
	// Подписка на свечи
	var subscription = new Subscription(
		TimeSpan.FromMinutes(5).TimeFrame(),
		_security);
	
	// Привязываем элемент свечей к подписке
	_chart.AddElement(candleArea, candleElement, subscription);
	
	// Запускаем подписку и обрабатываем индикаторы
	_connector.Subscribe(subscription);
	
	_connector.CandleReceived += (sub, candle) =>
	{
		if (sub != subscription || candle.State != CandleStates.Finished)
			return;
		
		// Вычисляем значения индикаторов
		var smaValue = sma.Process(candle);
		var rsiValue = rsi.Process(candle);
		
		// Отрисовываем значения на графике
		var chartData = _chart.CreateData();
		chartData
			.Group(candle.OpenTime)
				.Add(smaElement, smaValue)
				.Add(rsiElement, rsiValue);

		this.GuiAsync(() => _chart.Draw(chartData));
	};
}

Отображение заявок и сделок на графике

Для отображения заявок и сделок на графике используются специальные элементы:

// Добавление элементов для отображения заявок и сделок
private void AddOrdersAndTradesToChart()
{
	// Создаем элементы для отображения заявок и сделок
	var orderElement = _chart.CreateOrderElement();
	var tradeElement = _chart.CreateTradeElement();

	// Добавляем элементы на область графика
	_chart.AddElement(_areaComb, orderElement);
	_chart.AddElement(_areaComb, tradeElement);
	
	// Подписываемся на события получения заявок и сделок
	_connector.OrderReceived += (subscription, order) =>
	{
		if (order.Security != _security)
			return;
		
		// Отрисовываем заявку на графике
		var chartData = _chart.CreateData();
		chartData.Group(order.Time).Add(orderElement, order);

		this.GuiAsync(() => _chart.Draw(chartData));
	};
	
	_connector.OwnTradeReceived += (subscription, trade) =>
	{
		if (trade.Order.Security != _security)
			return;
		
		// Отрисовываем сделку на графике
		var chartData = _chart.CreateData();
		chartData.Group(trade.Time).Add(tradeElement, trade);

		this.GuiAsync(() => _chart.Draw(chartData));
	};
}

Настройка внешнего вида графика

Можно настроить различные аспекты внешнего вида графика:

// Настройка внешнего вида графика
private void ConfigureChartAppearance()
{
	// Настройка области графика
	_areaComb.Height = 300;

	// Настройка элемента свечей
	_candleElement.DrawStyle = ChartCandleDrawStyles.CandleStick;
	_candleElement.UpFillColor = Colors.Green;
	_candleElement.DownFillColor = Colors.Red;
	_candleElement.StrokeThickness = 1;

	// Настройка всего графика
	_chart.IsAutoRange = true;            // Автоматический масштаб
}

Масштабирование и прокрутка графика

Управление масштабом и прокруткой графика осуществляется через свойства IChart:

// Настройка масштабирования и прокрутки
private void ConfigureChartZoomAndScroll()
{
	// Включаем автоматическую прокрутку при поступлении новых данных
	_chart.IsAutoScroll = true;

	// Сброс масштаба к автоматическому
	_chart.IsAutoRange = true;
}

Экспорт графика в изображение

Для сохранения графика в файл:

// Экспорт графика в изображение
private void ExportChartToImage()
{
	// Создаем объект для сохранения изображения
	var saveFileDialog = new SaveFileDialog
	{
		Filter = "PNG Image|*.png|JPEG Image|*.jpg|BMP Image|*.bmp",
		Title = "Save Chart Image"
	};
	
	if (saveFileDialog.ShowDialog() == true)
	{
		// Создаем изображение из графика
		var rtb = new RenderTargetBitmap(
			(int)_chart.ActualWidth, 
			(int)_chart.ActualHeight, 
			96, 96, 
			PixelFormats.Pbgra32);
		
		rtb.Render(_chart);
		
		// Сохраняем изображение в выбранный формат
		BitmapEncoder encoder;
		
		switch (Path.GetExtension(saveFileDialog.FileName).ToLower())
		{
			case ".jpg":
				encoder = new JpegBitmapEncoder();
				break;
			case ".bmp":
				encoder = new BmpBitmapEncoder();
				break;
			default:
				encoder = new PngBitmapEncoder();
				break;
		}
		
		encoder.Frames.Add(BitmapFrame.Create(rtb));
		
		using (var fileStream = new FileStream(saveFileDialog.FileName, FileMode.Create))
		{
			encoder.Save(fileStream);
		}
	}
}

Очистка графика

Для очистки данных на графике:

// Очистка графика или его элементов
private void ClearChart()
{
	// Очистка всех элементов графика
	_chart.Reset(_chart.GetElements());

	// Удаление всех областей с графика
	_chart.ClearAreas();
}

Пример отображения свечей на графике приведен в пункте Свечи.

См. также

Компоненты для построения графиков