Liquidex V1 es una estrategia de scalping por ruptura convertida del asesor experto MQL original. Combina un filtro de rango y una media móvil ponderada (WMA) para identificar oportunidades a corto plazo.
Lógica de trading
Para cada vela completada, la estrategia mide su rango (high - low).
Si el rango de la vela es menor que RangeFilter, la vela se ignora.
Se calcula una WMA con período MaPeriod usando precios de cierre.
Cuando la vela abre por debajo de la WMA y cierra por encima, se envía una orden de compra a mercado.
Cuando la vela abre por encima de la WMA y cierra por debajo, se envía una orden de venta a mercado.
Cada posición está protegida por un stop-loss definido en StopLoss.
Parámetros
RangeFilter – rango mínimo de la vela en unidades de precio requerido para operar.
MaPeriod – número de períodos para la media móvil ponderada.
StopLoss – stop-loss de protección en puntos.
CandleType – serie de velas utilizada para el análisis.
La estrategia usa Strategy.Volume como tamaño de la orden e invierte la posición cuando aparece una señal opuesta.
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>
/// WMA crossover strategy with range filter.
/// </summary>
public class LiquidexV1Strategy : Strategy
{
private readonly StrategyParam<int> _maPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevClose;
private decimal _prevWma;
private bool _hasPrev;
public int MaPeriod { get => _maPeriod.Value; set => _maPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public LiquidexV1Strategy()
{
_maPeriod = Param(nameof(MaPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("MA Period", "WMA period", "Indicators");
_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();
_prevClose = 0;
_prevWma = 0;
_hasPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var wma = new WeightedMovingAverage { Length = MaPeriod };
SubscribeCandles(CandleType)
.Bind(wma, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal wmaVal)
{
if (candle.State != CandleStates.Finished) return;
if (!_hasPrev)
{
_prevClose = candle.ClosePrice;
_prevWma = wmaVal;
_hasPrev = true;
return;
}
var crossUp = _prevClose <= _prevWma && candle.ClosePrice > wmaVal;
var crossDown = _prevClose >= _prevWma && candle.ClosePrice < wmaVal;
if (crossUp && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (crossDown && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
_prevClose = candle.ClosePrice;
_prevWma = wmaVal;
}
}
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 WeightedMovingAverage
from StockSharp.Algo.Strategies import Strategy
class liquidex_v1_strategy(Strategy):
def __init__(self):
super(liquidex_v1_strategy, self).__init__()
self._ma_period = self.Param("MaPeriod", 10) \
.SetDisplay("MA Period", "WMA period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle type", "General")
self._prev_close = 0.0
self._prev_wma = 0.0
self._has_prev = False
@property
def ma_period(self):
return self._ma_period.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(liquidex_v1_strategy, self).OnReseted()
self._prev_close = 0.0
self._prev_wma = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(liquidex_v1_strategy, self).OnStarted2(time)
wma = WeightedMovingAverage()
wma.Length = self.ma_period
self.SubscribeCandles(self.candle_type).Bind(wma, self.process_candle).Start()
def process_candle(self, candle, wma_val):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
wv = float(wma_val)
if not self._has_prev:
self._prev_close = close
self._prev_wma = wv
self._has_prev = True
return
cross_up = self._prev_close <= self._prev_wma and close > wv
cross_down = self._prev_close >= self._prev_wma and close < wv
if cross_up and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif cross_down and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_close = close
self._prev_wma = wv
def CreateClone(self):
return liquidex_v1_strategy()