Ver no GitHub

Estratégia de Setas de Tendência

Esta estratégia opera rompimentos quando o preço de fechamento se move além de extremos recentes. Ela calcula os preços de fechamento mais altos e mais baixos durante um período configurável. Uma nova tendência de alta é detectada quando o fechamento supera a máxima recente, enquanto uma tendência de baixa começa quando o fechamento cai abaixo da mínima recente.

Quando uma nova tendência de alta é detectada, posições vendidas existentes podem ser fechadas e posições compradas opcionais abertas. Ao contrário, uma nova tendência de baixa permite fechar posições compradas e opcionalmente abrir vendidas. A estratégia processa apenas velas completadas e usa a API de alto nível do StockSharp.

Parâmetros

  • Period – número de barras para determinar os extremos recentes.
  • Candle Type – período das velas.
  • Open Long – permitir a abertura de posições compradas.
  • Open Short – permitir a abertura de posições vendidas.
  • Close Long – permitir o fechamento de posições compradas.
  • Close Short – permitir o fechamento de posições vendidas.

Lógica

  1. Inscrever-se nos dados de velas do período selecionado.
  2. Rastrear os fechamentos mais altos e mais baixos ao longo do período usando os indicadores Highest e Lowest.
  3. Quando o preço rompe acima do fechamento mais alto, sinalizar tendência de alta; quando abaixo do fechamento mais baixo, sinalizar tendência de baixa.
  4. Entrar ou sair de posições de acordo com a nova tendência e as opções habilitadas.
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>
/// Trend arrows strategy based on breakouts of recent extremes.
/// Detects when price moves above the highest close or below the lowest close
/// over the specified period and trades in the direction of the breakout.
/// </summary>
public class TrendArrowsStrategy : Strategy
{
	private readonly StrategyParam<int> _period;
	private readonly StrategyParam<DataType> _candleType;

	private bool _prevTrendUp;
	private bool _prevTrendDown;
	private decimal? _prevHighest;
	private decimal? _prevLowest;

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

	public TrendArrowsStrategy()
	{
		_period = Param(nameof(Period), 15)
			.SetDisplay("Period", "Number of bars for extreme calculation", "Parameters")
			.SetOptimize(5, 30, 5);

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe of candles", "Parameters");
	}

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevTrendUp = false;
		_prevTrendDown = false;
		_prevHighest = null;
		_prevLowest = null;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_prevTrendUp = false;
		_prevTrendDown = false;
		_prevHighest = null;
		_prevLowest = null;

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

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(highest, lowest, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, highest);
			DrawIndicator(area, lowest);
			DrawOwnTrades(area);
		}
	}

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

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		// Use previous bar's highest/lowest to detect breakout
		if (_prevHighest is null || _prevLowest is null)
		{
			_prevHighest = highestVal;
			_prevLowest = lowestVal;
			return;
		}

		var trendUp = false;
		var trendDown = false;

		if (candle.ClosePrice > _prevHighest.Value)
			trendUp = true;
		else if (candle.ClosePrice < _prevLowest.Value)
			trendDown = true;
		else
		{
			trendUp = _prevTrendUp;
			trendDown = _prevTrendDown;
		}

		// Buy when up trend appears
		if (!_prevTrendUp && trendUp && Position <= 0)
			BuyMarket();

		// Sell when down trend appears
		if (!_prevTrendDown && trendDown && Position >= 0)
			SellMarket();

		_prevTrendUp = trendUp;
		_prevTrendDown = trendDown;
		_prevHighest = highestVal;
		_prevLowest = lowestVal;
	}
}