在 GitHub 上查看

TCPivot Stop 策略

该策略交易日内枢轴线的突破。枢轴点按照经典交易员公式,用前一日的最高价、最低价和收盘价计算。当收盘价向上突破枢轴线时开多单;当收盘价向下突破枢轴线时开空单。

进场后系统将某个支撑或阻力位同时用作止盈和止损。具体使用哪个级别由 Target Level 参数决定:

  • 1 – 使用 Support1/Resistance1
  • 2 – 使用 Support2/Resistance2
  • 3 – 使用 Support3/Resistance3

如果启用 Intraday Only,所有持仓将在平台时间 23:00 被平仓。

细节

  • 入场条件
    • 多头:上一根收盘价 ≤ 枢轴 && 当前收盘价 > 枢轴。
    • 空头:上一根收盘价 ≥ 枢轴 && 当前收盘价 < 枢轴。
  • 出场条件
    • 多头:收盘价 ≥ 选定阻力位或收盘价 ≤ 选定支撑位。
    • 空头:收盘价 ≤ 选定支撑位或收盘价 ≥ 选定阻力位。
    • 若启用 Intraday Only,所有仓位在 23:00 平仓。
  • 指标:仅使用枢轴点计算。
  • 时间框架:可配置,默认 5 分钟K线。
  • 止损:基于所选枢轴级别的止损和止盈。
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>
/// Pivot-based breakout strategy.
/// Buys when close crosses above calculated pivot, sells when it crosses below.
/// Uses support/resistance levels for exits.
/// </summary>
public class TcpPivotStopStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;

	private decimal _pivot;
	private decimal _res1, _sup1;
	private decimal _prevClose;
	private decimal _prevHigh;
	private decimal _prevLow;
	private int _barCount;

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

	public TcpPivotStopStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Time frame", "General");
	}

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

	protected override void OnReseted()
	{
		base.OnReseted();
		_pivot = _res1 = _sup1 = 0;
		_prevClose = _prevHigh = _prevLow = 0;
		_barCount = 0;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		SubscribeCandles(CandleType).Bind(ProcessCandle).Start();
	}

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

		_barCount++;

		// Recalculate pivot every 12 bars (~2 days for 4h candles)
		if (_barCount % 12 == 0 && _prevHigh > 0)
		{
			_pivot = (_prevHigh + _prevLow + _prevClose) / 3m;
			_res1 = 2m * _pivot - _prevLow;
			_sup1 = 2m * _pivot - _prevHigh;
		}

		_prevHigh = candle.HighPrice;
		_prevLow = candle.LowPrice;

		var close = candle.ClosePrice;

		if (_pivot > 0 && _prevClose > 0)
		{
			// Cross above pivot => long
			if (_prevClose <= _pivot && close > _pivot && Position <= 0)
			{
				if (Position < 0) BuyMarket();
				BuyMarket();
			}
			// Cross below pivot => short
			else if (_prevClose >= _pivot && close < _pivot && Position >= 0)
			{
				if (Position > 0) SellMarket();
				SellMarket();
			}
			// Exit long at resistance or support
			else if (Position > 0 && (close >= _res1 || close <= _sup1))
			{
				SellMarket();
			}
			// Exit short at support or resistance
			else if (Position < 0 && (close <= _sup1 || close >= _res1))
			{
				BuyMarket();
			}
		}

		_prevClose = close;
	}
}