A estratégia Heiken Ashi Smoothed MTF é uma versão do consultor especialista "HASNEWJ" MetaTrader. Ele reconstrói o indicador Heiken Ashi suavizado personalizado em seis intervalos de tempo (M1, M5, M15, M30, H1, H4) e aguarda o alinhamento da tendência nos quadros mais altos. Uma negociação é aberta quando o fluxo inferior do M5 mostra uma nova retração, enquanto as velas suavizadas de longo prazo permanecem fortemente de alta ou de baixa. A lógica manual de stop-loss e take-profit replica o comportamento do EA original, incluindo a capacidade de ampliar ligeiramente o stop após uma negociação perdedora.
Indicadores e Dados
Velas Heiken Ashi suavizadas em M1, M5, M15, M30, H1 e H4.
A primeira passagem de suavização aplica um método/comprimento de média móvel configurável aos valores OHLC brutos.
A segunda passagem suaviza a abertura/fechamento provisório do Heiken Ashi com outra média móvel configurável.
Contadores direcionais que rastreiam quantas atualizações de um minuto cada período permaneceu de alta ou de baixa.
Preço bruto de fechamento da série M1 para verificações de gerenciamento de risco.
Lógica de entrada
Atualize a direção suavizada de Heiken Ashi para cada período de tempo sempre que uma vela termina.
Em cada vela M1 finalizada, aumente ou redefina os contadores de alta/baixa, dependendo da direção mais recente de cada período de tempo.
Condições de compra:
M5 suavizado Heiken Ashi é otimista e o contador de alta está abaixo de MaxM5TrendLength (padrão 10 atualizações).
M15 suavizado Heiken Ashi é otimista e seu contador de alta está acima de MinM15TrendLength (padrão 200 atualizações).
As velas Heiken Ashi suavizadas M30, H1 e H4 também são otimistas.
Nenhuma posição longa está aberta no momento (a exposição curta é permitida e será invertida).
Condições de venda:
M5 suavizado Heiken Ashi está em baixa e o contador de baixa está abaixo de MaxM5TrendLength.
M15 suavizado Heiken Ashi está em baixa e seu contador de baixa está acima de MinM15TrendLength.
As velas suavizadas M30, H1 e H4 são de baixa.
Nenhuma posição curta está aberta no momento (a exposição longa foi fechada ou revertida).
O volume da ordem de mercado é igual a TradeVolume mais o valor absoluto da exposição oposta para garantir que os flips fechem a negociação anterior.
Gestão de risco
Um stop-loss e um take-profit manuais são avaliados em cada vela M1 finalizada usando Security.PriceStep.
O take-profit fecha a posição assim que o preço se move TakeProfitPoints passos a favor da negociação.
O stop-loss fecha a posição assim que o preço se move StopLossPoints passos contra a negociação.
Após uma negociação perdedora, a próxima entrada amplia o stop-loss em ExtraStopLossPoints passos, imitando o sinalizador de "falha" do EA.
O volume de negociação é fixado em TradeVolume; nenhuma lógica de pirâmide ou escala é aplicada além de reverter a exposição existente.
Parâmetros
Nome
Descrição
Padrão
TradeVolume
Volume base do pedido usado para entradas
0.1
TakeProfitPoints
Distância de lucro em etapas de preço
20
StopLossPoints
Distância stop-loss em etapas de preço
500
ExtraStopLossPoints
Etapas de parada adicionais aplicadas após uma negociação perdida
5
FirstMaPeriod
Comprimento da primeira média móvel de suavização
6
FirstMaMethod
Método do primeiro MA de suavização (Simple, Exponential, Smoothed, LinearWeighted)
Smoothed
SecondMaPeriod
Comprimento da segunda média móvel de suavização
2
SecondMaMethod
Método da segunda suavização MA
LinearWeighted
MaxM5TrendLength
Número máximo de atualizações M5 permitidas antes de cancelar uma entrada de pullback
10
MinM15TrendLength
Número mínimo de atualizações M15 necessárias para confirmar a tendência de alta
200
M1CandleType
Tipo de dados para o fluxo base de velas de um minuto
TimeFrame(00:01:00)
M5CandleType
Tipo de dados para o fluxo de confirmação de cinco minutos
TimeFrame(00:05:00)
M15CandleType
Tipo de dados para o fluxo de confirmação de quinze minutos
TimeFrame(00:15:00)
M30CandleType
Tipo de dados para o fluxo de confirmação de trinta minutos
TimeFrame(00:30:00)
H1CandleType
Tipo de dados para o fluxo de confirmação por hora
TimeFrame(01:00:00)
H4CandleType
Tipo de dados para o fluxo de confirmação de quatro horas
TimeFrame(04:00:00)
Notas de uso
Os contadores direcionais são atualizados uma vez por vela M1 concluída, o que se aproxima dos contadores baseados em ticks de MetaTrader enquanto mantém a implementação orientada por velas.
Certifique-se de que Security.PriceStep esteja configurado; caso contrário, a estratégia volta para um passo de 0,0001 ao calcular os níveis de parada e meta.
Ambas as passagens de suavização dependem de médias móveis; experimentar diferentes combinações de métodos e períodos pode adaptar o sistema a instrumentos com diferentes perfis de volatilidade.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Heiken Ashi Smoothed MTF: EMA trend with RSI filter and ATR stops.
/// </summary>
public class HeikenAshiSmoothedMtfStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaLength;
private readonly StrategyParam<int> _rsiLength;
private readonly StrategyParam<int> _atrLength;
private decimal _prevClose;
private decimal _entryPrice;
public HeikenAshiSmoothedMtfStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Timeframe.", "General");
_emaLength = Param(nameof(EmaLength), 20)
.SetDisplay("EMA Length", "Trend filter.", "Indicators");
_rsiLength = Param(nameof(RsiLength), 14)
.SetDisplay("RSI Length", "RSI period.", "Indicators");
_atrLength = Param(nameof(AtrLength), 14)
.SetDisplay("ATR Length", "ATR period.", "Indicators");
}
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int EmaLength { get => _emaLength.Value; set => _emaLength.Value = value; }
public int RsiLength { get => _rsiLength.Value; set => _rsiLength.Value = value; }
public int AtrLength { get => _atrLength.Value; set => _atrLength.Value = value; }
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevClose = 0; _entryPrice = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevClose = 0; _entryPrice = 0;
var ema = new ExponentialMovingAverage { Length = EmaLength };
var rsi = new RelativeStrengthIndex { Length = RsiLength };
var atr = new AverageTrueRange { Length = AtrLength };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ema, rsi, atr, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, ema); DrawOwnTrades(area); }
}
private void ProcessCandle(ICandleMessage candle, decimal emaVal, decimal rsiVal, decimal atrVal)
{
if (candle.State != CandleStates.Finished) return;
var close = candle.ClosePrice;
if (_prevClose == 0 || atrVal <= 0) { _prevClose = close; return; }
if (Position > 0)
{
if (close < emaVal || close <= _entryPrice - atrVal * 1.5m || close >= _entryPrice + atrVal * 2.5m) { SellMarket(); _entryPrice = 0; }
}
else if (Position < 0)
{
if (close > emaVal || close >= _entryPrice + atrVal * 1.5m || close <= _entryPrice - atrVal * 2.5m) { BuyMarket(); _entryPrice = 0; }
}
if (Position == 0)
{
if (close > emaVal && _prevClose <= emaVal && rsiVal > 50) { _entryPrice = close; BuyMarket(); }
else if (close < emaVal && _prevClose >= emaVal && rsiVal < 50) { _entryPrice = close; SellMarket(); }
}
_prevClose = close;
}
}
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 ExponentialMovingAverage, RelativeStrengthIndex, AverageTrueRange
from StockSharp.Algo.Strategies import Strategy
class heiken_ashi_smoothed_mtf_strategy(Strategy):
"""
Heiken Ashi Smoothed MTF: EMA trend with RSI filter and ATR stops.
Buys on EMA cross up with RSI > 50. Sells on EMA cross down with RSI < 50.
Uses ATR for dynamic SL/TP.
"""
def __init__(self):
super(heiken_ashi_smoothed_mtf_strategy, self).__init__()
self._ema_length = self.Param("EmaLength", 20) \
.SetDisplay("EMA Length", "Trend filter", "Indicators")
self._rsi_length = self.Param("RsiLength", 14) \
.SetDisplay("RSI Length", "RSI period", "Indicators")
self._atr_length = self.Param("AtrLength", 14) \
.SetDisplay("ATR Length", "ATR period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._prev_close = 0.0
self._entry_price = 0.0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(heiken_ashi_smoothed_mtf_strategy, self).OnReseted()
self._prev_close = 0.0
self._entry_price = 0.0
def OnStarted2(self, time):
super(heiken_ashi_smoothed_mtf_strategy, self).OnStarted2(time)
ema = ExponentialMovingAverage()
ema.Length = self._ema_length.Value
rsi = RelativeStrengthIndex()
rsi.Length = self._rsi_length.Value
atr = AverageTrueRange()
atr.Length = self._atr_length.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(ema, rsi, atr, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema)
self.DrawOwnTrades(area)
def _process_candle(self, candle, ema_val, rsi_val, atr_val):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
ema = float(ema_val)
rsi = float(rsi_val)
atr = float(atr_val)
if self._prev_close == 0.0 or atr <= 0:
self._prev_close = close
return
if self.Position > 0:
if close < ema or close <= self._entry_price - atr * 1.5 or close >= self._entry_price + atr * 2.5:
self.SellMarket()
self._entry_price = 0.0
elif self.Position < 0:
if close > ema or close >= self._entry_price + atr * 1.5 or close <= self._entry_price - atr * 2.5:
self.BuyMarket()
self._entry_price = 0.0
if self.Position == 0:
if close > ema and self._prev_close <= ema and rsi > 50:
self._entry_price = close
self.BuyMarket()
elif close < ema and self._prev_close >= ema and rsi < 50:
self._entry_price = close
self.SellMarket()
self._prev_close = close
def CreateClone(self):
return heiken_ashi_smoothed_mtf_strategy()