La estrategia eInTradePanel automatiza el flujo de trabajo del panel de operaciones original de MetaTrader. Permite los mismos ocho modos de orden (mercado, stop, límite y stop-límite en ambas direcciones) mientras calcula automáticamente distancias de disparo, entrada, stop-loss y take-profit desde el spread actual y una estimación de ATR sensible a la volatilidad. Las órdenes de protección se simulan mediante el monitoreo de velas para que la estrategia pueda usarse con proveedores de datos que no admiten órdenes SL/TP adjuntas.
Características destacadas
Modos de orden – elegir entre Buy, Sell, Buy/Sell Stop, Buy/Sell Limit o Buy/Sell Stop-Limit. Las órdenes stop-límite se arman una vez que el precio alcanza la distancia de disparo y luego envían la entrada límite.
Distancias dinámicas – los niveles pendientes, disparadores, stops y objetivos son proporcionales al mayor entre el spread actual o un spread sintético derivado del ATR (ATR × AtrFactor). Cuando el ATR no está listo, se usa una distancia base de tick configurable.
Adaptación a la volatilidad – la longitud del ATR sigue el panel original (55) para que los offsets reaccionen a cambios de régimen sin ajuste extra.
Expiración de órdenes – ventana de cancelación opcional con cumplimiento de tiempo mínimo de vida (predeterminado 11 minutos) mantiene las órdenes pendientes obsoletas fuera del libro.
Gestión de riesgo – cada posición abierta se monitorea en cada vela cerrada; si el máximo/mínimo perfora el stop o objetivo calculado, la posición se cierra a mercado.
Consciencia de cotización – la estrategia se suscribe al libro de órdenes para obtener los mejores precios de oferta/demanda para cálculos de offset más precisos, recurriendo a los cierres de velas cuando la profundidad no está disponible.
Parámetros
Nombre
Descripción
Volume
Tamaño de orden usado para todas las entradas.
Mode
Modo de entrada (mercado, stop, límite o stop-límite).
Candle Type
Agregación usada para ATR y verificaciones de ejecución basadas en velas.
Base Ticks
Distancia mínima de tick cuando los datos de ATR no están disponibles.
Pending Multiplier
Multiplicador aplicado a la distancia base de tick para offsets de órdenes pendientes.
Trigger Multiplier
Multiplicador adicional para distancias de disparo stop-límite.
Stop Multiplier
Multiplicador para distancia de stop-loss (establecer en 0 para deshabilitar).
Take Multiplier
Multiplicador para distancia de take-profit (establecer en 0 para deshabilitar).
Use ATR
Habilita el escalado basado en ATR de todas las distancias.
ATR Factor
Fracción del ATR tratada como spread sintético al escalar.
Expiration
Minutos hasta que se cancelan las órdenes pendientes (0 las mantiene GTC).
Min Expiration
Tiempo de vida mínimo pendiente en minutos, replicando la protección del panel.
Lógica de negociación
Preparación de datos – la estrategia se suscribe al tipo de vela configurado y mantiene un ATR de 55 períodos actualizado. Las instantáneas del libro de órdenes actualizan el último precio de oferta/demanda visto.
Cálculo de distancias – cada vela finalizada recalcula la distancia base de tick desde el ATR y el spread, luego deriva precios pendientes, de disparo, stop y take-profit según el modo seleccionado.
Envío de órdenes –
Los modos de mercado se ejecutan inmediatamente en la siguiente vela finalizada mientras la estrategia está plana.
Los modos stop y límite colocan la orden pendiente correspondiente y opcionalmente la cancelan después de la ventana de expiración.
Los modos stop-límite esperan hasta que el precio de disparo es impreso por el máximo/mínimo de la vela, luego envían la entrada límite.
Supervisión de posición – una vez que una posición está abierta, la estrategia comprueba las velas completadas en busca de violaciones de stop o objetivo y cierra la posición a mercado si se viola algún nivel.
Restablecimiento de estado – cuando la estrategia está plana y no hay ninguna orden activa, recalcula los niveles para que se pueda preparar una nueva operación en la siguiente vela.
El enfoque refleja el panel manual mientras permanece compatible con la API de alto nivel de StockSharp y el flujo de órdenes asíncrono.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// EInTradePanel strategy. Uses ATR breakout for entries.
/// </summary>
public class EInTradePanelStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _atrPeriod;
private readonly StrategyParam<decimal> _multiplier;
private decimal? _prevClose;
private decimal? _prevAtr;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int AtrPeriod { get => _atrPeriod.Value; set => _atrPeriod.Value = value; }
public decimal Multiplier { get => _multiplier.Value; set => _multiplier.Value = value; }
public EInTradePanelStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
_atrPeriod = Param(nameof(AtrPeriod), 14).SetGreaterThanZero().SetDisplay("ATR Period", "ATR lookback", "Indicators");
_multiplier = Param(nameof(Multiplier), 1.5m).SetDisplay("Multiplier", "ATR multiplier for breakout", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevClose = null;
_prevAtr = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevClose = null; _prevAtr = null;
var atr = new AverageTrueRange { Length = AtrPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(atr, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, atr); DrawOwnTrades(area); }
}
private void ProcessCandle(ICandleMessage candle, decimal atrVal)
{
if (candle.State != CandleStates.Finished) return;
if (!IsFormedAndOnlineAndAllowTrading()) { _prevClose = candle.ClosePrice; _prevAtr = atrVal; return; }
if (_prevClose == null || _prevAtr == null) { _prevClose = candle.ClosePrice; _prevAtr = atrVal; return; }
var threshold = _prevAtr.Value * Multiplier;
var diff = candle.ClosePrice - _prevClose.Value;
if (diff > threshold && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
else if (diff < -threshold && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
_prevClose = candle.ClosePrice; _prevAtr = atrVal;
}
}
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 AverageTrueRange
from StockSharp.Algo.Strategies import Strategy
class e_in_trade_panel_strategy(Strategy):
def __init__(self):
super(e_in_trade_panel_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._atr_period = self.Param("AtrPeriod", 14) \
.SetDisplay("ATR Period", "ATR lookback", "Indicators")
self._multiplier = self.Param("Multiplier", 1.5) \
.SetDisplay("Multiplier", "ATR multiplier for breakout", "Indicators")
self._prev_close = None
self._prev_atr = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def AtrPeriod(self):
return self._atr_period.Value
@property
def Multiplier(self):
return self._multiplier.Value
def OnReseted(self):
super(e_in_trade_panel_strategy, self).OnReseted()
self._prev_close = None
self._prev_atr = None
def OnStarted2(self, time):
super(e_in_trade_panel_strategy, self).OnStarted2(time)
self._prev_close = None
self._prev_atr = None
atr = AverageTrueRange()
atr.Length = self.AtrPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(atr, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, atr)
self.DrawOwnTrades(area)
def _on_process(self, candle, atr_value):
if candle.State != CandleStates.Finished:
return
av = float(atr_value)
close = float(candle.ClosePrice)
if self._prev_close is None or self._prev_atr is None:
self._prev_close = close
self._prev_atr = av
return
threshold = self._prev_atr * float(self.Multiplier)
diff = close - self._prev_close
if diff > threshold and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif diff < -threshold and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_close = close
self._prev_atr = av
def CreateClone(self):
return e_in_trade_panel_strategy()