Ver no GitHub

Estratégia de nuvem da Mc Value

Esta pasta contém a porta StockSharp do consultor especialista MetaTrader "Mc_valute". O robô original combinou um curto média móvel exponencial (EMA) com três médias móveis suavizadas, um filtro de nuvem Ichimoku e múltiplas instâncias MACD enquanto escalando a tendência. A implementação StockSharp mantém a pilha principal de confirmação de tendências, mas simplifica o gerenciamento de posição a uma única exposição em cada direção para que a lógica se encaixe naturalmente no API de alto nível.

Lógica de negociação

  1. Filtro de preço EMA – o FilterMaLength EMA deve ficar acima (para posições compradas) ou abaixo (para posições vendidas) dos dois movimentos suavizados médias (BlueMaLength e LimeMaLength). As médias suavizadas emulam as linhas “azul” e “limão” do modelo MT4.
  2. Ichimoku confirmação da nuvem – o EMA também precisa estar fora da nuvem. Negociações longas requerem o filtro EMA acima de ambos Senkou se estende enquanto as negociações curtas exigem que ele permaneça abaixo do fundo da nuvem.
  3. MACD verificação de impulso – a linha MACD principal deve estar acima de sua linha de sinal para entradas longas e abaixo dela para entradas curtas. Apenas o primeiro MACD conjunto do EA original é mantido porque as cópias restantes foram desativadas na versão final do MQL.
  4. Gerenciamento de posição única – sempre que um novo sinal aparece, a estratégia compensa qualquer posição oposta existente e abre uma nova negociação com o Volume configurado. As ordens de proteção são atualizadas imediatamente após o envio da ordem de mercado.
  5. Avaliação vela por vela – todos os indicadores operam no prazo definido por CandleType. As decisões de negociação são tomadas apenas em velas finalizadas para espelhar o manipulador MT4 start() que processou barras fechadas.

Gestão de risco

  • TakeProfit e StopLoss são medidos em faixas de preço. Após cada entrada, o ajudante SetTakeProfit e SetStopLoss funções são chamadas usando o tamanho de posição resultante esperado, que reflete o comportamento do MT4 onde as paradas foram aplicadas por bilhete.
  • O consultor especialista original fez uma pirâmide de até três pedidos adicionais usando a distância Step. A porta StockSharp mantém um posição única para permanecer entre os ajudantes de pedidos de alto nível. Os usuários que precisam de escalonamento podem aumentar Volume ou clonar o estratégia em vários portfólios.

Parâmetros

Parâmetro Descrição
Volume Tamanho base da negociação usado pelas chamadas BuyMarket/SellMarket de alto nível.
CandleType Série primária de velas que orienta os indicadores e a lógica comercial.
FilterMaLength Comprimento do filtro de tendência EMA.
BlueMaLength, LimeMaLength Comprimentos das duas médias móveis suavizadas atuando como banda direcional.
MacdFastLength, MacdSlowLength, MacdSignalLength EMA comprimentos para a confirmação MACD.
TenkanLength, KijunLength, SenkouLength Ichimoku Configurações Kinko Hyo para o filtro de nuvem.
TakeProfit, StopLoss Distâncias de proteção expressas em faixas de preço.

Notas de uso

  1. Mudanças de indicador – MetaTrader permitiu parâmetros de "mudança" diferentes de zero ao construir as médias móveis suavizadas. StockSharp os indicadores funcionam na barra atual, portanto a porta ignora essas mudanças enquanto mantém os períodos originais.
  2. MACD variantes – o código-fonte declarou três blocos MACD, mas apenas o primeiro participou de sinais ao vivo. O porto segue esse comportamento; filtros MACD adicionais podem ser reativados duplicando as ligações do indicador.
  3. Negociações de escalonamento – o robô MT4 enviou até três pedidos médios separados por Step pontos. Este comportamento está documentado mas omitido intencionalmente porque as estratégias de alto nível operam com uma única posição agregada.
  4. Bloco de proteçãoStartProtection() é invocado uma vez durante a inicialização para que a infraestrutura integrada supervisione a parada e direcionar pedidos mesmo após reconexões.

Arquivos

  • CS/McValuteCloudStrategy.cs – Implementação C# usando a estratégia de alto nível API com vinculações de indicadores e detalhes comentários.
  • README.md – Documentação em inglês (este arquivo).
  • README_zh.md – Tradução simplificada para chinês.
  • README_ru.md – Tradução russa.
using System;
using System.Linq;
using System.Collections.Generic;

