La estrategia Heiken Ashi Smoothed MTF es una adaptación del asesor experto "HASNEWJ" MetaTrader. Reconstruye el indicador Heiken Ashi suavizado personalizado en seis marcos de tiempo (M1, M5, M15, M30, H1, H4) y espera la alineación de la tendencia en los marcos superiores. Se abre una operación cuando la corriente inferior de M5 muestra un nuevo retroceso mientras que las velas suavizadas a largo plazo siguen siendo fuertemente alcistas o bajistas. La lógica manual de stop-loss y take-profit replica el comportamiento del EA original, incluida la capacidad de ampliar ligeramente el stop después de una operación perdedora.
Indicadores y datos
Velas Heiken Ashi suavizadas en M1, M5, M15, M30, H1 y H4.
La primera pasada de suavizado aplica un método/longitud de promedio móvil configurable a los valores OHLC sin procesar.
La segunda pasada suaviza la apertura/cierre provisional de Heiken Ashi con otra media móvil configurable.
Contadores direccionales que rastrean cuántas actualizaciones de un minuto cada período de tiempo se ha mantenido alcista o bajista.
Precio de cierre bruto de la serie M1 para comprobaciones de gestión de riesgos.
Lógica de entrada
Actualice la dirección Heiken Ashi suavizada para cada período de tiempo cada vez que finalice una vela.
En cada vela M1 terminada, incremente o reinicie los contadores alcistas/bajistas dependiendo de la última dirección de cada período de tiempo.
Condiciones de compra:
M5 suavizado Heiken Ashi es alcista y el contador alcista está por debajo de MaxM5TrendLength (10 actualizaciones predeterminadas).
El Heiken Ashi suavizado M15 es alcista y su contador alcista está por encima de MinM15TrendLength (200 actualizaciones predeterminadas).
Las velas Heiken Ashi suavizadas M30, H1 y H4 también son alcistas.
Actualmente no hay ninguna posición larga abierta (se permite la exposición corta y se invertirá).
Condiciones de venta:
M5 suavizado Heiken Ashi es bajista y el contador bajista está por debajo de MaxM5TrendLength.
M15 suavizado Heiken Ashi es bajista y su contador bajista está por encima de MinM15TrendLength.
Las velas suavizadas M30, H1 y H4 son bajistas.
Actualmente no hay ninguna posición corta abierta (la exposición larga está cerrada o revertida).
El volumen de la orden de mercado es igual a TradeVolume más el valor absoluto de la exposición opuesta para garantizar que los cambios cierren la operación anterior.
Gestión del riesgo
Se evalúan manualmente un stop-loss y una toma de ganancias en cada vela M1 terminada usando Security.PriceStep.
La toma de ganancias cierra la posición una vez que el precio se mueve TakeProfitPoints pasos a favor de la operación.
El stop-loss cierra la posición una vez que el precio se mueve StopLossPoints pasos en contra de la operación.
Después de una operación perdedora, la siguiente entrada amplía el límite de pérdidas en ExtraStopLossPoints pasos, imitando la bandera de "fallo" de EA.
El volumen comercial está fijado por TradeVolume; no se aplica ninguna lógica piramidal o de escalamiento más allá de revertir la exposición existente.
Parámetros
Nombre
Descripción
Predeterminado
TradeVolume
Volumen de pedido base utilizado para las entradas
0.1
TakeProfitPoints
Distancia de toma de ganancias en pasos de precios
20
StopLossPoints
Distancia de stop-loss en pasos de precio
500
ExtraStopLossPoints
Se aplican pasos de parada adicionales después de una operación perdedora
5
FirstMaPeriod
Longitud de la primera media móvil de suavizado
6
FirstMaMethod
Método del primer MA de suavizado (Simple, Exponential, Smoothed, LinearWeighted)
Smoothed
SecondMaPeriod
Longitud de la segunda media móvil de suavizado
2
SecondMaMethod
Método del segundo suavizado MA.
LinearWeighted
MaxM5TrendLength
Número máximo de actualizaciones de M5 permitidas antes de cancelar una entrada de retroceso
10
MinM15TrendLength
Número mínimo de actualizaciones de M15 necesarias para confirmar la tendencia más alta
200
M1CandleType
Tipo de datos para el flujo de velas base de un minuto
TimeFrame(00:01:00)
M5CandleType
Tipo de datos para el flujo de confirmación de cinco minutos
TimeFrame(00:05:00)
M15CandleType
Tipo de datos para el flujo de confirmación de quince minutos
TimeFrame(00:15:00)
M30CandleType
Tipo de datos para el flujo de confirmación de treinta minutos
TimeFrame(00:30:00)
H1CandleType
Tipo de datos para el flujo de confirmación por hora
TimeFrame(01:00:00)
H4CandleType
Tipo de datos para el flujo de confirmación de cuatro horas
TimeFrame(04:00:00)
Notas de uso
Los contadores direccionales se actualizan una vez por vela M1 terminada, lo que se aproxima a los contadores basados en ticks de MetaTrader mientras se mantiene la implementación impulsada por velas.
Asegúrese de que Security.PriceStep esté configurado; de lo contrario, la estrategia vuelve a caer a un paso de 0,0001 al calcular los niveles objetivo y de parada.
Ambos pases de suavizado se basan en promedios móviles; experimentar con diferentes combinaciones de métodos y períodos puede adaptar el sistema a instrumentos con diferentes perfiles de volatilidad.
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()