Esta estratégia recria o comportamento do consultor especialista MetaTrader "OsMA Four Colors Arrow" dentro da estrutura StockSharp. O EA original reage às setas coloridas produzidas pelo indicador que o acompanha sempre que o OsMA (MACD histograma) muda de fase. Na versão StockSharp, o mesmo comportamento é modelado monitorando cruzamentos zero do histograma MACD: uma linha de alta (o histograma se move de negativo para positivo) aciona entradas longas, enquanto uma linha de baixa aciona entradas curtas. O modo reverso opcional vira a lógica de cabeça para baixo para testes de hedge ou de reversão à média.
O modelo funciona apenas com velas finalizadas e pode impor uma sessão de negociação diária semelhante ao filtro de tempo oferecido pela versão MQL. O gerenciamento de dinheiro integrado inclui volume de negociação configurável, um limite para o número de posições agregadas e proteção automatizada de stop-loss/take-profit/trailing expressa em pips.
Lógica de negociação
Assine o período de tempo selecionado e calcule um histograma MACD (OsMA) usando comprimentos configuráveis de sinal rápido, lento e EMA.
Quando uma vela fecha, verifique o sinal do histograma:
Histograma cruzando acima de zero → seta de alta → sinal de compra.
Histograma cruzando abaixo de zero → seta de baixa → sinal de venda.
Aplique recursos opcionais antes de enviar um pedido:
Filtro de direção (somente longo, somente curto ou ambos).
Modo reverso para inverter sinais.
Feche a exposição oposta existente antes de abrir a nova negociação.
Limite a uma posição ativa ou acumule até a exposição máxima configurada.
As ordens de mercado são enviadas com o tamanho de lote configurado. StartProtection converte entradas de pip em compensações de preços absolutos para executar o gerenciamento de stop-loss, take-profit e trailing automaticamente.
As negociações são ignoradas fora da sessão intradiária permitida quando o filtro de tempo está habilitado.
Parâmetros
Nome
Descrição
CandleType
Prazo usado para cálculos e geração de sinal.
FastPeriod / SlowPeriod / SignalPeriod
EMA comprimentos para o histograma MACD (OsMA).
StopLossPips / TakeProfitPips
Metas de risco em pips. Defina como zero para desativar.
TrailingActivatePips
Lucro (em pips) necessário antes que o trailing stop possa se mover.
TrailingStopPips
Distância final em pips. Zero desativa o módulo final.
TrailingStepPips
Pips extras que devem ser ganhos antes de apertar o trailing stop novamente.
MaxPositions
Unidades máximas de posição agregada (TradeVolume múltiplos). Zero significa ilimitado.
ReverseSignals
Inverta a direção de entrada (compra ↔ venda).
DirectionMode
Restrinja os sinais para somente longos, somente curtos ou ambos.
CloseOppositePositions
Feche qualquer exposição oposta antes de agir no novo sinal.
OnlyOnePosition
Se true, impede a adição a uma posição já aberta na mesma direção.
UseTimeControl
Habilite o filtro da sessão de negociação intradiária.
StartHour, StartMinute, EndHour, EndMinute
Limites da sessão (o final pode ser anterior ao início para cobrir sessões noturnas).
TradeVolume
Volume do pedido em lotes.
Notas
As entradas de parada móvel imitam o EA: o rastreamento fica disponível somente após TrailingActivatePips e se move em etapas definidas por TrailingStepPips.
A estratégia exige que o título tenha PriceStep e Decimals válidos para converter pips em compensações de preço. Os padrões voltam para uma unidade de preço absoluto se o instrumento não os fornecer.
Se MaxPositions for maior que um, a estratégia pode ser gradualmente ampliada adicionando repetidamente TradeVolume respeitando o limite máximo de exposição.
Quando UseTimeControl está ativado e os horários de início e término coincidem, a negociação é desativada para evitar sessões ambíguas.
A lógica atua apenas em velas fechadas; não há envio de pedido intra-barra, correspondendo ao comportamento do modelo MQL.
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>
/// Simplified from "OsMA Four Colors Arrow" MetaTrader expert.
/// Uses MACD histogram (OsMA) zero-crossing as entry signal.
/// Buys when histogram crosses above zero, sells when it crosses below.
/// </summary>
public class OsMaFourColorsArrowStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _signalPeriod;
private MovingAverageConvergenceDivergence _macd;
private readonly Queue<decimal> _macdHistory = new();
private decimal? _prevHistogram;
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 SignalPeriod
{
get => _signalPeriod.Value;
set => _signalPeriod.Value = value;
}
public OsMaFourColorsArrowStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Timeframe used for signal generation", "General");
_fastPeriod = Param(nameof(FastPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("Fast EMA", "Fast EMA length for MACD", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 50)
.SetGreaterThanZero()
.SetDisplay("Slow EMA", "Slow EMA length for MACD", "Indicators");
_signalPeriod = Param(nameof(SignalPeriod), 12)
.SetGreaterThanZero()
.SetDisplay("Signal Period", "Signal line smoothing period", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevHistogram = null;
_macdHistory.Clear();
_macd = new MovingAverageConvergenceDivergence
{
ShortMa = { Length = FastPeriod },
LongMa = { Length = SlowPeriod },
};
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_macd, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _macd);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal macdValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!_macd.IsFormed)
return;
// Compute signal line as SMA of MACD values
_macdHistory.Enqueue(macdValue);
if (_macdHistory.Count > SignalPeriod)
_macdHistory.Dequeue();
if (_macdHistory.Count < SignalPeriod)
{
_prevHistogram = null;
return;
}
decimal sum = 0;
var history = _macdHistory.ToArray();
foreach (var v in history)
sum += v;
var signal = sum / history.Length;
// OsMA = MACD - Signal (histogram)
var histogram = macdValue - signal;
if (_prevHistogram is null)
{
_prevHistogram = histogram;
return;
}
var volume = Volume;
if (volume <= 0)
volume = 1;
var crossUp = _prevHistogram.Value <= 0 && histogram > 0;
var crossDown = _prevHistogram.Value >= 0 && histogram < 0;
if (crossUp)
{
if (Position <= 0)
BuyMarket(Position < 0 ? Math.Abs(Position) + volume : volume);
}
else if (crossDown)
{
if (Position >= 0)
SellMarket(Position > 0 ? Math.Abs(Position) + volume : volume);
}
_prevHistogram = histogram;
}
/// <inheritdoc />
protected override void OnReseted()
{
_macd = null;
_prevHistogram = null;
_macdHistory.Clear();
base.OnReseted();
}
}