Ver no GitHub

Estratégia Simple 2 MA I

Visão geral

Simple 2 MA I é uma estratégia de seguimento de tendência que replica a lógica central do expert advisor original do MetaTrader. Ela usa um par de médias móveis ponderadas lineares (LWMAs) calculadas sobre preços típicos para identificar a tendência dominante. Confirmação de momentum e filtros de direção MACD removem sinais fracos. A estratégia opcionalmente gerencia risco por meio de stop-loss automático, take-profit, movimentos para break-even e trailing stops baseados em candles.

Lógica de negociação

Configuração comprada

  1. A LWMA rápida está acima da LWMA lenta, confirmando uma tendência de alta.
  2. A mínima do candle de duas barras atrás está abaixo da máxima da barra anterior, sinalizando estrutura altista recente.
  3. Pelo menos uma das três últimas leituras de taxa de variação está acima do limite de momentum configurado.
  4. A linha MACD está acima da linha de sinal.
  5. O volume líquido da posição é menor que o limite Max Net Volume.

Quando todas as condições são atendidas, a estratégia fecha exposição vendida (se houver) e compra a mercado.

Configuração vendida

  1. A LWMA rápida está abaixo da LWMA lenta, confirmando uma tendência de baixa.
  2. A mínima da barra anterior está abaixo da máxima da barra de dois períodos atrás, indicando estrutura baixista.
  3. Pelo menos uma das três últimas leituras de taxa de variação está acima do limite de momentum (valor absoluto).
  4. A linha MACD está abaixo da linha de sinal.
  5. O volume líquido da posição é menor que Max Net Volume.

Quando as condições se mantêm, a estratégia cobre compradas (se houver) e vende a mercado.

Gestão de risco

  • Stop-loss / take-profit: distâncias fixas opcionais definidas em pontos relativos ao preço de entrada.
  • Break-even: quando o preço atinge a distância de gatilho em lucro, o stop é movido para entrada ± offset.
  • Trailing por candle: depois que a distância de ativação é alcançada, o stop segue extremos de candles com um buffer configurável.
  • Ordens de proteção são canceladas automaticamente quando a posição é fechada.

Parâmetros

Nome Descrição Padrão
Candle Type Período usado para cálculos dos indicadores. Candles de 15 minutos
Fast LWMA Período da LWMA rápida. 6
Slow LWMA Período da LWMA lenta. 85
Momentum Length Período de retrospectiva do indicador de taxa de variação. 14
Momentum Threshold Valor absoluto mínimo de taxa de variação exigido. 0.3
MACD Fast Comprimento da EMA rápida usada no MACD. 12
MACD Slow Comprimento da EMA lenta usada no MACD. 26
MACD Signal Comprimento da EMA de sinal usada no MACD. 9
Use Stop-Loss Habilita a colocação de ordens stop-loss. true
Stop-Loss (points) Distância do preço de entrada até o stop-loss. 20
Use Take-Profit Habilita a colocação de ordens take-profit. true
Take-Profit (points) Distância do preço de entrada até o take-profit. 50
Use Break-Even Habilita o movimento automático para break-even. true
Break-Even Trigger Lucro (pontos) necessário antes do break-even. 30
Break-Even Offset Offset (pontos) adicionado ao mover para break-even. 30
Use Candle Trailing Habilita trailing stops baseados em extremos de candles. true
Trailing Activation Lucro (pontos) exigido antes da ativação do trailing. 40
Trailing Padding Distância extra (pontos) adicionada ao extremo do candle. 10
Max Net Volume Volume líquido absoluto máximo permitido. 1

Observações

  • Todas as distâncias de preço são expressas em passos de preço do ativo (pontos). A estratégia multiplica automaticamente valores de parâmetros pelo tamanho do tick do ativo.
  • O mapeamento padrão de períodos segue os padrões do expert original, mas pode ser ajustado livremente.
  • A estratégia espera candles concluídos. Barras não finalizadas são ignoradas para permanecer consistente com o EA de origem.
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;

public class Simple2MaIStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _stopLossPoints;
	private readonly StrategyParam<int> _takeProfitPoints;

	private ExponentialMovingAverage _fast;
	private ExponentialMovingAverage _slow;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;
	private int _cooldown;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
	public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }

	public Simple2MaIStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 14).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
		_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
		_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
		_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
	}

	protected override void OnReseted()
	{
		base.OnReseted();
		_fast = null; _slow = null;
		_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_fast = new ExponentialMovingAverage { Length = FastPeriod };
		_slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
		subscription.Bind(_fast, _slow, ProcessCandle);
		subscription.Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
		if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }

		var close = candle.ClosePrice;
		var step = Security?.PriceStep ?? 1m;

		if (Position > 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}
		else if (Position < 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}

		if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
		{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
		else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
		{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }

		_prevFast = fastValue; _prevSlow = slowValue;
	}
}