A estratégia transporta o consultor especialista "MACD Four Colors 2 Martingale" de MetaTrader para StockSharp. Ele mantém a lógica original construída em torno da interpretação de "cor" MACD e de um modelo de dimensionamento de posição martingale.
Visão geral
O indicador subjacente pinta o histograma MACD com cinco cores. No "novo" esquema de cores padrão, o histograma muda de cor dependendo se a linha MACD sobe ou desce acima/abaixo da linha zero. O Expert Advisor abre uma posição sempre que as cores transitam de prata para amarelo (negativo MACD diminuindo novamente) ou de vermelho para azul (positivo MACD rolando). A versão StockSharp reproduz esta sequência reconstruindo as cores a partir de valores MACD.
Apenas uma cesta direcional de negociações está ativa a qualquer momento. Uma nova negociação só é permitida se o seu preço melhorar a entrada média da cesta atual (preço mais baixo para posições compradas, preço mais alto para posições vendidas). Cada nova entrada multiplica o último volume preenchido por um coeficiente de lote configurável, implementando a média martingale do EA original.
Regras de negociação
Lógica do indicador: um indicador MovingAverageConvergenceDivergenceSignal com a configuração clássica 26/12/9 gera valores MACD.
Reconstrução de cores: a estratégia compara os dois valores MACD mais recentes. O negativo crescente MACD mapeia para a cor 1 (prata), o positivo crescente para a cor 2 (vermelho), o positivo decrescente para a cor 3 (azul) e o negativo descendente para a cor 4 (amarelo).
Entrada longa: acionada quando as cores reconstruídas se movem de 1 para 4 enquanto o MACD na barra anterior permanece abaixo de zero. A negociação é executada apenas se não houver exposição curta e o novo preço for inferior a qualquer entrada longa existente.
Entrada curta: acionada quando as cores passam de 2 para 3 enquanto o MACD na barra anterior permanece acima de zero. A negociação só dispara se não houver exposição longa e o novo preço for superior a qualquer entrada curta existente.
Gerenciamento de volume: o primeiro pedido usa InitialVolume. Cada pedido subsequente dentro da mesma cesta multiplica o último volume executado por LotCoefficient. Definir o coeficiente ≤ 0 desativa o multiplicador.
Controle de lucros e perdas: O PnL flutuante é avaliado em cada vela finalizada. Acertar TargetProfit fecha todas as posições e reinicia o ciclo martingale. A violação de MaxDrawdown (interpretada como um limite de perda) também fecha tudo e reinicia o ciclo. Limites negativos são suportados como no código original.
Saída de posição: Além das metas monetárias, não há paradas automáticas. As posições permanecem abertas até que um limite de risco seja atingido ou o usuário intervenha manualmente.
Parâmetros
CandleType(DataType, padrão 1h) – período para o cálculo de MACD.
InitialVolume(decimal, padrão 1) – volume do primeiro pedido em uma cesta.
LotCoefficient(decimal, padrão 2) – multiplicador aplicado ao volume anterior quando o martingale está ativo.
MaxDrawdown(decimal, padrão 50) – limite de perda flutuante (em dinheiro) que força a liquidação. Valores positivos observam -MaxDrawdown, valores negativos usam o valor exato.
TargetProfit(decimal, padrão 150) – meta de lucro flutuante (em dinheiro) que fecha a cesta. Valores negativos invertem a comparação como na versão MQL.
FastEmaPeriod(int, padrão 12) – comprimento do EMA rápido para MACD.
SlowEmaPeriod(int, padrão 26) – duração da lentidão EMA para MACD.
SignalPeriod(int, padrão 9) – comprimento do sinal EMA para suavização MACD.
Notas de uso
Funciona em qualquer instrumento que defina PriceStep e StepPrice, porque o PnL não realizado é calculado a partir das especificações da exchange.
O dimensionamento do martingale pode aumentar a posição rapidamente. Valide os limites de risco antes de permitir a negociação em uma conta real.
Para análise visual anexe a área do gráfico criada pela estratégia. Ele traça velas, o indicador MACD e as negociações executadas.
Filtros de catálogo
Categoria: Média de Tendência/Momentum
Direção: Ambas (cestas longas e curtas)
Indicadores: MACD
Paradas: somente saída baseada em dinheiro
Prazo: Configurável (padrão 1h)
Complexidade: Intermediário
Risco: Alto devido à escala de martingale
Automação: Totalmente automatizado depois de iniciado
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// MACD histogram crossover with martingale volume scaling.
/// Based on the MACD Four Colors 2 Martingale expert advisor.
/// </summary>
public class MacdFourColors2MartingaleStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastEmaPeriod;
private readonly StrategyParam<int> _slowEmaPeriod;
private readonly StrategyParam<int> _signalPeriod;
private readonly StrategyParam<decimal> _lotCoefficient;
private readonly StrategyParam<int> _maxMartingale;
private MovingAverageConvergenceDivergence _macd;
private readonly System.Collections.Generic.Queue<decimal> _macdHistory = new();
private decimal? _prevHistogram;
private decimal _currentVolume;
private int _consecutiveLosses;
private decimal _entryPrice;
/// <summary>
/// Type of candles used for MACD analysis.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Period of the fast EMA inside MACD.
/// </summary>
public int FastEmaPeriod
{
get => _fastEmaPeriod.Value;
set => _fastEmaPeriod.Value = value;
}
/// <summary>
/// Period of the slow EMA inside MACD.
/// </summary>
public int SlowEmaPeriod
{
get => _slowEmaPeriod.Value;
set => _slowEmaPeriod.Value = value;
}
/// <summary>
/// Period of the signal line.
/// </summary>
public int SignalPeriod
{
get => _signalPeriod.Value;
set => _signalPeriod.Value = value;
}
/// <summary>
/// Multiplier applied after a losing trade.
/// </summary>
public decimal LotCoefficient
{
get => _lotCoefficient.Value;
set => _lotCoefficient.Value = value;
}
/// <summary>
/// Maximum number of martingale steps before resetting.
/// </summary>
public int MaxMartingale
{
get => _maxMartingale.Value;
set => _maxMartingale.Value = value;
}
/// <summary>
/// Initialize strategy parameters.
/// </summary>
public MacdFourColors2MartingaleStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Type of candles for MACD analysis", "General");
_fastEmaPeriod = Param(nameof(FastEmaPeriod), 20)
.SetDisplay("Fast EMA", "Fast EMA period for MACD", "Indicators")
.SetGreaterThanZero();
_slowEmaPeriod = Param(nameof(SlowEmaPeriod), 50)
.SetDisplay("Slow EMA", "Slow EMA period for MACD", "Indicators")
.SetGreaterThanZero();
_signalPeriod = Param(nameof(SignalPeriod), 12)
.SetDisplay("Signal Period", "Signal line smoothing period", "Indicators")
.SetGreaterThanZero();
_lotCoefficient = Param(nameof(LotCoefficient), 1.5m)
.SetDisplay("Lot Coefficient", "Multiplier after a loss", "Money Management")
.SetGreaterThanZero();
_maxMartingale = Param(nameof(MaxMartingale), 5)
.SetDisplay("Max Martingale", "Maximum consecutive doublings", "Money Management")
.SetGreaterThanZero();
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevHistogram = null;
_currentVolume = Volume > 0 ? Volume : 1;
_consecutiveLosses = 0;
_entryPrice = 0;
_macdHistory.Clear();
_macd = new MovingAverageConvergenceDivergence
{
ShortMa = { Length = FastEmaPeriod },
LongMa = { Length = SlowEmaPeriod }
};
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_macd, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal macdValue)
{
if (candle.State != CandleStates.Finished)
return;
_macdHistory.Enqueue(macdValue);
while (_macdHistory.Count > SignalPeriod)
_macdHistory.Dequeue();
if (!_macd.IsFormed || _macdHistory.Count < SignalPeriod)
{
_prevHistogram = null;
return;
}
// Calculate signal line (SMA of MACD)
var sum = 0m;
var history = _macdHistory.ToArray();
foreach (var v in history)
sum += v;
var signalValue = sum / history.Length;
var histogram = macdValue - signalValue;
if (_prevHistogram is null)
{
_prevHistogram = histogram;
return;
}
var crossUp = _prevHistogram < 0 && histogram >= 0;
var crossDown = _prevHistogram >= 0 && histogram < 0;
if (crossUp)
{
// Check for loss on closing short
if (Position < 0)
{
var pnl = _entryPrice - candle.ClosePrice;
if (pnl < 0)
{
_consecutiveLosses++;
if (_consecutiveLosses <= MaxMartingale)
_currentVolume *= LotCoefficient;
}
else
{
_consecutiveLosses = 0;
_currentVolume = Volume > 0 ? Volume : 1;
}
BuyMarket(Math.Abs(Position) + _currentVolume);
_entryPrice = candle.ClosePrice;
}
else if (Position == 0)
{
BuyMarket(_currentVolume);
_entryPrice = candle.ClosePrice;
}
}
else if (crossDown)
{
// Check for loss on closing long
if (Position > 0)
{
var pnl = candle.ClosePrice - _entryPrice;
if (pnl < 0)
{
_consecutiveLosses++;
if (_consecutiveLosses <= MaxMartingale)
_currentVolume *= LotCoefficient;
}
else
{
_consecutiveLosses = 0;
_currentVolume = Volume > 0 ? Volume : 1;
}
SellMarket(Math.Abs(Position) + _currentVolume);
_entryPrice = candle.ClosePrice;
}
else if (Position == 0)
{
SellMarket(_currentVolume);
_entryPrice = candle.ClosePrice;
}
}
_prevHistogram = histogram;
}
/// <inheritdoc />
protected override void OnReseted()
{
_macd = null;
_prevHistogram = null;
_currentVolume = 0;
_consecutiveLosses = 0;
_entryPrice = 0;
_macdHistory.Clear();
base.OnReseted();
}
}