A Estratégia HPCS Inter5 é um script de impulso único convertido do MetaTrader 4 especialista _HPCS_Inter5_MT4_EA_V01_WE. Quando a estratégia é iniciada, ela inspeciona as últimas velas concluídas e, se o preço de fechamento de cinco barras atrás for superior ao fechamento mais recente, envia uma ordem de compra de mercado. As distâncias protetoras opcionais de stop-loss e take-profit emulam o comportamento baseado em pip do EA original.
Lógica de negociação
Assine a série de velas configurada e mantenha os últimos seis fechamentos concluídos.
Depois que o buffer for preenchido, compare o fechamento de cinco barras atrás com o fechamento mais recente (Close[5] > Close[1] em termos de MetaTrader).
Se a condição for satisfeita e nenhuma negociação tiver sido realizada ainda, envie uma ordem de compra a mercado com o volume configurado.
As ordens de proteção são armadas uma vez na inicialização por meio de StartProtection, usando a conversão de pip no estilo MetaTrader: instrumentos com 3 ou 5 decimais multiplicam PriceStep por 10 para determinar o tamanho do pip, caso contrário, o PriceStep bruto é usado.
A estratégia não abre negociações adicionais e ignora todos os sinais subsequentes quando a primeira posição é preenchida.
Parâmetros
Nome
Padrão
Descrição
Candle Type
Período de 1 minuto
Tipo de vela usado para coletar os preços de fechamento. Defina-o para o período de tempo que corresponde ao intervalo de sinal desejado.
Stop Loss (pips)
10
Distância para o stop loss de proteção em MetaTrader pips. Um valor de 0 desativa a parada.
Take Profit (pips)
10
Distância para o take-profit protetor em MetaTrader pips. Um valor de 0 desativa o lucro.
Trade Volume
1
Volume da ordem de mercado submetida quando a condição de entrada é acionada.
Notas de implementação
A estratégia requer um Security.PriceStep configurado (ou Security.Step) para converter distâncias pip. Se esta informação estiver faltando, os deslocamentos de proteção permanecerão inativos, mas o sinal de entrada ainda funcionará.
Somente velas finalizadas (CandleStates.Finished) são processadas para corresponder ao comportamento MetaTrader que depende de Close[1] e valores mais antigos.
O buffer interno contém exatamente seis fechamentos sem usar o histórico do indicador, respeitando a natureza minimalista da fonte EA.
IsFormedAndOnlineAndAllowTrading() é verificado antes de enviar o pedido para garantir que o ambiente esteja pronto para execução.
Dicas de uso
Atribua um instrumento Forex com configurações adequadas de preço e volume.
Ajuste o Candle Type para corresponder ao período que você deseja analisar.
Deixe o stop-loss ou o take-profit em zero se preferir gerenciar as saídas manualmente.
Reinicie a estratégia sempre que desejar reavaliar a condição de entrada, pois ela é acionada apenas uma vez por sessão.
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;
using StockSharp.Algo;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Single-shot momentum strategy converted from the "_HPCS_Inter5" MetaTrader script.
/// Places one market buy when the close price from five bars ago exceeds the most recent close.
/// </summary>
public class HpcsInter5Strategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _stopLossPips;
private readonly StrategyParam<int> _takeProfitPips;
private readonly StrategyParam<decimal> _tradeVolume;
private readonly decimal?[] _recentCloses = new decimal?[6];
private decimal _pipSize;
private bool _wasLongSignal;
private bool _hasSignal;
/// <summary>
/// Candle type used to evaluate the closing prices.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Stop-loss distance expressed in MetaTrader-style pips.
/// </summary>
public int StopLossPips
{
get => _stopLossPips.Value;
set => _stopLossPips.Value = value;
}
/// <summary>
/// Take-profit distance expressed in MetaTrader-style pips.
/// </summary>
public int TakeProfitPips
{
get => _takeProfitPips.Value;
set => _takeProfitPips.Value = value;
}
/// <summary>
/// Trade volume submitted with the market entry.
/// </summary>
public decimal TradeVolume
{
get => _tradeVolume.Value;
set => _tradeVolume.Value = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="HpcsInter5Strategy"/> class.
/// </summary>
public HpcsInter5Strategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(120).TimeFrame())
.SetDisplay("Candle Type", "Candle type used for the close comparison", "General");
_stopLossPips = Param(nameof(StopLossPips), 20)
.SetDisplay("Stop Loss (pips)", "Stop-loss distance expressed in pips", "Risk Management");
_takeProfitPips = Param(nameof(TakeProfitPips), 20)
.SetDisplay("Take Profit (pips)", "Take-profit distance expressed in pips", "Risk Management");
_tradeVolume = Param(nameof(TradeVolume), 1m)
.SetGreaterThanZero()
.SetDisplay("Trade Volume", "Volume submitted with the market entry", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
Array.Clear(_recentCloses, 0, _recentCloses.Length);
_pipSize = 0m;
_wasLongSignal = false;
_hasSignal = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
if (Security is null)
throw new InvalidOperationException("Security must be assigned before starting the strategy.");
base.OnStarted2(time);
InitializePipSize();
Volume = TradeVolume;
_wasLongSignal = false;
_hasSignal = false;
var stopLoss = StopLossPips > 0 && _pipSize > 0m
? new Unit(StopLossPips * _pipSize, UnitTypes.Absolute)
: null;
var takeProfit = TakeProfitPips > 0 && _pipSize > 0m
? new Unit(TakeProfitPips * _pipSize, UnitTypes.Absolute)
: null;
if (stopLoss != null || takeProfit != null)
StartProtection(stopLoss: stopLoss, takeProfit: takeProfit);
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
ShiftCloses(candle.ClosePrice);
if (_recentCloses[1] is not decimal lastClose || _recentCloses[5] is not decimal olderClose)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var threshold = lastClose * 0.005m;
var longSignal = olderClose - lastClose > threshold;
var shortSignal = lastClose - olderClose > threshold;
var crossedLong = longSignal && (!_hasSignal || !_wasLongSignal);
var crossedShort = shortSignal && (!_hasSignal || _wasLongSignal);
if (crossedLong && Position <= 0)
{
BuyMarket();
}
else if (crossedShort && Position >= 0)
{
SellMarket();
}
if (longSignal || shortSignal)
{
_wasLongSignal = longSignal;
_hasSignal = true;
}
}
private void ShiftCloses(decimal close)
{
for (var i = _recentCloses.Length - 1; i > 0; i--)
_recentCloses[i] = _recentCloses[i - 1];
_recentCloses[0] = close;
}
private void InitializePipSize()
{
var step = Security.PriceStep ?? 0.01m;
if (step <= 0m)
step = 0.01m;
var pipFactor = Security.Decimals is 3 or 5 ? 10m : 1m;
_pipSize = step * pipFactor;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates, Unit, UnitTypes
from StockSharp.Algo.Strategies import Strategy
class hpcs_inter5_strategy(Strategy):
"""
HPCS Inter5: momentum strategy comparing close from 5 bars ago
vs current close. Buys when older close exceeds recent by threshold.
Sells on reverse. Uses StartProtection for SL/TP.
"""
def __init__(self):
super(hpcs_inter5_strategy, self).__init__()
self._stop_loss_pips = self.Param("StopLossPips", 20) \
.SetDisplay("Stop Loss (pips)", "Stop-loss distance in pips", "Risk Management")
self._take_profit_pips = self.Param("TakeProfitPips", 20) \
.SetDisplay("Take Profit (pips)", "Take-profit distance in pips", "Risk Management")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(120))) \
.SetDisplay("Candle Type", "Candle type for close comparison", "General")
self._recent_closes = [None] * 6
self._pip_size = 0.0
self._was_long_signal = False
self._has_signal = False
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(hpcs_inter5_strategy, self).OnReseted()
self._recent_closes = [None] * 6
self._pip_size = 0.0
self._was_long_signal = False
self._has_signal = False
def OnStarted2(self, time):
super(hpcs_inter5_strategy, self).OnStarted2(time)
step = 0.01
if self.Security is not None and self.Security.PriceStep is not None:
step = float(self.Security.PriceStep)
if step <= 0:
step = 0.01
decimals = 0
if self.Security is not None and self.Security.Decimals is not None:
decimals = int(self.Security.Decimals)
pip_factor = 10.0 if decimals in (3, 5) else 1.0
self._pip_size = step * pip_factor
sl_pips = self._stop_loss_pips.Value
tp_pips = self._take_profit_pips.Value
sl = None
tp = None
if sl_pips > 0 and self._pip_size > 0:
sl = Unit(sl_pips * self._pip_size, UnitTypes.Absolute)
if tp_pips > 0 and self._pip_size > 0:
tp = Unit(tp_pips * self._pip_size, UnitTypes.Absolute)
if sl is not None or tp is not None:
self.StartProtection(tp, sl)
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._process_candle).Start()
def _process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
for i in range(len(self._recent_closes) - 1, 0, -1):
self._recent_closes[i] = self._recent_closes[i - 1]
self._recent_closes[0] = close
last_close = self._recent_closes[1]
older_close = self._recent_closes[5]
if last_close is None or older_close is None:
return
threshold = last_close * 0.005
long_signal = older_close - last_close > threshold
short_signal = last_close - older_close > threshold
crossed_long = long_signal and (not self._has_signal or not self._was_long_signal)
crossed_short = short_signal and (not self._has_signal or self._was_long_signal)
if crossed_long and self.Position <= 0:
self.BuyMarket()
elif crossed_short and self.Position >= 0:
self.SellMarket()
if long_signal or short_signal:
self._was_long_signal = long_signal
self._has_signal = True
def CreateClone(self):
return hpcs_inter5_strategy()