Ver no GitHub

Pedidos de dias e horários específicos

Esta estratégia replica o MetaTrader especialista "Dia e hora específicos do Expert Advisor". Ele coloca ordens de compra e/ou venda em um carimbo de data/hora programado e, opcionalmente, remove todas as exposições em outro carimbo de data/hora. A versão StockSharp mantém o comportamento original de gerenciamento de risco, incluindo trailing stops opcionais e movimentos de equilíbrio.

Lógica central

  1. Agendamento

    • OpenTime – momento em que os pedidos são criados.
    • CloseTime – momento em que as posições são achatadas e as ordens pendentes podem ser removidas. Ambas as verificações aceitam uma janela de um minuto, correspondendo à comparação TimeToString(..., TIME_MINUTES) usada no código MT4.
  2. Colocação de pedido

    • OrderPlacement escolhe entre ordens de mercado, stop ou limite.
    • OpenBuyOrders / OpenSellOrders habilite as rotas desejadas.
    • OrderDistancePoints compensa o preço das ordens pendentes em vários pontos (pips).
    • PendingExpireMinutes cancela pedidos pendentes automaticamente quando o período de validade termina.
  3. Gerenciamento de volumes

    • LotSizing = Manual envia o ManualVolume fixo.
    • LotSizing = Automatic calcula o volume a partir do valor atual do portfólio e do tamanho do contrato do instrumento: volume = (portfolio / contractSize) * RiskFactor. O resultado é alinhado a Security.VolumeStep e fixado entre MinVolume/MaxVolume quando disponível.
  4. Lógica de proteção

    • StopLossPoints e TakeProfitPoints traduzem as distâncias originais baseadas em pontos em preços absolutos usando o tamanho do pip do instrumento.
    • TrailingStopEnabled + TrailingStepPoints e BreakEvenEnabled movem o stop de proteção exatamente como o script MQL, usando atualizações de oferta/venda como acionadores.
    • Quando as condições de stop-loss ou take-profit são atingidas, a posição é fechada com uma ordem de mercado, refletindo o comportamento do MT4 de modificar os stops para um novo preço.
  5. Fase de encerramento

    • Quando CloseOwnOrders ou CloseAllOrders está ativado, a estratégia sai de qualquer posição aberta na janela de fechamento.
    • DeletePendingOrders remove todos os pedidos pendentes restantes ao mesmo tempo.

Parâmetros

Nome Descrição
OpenTime, CloseTime Carimbos de data e hora UTC para entrada e saída do mercado.
OrderPlacement Comercialize, pare ou limite a colocação de pedidos.
OpenBuyOrders, OpenSellOrders Instruções para ativar.
TakeProfitPoints, StopLossPoints Distâncias de proteção expressas em pontos (0 desabilita).
TrailingStopEnabled, TrailingStepPoints Habilite o trailing stop e defina o avanço mínimo antes de movê-lo.
BreakEvenEnabled, BreakEvenAfterPoints Mude o stop para o ponto de equilíbrio quando o lucro exceder o limite.
OrderDistancePoints Offset usado para pedidos pendentes.
PendingExpireMinutes Janela de expiração para pedidos pendentes.
LotSizing Dimensionamento de volume manual ou automático.
RiskFactor, ManualVolume Entradas para os modos de dimensionamento.
CloseOwnOrders, CloseAllOrders, DeletePendingOrders Controle como as posições e ordens pendentes são fechadas no final.

Notas

  • A classe reside no namespace StockSharp.Samples.Strategies com recuo de tabulação conforme exigido pelas diretrizes do projeto.
  • Os dados de nível 1 são usados para reproduzir a lógica sensível à oferta/venda da versão MQL (trailing stop, colocação de ordem pendente).
  • As configurações de MagicNumber do MT4 não são necessárias porque StockSharp já isola ordens de estratégia.

Uso

  1. Compile o projeto via AlgoTrading.sln e anexe a estratégia a um par segurança/portfólio.
  2. Ajuste o cronograma, o tipo de pedido e os parâmetros de risco conforme necessário.
  3. Inicie a estratégia antes de OpenTime; os pedidos serão enviados automaticamente assim que a janela começar.
  4. Mantenha a estratégia em execução até depois de CloseTime se desejar que a etapa de nivelamento automático seja acionada.
namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// Specific Day Time strategy: SMA crossover with time filter.
/// Trades only during specific hours, using fast/slow SMA crossover.
/// </summary>
public class SpecificDayTimeStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _tradeHour;
	private readonly StrategyParam<int> _cooldownBars;

	private int _cooldown;

	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 TradeHour { get => _tradeHour.Value; set => _tradeHour.Value = value; }
	public int CooldownBars { get => _cooldownBars.Value; set => _cooldownBars.Value = value; }

	public SpecificDayTimeStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_fastPeriod = Param(nameof(FastPeriod), 8)
			.SetGreaterThanZero()
			.SetDisplay("Fast SMA", "Fast SMA period", "Indicators");
		_slowPeriod = Param(nameof(SlowPeriod), 21)
			.SetGreaterThanZero()
			.SetDisplay("Slow SMA", "Slow SMA period", "Indicators");
		_tradeHour = Param(nameof(TradeHour), 12)
			.SetDisplay("Trade Hour", "Hour when entries are allowed", "Trading")
			.SetRange(0, 23);
		_cooldownBars = Param(nameof(CooldownBars), 8)
			.SetGreaterThanZero()
			.SetDisplay("Cooldown Bars", "Bars to wait between orders", "Trading");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_cooldown = 0;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_cooldown = 0;
		var fast = new SimpleMovingAverage { Length = FastPeriod };
		var slow = new SimpleMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(fast, slow, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
	{
		if (candle.State != CandleStates.Finished) return;

		if (_cooldown > 0)
			_cooldown--;

		var bullishTrend = fastValue > slowValue;
		var bearishTrend = fastValue < slowValue;

		if (_cooldown == 0 && candle.OpenTime.Hour == TradeHour)
		{
			if (bullishTrend && Position <= 0)
			{
				BuyMarket();
				_cooldown = CooldownBars;
			}
			else if (bearishTrend && Position >= 0)
			{
				SellMarket();
				_cooldown = CooldownBars;
			}
		}
		else if (_cooldown == 0)
		{
			if (Position > 0 && bearishTrend)
			{
				SellMarket();
				_cooldown = CooldownBars;
			}
			else if (Position < 0 && bullishTrend)
			{
				BuyMarket();
				_cooldown = CooldownBars;
			}
		}
	}
}