Estrategia de cuadrícula de límites pendiente (MQL/8147 Conversión)
Descripción general
La Estrategia de cuadrícula de límites pendiente reproduce el comportamiento del experto MetaTrader
almacenado en MQL/8147. La estrategia construye una cuadrícula simétrica de órdenes límite pendientes.
alrededor de los precios actuales de oferta y demanda. Mantiene la red activa mientras las ganancias flotan.
permanece dentro de un objetivo de ganancias configurado y un umbral de reducción. Cuando uno de los
se superan los umbrales, se cancelan todas las órdenes, se aplanan las posiciones abiertas y
la red se reconstruye utilizando el patrimonio de la nueva cuenta como base de referencia.
Lógica de trading
Suscríbase a los datos de nivel uno para realizar un seguimiento de los mejores precios de oferta y demanda.
Capture el capital de la cuenta la primera vez que se reciban datos en vivo y guárdelos como
la línea base de la sesión.
Coloque LevelsPerSide límites de venta por encima del mercado y la misma cantidad de compras
límites por debajo del mercado. La distancia entre los niveles de la cuadrícula está controlada por
GridStepPoints convertido al paso del precio del instrumento.
Mantenga las órdenes pendientes sin volver a emitir nuevas cuando se ejecuten. el
La cuadrícula se recrea solo después de un reinicio completo.
Supervise continuamente el PnL flotante:
Si la ganancia alcanza ProfitTargetCurrency, cierre toda exposición y reiníciela.
Si la reducción excede MaxDrawdownCurrency, aplana el libro y reinícialo.
Después de cada reinicio, la equidad de referencia se captura nuevamente y se reconstruye la red.
utilizando la instantánea de oferta/demanda más reciente.
Parámetros
Parámetro
Descripción
ProfitTargetCurrency
Beneficio neto (en la moneda de la cuenta) que desencadena un reinicio completo de la red.
MaxDrawdownCurrency
Pérdida flotante máxima tolerada antes de que se cierre toda exposición.
GridStepPoints
Distancia entre niveles consecutivos de la grilla expresada en puntos de corredor.
LevelsPerSide
Número de órdenes pendientes creadas por encima y por debajo del mercado.
OrderVolume
Volumen asignado a cada orden límite pendiente.
Gestión del riesgo
La estrategia no adjunta paradas ni objetivos por orden. En cambio, supervisa el
pérdidas y ganancias agregadas. El ayudante RequestFlatten cancela los pedidos pendientes y
utiliza órdenes de mercado (a través de ClosePosition) para eliminar cualquier exposición abierta. Después del
Cuando se completa el aplanamiento, el estado de la red y la equidad de referencia se restablecen antes de colocar
nuevos pedidos.
Notas
Los precios están normalizados a través de Security.ShrinkPrice para respetar el cambio.
paso de precio.
El valor "Punto" MetaTrader se emula analizando el instrumento PriceStep
para hacer coincidir cotizaciones de cuatro y cinco dígitos.
La estrategia evita reenviar los pedidos de la grilla una vez realizados, imitando el
experto original que se basaba en variables de bandera para mantener cada nivel único hasta
se produce un reinicio manual o automático.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class PendingLimitGridStrategy : Strategy
{
private readonly StrategyParam<int> _channelPeriod;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _cooldownBars;
private decimal _prevClose;
private decimal _prevMid;
private bool _hasPrev;
private int _barsSinceLastTrade;
public int ChannelPeriod { get => _channelPeriod.Value; set => _channelPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int CooldownBars { get => _cooldownBars.Value; set => _cooldownBars.Value = value; }
public PendingLimitGridStrategy()
{
_channelPeriod = Param(nameof(ChannelPeriod), 24).SetDisplay("Channel Period", "Grid channel lookback", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
_cooldownBars = Param(nameof(CooldownBars), 200).SetDisplay("Cooldown Bars", "Minimum bars between trades", "Risk");
}
protected override void OnReseted()
{
base.OnReseted();
_prevClose = 0;
_prevMid = 0;
_hasPrev = false;
_barsSinceLastTrade = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
_barsSinceLastTrade = 0;
var highest = new Highest { Length = ChannelPeriod };
var lowest = new Lowest { Length = ChannelPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(highest, lowest, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal highest, decimal lowest)
{
if (candle.State != CandleStates.Finished) return;
var close = candle.ClosePrice;
var mid = (highest + lowest) / 2;
if (!_hasPrev) { _prevClose = close; _prevMid = mid; _hasPrev = true; return; }
_barsSinceLastTrade++;
if (_barsSinceLastTrade >= CooldownBars)
{
if (_prevClose <= _prevMid && close > mid && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
_barsSinceLastTrade = 0;
}
else if (_prevClose >= _prevMid && close < mid && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
_barsSinceLastTrade = 0;
}
}
_prevClose = close;
_prevMid = mid;
}
}
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 Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
from datatype_extensions import *
from indicator_extensions import *
class pending_limit_grid_strategy(Strategy):
def __init__(self):
super(pending_limit_grid_strategy, self).__init__()
self._channel_period = self.Param("ChannelPeriod", 24).SetDisplay("Channel Period", "Grid channel lookback", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Candle timeframe", "General")
@property
def CandleType(self): return self._candle_type.Value
@CandleType.setter
def CandleType(self, value): self._candle_type.Value = value
def OnReseted(self):
super(pending_limit_grid_strategy, self).OnReseted()
self._has_prev = False
self._prev_close = 0
self._prev_mid = 0
def OnStarted2(self, time):
super(pending_limit_grid_strategy, self).OnStarted2(time)
self._has_prev = False
self._prev_close = 0
self._prev_mid = 0
highest = Highest()
highest.Length = self._channel_period.Value
lowest = Lowest()
lowest.Length = self._channel_period.Value
sub = self.SubscribeCandles(self.CandleType)
sub.Bind(highest, lowest, self.OnProcess).Start()
def OnProcess(self, candle, highest, lowest):
if candle.State != CandleStates.Finished:
return
close = candle.ClosePrice
mid = (highest + lowest) / 2.0
if not self._has_prev:
self._prev_close = close
self._prev_mid = mid
self._has_prev = True
return
if self._prev_close <= self._prev_mid and close > mid and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif self._prev_close >= self._prev_mid and close < mid and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_close = close
self._prev_mid = mid
def CreateClone(self):
return pending_limit_grid_strategy()