Ver no GitHub

Estratégia TCPivot Stop

Esta estratégia opera rompimentos através da linha de pivô diária. Calcula os níveis de pivô clássicos dos traders de floor a partir da máxima, mínima e fechamento do dia anterior. Uma posição comprada é aberta quando o preço de fechamento cruza acima do pivô. Uma posição vendida é aberta quando o preço de fechamento cruza abaixo do pivô.

Após a entrada, o sistema utiliza um dos níveis de suporte ou resistência tanto como alvo de lucro quanto de stop loss. O nível é selecionado pelo parâmetro Target Level:

  • 1 – usa Support1/Resistance1.
  • 2 – usa Support2/Resistance2.
  • 3 – usa Support3/Resistance3.

Se Intraday Only estiver ativado, todas as posições abertas são fechadas às 23:00 horário da plataforma.

Detalhes

  • Critérios de entrada
    • Comprado: fechamento anterior ≤ pivô e fechamento atual > pivô.
    • Vendido: fechamento anterior ≥ pivô e fechamento atual < pivô.
  • Critérios de saída
    • Comprado: fechamento ≥ nível de resistência selecionado ou fechamento ≤ nível de suporte selecionado.
    • Vendido: fechamento ≤ nível de suporte selecionado ou fechamento ≥ nível de resistência selecionado.
    • Se Intraday Only for verdadeiro, todas as posições são fechadas às 23:00.
  • Indicadores: apenas cálculo clássico de pivô.
  • Período: configurável; velas de 5 minutos por padrão.
  • Stops: stop-loss e take-profit baseados no nível de pivô escolhido.
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;
	}
}