Estrategia de Tendencia Color LeMan
Esta estrategia es un port del asesor experto original de MQL5 ColorLeManTrend. Utiliza un indicador de tendencia personalizado basado en máximos y mínimos para identificar la dirección del mercado.
Idea
El indicador calcula líneas alcistas y bajistas utilizando valores extremos de máximos y mínimos durante tres períodos de retroceso diferentes. Las medias móviles exponenciales suavizan estos valores. Las decisiones de trading se basan en los cruces de las líneas alcistas y bajistas:
- Cuando la línea alcista anterior está por encima de la bajista y la línea alcista actual cae por debajo de la bajista, se genera una señal de compra.
- Cuando la línea alcista anterior está por debajo de la bajista y la línea alcista actual sube por encima de la bajista, se genera una señal de venta.
- Indicadores opcionales controlan si se pueden abrir o cerrar posiciones largas o cortas.
Parámetros
CandleType– marco temporal para los cálculos del indicador.Min– período para el cálculo del extremo más corto.Midle– período para el cálculo del extremo medio.Max– período para el cálculo del extremo más largo.PeriodEma– período de suavizado para las líneas alcista y bajista.StopLossPoints– stop de protección en puntos.TakeProfitPoints– take profit en puntos.AllowBuy– habilitar entradas largas.AllowSell– habilitar entradas cortas.AllowBuyClose– permitir el cierre de posiciones largas.AllowSellClose– permitir el cierre de posiciones cortas.Volume– volumen de trading por orden.
Notas
La estrategia procesa únicamente velas terminadas y utiliza órdenes de mercado para todas las operaciones. Los valores de stop-loss y take-profit se aplican mediante la protección de posición incorporada.
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Strategy based on the Color LeMan Trend indicator.
/// </summary>
public class ColorLemanTrendStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _minPeriod;
private readonly StrategyParam<int> _midPeriod;
private readonly StrategyParam<int> _maxPeriod;
private readonly StrategyParam<int> _emaPeriod;
private readonly StrategyParam<decimal> _stopLossPoints;
private readonly StrategyParam<decimal> _takeProfitPoints;
private readonly StrategyParam<bool> _allowBuy;
private readonly StrategyParam<bool> _allowSell;
private readonly StrategyParam<bool> _allowBuyClose;
private readonly StrategyParam<bool> _allowSellClose;
private ExponentialMovingAverage _bullsEma;
private ExponentialMovingAverage _bearsEma;
private decimal? _prevBulls;
private decimal? _prevBears;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int Min { get => _minPeriod.Value; set => _minPeriod.Value = value; }
public int Midle { get => _midPeriod.Value; set => _midPeriod.Value = value; }
public int Max { get => _maxPeriod.Value; set => _maxPeriod.Value = value; }
public int PeriodEma { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
public decimal StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
public decimal TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }
public bool AllowBuy { get => _allowBuy.Value; set => _allowBuy.Value = value; }
public bool AllowSell { get => _allowSell.Value; set => _allowSell.Value = value; }
public bool AllowBuyClose { get => _allowBuyClose.Value; set => _allowBuyClose.Value = value; }
public bool AllowSellClose { get => _allowSellClose.Value; set => _allowSellClose.Value = value; }
/// <summary>
/// Initializes a new instance of <see cref="ColorLemanTrendStrategy"/>.
/// </summary>
public ColorLemanTrendStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for indicator", "General");
_minPeriod = Param(nameof(Min), 13)
.SetGreaterThanZero()
.SetDisplay("Min", "Shortest period", "Indicator")
;
_midPeriod = Param(nameof(Midle), 21)
.SetGreaterThanZero()
.SetDisplay("Midle", "Middle period", "Indicator")
;
_maxPeriod = Param(nameof(Max), 34)
.SetGreaterThanZero()
.SetDisplay("Max", "Longest period", "Indicator")
;
_emaPeriod = Param(nameof(PeriodEma), 3)
.SetGreaterThanZero()
.SetDisplay("EMA Period", "Smoothing length", "Indicator")
;
_stopLossPoints = Param(nameof(StopLossPoints), 1000m)
.SetDisplay("Stop Loss", "Stop loss in points", "Protection")
;
_takeProfitPoints = Param(nameof(TakeProfitPoints), 2000m)
.SetDisplay("Take Profit", "Take profit in points", "Protection")
;
_allowBuy = Param(nameof(AllowBuy), true)
.SetDisplay("Allow Buy", "Enable long entries", "Trading");
_allowSell = Param(nameof(AllowSell), true)
.SetDisplay("Allow Sell", "Enable short entries", "Trading");
_allowBuyClose = Param(nameof(AllowBuyClose), true)
.SetDisplay("Allow Buy Close", "Allow closing longs", "Trading");
_allowSellClose = Param(nameof(AllowSellClose), true)
.SetDisplay("Allow Sell Close", "Allow closing shorts", "Trading");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_bullsEma?.Reset();
_bearsEma?.Reset();
_bullsEma = null!;
_bearsEma = null!;
_prevBulls = null;
_prevBears = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_bullsEma = new EMA { Length = PeriodEma };
_bearsEma = new EMA { Length = PeriodEma };
var highestMin = new Highest { Length = Min };
var highestMid = new Highest { Length = Midle };
var highestMax = new Highest { Length = Max };
var lowestMin = new Lowest { Length = Min };
var lowestMid = new Lowest { Length = Midle };
var lowestMax = new Lowest { Length = Max };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(highestMin, highestMid, highestMax, lowestMin, lowestMid, lowestMax, ProcessCandle)
.Start();
StartProtection(
new Unit(TakeProfitPoints, UnitTypes.Absolute),
new Unit(StopLossPoints, UnitTypes.Absolute),
false);
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle,
decimal highestMin, decimal highestMid, decimal highestMax,
decimal lowestMin, decimal lowestMid, decimal lowestMax)
{
if (candle.State != CandleStates.Finished)
return;
var hh = 3m * candle.HighPrice - (highestMin + highestMid + highestMax);
var ll = (lowestMin + lowestMid + lowestMax) - 3m * candle.LowPrice;
var bullsValue = _bullsEma.Process(hh, candle.OpenTime, true);
var bearsValue = _bearsEma.Process(ll, candle.OpenTime, true);
if (!bullsValue.IsFinal || !bearsValue.IsFinal || bullsValue.IsEmpty || bearsValue.IsEmpty)
return;
if (!_bullsEma.IsFormed || !_bearsEma.IsFormed)
return;
var bulls = bullsValue.ToDecimal();
var bears = bearsValue.ToDecimal();
bool buyOpen = false;
bool sellOpen = false;
bool buyClose = false;
bool sellClose = false;
if (_prevBulls is decimal prevUp && _prevBears is decimal prevDn)
{
if (prevUp > prevDn)
{
if (AllowBuy && bulls <= bears)
buyOpen = true;
if (AllowSellClose)
sellClose = true;
}
if (prevUp < prevDn)
{
if (AllowSell && bulls >= bears)
sellOpen = true;
if (AllowBuyClose)
buyClose = true;
}
}
_prevBulls = bulls;
_prevBears = bears;
if (sellClose && Position < 0)
BuyMarket(Volume);
if (buyClose && Position > 0)
SellMarket(Volume);
if (buyOpen && Position <= 0)
BuyMarket(Volume);
if (sellOpen && Position >= 0)
SellMarket(Volume);
}
}
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, Unit, UnitTypes
from StockSharp.Algo.Indicators import ExponentialMovingAverage, Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
from indicator_extensions import *
class color_leman_trend_strategy(Strategy):
def __init__(self):
super(color_leman_trend_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe for indicator", "General")
self._min_period = self.Param("Min", 13) \
.SetDisplay("Min", "Shortest period", "Indicator")
self._mid_period = self.Param("Midle", 21) \
.SetDisplay("Midle", "Middle period", "Indicator")
self._max_period = self.Param("Max", 34) \
.SetDisplay("Max", "Longest period", "Indicator")
self._ema_period = self.Param("PeriodEma", 3) \
.SetDisplay("EMA Period", "Smoothing length", "Indicator")
self._stop_loss_points = self.Param("StopLossPoints", 1000.0) \
.SetDisplay("Stop Loss", "Stop loss in points", "Protection")
self._take_profit_points = self.Param("TakeProfitPoints", 2000.0) \
.SetDisplay("Take Profit", "Take profit in points", "Protection")
self._allow_buy = self.Param("AllowBuy", True) \
.SetDisplay("Allow Buy", "Enable long entries", "Trading")
self._allow_sell = self.Param("AllowSell", True) \
.SetDisplay("Allow Sell", "Enable short entries", "Trading")
self._allow_buy_close = self.Param("AllowBuyClose", True) \
.SetDisplay("Allow Buy Close", "Allow closing longs", "Trading")
self._allow_sell_close = self.Param("AllowSellClose", True) \
.SetDisplay("Allow Sell Close", "Allow closing shorts", "Trading")
self._bulls_ema = None
self._bears_ema = None
self._prev_bulls = None
self._prev_bears = None
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def Min(self):
return self._min_period.Value
@Min.setter
def Min(self, value):
self._min_period.Value = value
@property
def Midle(self):
return self._mid_period.Value
@Midle.setter
def Midle(self, value):
self._mid_period.Value = value
@property
def Max(self):
return self._max_period.Value
@Max.setter
def Max(self, value):
self._max_period.Value = value
@property
def PeriodEma(self):
return self._ema_period.Value
@PeriodEma.setter
def PeriodEma(self, value):
self._ema_period.Value = value
@property
def StopLossPoints(self):
return self._stop_loss_points.Value
@StopLossPoints.setter
def StopLossPoints(self, value):
self._stop_loss_points.Value = value
@property
def TakeProfitPoints(self):
return self._take_profit_points.Value
@TakeProfitPoints.setter
def TakeProfitPoints(self, value):
self._take_profit_points.Value = value
@property
def AllowBuy(self):
return self._allow_buy.Value
@AllowBuy.setter
def AllowBuy(self, value):
self._allow_buy.Value = value
@property
def AllowSell(self):
return self._allow_sell.Value
@AllowSell.setter
def AllowSell(self, value):
self._allow_sell.Value = value
@property
def AllowBuyClose(self):
return self._allow_buy_close.Value
@AllowBuyClose.setter
def AllowBuyClose(self, value):
self._allow_buy_close.Value = value
@property
def AllowSellClose(self):
return self._allow_sell_close.Value
@AllowSellClose.setter
def AllowSellClose(self, value):
self._allow_sell_close.Value = value
def OnStarted2(self, time):
super(color_leman_trend_strategy, self).OnStarted2(time)
self._bulls_ema = ExponentialMovingAverage()
self._bulls_ema.Length = self.PeriodEma
self._bears_ema = ExponentialMovingAverage()
self._bears_ema.Length = self.PeriodEma
highest_min = Highest()
highest_min.Length = self.Min
highest_mid = Highest()
highest_mid.Length = self.Midle
highest_max = Highest()
highest_max.Length = self.Max
lowest_min = Lowest()
lowest_min.Length = self.Min
lowest_mid = Lowest()
lowest_mid.Length = self.Midle
lowest_max = Lowest()
lowest_max.Length = self.Max
self.SubscribeCandles(self.CandleType) \
.Bind(highest_min, highest_mid, highest_max, lowest_min, lowest_mid, lowest_max, self.ProcessCandle) \
.Start()
self.StartProtection(
takeProfit=Unit(self.TakeProfitPoints, UnitTypes.Absolute),
stopLoss=Unit(self.StopLossPoints, UnitTypes.Absolute)
)
def ProcessCandle(self, candle, h_min, h_mid, h_max, l_min, l_mid, l_max):
if candle.State != CandleStates.Finished:
return
high = float(candle.HighPrice)
low = float(candle.LowPrice)
hh = 3.0 * high - (float(h_min) + float(h_mid) + float(h_max))
ll = (float(l_min) + float(l_mid) + float(l_max)) - 3.0 * low
t = candle.OpenTime
bulls_result = process_float(self._bulls_ema, hh, t, True)
bears_result = process_float(self._bears_ema, ll, t, True)
if bulls_result.IsEmpty or bears_result.IsEmpty:
return
if not self._bulls_ema.IsFormed or not self._bears_ema.IsFormed:
return
bulls = float(bulls_result)
bears = float(bears_result)
buy_open = False
sell_open = False
buy_close = False
sell_close = False
if self._prev_bulls is not None and self._prev_bears is not None:
if self._prev_bulls > self._prev_bears:
if self.AllowBuy and bulls <= bears:
buy_open = True
if self.AllowSellClose:
sell_close = True
if self._prev_bulls < self._prev_bears:
if self.AllowSell and bulls >= bears:
sell_open = True
if self.AllowBuyClose:
buy_close = True
self._prev_bulls = bulls
self._prev_bears = bears
if sell_close and self.Position < 0:
self.BuyMarket()
if buy_close and self.Position > 0:
self.SellMarket()
if buy_open and self.Position <= 0:
self.BuyMarket()
if sell_open and self.Position >= 0:
self.SellMarket()
def OnReseted(self):
super(color_leman_trend_strategy, self).OnReseted()
self._bulls_ema = None
self._bears_ema = None
self._prev_bulls = None
self._prev_bears = None
def CreateClone(self):
return color_leman_trend_strategy()