K线

S# 支持以下类型的K线:

  • TimeFrameCandleMessage - 基于时间间隔(时间周期)的K线。既可以设置常用周期(分钟、小时、日),也可以设置自定义周期,例如 21 秒、4.5 分钟等。
  • RangeCandleMessage - 价格范围K线。当出现价格超出允许范围的成交时,会创建新K线。每次都根据第一笔成交的价格确定允许范围。
  • VolumeCandleMessage - 在成交总量超过指定限制前持续形成K线。如果新成交使数量超过允许值,则该成交会计入下一根新K线。
  • TickCandleMessage - 与 VolumeCandleMessage 类似,但使用成交笔数而不是成交量作为限制。
  • PnFCandleMessage - 点数图K线(X-O 图)。
  • RenkoCandleMessage - 砖形图(Renko)K线。

K线的使用方法可参阅 Samples/02_Candles/01_Realtime 文件夹中的示例。

下图分别展示 TimeFrameCandleMessageRangeCandleMessage 图表:

时间周期蜡烛图示例

区间蜡烛图示例

开始获取数据

  1. 要获取K线,请使用 Subscription 类创建订阅:
// 创建 5 分钟 K线订阅
var subscription = new Subscription(
	DataType.TimeFrame(TimeSpan.FromMinutes(5)),  // 带有时间框架设置的数据类型
	security)  // 交易品种
{
	// 通过 MarketData 属性配置附加参数
	MarketData = 
	{
		// 请求历史数据的期间(最近 30 天)
		From = DateTime.Today.Subtract(TimeSpan.FromDays(30)),
		To = DateTime.Now
	}
};
  1. 要接收K线,请订阅 Connector.CandleReceived 事件。出现可供处理的新值时,该事件会发出通知:
// 订阅 K线接收事件
_connector.CandleReceived += OnCandleReceived;

// K线接收事件处理器
private void OnCandleReceived(Subscription subscription, ICandleMessage candle)
{
	// 这里 subscription 是我们创建的订阅对象
	// candle — 接收到的 K线
	
	// 检查 K线是否属于我们的订阅
	if (subscription == _candleSubscription)
	{
		// 在图表上绘制 K线
		Chart.Draw(_candleElement, candle);
	}
}

Tip

Chart 图形组件用于显示K线。

  1. 接下来,通过 Connector.Subscribe 方法启动订阅:
// 启动订阅
_connector.Subscribe(subscription);

之后会开始调用 Connector.CandleReceived 事件。

  1. Connector.CandleReceived 事件不仅会在出现新K线时调用,当前K线发生变化时也会调用。

如果只需要显示已完成的K线,应检查所接收K线的 ICandleMessage.State 属性:

private void OnCandleReceived(Subscription subscription, ICandleMessage candle)
{
	// 检查 K线是否属于我们的订阅
	if (subscription != _candleSubscription)
		return;
	
	// 检查 K线是否已完成
	if (candle.State == CandleStates.Finished) 
	{
		// 创建绘制数据
		var chartData = new ChartDrawData();
		chartData.Group(candle.OpenTime).Add(_candleElement, candle);
		
		// 在图表上绘制 K线
		this.GuiAsync(() => Chart.Draw(chartData));
	}
}
  1. 还可以为订阅配置其他参数:
  • K线构建模式 - 指定请求现成数据,还是使用其他数据类型构建K线:
// 仅请求现成数据
subscription.MarketData.BuildMode = MarketDataBuildModes.Load;

// 仅从其他数据类型构建
subscription.MarketData.BuildMode = MarketDataBuildModes.Build;

// 请求现成数据,若不可用则构建
subscription.MarketData.BuildMode = MarketDataBuildModes.LoadAndBuild;
  • K线构建数据源 - 如果无法直接获取K线,指定使用哪种数据类型进行构建:
// 从 tick 成交构建 K线
subscription.MarketData.BuildFrom = DataType.Ticks;

// 从订单簿构建 K线
subscription.MarketData.BuildFrom = DataType.MarketDepth;

// 从 Level1 构建 K线
subscription.MarketData.BuildFrom = DataType.Level1;
  • K线构建字段 - 某些数据类型必须指定此参数:
// 按 Level1 中的最佳 bid 价格构建 K线
subscription.MarketData.BuildField = Level1Fields.BestBidPrice;

// 按 Level1 中的最佳 ask 价格构建 K线
subscription.MarketData.BuildField = Level1Fields.BestAskPrice;

