Работа с графиком в стратегии
В StockSharp класс Strategy предоставляет удобный интерфейс для визуализации торговой активности на графике. В этой статье мы рассмотрим, как получить доступ к графику из стратегии, как создавать области (ChartArea), добавлять различные элементы (свечи, индикаторы, сделки) и отрисовывать данные.
Получение доступа к графику
Метод GetChart
Для получения доступа к графику из стратегии используется метод Strategy.GetChart():
protected override void OnStarted(DateTimeOffset time)
{
base.OnStarted(time);
// Получение графика
_chart = GetChart();
// Проверка доступности графика
if (_chart != null)
{
// Инициализация графика
InitializeChart();
}
else
{
// График недоступен, например, при запуске в консольном режиме
LogInfo("График недоступен. Визуализация отключена.");
}
}
Метод GetChart() возвращает интерфейс IChart, который предоставляет доступ к функциям графика. Важно проверять результат на null
, так как график может быть недоступен, например, при запуске стратегии в консольном режиме или в облачном тестировании.
Метод SetChart
В некоторых случаях график может быть установлен извне. Для этого используется метод Strategy.SetChart:
// Установка графика из внешнего источника
public void ConfigureVisualization(IChart chart)
{
SetChart(chart);
if (chart != null)
{
InitializeChart();
}
}
Создание областей графика (ChartArea)
После получения доступа к графику можно создать одну или несколько областей для отображения различных данных. Для этого используется метод CreateChartArea:
private void InitializeChart()
{
// Создание основной области для свечей и индикаторов
_mainArea = CreateChartArea();
// Создание дополнительной области для объема
_volumeArea = CreateChartArea();
// Настройка областей и добавление элементов
ConfigureChartElements();
}
Также можно использовать метод IChart.AddArea напрямую:
private void InitializeChart()
{
// Очистка существующих областей, если необходимо
foreach (var area in _chart.Areas.ToArray())
_chart.RemoveArea(area);
// Создание основной области для свечей и индикаторов
_mainArea = _chart.AddArea();
// Создание дополнительной области для объема
_volumeArea = _chart.AddArea();
// Настройка областей и добавление элементов
ConfigureChartElements();
}
Добавление элементов на график
После создания областей графика можно добавить различные элементы для отображения данных. StockSharp поддерживает различные типы элементов, такие как свечи, индикаторы, сделки и заявки.
Добавление свечей
Для отображения свечей используется метод AddCandles области графика:
private void ConfigureChartElements()
{
// Добавление элемента для отображения свечей в основной области
_candleElement = _mainArea.AddCandles();
// Настройка отображения свечей
_candleElement.DrawStyle = ChartCandleDrawStyles.CandleStick; // Японские свечи
_candleElement.AntiAliasing = true; // Сглаживание
_candleElement.UpFillColor = Color.Green; // Цвет тела растущей свечи
_candleElement.DownFillColor = Color.Red; // Цвет тела падающей свечи
_candleElement.UpBorderColor = Color.DarkGreen; // Цвет границы растущей свечи
_candleElement.DownBorderColor = Color.DarkRed; // Цвет границы падающей свечи
_candleElement.StrokeThickness = 1; // Толщина линии
_candleElement.ShowAxisMarker = true; // Показывать маркер на оси Y
}
Интерфейс IChartCandleElement предоставляет множество свойств для настройки отображения свечей:
DrawStyle - стиль отображения свечей:
- CandleStick - японские свечи
- Ohlc - бары
- LineOpen/LineHigh/LineLow/LineClose - линии по соответствующей цене
- BoxVolume - объемные боксы
- ClusterProfile - кластерный профиль
- Area - область
- PnF - график типа крестики-нолики
Цветовые настройки:
- UpFillColor/DownFillColor - цвет тела растущей/падающей свечи
- UpBorderColor/DownBorderColor - цвет границы растущей/падающей свечи
- LineColor - цвет линии для линейных типов графиков
- AreaColor - цвет области для типа Area
Другие настройки:
- StrokeThickness - толщина линии
- AntiAliasing - сглаживание
- ShowAxisMarker - показывать маркер на оси Y
Добавление индикаторов
Для отображения индикаторов используется метод DrawIndicator:
// Создание индикаторов
_sma = new SimpleMovingAverage { Length = SmaLength };
_bollinger = new BollingerBands
{
Length = BollingerLength,
Deviation = BollingerDeviation
};
// Добавление индикаторов в коллекцию стратегии
Indicators.Add(_sma);
Indicators.Add(_bollinger);
// Визуализация индикаторов
_smaElement = DrawIndicator(_mainArea, _sma, Color.Blue);
_bollingerUpperElement = DrawIndicator(_mainArea, _bollinger, Color.Purple);
_bollingerLowerElement = DrawIndicator(_mainArea, _bollinger, Color.Purple);
_bollingerMiddleElement = DrawIndicator(_mainArea, _bollinger, Color.Gray);
Метод DrawIndicator автоматически создает элемент индикатора и добавляет его в указанную область графика. Можно указать цвет и дополнительный цвет для отображения.
Также можно добавить элемент индикатора напрямую через метод AddIndicator области графика:
// Добавление SMA непосредственно через область графика
var smaElement = _mainArea.AddIndicator(_sma);
smaElement.Color = Color.Blue;
smaElement.StrokeThickness = 2;
smaElement.DrawStyle = DrawStyles.Line;
smaElement.AntiAliasing = true;
smaElement.ShowAxisMarker = true;
smaElement.AutoAssignYAxis = true; // Автоматически назначить ось Y
Интерфейс IChartIndicatorElement предоставляет следующие свойства для настройки:
- Color - основной цвет индикатора
- AdditionalColor - дополнительный цвет (для индикаторов с двумя линиями)
- StrokeThickness - толщина линии
- AntiAliasing - сглаживание
- DrawStyle - стиль рисования (линия, точки, гистограмма и т.д.)
- ShowAxisMarker - показывать маркер на оси Y
- AutoAssignYAxis - автоматически назначить ось Y
Добавление сделок
Для отображения сделок используется метод DrawOwnTrades:
// Добавление элемента для отображения сделок
_tradesElement = DrawOwnTrades(_mainArea);
// Настройка отображения сделок
_tradesElement.BuyBrush = Color.Green; // Цвет покупок
_tradesElement.SellBrush = Color.Red; // Цвет продаж
_tradesElement.PointSize = 10; // Размер точки
Добавление заявок
Для отображения заявок используется метод DrawOrders:
// Добавление элемента для отображения заявок
_ordersElement = DrawOrders(_mainArea);
// Настройка отображения заявок
_ordersElement.ActiveBrush = Color.Blue; // Цвет активных заявок
_ordersElement.CanceledBrush = Color.Gray; // Цвет отмененных заявок
_ordersElement.DoneBrush = Color.Green; // Цвет исполненных заявок
_ordersElement.ErrorColor = Color.Red; // Цвет ошибок
_ordersElement.PointSize = 8; // Размер точки
Интерфейс IChartOrderElement предоставляет следующие свойства для настройки:
- ActiveBrush - цвет активных заявок
- CanceledBrush - цвет отмененных заявок
- DoneBrush - цвет исполненных заявок
- ErrorColor - цвет ошибок
- ErrorStrokeColor - цвет обводки ошибок
- Filter - фильтр отображения заявок
Отрисовка данных на графике
После настройки всех элементов графика можно приступить к отрисовке данных. Для этого используются различные методы в зависимости от типа данных.
Отрисовка свечей и индикаторов
Наиболее эффективный способ отрисовки данных — использование метода IChart.Draw с объектом IChartDrawData:
private void ProcessCandle(ICandleMessage candle)
{
// Обработка свечи в индикаторах
var smaValue = _sma.Process(candle);
var bollingerValue = _bollinger.Process(candle);
// Если график недоступен, пропускаем отрисовку
if (_chart == null)
return;
// Создаем данные для отрисовки
var drawData = _chart.CreateData();
// Группируем данные по времени свечи
var group = drawData.Group(candle.OpenTime);
// Добавляем свечу
group.Add(_candleElement,
candle.DataType,
candle.SecurityId,
candle.OpenPrice,
candle.HighPrice,
candle.LowPrice,
candle.ClosePrice,
candle.PriceLevels,
candle.State);
// Добавляем значения индикаторов
group.Add(_smaElement, smaValue);
if (bollingerValue != null)
{
group.Add(_bollingerUpperElement, bollingerValue);
group.Add(_bollingerMiddleElement, bollingerValue);
group.Add(_bollingerLowerElement, bollingerValue);
}
// Отрисовываем данные на графике
_chart.Draw(drawData);
}
Метод IChart.CreateData создает объект IChartDrawData, который используется для группировки и добавления данных для разных элементов графика. Группировка данных производится по временной метке с помощью метода Group.
Для добавления данных разного типа используются различные перегрузки метода Add объекта IChartDrawDataItem.
Отрисовка сделок и заявок
Для отрисовки сделок и заявок обычно используется автоматический механизм, который срабатывает при получении новых сделок или изменении заявок. Однако, если требуется отрисовать их вручную, можно использовать следующий код:
// Отрисовка сделки
var tradeDrawData = _chart.CreateData();
var tradeGroup = tradeDrawData.Group(trade.Time);
tradeGroup.Add(_tradesElement, trade.Id, trade.StringId, trade.Side, trade.Price, trade.Volume);
_chart.Draw(tradeDrawData);
// Отрисовка заявки
var orderDrawData = _chart.CreateData();
var orderGroup = orderDrawData.Group(order.Time);
orderGroup.Add(_ordersElement, order.Id, order.StringId, order.Side, order.Price, order.Volume);
_chart.Draw(orderDrawData);
Полный пример отрисовки графика в стратегии
Ниже приведен полный пример стратегии с настройкой и отрисовкой графика:
public class SmaStrategy : Strategy
{
private readonly StrategyParam<int> _smaLength;
private readonly StrategyParam<int> _bollingerLength;
private readonly StrategyParam<decimal> _bollingerDeviation;
private SimpleMovingAverage _sma;
private BollingerBands _bollinger;
private IChart _chart;
private IChartArea _mainArea;
private IChartArea _volumeArea;
private IChartCandleElement _candleElement;
private IChartIndicatorElement _smaElement;
private IChartIndicatorElement _bollingerUpperElement;
private IChartIndicatorElement _bollingerMiddleElement;
private IChartIndicatorElement _bollingerLowerElement;
private IChartOrderElement _ordersElement;
private IChartTradeElement _tradesElement;
public SmaStrategy()
{
_smaLength = Param(nameof(SmaLength), 20);
_bollingerLength = Param(nameof(BollingerLength), 20);
_bollingerDeviation = Param(nameof(BollingerDeviation), 2m);
}
public int SmaLength
{
get => _smaLength.Value;
set => _smaLength.Value = value;
}
public int BollingerLength
{
get => _bollingerLength.Value;
set => _bollingerLength.Value = value;
}
public decimal BollingerDeviation
{
get => _bollingerDeviation.Value;
set => _bollingerDeviation.Value = value;
}
protected override void OnStarted(DateTimeOffset time)
{
base.OnStarted(time);
// Создание индикаторов
_sma = new SimpleMovingAverage { Length = SmaLength };
_bollinger = new BollingerBands
{
Length = BollingerLength,
Deviation = BollingerDeviation
};
// Добавление индикаторов в коллекцию стратегии
Indicators.Add(_sma);
Indicators.Add(_bollinger);
// Получение графика
_chart = GetChart();
// Инициализация графика, если он доступен
if (_chart != null)
{
InitializeChart();
}
// Подписка на свечи
var subscription = new Subscription(
DataType.TimeFrame(TimeSpan.FromMinutes(5)),
Security);
subscription
.WhenCandlesFinished(this)
.Do(ProcessCandle)
.Apply(this);
Subscribe(subscription);
}
private void InitializeChart()
{
// Очистка существующих областей
foreach (var area in _chart.Areas.ToArray())
_chart.RemoveArea(area);
// Создание основной области для свечей и индикаторов
_mainArea = _chart.AddArea();
// Создание дополнительной области для объема
_volumeArea = _chart.AddArea();
// Настройка элементов графика
ConfigureChartElements();
}
private void ConfigureChartElements()
{
// Добавление элемента для отображения свечей
_candleElement = _mainArea.AddCandles();
_candleElement.DrawStyle = ChartCandleDrawStyles.CandleStick;
_candleElement.AntiAliasing = true;
_candleElement.UpFillColor = Color.Green;
_candleElement.DownFillColor = Color.Red;
_candleElement.UpBorderColor = Color.DarkGreen;
_candleElement.DownBorderColor = Color.DarkRed;
_candleElement.StrokeThickness = 1;
_candleElement.ShowAxisMarker = true;
// Добавление элементов для индикаторов
_smaElement = _mainArea.AddIndicator(_sma);
_smaElement.Color = Color.Blue;
_smaElement.StrokeThickness = 2;
_bollingerUpperElement = _mainArea.AddIndicator(_bollinger);
_bollingerUpperElement.Color = Color.Purple;
_bollingerUpperElement.StrokeThickness = 1;
_bollingerMiddleElement = _mainArea.AddIndicator(_bollinger);
_bollingerMiddleElement.Color = Color.Gray;
_bollingerMiddleElement.StrokeThickness = 1;
_bollingerLowerElement = _mainArea.AddIndicator(_bollinger);
_bollingerLowerElement.Color = Color.Purple;
_bollingerLowerElement.StrokeThickness = 1;
// Добавление элементов для заявок и сделок
_ordersElement = DrawOrders(_mainArea);
_tradesElement = DrawOwnTrades(_mainArea);
}
private void ProcessCandle(ICandleMessage candle)
{
// Обработка свечи индикаторами
var smaValue = _sma.Process(candle);
var bollingerValue = _bollinger.Process(candle);
// Если график недоступен, пропускаем отрисовку
if (_chart == null)
return;
// Отрисовка данных на графике
var drawData = _chart.CreateData();
var group = drawData.Group(candle.OpenTime);
// Добавление свечи
group.Add(_candleElement,
candle.DataType,
candle.SecurityId,
candle.OpenPrice,
candle.HighPrice,
candle.LowPrice,
candle.ClosePrice,
candle.PriceLevels,
candle.State);
// Добавление значений индикаторов
group.Add(_smaElement, smaValue);
if (bollingerValue != null)
{
group.Add(_bollingerUpperElement, bollingerValue);
group.Add(_bollingerMiddleElement, bollingerValue);
group.Add(_bollingerLowerElement, bollingerValue);
}
// Отрисовка данных на графике
_chart.Draw(drawData);
// Торговая логика
if (!IsFormed)
return;
// ... реализация торговой логики ...
}
}
Заключение
Использование графиков в стратегиях StockSharp позволяет визуализировать торговую активность, что значительно упрощает разработку, отладку и мониторинг торговых стратегий. Класс Strategy предоставляет множество методов для работы с графиками, позволяющих легко добавлять различные элементы и отрисовывать данные.
При разработке стратегии с графическим интерфейсом всегда следует учитывать, что график может быть недоступен, например, при запуске в консольном режиме или в облачном тестировании. Поэтому важно проверять результат метода GetChart() на null
и предусматривать альтернативный сценарий работы стратегии без визуализации.