A estratégia replica o comportamento do Consultor Especialista original MostasHaR15 Pivot MQL5 usando a API de alto nível do StockSharp. Combina cálculos clássicos de pivô diário de suelo com filtros de momentum do ADX, diferenciais de EMA e o histograma MACD (OsMA). A estratégia opera em um fluxo de velas intradía (1 hora por padrão) e consome a vela diária completada anterior para reconstruir o mapa de pivô em cada barra.
Lógica de negociação
Grade de pivô – os máximos, mínimos e fechamentos diários anteriores são usados para calcular o pivô principal (P), três níveis de resistência (R1–R3), três níveis de suporte (S1–S3) e seis pontos médios (M0–M5). O fechamento da vela atual é comparado com essa escada para identificar o segmento de suporte e resistência circundante. Um caso especial herdado do EA mapeia preços entre M5 e R3 de volta ao intervalo S3/M0.
Filtro de distância – as negociações são permitidas apenas quando a distância para o nível de take-profit mais próximo é maior que MinimumDistancePips (14 pips por padrão), que corresponde aos filtros originais dif1/dif2.
Entradas compradas requerem tudo o seguinte:
A linha principal ADX excede AdxThreshold (20) e o +DI está tanto subindo quanto acima do –DI.
A EMA de 5 períodos nos fechamentos de velas está pelo menos EmaSlopePips (5 pips) acima da EMA de 8 períodos nas aberturas de velas, e a barra anterior mostrou o mesmo ordenamento EMA de alta.
O histograma MACD (OsMA) aumentou em comparação com a barra anterior.
Entradas vendidas espelham as condições compradas com força –DI, spread EMA baixista e um histograma MACD caindo.
Apenas uma posição líquida é permitida. As ordens são colocadas com execução de mercado via BuyMarket()/SellMarket().
Gestão de posição
Stop-loss – opcional, localizado StopLossPips abaixo/acima do preço de entrada. Definir o parâmetro como 0 desativa o stop inicial, como no EA.
Take-profit – fixo na fronteira de pivô mais próxima que envolve o preço atual quando a posição é aberta.
Stop trailing – replica a lógica de trailing original. Uma vez que o preço avança mais de TrailingStopPips + TrailingStepPips desde a entrada, o stop é movido para manter uma distância de trailing de TrailingStopPips. O trailing pode ser desativado definindo TrailingStopPips como 0.
Se o stop-loss, trailing stop ou take-profit for atingido durante uma vela, a posição é encerrada no fechamento dessa vela.
Parâmetros da estratégia
Parâmetro
Descrição
Padrão
CandleType
Série de velas intradía usada para negociação.
Período de 1 hora
DailyCandleType
Série de velas diárias para cálculos de pivô.
Período de 1 dia
StopLossPips
Distância do stop-loss em pips. Definir 0 para desativar.
20
TrailingStopPips
Distância do stop trailing em pips.
5
TrailingStepPips
Movimento mínimo favorável antes que o trailing seja atualizado. Deve ser >0 se o trailing estiver habilitado.
5
MinimumDistancePips
Distância mínima em pips para a fronteira de pivô mais próxima antes de entrar em uma negociação.
14
EmaSlopePips
Separação necessária entre a EMA de fechamento e a EMA de abertura.
5
AdxThreshold
Leitura mínima de ADX para negociações compradas e vendidas.
20
AdxPeriod
Comprimento do indicador ADX.
14
EmaClosePeriod
Período EMA aplicado aos fechamentos de velas.
5
EmaOpenPeriod
Período EMA aplicado às aberturas de velas.
8
MacdFastPeriod
Período EMA rápida dentro do histograma MACD.
12
MacdSlowPeriod
Período EMA lenta dentro do histograma MACD.
26
MacdSignalPeriod
Período EMA de sinal dentro do histograma MACD.
9
Notas de conversão
A estratégia mantém o comportamento incomum do EA onde o intervalo de preços entre o nível médio M5 e a resistência R3 é mapeado de volta ao par de suporte/resistência S3/M0.
Todos os valores de indicadores são processados apenas em velas completadas. Nenhuma coleção histórica é armazenada; todo o estado é mantido em campos escalares conforme as diretrizes do repositório.
Os comentários na estratégia permanecem em inglês por instrução do repositório.
Dicas de uso
Ajuste CandleType e DailyCandleType ao aplicar a estratégia a mercados com diferentes sessões de negociação.
Como a lógica de stop-loss e trailing é avaliada em velas fechadas, pode aparecer slippage adicional em mercados rápidos em comparação com a execução no nível de tick no EA original.
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>
/// MostasHar15 Pivot strategy (simplified).
/// Uses daily pivot levels with RSI filter for entries.
/// </summary>
public class MostasHar15PivotStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<DataType> _dailyCandleType;
private readonly StrategyParam<int> _rsiLength;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public DataType DailyCandleType
{
get => _dailyCandleType.Value;
set => _dailyCandleType.Value = value;
}
public int RsiLength
{
get => _rsiLength.Value;
set => _rsiLength.Value = value;
}
public MostasHar15PivotStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Trading candles", "General");
_dailyCandleType = Param(nameof(DailyCandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Daily Candle Type", "Higher timeframe for pivots", "General");
_rsiLength = Param(nameof(RsiLength), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Length", "RSI period", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi = new RelativeStrengthIndex { Length = RsiLength };
decimal pivotHigh = 0;
decimal pivotLow = 0;
decimal pivotMid = 0;
bool hasPivot = false;
// Subscribe to higher timeframe for pivot levels
var dailySub = SubscribeCandles(DailyCandleType);
dailySub
.Bind((ICandleMessage candle) =>
{
if (candle.State != CandleStates.Finished)
return;
pivotMid = (candle.HighPrice + candle.LowPrice + candle.ClosePrice) / 3m;
pivotHigh = 2m * pivotMid - candle.LowPrice;
pivotLow = 2m * pivotMid - candle.HighPrice;
hasPivot = true;
})
.Start();
// Subscribe to trading timeframe with RSI
var tradeSub = SubscribeCandles(CandleType);
tradeSub
.Bind(rsi, (ICandleMessage candle, decimal rsiVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (!hasPivot)
return;
var close = candle.ClosePrice;
// Long: price above pivot, RSI momentum confirms
if (close > pivotMid && rsiVal > 55 && Position <= 0)
BuyMarket();
// Short: price below pivot, RSI confirms weakness
else if (close < pivotMid && rsiVal < 45 && Position >= 0)
SellMarket();
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, tradeSub);
DrawIndicator(area, rsi);
DrawOwnTrades(area);
}
}
}
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
from StockSharp.Algo.Indicators import RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class mostas_har15_pivot_strategy(Strategy):
def __init__(self):
super(mostas_har15_pivot_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Trading candles", "General")
self._daily_candle_type = self.Param("DailyCandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Daily Candle Type", "Higher timeframe for pivots", "General")
self._rsi_length = self.Param("RsiLength", 14) \
.SetDisplay("RSI Length", "RSI period", "Indicators")
self._pivot_mid = 0.0
self._has_pivot = False
@property
def CandleType(self):
return self._candle_type.Value
@property
def DailyCandleType(self):
return self._daily_candle_type.Value
@property
def RsiLength(self):
return self._rsi_length.Value
def OnReseted(self):
super(mostas_har15_pivot_strategy, self).OnReseted()
self._pivot_mid = 0.0
self._has_pivot = False
def OnStarted2(self, time):
super(mostas_har15_pivot_strategy, self).OnStarted2(time)
self._pivot_mid = 0.0
self._has_pivot = False
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiLength
daily_sub = self.SubscribeCandles(self.DailyCandleType)
daily_sub.Bind(self._on_daily_candle).Start()
trade_sub = self.SubscribeCandles(self.CandleType)
trade_sub.Bind(rsi, self._on_trade_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, trade_sub)
self.DrawOwnTrades(area)
def _on_daily_candle(self, candle):
if candle.State != CandleStates.Finished:
return
high = float(candle.HighPrice)
low = float(candle.LowPrice)
close = float(candle.ClosePrice)
self._pivot_mid = (high + low + close) / 3.0
self._has_pivot = True
def _on_trade_candle(self, candle, rsi_value):
if candle.State != CandleStates.Finished:
return
if not self._has_pivot:
return
close = float(candle.ClosePrice)
rv = float(rsi_value)
if close > self._pivot_mid and rv > 55 and self.Position <= 0:
self.BuyMarket()
elif close < self._pivot_mid and rv < 45 and self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return mostas_har15_pivot_strategy()