在策略中使用图表
在 StockSharp 中,Strategy 类提供了一个便捷的界面,用于在图表上可视化交易活动。在本文中,我们将探讨如何从策略访问图表、创建区域 (ChartArea)、添加各种元素(K线、指标、交易)以及渲染数据。
访问图表
获取图表方法
要从策略中访问图表,请使用 Strategy.GetChart() 方法:
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(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();
}
}
创建图表区域
在获取图表访问权限后,您可以创建一个或多个区域来显示各种数据。使用 CreateChartArea 方法:
private void InitializeChart()
{
// 创建 K线和指标的主区域
_mainArea = CreateChartArea();
// 创建成交量的附加区域
_volumeArea = CreateChartArea();
// 配置区域并添加元素
ConfigureChartElements();
}
你也可以直接使用 IChart.AddArea 方法:
private void InitializeChart()
{
// 必要时清除现有区域
foreach (var area in _chart.Areas.ToArray())
_chart.RemoveArea(area);
// 创建 K线和指标的主区域
_mainArea = _chart.AddArea();
// 创建成交量的附加区域
_volumeArea = _chart.AddArea();
// 配置区域并添加元素
ConfigureChartElements();
}
向图表添加元素
创建图表区域后,您可以添加各种元素来显示数据。StockSharp 支持不同类型的元素,如K线、指标、交易和订单。
添加K线
要显示K线,请使用图表区域的 AddCandles 方法:
private void ConfigureChartElements()
{
// 向主区域添加 K线元素
_candleElement = _mainArea.AddCandles();
// 配置 K线显示
_candleElement.DrawStyle = ChartCandleDrawStyles.CandleStick; // 日式K线
_candleElement.AntiAliasing = true; // Smoothing
_candleElement.UpFillColor = Color.Green; // 上涨K线实体颜色
_candleElement.DownFillColor = Color.Red; // 下跌K线实体颜色
_candleElement.UpBorderColor = Color.DarkGreen; // 上涨K线边框颜色
_candleElement.DownBorderColor = Color.DarkRed; // 下跌K线边框颜色
_candleElement.StrokeThickness = 1; // 线条粗细
_candleElement.ShowAxisMarker = true; // 显示Y轴标记
}
IChartCandleElement 接口提供了许多用于配置K线显示的属性:
绘图样式 - K线显示风格:
- K线 - 日本K线
- OHLC - 柱状图
- LineOpen/LineHigh/LineLow/LineClose - 分别表示相应价格的线
- 箱体体积 - 体积盒
- ClusterProfile - 集群配置文件
- 区域 - 区域
- PnF - 点数图表
颜色设置:
- UpFillColor/DownFillColor - 上涨/下跌K线实体颜色
- UpBorderColor/DownBorderColor - 上涨/下跌K线边框颜色
- LineColor - 线型图的线条颜色
- AreaColor - 区域类型的区域颜色
其他设置:
- StrokeThickness - 线条粗细
- 抗锯齿 - 平滑
- 显示坐标轴标记 - 显示 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 接口提供以下属性用于配置:
- 颜色 - 主要指示颜色
- 附加颜色 - 附加颜色(用于有两条线的指示器)
- StrokeThickness - 线条粗细
- 抗锯齿 - 平滑
- DrawStyle - 绘图风格(线条、点、直方图等)
- 显示坐标轴标记 - 显示 Y 轴标记
- AutoAssignYAxis - 自动分配 Y 轴
添加交易
要显示交易,请使用 DrawOwnTrades 方法:
// 添加用于显示成交的元素
_tradesElement = DrawOwnTrades(_mainArea);
// 配置成交显示
_tradesElement.BuyBrush = Color.Green; // Buy color
_tradesElement.SellBrush = Color.Red; // Sell color
_tradesElement.PointSize = 10; // Point size
添加订单
要显示订单,请使用 DrawOrders 方法:
// 添加用于显示订单的元素
_ordersElement = DrawOrders(_mainArea);
// 配置订单显示
_ordersElement.ActiveBrush = Color.Blue; // 活跃订单颜色
_ordersElement.CanceledBrush = Color.Gray; // 已取消订单颜色
_ordersElement.DoneBrush = Color.Green; // 已完成订单颜色
_ordersElement.ErrorColor = Color.Red; // 错误颜色
_ordersElement.PointSize = 8; // Point size
IChartOrderElement 接口提供以下属性用于配置:
- ActiveBrush - 活动订单的颜色
- 已取消画笔 - 已取消订单的颜色
- 已完成笔刷 - 已完成订单的颜色
- 错误颜色 - 错误颜色
- ErrorStrokeColor - 错误边框颜色
- 筛选 - 订单显示筛选
在图表上绘制数据
在配置所有图表元素后,您可以开始绘制数据。根据数据的类型使用不同的方法。
绘制K线和指标
绘制数据的最高效方法是使用 IChart.Draw 方法配合 IChartDrawData 对象:
private void ProcessCandle(ICandleMessage candle)
{
// 在指标中处理 K线
var smaValue = _sma.Process(candle);
var bollingerValue = _bollinger.Process(candle);
// 如果图表不可用,则跳过绘制
if (_chart == null)
return;
// 创建绘制数据
var drawData = _chart.CreateData();
// 按 K线时间分组数据
var group = drawData.Group(candle.OpenTime);
// 添加 K线
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 OnStarted2(DateTime time)
{
base.OnStarted2(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();
}
// 订阅 K线
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);
// 创建 K线和指标的主区域
_mainArea = _chart.AddArea();
// 创建成交量的附加区域
_volumeArea = _chart.AddArea();
// 配置图表元素
ConfigureChartElements();
}
private void ConfigureChartElements()
{
// 添加用于显示 K线的元素
_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)
{
// 用指标处理 K线
var smaValue = _sma.Process(candle);
var bollingerValue = _bollinger.Process(candle);
// 如果图表不可用,则跳过绘制
if (_chart == null)
return;
// 在图表上绘制数据
var drawData = _chart.CreateData();
var group = drawData.Group(candle.OpenTime);
// 添加 K线
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 非常重要,并为策略在无可视化的情况下运行提供替代方案。