Estratégia Avançada de Cruzamento de EMA
Esta estratégia vai comprado quando uma EMA de curto prazo cruza acima de uma EMA de longo prazo, filtrando sinais com ATR normalizado, força de tendência ADX e uma verificação de direção do SuperTrend. Os níveis de stop-loss e take-profit se adaptam com base na força do USD inferida a partir de uma EMA de 50 períodos.
Detalhes
- Critérios de entrada:
- EMA curta cruza acima da EMA longa.
- ATR normalizado acima dos limites dependendo da direção da tendência.
- SuperTrend confirma mercado altista ou baixista.
- Critérios de saída:
- Cruzamento inverso de EMA ou ADX acima do limite após um período mínimo de manutenção.
- Stop-loss ou take-profit atingido.
- Indicadores: EMA, ATR, ADX, SuperTrend, SMA (volume).
- Stops: Stop-loss e take-profit percentuais dinâmicos.
- Tipo: Seguidor de tendência.
- Período: 30 minutos (padrão).
namespace StockSharp.Samples.Strategies;
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
/// <summary>
/// Advanced EMA Cross Strategy - uses EMA crossover with ADX filter.
/// </summary>
public class AdvancedEmaCrossStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaShortLength;
private readonly StrategyParam<int> _emaLongLength;
private readonly StrategyParam<int> _adxPeriod;
private readonly StrategyParam<decimal> _adxHighLevel;
private readonly StrategyParam<int> _cooldownBars;
private decimal _prevEmaShort;
private decimal _prevEmaLong;
private int _cooldownRemaining;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int EmaShortLength { get => _emaShortLength.Value; set => _emaShortLength.Value = value; }
public int EmaLongLength { get => _emaLongLength.Value; set => _emaLongLength.Value = value; }
public int AdxPeriod { get => _adxPeriod.Value; set => _adxPeriod.Value = value; }
public decimal AdxHighLevel { get => _adxHighLevel.Value; set => _adxHighLevel.Value = value; }
public int CooldownBars { get => _cooldownBars.Value; set => _cooldownBars.Value = value; }
public AdvancedEmaCrossStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
_emaShortLength = Param(nameof(EmaShortLength), 8)
.SetGreaterThanZero()
.SetDisplay("EMA Short Length", "Short EMA period", "EMA");
_emaLongLength = Param(nameof(EmaLongLength), 20)
.SetGreaterThanZero()
.SetDisplay("EMA Long Length", "Long EMA period", "EMA");
_adxPeriod = Param(nameof(AdxPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("ADX Period", "ADX calculation period", "ADX");
_adxHighLevel = Param(nameof(AdxHighLevel), 20m)
.SetDisplay("ADX Level", "ADX threshold for trending market", "ADX");
_cooldownBars = Param(nameof(CooldownBars), 10)
.SetDisplay("Cooldown Bars", "Bars between trades", "Risk");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevEmaShort = 0;
_prevEmaLong = 0;
_cooldownRemaining = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var emaShort = new ExponentialMovingAverage { Length = EmaShortLength };
var emaLong = new ExponentialMovingAverage { Length = EmaLongLength };
var adx = new AverageDirectionalIndex { Length = AdxPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(emaShort, emaLong, adx, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, emaShort);
DrawIndicator(area, emaLong);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue emaShortValue, IIndicatorValue emaLongValue, IIndicatorValue adxValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var emaShort = emaShortValue.ToDecimal();
var emaLong = emaLongValue.ToDecimal();
var adxTyped = (IAverageDirectionalIndexValue)adxValue;
if (adxTyped.MovingAverage is not decimal adx)
{
_prevEmaShort = emaShort;
_prevEmaLong = emaLong;
return;
}
if (_prevEmaShort == 0)
{
_prevEmaShort = emaShort;
_prevEmaLong = emaLong;
return;
}
if (_cooldownRemaining > 0)
{
_cooldownRemaining--;
_prevEmaShort = emaShort;
_prevEmaLong = emaLong;
return;
}
var crossover = _prevEmaShort <= _prevEmaLong && emaShort > emaLong;
var crossunder = _prevEmaShort >= _prevEmaLong && emaShort < emaLong;
var trending = adx > AdxHighLevel;
if (crossover && trending && Position <= 0)
{
if (Position < 0)
BuyMarket(Math.Abs(Position));
BuyMarket(Volume);
_cooldownRemaining = CooldownBars;
}
else if (crossunder && trending && Position >= 0)
{
if (Position > 0)
SellMarket(Math.Abs(Position));
SellMarket(Volume);
_cooldownRemaining = CooldownBars;
}
_prevEmaShort = emaShort;
_prevEmaLong = emaLong;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage, AverageDirectionalIndex, IndicatorHelper
from StockSharp.Algo.Strategies import Strategy
class advanced_ema_cross_strategy(Strategy):
def __init__(self):
super(advanced_ema_cross_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30))) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._ema_short_length = self.Param("EmaShortLength", 8) \
.SetGreaterThanZero() \
.SetDisplay("EMA Short Length", "Short EMA period", "EMA")
self._ema_long_length = self.Param("EmaLongLength", 20) \
.SetGreaterThanZero() \
.SetDisplay("EMA Long Length", "Long EMA period", "EMA")
self._adx_period = self.Param("AdxPeriod", 14) \
.SetGreaterThanZero() \
.SetDisplay("ADX Period", "ADX calculation period", "ADX")
self._adx_high_level = self.Param("AdxHighLevel", 20.0) \
.SetDisplay("ADX Level", "ADX threshold for trending market", "ADX")
self._cooldown_bars = self.Param("CooldownBars", 10) \
.SetDisplay("Cooldown Bars", "Bars between trades", "Risk")
self._prev_ema_short = 0.0
self._prev_ema_long = 0.0
self._cooldown_remaining = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(advanced_ema_cross_strategy, self).OnReseted()
self._prev_ema_short = 0.0
self._prev_ema_long = 0.0
self._cooldown_remaining = 0
def OnStarted2(self, time):
super(advanced_ema_cross_strategy, self).OnStarted2(time)
ema_short = ExponentialMovingAverage()
ema_short.Length = int(self._ema_short_length.Value)
ema_long = ExponentialMovingAverage()
ema_long.Length = int(self._ema_long_length.Value)
adx = AverageDirectionalIndex()
adx.Length = int(self._adx_period.Value)
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(ema_short, ema_long, adx, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema_short)
self.DrawIndicator(area, ema_long)
self.DrawOwnTrades(area)
def _on_process(self, candle, ema_short_value, ema_long_value, adx_value):
if candle.State != CandleStates.Finished:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
ema_s = float(IndicatorHelper.ToDecimal(ema_short_value))
ema_l = float(IndicatorHelper.ToDecimal(ema_long_value))
adx_ma = adx_value.MovingAverage
if adx_ma is None:
self._prev_ema_short = ema_s
self._prev_ema_long = ema_l
return
adx_v = float(adx_ma)
if self._prev_ema_short == 0:
self._prev_ema_short = ema_s
self._prev_ema_long = ema_l
return
if self._cooldown_remaining > 0:
self._cooldown_remaining -= 1
self._prev_ema_short = ema_s
self._prev_ema_long = ema_l
return
cooldown = int(self._cooldown_bars.Value)
crossover = self._prev_ema_short <= self._prev_ema_long and ema_s > ema_l
crossunder = self._prev_ema_short >= self._prev_ema_long and ema_s < ema_l
trending = adx_v > float(self._adx_high_level.Value)
if crossover and trending and self.Position <= 0:
if self.Position < 0:
self.BuyMarket(Math.Abs(self.Position))
self.BuyMarket(self.Volume)
self._cooldown_remaining = cooldown
elif crossunder and trending and self.Position >= 0:
if self.Position > 0:
self.SellMarket(Math.Abs(self.Position))
self.SellMarket(self.Volume)
self._cooldown_remaining = cooldown
self._prev_ema_short = ema_s
self._prev_ema_long = ema_l
def CreateClone(self):
return advanced_ema_cross_strategy()