// 按订单簿中的点差中间价构建 K线
subscription.MarketData.BuildField = Level1Fields.SpreadMiddle;
  • 成交量分布 - 计算K线的成交量分布:
// 启用成交量分布计算
subscription.MarketData.IsCalcVolumeProfile = true;

不同K线类型的订阅示例

标准时间周期K线

// 5 分钟 K线
var timeFrameSubscription = new Subscription(
	DataType.TimeFrame(TimeSpan.FromMinutes(5)),
	security);
_connector.Subscribe(timeFrameSubscription);

仅加载历史K线

// 仅加载历史 K线,不切换到实时模式
var historicalSubscription = new Subscription(
	DataType.TimeFrame(TimeSpan.FromMinutes(5)),
	security)
{
	MarketData =
	{
		From = DateTime.Today.Subtract(TimeSpan.FromDays(30)),
		To = DateTime.Today,  // 指定结束日期
		BuildMode = MarketDataBuildModes.Load  // 仅加载现成数据
	}
};
_connector.Subscribe(historicalSubscription);

使用逐笔成交构建非标准时间周期K线

// 从 tick 构建的 21 秒周期 K线
var customTimeFrameSubscription = new Subscription(
	DataType.TimeFrame(TimeSpan.FromSeconds(21)),
	security)
{
	MarketData =
	{
		BuildMode = MarketDataBuildModes.Build,
		BuildFrom = DataType.Ticks
	}
};
_connector.Subscribe(customTimeFrameSubscription);

使用市场深度数据构建K线

// 按订单簿点差中间价构建的 K线
var depthBasedSubscription = new Subscription(
	DataType.TimeFrame(TimeSpan.FromMinutes(1)),
	security)
{
	MarketData =
	{
		BuildMode = MarketDataBuildModes.Build,
		BuildFrom = DataType.MarketDepth,
		BuildField = Level1Fields.SpreadMiddle
	}
};
_connector.Subscribe(depthBasedSubscription);

带成交量分布的K线

// 带成交量分布计算的 5 分钟 K线
var volumeProfileSubscription = new Subscription(
	DataType.TimeFrame(TimeSpan.FromMinutes(5)),
	security)
{
	MarketData =
	{
		BuildMode = MarketDataBuildModes.LoadAndBuild,
		BuildFrom = DataType.Ticks,
		IsCalcVolumeProfile = true
	}
};
_connector.Subscribe(volumeProfileSubscription);

成交量K线

// 成交量 K线(每根 K线包含 1000 份合约的成交量)
var volumeCandleSubscription = new Subscription(
	DataType.Volume(1000m),  // 指定 K线类型和成交量
	security)
{
	MarketData =
	{
		BuildMode = MarketDataBuildModes.Build,
		BuildFrom = DataType.Ticks
	}
};
_connector.Subscribe(volumeCandleSubscription);

成交笔数K线

// tick 数 K线(每根 K线包含 1000 笔成交)
var tickCandleSubscription = new Subscription(
	DataType.Tick(1000),  // 指定 K线类型和成交笔数
	security)
{
	MarketData =
	{
		BuildMode = MarketDataBuildModes.Build,
		BuildFrom = DataType.Ticks
	}
};
_connector.Subscribe(tickCandleSubscription);

价格范围K线

// 范围为 0.1 单位的价格区间 K线
var rangeCandleSubscription = new Subscription(
	DataType.Range(0.1m),  // 指定 K线类型和价格范围
	security)
{
	MarketData =
	{
		BuildMode = MarketDataBuildModes.Build,
		BuildFrom = DataType.Ticks
	}
};
_connector.Subscribe(rangeCandleSubscription);

砖形图K线

// 步长为 0.1 的 Renko K线
var renkoCandleSubscription = new Subscription(
	DataType.Renko(0.1m),  // 指定 K线类型和砖块大小
	security)
{
	MarketData =
	{
		BuildMode = MarketDataBuildModes.Build,
		BuildFrom = DataType.Ticks
	}
};
_connector.Subscribe(renkoCandleSubscription);

点数图K线(P&F)

// Point and Figure K线
var pnfCandleSubscription = new Subscription(
	DataType.PnF(new PnfArg { BoxSize = 0.1m, ReversalAmount = 1 }),  // 指定 P&F 参数
	security)
{
	MarketData =
	{
		BuildMode = MarketDataBuildModes.Build,
		BuildFrom = DataType.Ticks
	}
};
_connector.Subscribe(pnfCandleSubscription);

后续步骤

图表

自定义K线类型