Estrategia de reversión de momentum adaptada del experto MQL5 "e-TurboFx". El sistema observa una serie de velas cuyos cuerpos crecen en tamaño en la misma dirección. Después de varias velas bajistas con cuerpos en expansión, la estrategia compra esperando un rebote. Después de varias velas alcistas con cuerpos crecientes, vende. El stop-loss y el take-profit opcionales se establecen en puntos de precio brutos.
Detalles
Criterios de entrada:
Largo: N velas bajistas consecutivas y cada cuerpo mayor que el anterior
Corto: N velas alcistas consecutivas y cada cuerpo mayor que el anterior
Largo/Corto: Ambos
Criterios de salida: Stop-loss o take-profit
Stops: Puntos mediante StartProtection
Valores predeterminados:
BarsCount = 3
StopLossPoints = 700
TakeProfitPoints = 1200
CandleType = TimeSpan.FromMinutes(1).TimeFrame()
Filtros:
Categoría: Price Action
Dirección: Ambos
Indicadores: Ninguno
Stops: Sí
Complejidad: Básico
Marco temporal: Intradía
Estacionalidad: No
Redes neuronales: No
Divergencia: No
Nivel de riesgo: Medio
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>
/// Reversal candle pattern strategy with EMA filter.
/// </summary>
public class ETurboFxStrategy : Strategy
{
private readonly StrategyParam<int> _emaPeriod;
private readonly StrategyParam<DataType> _candleType;
private int _bearCount;
private int _bullCount;
private decimal _prevBody;
private bool _hasPrev;
public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public ETurboFxStrategy()
{
_emaPeriod = Param(nameof(EmaPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("EMA Period", "EMA trend filter period", "Parameters");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle type", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_bearCount = 0;
_bullCount = 0;
_prevBody = 0;
_hasPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
SubscribeCandles(CandleType)
.Bind(ema, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal emaVal)
{
if (candle.State != CandleStates.Finished) return;
var body = Math.Abs(candle.ClosePrice - candle.OpenPrice);
if (candle.ClosePrice < candle.OpenPrice)
{
_bearCount++;
if (_hasPrev && body > _prevBody)
_bearCount = Math.Min(_bearCount, 10);
else
_bearCount = 1;
_bullCount = 0;
}
else if (candle.ClosePrice > candle.OpenPrice)
{
_bullCount++;
if (_hasPrev && body > _prevBody)
_bullCount = Math.Min(_bullCount, 10);
else
_bullCount = 1;
_bearCount = 0;
}
else
{
_bearCount = 0;
_bullCount = 0;
}
_prevBody = body;
_hasPrev = true;
// Buy reversal after 3 bearish candles when price above EMA
if (_bearCount >= 3 && candle.ClosePrice > emaVal && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
// Sell reversal after 3 bullish candles when price below EMA
else if (_bullCount >= 3 && candle.ClosePrice < emaVal && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
}
}
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
from StockSharp.Algo.Strategies import Strategy
class e_turbo_fx_strategy(Strategy):
def __init__(self):
super(e_turbo_fx_strategy, self).__init__()
self._ema_period = self.Param("EmaPeriod", 20) \
.SetDisplay("EMA Period", "EMA trend filter period", "Parameters")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle type", "General")
self._bear_count = 0
self._bull_count = 0
self._prev_body = 0.0
self._has_prev = False
@property
def ema_period(self):
return self._ema_period.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(e_turbo_fx_strategy, self).OnReseted()
self._bear_count = 0
self._bull_count = 0
self._prev_body = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(e_turbo_fx_strategy, self).OnStarted2(time)
ema = ExponentialMovingAverage()
ema.Length = self.ema_period
self.SubscribeCandles(self.candle_type).Bind(ema, self.process_candle).Start()
def process_candle(self, candle, ema_val):
if candle.State != CandleStates.Finished:
return
body = abs(float(candle.ClosePrice) - float(candle.OpenPrice))
if float(candle.ClosePrice) < float(candle.OpenPrice):
self._bear_count += 1
if self._has_prev and body > self._prev_body:
self._bear_count = min(self._bear_count, 10)
else:
self._bear_count = 1
self._bull_count = 0
elif float(candle.ClosePrice) > float(candle.OpenPrice):
self._bull_count += 1
if self._has_prev and body > self._prev_body:
self._bull_count = min(self._bull_count, 10)
else:
self._bull_count = 1
self._bear_count = 0
else:
self._bear_count = 0
self._bull_count = 0
self._prev_body = body
self._has_prev = True
ev = float(ema_val)
close = float(candle.ClosePrice)
if self._bear_count >= 3 and close > ev and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif self._bull_count >= 3 and close < ev and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
def CreateClone(self):
return e_turbo_fx_strategy()