Estratégia Heikin Ashi V2
Esta segunda versão do sistema Heikin Ashi adiciona um filtro EMA. As operações ocorrem apenas quando a direção da vela Heikin Ashi concorda com a tendência definida pela EMA. O filtro ajuda a evitar sinais contra a tendência que a abordagem HA pura pode gerar.
Detalhes
- Critérios de entrada:
- Comprado:
HA_Close > HA_OpeneClose > EMA - Vendido:
HA_Close < HA_OpeneClose < EMA
- Comprado:
- Comprado/Vendido: Ambos
- Critérios de saída:
- Sinal oposto
- Stops: Nenhum
- Valores padrão:
EmaLength= 20
- Filtros:
- Categoria: Seguidor de tendência
- Direção: Ambos
- Indicadores: Heikin Ashi, EMA
- Stops: Não
- Complexidade: Baixo
- Período: Curto prazo
- Sazonalidade: Não
- Redes neurais: Não
- Divergência: Não
- Nível de risco: Médio
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>
/// Heikin Ashi V2 strategy.
/// Goes long when the Heikin Ashi candle is bullish and the close is above the EMA, and short when the Heikin Ashi
/// candle is bearish and the close is below the EMA. The opposite signal reverses the position.
/// </summary>
public class HeikinAshiV2Strategy : Strategy
{
private readonly StrategyParam<int> _emaLength;
private readonly StrategyParam<DataType> _candleType;
private decimal? _prevHaOpen;
private decimal? _prevHaClose;
/// <summary>
/// EMA period.
/// </summary>
public int EmaLength
{
get => _emaLength.Value;
set => _emaLength.Value = value;
}
/// <summary>
/// Candle type for strategy calculation.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public HeikinAshiV2Strategy()
{
_emaLength = Param(nameof(EmaLength), 20)
.SetGreaterThanZero()
.SetDisplay("EMA Length", "EMA trend filter period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle type", "Candle type for strategy calculation", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevHaOpen = null;
_prevHaClose = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevHaOpen = null;
_prevHaClose = null;
var ema = new ExponentialMovingAverage { Length = EmaLength };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(ema, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ema);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue emaValue)
{
if (candle.State != CandleStates.Finished)
return;
var haClose = (candle.OpenPrice + candle.HighPrice + candle.LowPrice + candle.ClosePrice) / 4m;
var haOpen = _prevHaOpen is decimal prevOpen && _prevHaClose is decimal prevClose
? (prevOpen + prevClose) / 2m
: (candle.OpenPrice + candle.ClosePrice) / 2m;
_prevHaOpen = haOpen;
_prevHaClose = haClose;
if (!emaValue.IsFormed)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var ema = emaValue.ToDecimal();
var close = candle.ClosePrice;
if (haClose > haOpen && close > ema && Position <= 0)
BuyMarket(Volume + Math.Abs(Position));
else if (haClose < haOpen && close < ema && Position >= 0)
SellMarket(Volume + Math.Abs(Position));
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Decimal
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class heikin_ashi_v2_strategy(Strategy):
"""
Heikin Ashi V2 strategy.
Goes long when the Heikin Ashi candle is bullish and the close is above the EMA, and short when the Heikin Ashi
candle is bearish and the close is below the EMA. The opposite signal reverses the position.
"""
def __init__(self):
super(heikin_ashi_v2_strategy, self).__init__()
self._ema_length = self.Param("EmaLength", 20) \
.SetGreaterThanZero() \
.SetDisplay("EMA Length", "EMA trend filter period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30))) \
.SetDisplay("Candle type", "Candle type for strategy calculation", "General")
self._prev_ha_open = None
self._prev_ha_close = None
@property
def CandleType(self):
return self._candle_type.Value
def GetWorkingSecurities(self):
return [(self.Security, self.CandleType)]
def OnReseted(self):
super(heikin_ashi_v2_strategy, self).OnReseted()
self._prev_ha_open = None
self._prev_ha_close = None
def OnStarted2(self, time):
super(heikin_ashi_v2_strategy, self).OnStarted2(time)
self._prev_ha_open = None
self._prev_ha_close = None
ema = ExponentialMovingAverage()
ema.Length = self._ema_length.Value
subscription = self.SubscribeCandles(self.CandleType)
subscription.BindEx(ema, 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_value):
if candle.State != CandleStates.Finished:
return
open_price = float(candle.OpenPrice)
close = float(candle.ClosePrice)
ha_close = (open_price + float(candle.HighPrice) + float(candle.LowPrice) + close) / 4.0
if self._prev_ha_open is not None and self._prev_ha_close is not None:
ha_open = (self._prev_ha_open + self._prev_ha_close) / 2.0
else:
ha_open = (open_price + close) / 2.0
self._prev_ha_open = ha_open
self._prev_ha_close = ha_close
if not ema_value.IsFormed:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
ema = float(ema_value.GetValue[Decimal](None))
if ha_close > ha_open and close > ema and self.Position <= 0:
self.BuyMarket(self.Volume + abs(self.Position))
elif ha_close < ha_open and close < ema and self.Position >= 0:
self.SellMarket(self.Volume + abs(self.Position))
def CreateClone(self):
return heikin_ashi_v2_strategy()