using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Trend-following strategy inspired by the "Mc_valute" MetaTrader expert advisor.
/// Combines smoothed moving averages, an Ichimoku cloud filter and a MACD confirmation.
/// </summary>
public class McValuteCloudStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _filterMaLength;
	private readonly StrategyParam<int> _blueMaLength;
	private readonly StrategyParam<int> _limeMaLength;
	private readonly StrategyParam<int> _macdFastLength;
	private readonly StrategyParam<int> _macdSlowLength;
	private readonly StrategyParam<int> _macdSignalLength;
	private readonly StrategyParam<int> _tenkanLength;
	private readonly StrategyParam<int> _kijunLength;
	private readonly StrategyParam<int> _senkouLength;
	private readonly StrategyParam<int> _takeProfit;
	private readonly StrategyParam<int> _stopLoss;

	private ExponentialMovingAverage _filterMa;
	private SmoothedMovingAverage _blueMa;
	private SmoothedMovingAverage _limeMa;
	private MovingAverageConvergenceDivergenceSignal _macd;
	private Ichimoku _ichimoku;

	private decimal? _filterValue;
	private decimal? _blueValue;
	private decimal? _limeValue;
	private decimal? _senkouAValue;
	private decimal? _senkouBValue;
	private decimal? _macdMainValue;
	private decimal? _macdSignalValue;

	private DateTimeOffset _lastProcessedTime;

	/// <summary>
	/// Initializes a new instance of the <see cref="McValuteCloudStrategy"/> class.
	/// </summary>
	public McValuteCloudStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
		.SetDisplay("Candle Type", "Primary timeframe used for signals", "General");

		_filterMaLength = Param(nameof(FilterMaLength), 3)
		.SetDisplay("Filter EMA", "Length of the trend filter EMA", "Trend")
		
		.SetOptimize(2, 20, 1);

		_blueMaLength = Param(nameof(BlueMaLength), 13)
		.SetDisplay("Blue SMMA", "Length of the slower smoothed MA", "Trend")
		
		.SetOptimize(5, 60, 1);

		_limeMaLength = Param(nameof(LimeMaLength), 5)
		.SetDisplay("Lime SMMA", "Length of the faster smoothed MA", "Trend")
		
		.SetOptimize(3, 40, 1);

		_macdFastLength = Param(nameof(MacdFastLength), 12)
		.SetDisplay("MACD Fast", "Short EMA length for the MACD", "Momentum")
		
		.SetOptimize(5, 30, 1);

		_macdSlowLength = Param(nameof(MacdSlowLength), 26)
		.SetDisplay("MACD Slow", "Long EMA length for the MACD", "Momentum")
		
		.SetOptimize(10, 80, 1);

		_macdSignalLength = Param(nameof(MacdSignalLength), 9)
		.SetDisplay("MACD Signal", "Signal EMA length for the MACD", "Momentum")
		
		.SetOptimize(3, 30, 1);

		_tenkanLength = Param(nameof(TenkanLength), 12)
		.SetDisplay("Tenkan", "Tenkan-sen length for the Ichimoku cloud", "Ichimoku")
		
		.SetOptimize(5, 30, 1);

		_kijunLength = Param(nameof(KijunLength), 20)
		.SetDisplay("Kijun", "Kijun-sen length for the Ichimoku cloud", "Ichimoku")
		
		.SetOptimize(10, 60, 1);

		_senkouLength = Param(nameof(SenkouLength), 40)
		.SetDisplay("Senkou Span B", "Span B length for the Ichimoku cloud", "Ichimoku")
		
		.SetOptimize(20, 120, 1);

		_takeProfit = Param(nameof(TakeProfit), 30)
		.SetDisplay("Take Profit", "Take profit distance in points", "Risk")
		
		.SetOptimize(10, 200, 5);

		_stopLoss = Param(nameof(StopLoss), 350)
		.SetDisplay("Stop Loss", "Stop loss distance in points", "Risk")
		
		.SetOptimize(50, 600, 10);

		_lastProcessedTime = DateTimeOffset.MinValue;
	}

	/// <summary>
	/// Timeframe used for the working candles.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	/// <summary>
	/// Length of the EMA filter.
	/// </summary>
	public int FilterMaLength
	{
		get => _filterMaLength.Value;
		set => _filterMaLength.Value = value;
	}

	/// <summary>
	/// Length of the slower smoothed moving average.
	/// </summary>
	public int BlueMaLength
	{
		get => _blueMaLength.Value;
		set => _blueMaLength.Value = value;
	}

	/// <summary>
	/// Length of the faster smoothed moving average.
	/// </summary>
	public int LimeMaLength
	{
		get => _limeMaLength.Value;
		set => _limeMaLength.Value = value;
	}

	/// <summary>
	/// Fast EMA length used by the MACD.
	/// </summary>
	public int MacdFastLength
	{
		get => _macdFastLength.Value;
		set => _macdFastLength.Value = value;
	}

	/// <summary>
	/// Slow EMA length used by the MACD.
	/// </summary>
	public int MacdSlowLength
	{
		get => _macdSlowLength.Value;
		set => _macdSlowLength.Value = value;
	}

	/// <summary>
	/// Signal EMA length used by the MACD.
	/// </summary>
	public int MacdSignalLength
	{
		get => _macdSignalLength.Value;
		set => _macdSignalLength.Value = value;
	}

	/// <summary>
	/// Tenkan-sen length for the Ichimoku indicator.
	/// </summary>
	public int TenkanLength
	{
		get => _tenkanLength.Value;
		set => _tenkanLength.Value = value;
	}

	/// <summary>
	/// Kijun-sen length for the Ichimoku indicator.
	/// </summary>
	public int KijunLength
	{
		get => _kijunLength.Value;
		set => _kijunLength.Value = value;
	}

	/// <summary>
	/// Senkou Span B length for the Ichimoku indicator.
	/// </summary>
	public int SenkouLength
	{
		get => _senkouLength.Value;
		set => _senkouLength.Value = value;
	}

	/// <summary>
	/// Take profit distance in points.
	/// </summary>
	public int TakeProfit
	{
		get => _takeProfit.Value;
		set => _takeProfit.Value = value;
	}

	/// <summary>
	/// Stop loss distance in points.
	/// </summary>
	public int StopLoss
	{
		get => _stopLoss.Value;
		set => _stopLoss.Value = value;
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_filterMa = null;
		_blueMa = null;
		_limeMa = null;
		_macd = null;
		_ichimoku = null;
		_filterValue = null;
		_blueValue = null;
		_limeValue = null;
		_senkouAValue = null;
		_senkouBValue = null;
		_macdMainValue = null;
		_macdSignalValue = null;
		_lastProcessedTime = DateTimeOffset.MinValue;
	}

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

		_filterMa = new ExponentialMovingAverage { Length = FilterMaLength };
		_blueMa = new SmoothedMovingAverage { Length = BlueMaLength };
		_limeMa = new SmoothedMovingAverage { Length = LimeMaLength };

		_macd = new MovingAverageConvergenceDivergenceSignal
		{
			Macd =
			{
				ShortMa = { Length = MacdFastLength },
				LongMa = { Length = MacdSlowLength },
			},
			SignalMa = { Length = MacdSignalLength }
		};

		_ichimoku = new Ichimoku
		{
			Tenkan = { Length = TenkanLength },
			Kijun = { Length = KijunLength },
			SenkouB = { Length = SenkouLength }
		};

		var subscription = SubscribeCandles(CandleType);
		subscription
		.Bind(_filterMa, _blueMa, _limeMa, ProcessMovingAverages)
		.BindEx(_macd, ProcessMacd)
		.BindEx(_ichimoku, ProcessIchimoku)
		.Start();

		StartProtection(null, null);

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, _filterMa);
			DrawIndicator(area, _blueMa);
			DrawIndicator(area, _limeMa);
			DrawIndicator(area, _macd);
			DrawOwnTrades(area);
		}
	}

	private void ProcessMovingAverages(ICandleMessage candle, decimal filter, decimal blue, decimal lime)
	{
		if (candle.State != CandleStates.Finished)
		return;

		_filterValue = filter;
		_blueValue = blue;
		_limeValue = lime;

		TryTrade(candle);
	}

	private void ProcessMacd(ICandleMessage candle, IIndicatorValue macdValue)
	{
		if (candle.State != CandleStates.Finished)
		return;

		var typed = (MovingAverageConvergenceDivergenceSignalValue)macdValue;
		if (typed.Macd is not decimal macd || typed.Signal is not decimal signal)
		return;

		_macdMainValue = macd;
		_macdSignalValue = signal;

		TryTrade(candle);
	}

	private void ProcessIchimoku(ICandleMessage candle, IIndicatorValue value)
	{
		if (candle.State != CandleStates.Finished)
		return;

		var ichimokuValue = (IchimokuValue)value;
		if (ichimokuValue.SenkouA is not decimal spanA || ichimokuValue.SenkouB is not decimal spanB)
		return;

		_senkouAValue = spanA;
		_senkouBValue = spanB;

		TryTrade(candle);
	}

	private void TryTrade(ICandleMessage candle)
	{
		// indicators formed check removed

		if (candle.State != CandleStates.Finished)
		return;

		if (_lastProcessedTime == candle.OpenTime)
		return;

		if (_filterValue is not decimal filter ||
		_blueValue is not decimal blue ||
		_limeValue is not decimal lime ||
		_senkouAValue is not decimal spanA ||
		_senkouBValue is not decimal spanB ||
		_macdMainValue is not decimal macd ||
		_macdSignalValue is not decimal signal)
		{
			return;
		}

		_lastProcessedTime = candle.OpenTime;

		var cloudTop = Math.Max(spanA, spanB);
		var cloudBottom = Math.Min(spanA, spanB);
		var maUpper = Math.Max(blue, lime);
		var maLower = Math.Min(blue, lime);

		var allowLong = filter > maUpper && filter > cloudTop && macd > signal;
		var allowShort = filter < maLower && filter < cloudBottom && macd < signal;

		var closePrice = candle.ClosePrice;

		if (allowLong && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		else if (allowShort && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}
	}
}