A Estratégia do Corredor de Retração Matinal replica o comportamento do consultor especialista "3_Otkat_Sys_v1_2" MetaTrader 4. O sistema negocia uma vez por dia durante a sessão da manhã, avaliando a interação entre o preço atual e o corredor de preços formado por velas separadas por 29 barras. Ele reage aos recuos matinais após um forte movimento durante a noite e atribui imediatamente níveis de take-profit assimétricos para posições longas e curtas.
Lógica de negociação
Filtro de sessão – as ordens são consideradas apenas dentro do horário de negociação configurado (padrão 05:00 horário da plataforma) e durante os primeiros minutos dessa hora. Segundas e sextas-feiras são excluídas de acordo com o EA original.
Cálculos do corredor de preços – para cada vela concluída, a estratégia mantém uma janela contínua das barras mais recentes. Ele compara:
o preço de abertura 29 barras atrás com o fechamento da vela anterior (Open[29] - Close[1]),
a vela anterior fecha com o preço de abertura 29 barras atrás (Close[1] - Open[29]),
a distância do próximo anterior ao mínimo mais baixo dentro da faixa de 29 barras,
a distância do máximo mais alto na mesma faixa até o fechamento anterior.
Regras de entrada – se o movimento noturno exceder o limite CorridorOpenClosePoints e o último pullback caber dentro do envelope PullbackPoints ± CorridorPullbackPoints configurado, uma posição de mercado será aberta no início da sessão da manhã:
Entradas longas requerem um movimento forte para baixo com um recuo superficial ou um movimento para cima com uma continuação estendida acima do corredor.
As entradas curtas refletem a lógica das configurações de baixa.
Gerenciamento de posição – cada negociação recebe:
um stop loss em StopLossPoints * PriceStep do preço de entrada,
um take-profit de TakeProfitPoints * PriceStep para posições vendidas e de (TakeProfitPoints + LongTakeProfitExtraPoints) * PriceStep para posições longas.
Saída diária – qualquer posição ainda aberta após o limite de fechamento configurado (padrão após 22h45) é fechada à força para evitar retenção durante a noite.
Parâmetros
Parâmetro
Descrição
TakeProfitPoints
Distância base de take-profit em pontos de instrumento, aplicada a negociações curtas. As negociações longas adicionam LongTakeProfitExtraPoints.
StopLossPoints
Distância de parada protetora nos pontos do instrumento.
PullbackPoints
Tamanho de retrocesso desejado em torno do qual a estratégia avalia as retrações.
CorridorOpenClosePoints
Distância mínima entre preços separados por 29 barras para confirmar impulso noturno.
CorridorPullbackPoints
Tolerância aplicada ao limite de recuo para criar o corredor de entrada.
LongTakeProfitExtraPoints
Pontos adicionais adicionados à meta de longo lucro.
TradeHour
Hora (0–23) durante a qual novas entradas são permitidas.
TradeMinuteLimit
Minuto máximo dentro da hora de negociação para aceitar novos sinais.
CloseHour
Hora em que a estratégia começa a verificar saídas baseadas em tempo.
CloseMinuteThreshold
Minuto dentro de CloseHour após o qual qualquer posição aberta é fechada.
CandleType
Período usado para assinaturas de velas (padrão 1 minuto).
Notas de implementação
A estratégia depende de Security.PriceStep para converter insumos baseados em pontos em distâncias de preços absolutos. Se o instrumento não fornecer uma etapa de preço válida, a lógica volta para 1.0.
Os níveis de stop-loss e take-profit são monitorados em cada vela concluída; a estratégia fecha posições com ordens de mercado quando o nível é ultrapassado dentro dessa faixa de velas.
A janela contínua contém as últimas 60 velas para cobrir os cálculos necessários de 29 barras e para imitar os auxiliares Lowest/Highest usados em MetaTrader.
A visualização do gráfico (velas e negociações próprias) fica disponível automaticamente quando uma área do gráfico é criada na aplicação host.
Dicas de uso
Certifique-se de que o volume da conta de negociação (propriedade Volume) esteja definido antes de iniciar a estratégia; o EA nunca dimensiona o tamanho da posição dinamicamente.
Mantenha o feed de dados alinhado com o fuso horário da sessão esperado pelo consultor especialista original para manter um comportamento idêntico.
Otimize os parâmetros do corredor ao aplicar a estratégia a mercados com diferentes perfis de volatilidade, porque os limites baseados em pontos foram ajustados para o instrumento original.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class MorningPullbackCorridorStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _cooldownCandles;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFast;
private decimal _prevSlow;
private bool _hasPrev;
private int _cooldownRemaining;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int CooldownCandles { get => _cooldownCandles.Value; set => _cooldownCandles.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public MorningPullbackCorridorStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 20).SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 80).SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
_cooldownCandles = Param(nameof(CooldownCandles), 100).SetDisplay("Cooldown", "Candles between signals", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = default;
_prevSlow = default;
_hasPrev = default;
_cooldownRemaining = default;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = 0;
_prevSlow = 0;
_hasPrev = false;
_cooldownRemaining = 0;
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fast, slow, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished) return;
if (!_hasPrev) { _prevFast = fast; _prevSlow = slow; _hasPrev = true; return; }
if (_cooldownRemaining > 0)
{
_cooldownRemaining--;
_prevFast = fast;
_prevSlow = slow;
return;
}
if (_prevFast <= _prevSlow && fast > slow && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
_cooldownRemaining = CooldownCandles;
}
else if (_prevFast >= _prevSlow && fast < slow && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
_cooldownRemaining = CooldownCandles;
}
_prevFast = fast;
_prevSlow = slow;
}
}