La Estrategia VR Smart Grid Lite replica la lógica del asesor experto MetaTrader con el mismo nombre. La estrategia construye una cuadrícula de promedio estilo martingala utilizando órdenes de mercado. El tamaño de la posición comienza a partir de un volumen base y se duplica cada vez que el precio se mueve contra la posición existente en una distancia definida por el usuario. La estrategia admite dos modos de salida: cerrar las operaciones extremas a un precio de obtención de beneficios ponderado o reducir parcialmente la exposición manteniendo la red activa.
Parámetros
Take Profit (pips) – distancia en pips utilizada para salir cuando solo hay una posición activa.
Volumen inicial: volumen de orden inicial para la primera operación en cada dirección.
Volumen máximo: límite máximo para cualquier pedido único abierto por la red.
Modo de cierre: Average cierra las órdenes más antiguas y más nuevas en un objetivo ponderado; PartClose cierra parte del pedido más nuevo y todo el pedido más antiguo.
Paso de la orden (pips): distancia mínima del precio que se debe recorrer respecto de la posición antes de abrir una nueva operación.
Beneficio mínimo (pips): margen de beneficio adicional agregado al precio de salida promedio ponderado.
Deslizamiento (pips): parámetro de marcador de posición conservado del EA original para que esté completo.
Tipo de vela: período de tiempo utilizado para impulsar la toma de decisiones (la vela completada anteriormente determina el sesgo comercial).
Algoritmo
En cada vela terminada, la estrategia evalúa la dirección de la vela anterior.
Si la vela anterior cerró alcista y no existen operaciones largas o el precio bajó en el paso configurado, se coloca una nueva orden de compra en el mercado.
Si la vela anterior cerró bajista y no existen operaciones cortas o el precio subió en el paso configurado, se coloca una nueva orden de mercado de venta.
Los volúmenes se calculan a partir de la posición con el precio más bajo en la dirección y se duplican en cada nuevo nivel, respetando el volumen máximo y los niveles de volumen del corredor.
Cuando sólo queda una posición, la estrategia aplica la distancia de toma de ganancias simple y sale al contacto.
Con múltiples posiciones, la estrategia calcula promedios ponderados utilizando las entradas extremas:
Modo promedio cierra ambos extremos cuando el precio alcanza el objetivo ponderado más el margen de beneficio mínimo.
Modo PartClose cierra una parte del pedido más nuevo igual al volumen inicial y cierra completamente el pedido más antiguo, lo que permite que la cuadrícula siga funcionando con una exposición reducida.
Se realiza un seguimiento de todas las posiciones ocupadas y cerradas para mantener el estado de la red interna sincronizado con la cartera en vivo.
Notas
La estrategia se basa en órdenes de mercado, por lo que la calidad real de la ejecución y el deslizamiento dependen de las condiciones del corredor.
Asegúrese de que las restricciones de volumen del instrumento (volumen mínimo y paso de volumen) sean compatibles con el volumen inicial seleccionado.
Como ocurre con cualquier enfoque de cuadrícula o martingala, el riesgo puede crecer rápidamente cuando los mercados tienen una fuerte tendencia contraria a la posición; Utilice una gestión prudente del dinero.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// VR Smart Grid Lite: grid trading based on price levels with SMA filter.
/// </summary>
public class VrSmartGridLiteStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<decimal> _gridPercent;
private readonly StrategyParam<int> _smaPeriod;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public decimal GridPercent
{
get => _gridPercent.Value;
set => _gridPercent.Value = value;
}
public int SmaPeriod
{
get => _smaPeriod.Value;
set => _smaPeriod.Value = value;
}
public VrSmartGridLiteStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_gridPercent = Param(nameof(GridPercent), 3.0m)
.SetGreaterThanZero()
.SetDisplay("Grid %", "Grid step percentage", "Grid");
_smaPeriod = Param(nameof(SmaPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("SMA Period", "SMA period for trend", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var sma = new SimpleMovingAverage { Length = SmaPeriod };
decimal? lastTradePrice = null;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(sma, (candle, smaVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var close = candle.ClosePrice;
if (!lastTradePrice.HasValue)
{
lastTradePrice = close;
return;
}
var step = lastTradePrice.Value * GridPercent / 100m;
if (close <= lastTradePrice.Value - step)
{
BuyMarket();
lastTradePrice = close;
}
else if (close >= lastTradePrice.Value + step)
{
SellMarket();
lastTradePrice = close;
}
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, sma);
DrawOwnTrades(area);
}
}
}
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 SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class vr_smart_grid_lite_strategy(Strategy):
def __init__(self):
super(vr_smart_grid_lite_strategy, self).__init__()
self._grid_percent = self.Param("GridPercent", 3.0) \
.SetDisplay("Grid %", "Grid step percentage", "Grid")
self._sma_period = self.Param("SmaPeriod", 20) \
.SetDisplay("SMA Period", "SMA period for trend", "Indicators")
self._sma = None
self._last_trade_price = None
@property
def grid_percent(self):
return self._grid_percent.Value
@property
def sma_period(self):
return self._sma_period.Value
def OnReseted(self):
super(vr_smart_grid_lite_strategy, self).OnReseted()
self._sma = None
self._last_trade_price = None
def OnStarted2(self, time):
super(vr_smart_grid_lite_strategy, self).OnStarted2(time)
self._sma = SimpleMovingAverage()
self._sma.Length = self.sma_period
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(30)))
subscription.Bind(self._sma, self._process_candle)
subscription.Start()
def _process_candle(self, candle, sma_value):
if candle.State != CandleStates.Finished:
return
if not self._sma.IsFormed:
return
close = float(candle.ClosePrice)
if self._last_trade_price is None:
self._last_trade_price = close
return
step = self._last_trade_price * self.grid_percent / 100.0
if close <= self._last_trade_price - step:
self.BuyMarket()
self._last_trade_price = close
elif close >= self._last_trade_price + step:
self.SellMarket()
self._last_trade_price = close
def CreateClone(self):
return vr_smart_grid_lite_strategy()