Ver no GitHub

Estratégia FXF Safe Trend Scalp V1 (C#)

A estratégia FXF Safe Trend Scalp V1 negocia rompimentos de linhas de tendência baseadas em ZigZag e reflete o comportamento do consultor especialista MetaTrader 4 original. Ele observa a distância entre o preço atual e as linhas dinâmicas de resistência/suporte construídas a partir de pivôs ZigZag recentes e alinha as negociações com um par de médias móveis simples. Stop-loss protetor, take-profit e saída de lucro flutuante reproduzem as regras de gestão de dinheiro do código-fonte.

Lógica de negociação

  1. Linhas de tendência em ziguezague
    • Um detector ZigZag manual procura altos e baixos alternados de oscilação usando os parâmetros configuráveis de profundidade, desvio e retrocesso.
    • Os últimos quatro máximos de oscilação definem a linha de resistência ativa, enquanto os últimos quatro mínimos de oscilação definem a linha de suporte ativa. A estratégia extrapola continuamente essas linhas para a barra atual.
    • Um sinal de entrada é preparado quando o preço de fechamento se aproxima de uma linha dentro de um deslocamento fixo (10 pontos por padrão).
  2. Filtro de média móvel
    • Uma média móvel simples rápida (comprimento 2) e uma média móvel simples lenta (comprimento 50) filtram a tendência.
    • As posições curtas exigem a MM rápida abaixo da MM lenta, enquanto as posições longas exigem a MM rápida acima da MM lenta.
  3. Execução de pedido
    • Os sinais são armazenados e ativados na próxima vela concluída, correspondendo à lógica de “nova barra” da versão MetaTrader.
    • Antes de abrir uma posição, a estratégia verifica se o spread não ultrapassa o máximo configurado e se nenhuma posição está aberta no momento.
  4. Gerenciamento de Riscos
    • As distâncias de stop-loss e take-profit são expressas em pontos e aplicadas imediatamente após o pedido ser atendido.
    • Uma meta de lucro flutuante fecha a posição quando o lucro não realizado (em unidades de preço vezes o volume) excede a recompensa configurada por lote.

Parâmetros

Nome Descrição
Candle Type Período de tempo usado para geração de sinal.
Volume Volume de negociação enviado com cada entrada.
ZigZag Depth Número mínimo de barras entre pivôs confirmados.
ZigZag Deviation (pts) O preço mínimo se move em pontos antes da mudança de direção.
ZigZag Backstep Barras necessárias antes de aceitar um pivô oposto.
Trend Offset (pts) Distância da linha de tendência que aciona um sinal.
Fast MA Length Comprimento da média móvel simples rápida.
Slow MA Length Comprimento da média móvel simples lenta.
Max Spread (pts) Spread máximo permitido, expresso em pontos.
Stop Loss (pts) Distância de parada protetora medida a partir do preço de entrada.
Take Profit (pts) Distância alvo de lucro medida a partir do preço de entrada.
Profit Target per Lot Lucro flutuante necessário (unidades de preço x volume) para fechar a posição.

Notas

  • Apenas uma posição é mantida por vez. Os sinais são ignorados enquanto uma negociação está aberta.
  • O filtro de spread depende das melhores cotações de compra/venda, portanto a estratégia deve estar conectada a uma fonte de dados que forneça informações de nível 1.
  • A versão Python da estratégia é omitida intencionalmente conforme solicitado.

Arquivos

  • CS/FXFSafeTrendScalpV1Strategy.cs – StockSharp implementação do consultor especialista.
namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// FXF Safe Trend Scalp V1 strategy: SMA crossover with ATR volatility filter.
/// Enters long when fast SMA crosses above slow SMA and ATR confirms volatility.
/// Enters short when fast SMA crosses below slow SMA.
/// </summary>
public class FxfSafeTrendScalpV1Strategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _atrPeriod;
	private readonly StrategyParam<int> _signalCooldownCandles;

	private decimal _prevFast;
	private decimal _prevSlow;
	private bool _hasPrev;
	private int _candlesSinceTrade;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public int AtrPeriod { get => _atrPeriod.Value; set => _atrPeriod.Value = value; }
	public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }

	public FxfSafeTrendScalpV1Strategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_fastPeriod = Param(nameof(FastPeriod), 5)
			.SetGreaterThanZero()
			.SetDisplay("Fast Period", "Fast SMA period", "Indicators");
		_slowPeriod = Param(nameof(SlowPeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("Slow Period", "Slow SMA period", "Indicators");
		_atrPeriod = Param(nameof(AtrPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("ATR Period", "ATR period", "Indicators");
		_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 3)
			.SetGreaterThanZero()
			.SetDisplay("Signal Cooldown", "Bars to wait between entries", "Trading");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFast = 0m;
		_prevSlow = 0m;
		_hasPrev = false;
		_candlesSinceTrade = SignalCooldownCandles;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_hasPrev = false;
		_candlesSinceTrade = SignalCooldownCandles;
		var fast = new SimpleMovingAverage { Length = FastPeriod };
		var slow = new SimpleMovingAverage { Length = SlowPeriod };
		var atr = new AverageTrueRange { Length = AtrPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(fast, slow, atr, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow, decimal atr)
	{
		if (candle.State != CandleStates.Finished) return;

		if (_candlesSinceTrade < SignalCooldownCandles)
			_candlesSinceTrade++;

		if (_hasPrev)
		{
			var close = candle.ClosePrice;
			var longSignal = _prevFast <= _prevSlow && fast > slow && close > slow + atr * 0.25m;
			var shortSignal = _prevFast >= _prevSlow && fast < slow && close < slow - atr * 0.25m;

			if (_candlesSinceTrade >= SignalCooldownCandles)
			{
				if (longSignal && Position <= 0)
				{
					BuyMarket();
					_candlesSinceTrade = 0;
				}
				else if (shortSignal && Position >= 0)
				{
					SellMarket();
					_candlesSinceTrade = 0;
				}
			}
		}

		_prevFast = fast;
		_prevSlow = slow;
		_hasPrev = true;
	}
}