在 GitHub 上查看

缺口回补策略

缺口回补策略利用连续15分钟K线之间的价格缺口。 当新的K线开盘价高于前一根K线的最高价且超过设定阈值时,策略做空并在前一最高价处挂买单,期待缺口被回补。 当开盘价低于前一最低价且超过阈值时,策略做多并在前一最低价处挂卖单。 阈值等于MinGapSize价格步长加上当前买卖价差。

细节

  • 入场条件:当前开盘价与前一最高/最低价之间的缺口大于MinGapSize加价差。
  • 多空方向:双向。
  • 出场条件:在前一根K线极值处的限价单。
  • 止损:无。
  • 默认值
    • MinGapSize = 1
    • Volume = 0.1
    • CandleType = 15 分钟
  • 筛选
    • 类别:缺口
    • 方向:双向
    • 指标:无
    • 止损:无
    • 复杂度:基础
    • 时间框架:日内 (15m)
    • 季节性:无
    • 神经网络:无
    • 背离:无
    • 风险等级:中等
using System;
using System.Collections.Generic;

using Ecng.Common;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Gap fill strategy using Highest/Lowest channel breakout.
/// </summary>
public class GapFillStrategy : Strategy
{
	private readonly StrategyParam<int> _channelPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevHigh;
	private decimal _prevLow;
	private bool _hasPrev;

	public int ChannelPeriod { get => _channelPeriod.Value; set => _channelPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public GapFillStrategy()
	{
		_channelPeriod = Param(nameof(ChannelPeriod), 12)
			.SetGreaterThanZero()
			.SetDisplay("Channel Period", "Highest/Lowest period", "Parameters");
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle type", "Data");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
		=> [(Security, CandleType)];

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevHigh = 0;
		_prevLow = 0;
		_hasPrev = false;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var highest = new Highest { Length = ChannelPeriod };
		var lowest = new Lowest { Length = ChannelPeriod };

		SubscribeCandles(CandleType)
			.Bind(highest, lowest, ProcessCandle)
			.Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal highVal, decimal lowVal)
	{
		if (candle.State != CandleStates.Finished) return;

		if (!_hasPrev)
		{
			_prevHigh = highVal;
			_prevLow = lowVal;
			_hasPrev = true;
			return;
		}

		if (candle.ClosePrice > _prevHigh && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
		}
		else if (candle.ClosePrice < _prevLow && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
		}

		_prevHigh = highVal;
		_prevLow = lowVal;
	}
}