A Estratégia VR Smart Grid Lite replica a lógica do consultor especialista MetaTrader com o mesmo nome. A estratégia constrói uma grade média no estilo martingale usando ordens de mercado. O dimensionamento da posição começa a partir de um volume base e duplica cada vez que o preço se move em relação à posição existente por uma distância definida pelo usuário. A estratégia suporta dois modos de saída: fechar as negociações extremas a um preço de lucro ponderado ou reduzir parcialmente a exposição, mantendo a rede ativa.
Parâmetros
Take Profit (pips) – distância em pips usada para sair quando apenas uma posição está ativa.
Volume inicial – volume inicial do pedido para a primeira negociação em cada direção.
Volume Máximo – limite máximo para qualquer pedido único aberto pela grade.
Modo Fechar – Average fecha os pedidos mais antigos e mais novos em uma meta ponderada; PartClose fecha parte do pedido mais recente e todo o pedido mais antigo.
Etapa da Ordem (pips) – distância mínima do preço que deve ser percorrida em relação à posição antes de uma nova negociação ser aberta.
Lucro Mínimo (pips) – margem de lucro adicional adicionada ao preço médio ponderado de saída.
Slippage (pips) – parâmetro de espaço reservado retido do EA original para fins de integridade.
Tipo de vela – período de tempo usado para orientar a tomada de decisão (a vela concluída anteriormente determina o viés de negociação).
Algoritmo
Em cada vela finalizada, a estratégia avalia a direção da vela anterior.
Se a vela anterior fechou em alta e não existem negociações longas ou o preço caiu na etapa configurada, uma nova ordem de mercado de compra será colocada.
Se a vela anterior fechou em baixa e não existem negociações curtas ou o preço subiu na etapa configurada, uma nova ordem de mercado de venda será colocada.
Os volumes são calculados a partir da posição de menor preço na direção e duplicados a cada novo nível, respeitando os passos de volume máximo e volume da corretora.
Quando resta apenas uma posição, a estratégia aplica a distância simples de take-profit e sai no toque.
Com múltiplas posições, a estratégia calcula médias ponderadas utilizando as entradas extremas:
Modo médio fecha ambos os extremos quando o preço atinge a meta ponderada mais o buffer de lucro mínimo.
Modo PartClose fecha uma parte do pedido mais recente igual ao volume inicial e fecha totalmente o pedido mais antigo, permitindo que a grade continue funcionando com exposição reduzida.
Todas as posições preenchidas e fechadas são rastreadas para manter o estado da grade interna sincronizado com o portfólio ativo.
Notas
A estratégia depende de ordens de mercado, portanto a qualidade real de execução e a derrapagem dependem das condições da corretora.
Certifique-se de que as restrições de volume do instrumento (volume mínimo e passo de volume) sejam compatíveis com o volume inicial selecionado.
Tal como acontece com qualquer abordagem de grelha ou martingale, o risco pode aumentar rapidamente quando os mercados tendem fortemente contra a posição; usar uma gestão prudente do dinheiro.
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()