Esta estratégia tenta negociar rompimentos de zonas de consolidação de curto prazo. Ela procura faixas de preço compactas no gráfico de 15 minutos e abre negociações quando o preço se afasta dessas faixas por uma distância especificada.
Lógica da estratégia
Para cada candle de 15 minutos finalizado, são calculados a máxima mais alta e a mínima mais baixa dos últimos 40 candles.
Se a distância entre esses extremos for inferior ao parâmetro Range, uma zona de consolidação é assumida.
Após o período Delay Open passar sem novas negociações, um rompimento acima do limite superior mais Distance pontos aciona uma posição comprada, enquanto um rompimento abaixo do limite inferior menos Distance pontos aciona uma posição vendida.
Um Stop Loss fixo e um trailing stop de Trail pontos são aplicados assim que uma posição é aberta.
Os limites de consolidação são redefinidos após decorridas as horas de Period.
Parâmetros
DelayOpen – Horas de espera antes de abrir uma nova negociação.
Distance – Distância de rompimento a partir do limite de consolidação em pontos.
Period – Horas após as quais os níveis de consolidação são recalculados.
Range – Tamanho máximo da zona de consolidação em pontos.
StopLoss – Stop loss inicial em pontos.
Trail – Distância do trailing stop em pontos.
Notas
A estratégia usa apenas a API de alto nível: os candles são recebidos via SubscribeCandles, e os valores dos indicadores são vinculados usando Bind. As ordens são enviadas com os métodos BuyMarket e SellMarket. Os comentários no código-fonte estão escritos em inglês.
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>
/// Breakout strategy based on consolidation zones.
/// </summary>
public class MaximusVxLiteStrategy : Strategy
{
private readonly StrategyParam<int> _lookback;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevHigh;
private decimal _prevLow;
private bool _hasPrev;
public int Lookback { get => _lookback.Value; set => _lookback.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public MaximusVxLiteStrategy()
{
_lookback = Param(nameof(Lookback), 20)
.SetDisplay("Lookback", "Highest/Lowest lookback period", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Time frame for candles", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_prevHigh = 0;
_prevLow = 0;
_hasPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var highest = new Highest { Length = Lookback };
var lowest = new Lowest { Length = Lookback };
SubscribeCandles(CandleType).Bind(highest, lowest, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal highest, decimal lowest)
{
if (candle.State != CandleStates.Finished) return;
if (!_hasPrev)
{
_prevHigh = highest;
_prevLow = lowest;
_hasPrev = true;
return;
}
var close = candle.ClosePrice;
// Breakout above previous highest
if (close > _prevHigh && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
// Breakout below previous lowest
else if (close < _prevLow && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
_prevHigh = highest;
_prevLow = lowest;
}
}
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
class maximus_vx_lite_strategy(Strategy):
def __init__(self):
super(maximus_vx_lite_strategy, self).__init__()
self._lookback = self.Param("Lookback", 20) \
.SetDisplay("Lookback", "Highest/Lowest lookback period", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Time frame for candles", "General")
self._prev_high = 0.0
self._prev_low = 0.0
self._has_prev = False
@property
def lookback(self):
return self._lookback.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(maximus_vx_lite_strategy, self).OnReseted()
self._prev_high = 0.0
self._prev_low = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(maximus_vx_lite_strategy, self).OnStarted2(time)
highest = Highest()
highest.Length = self.lookback
lowest = Lowest()
lowest.Length = self.lookback
self.SubscribeCandles(self.candle_type).Bind(highest, lowest, self.process_candle).Start()
def process_candle(self, candle, highest, lowest):
if candle.State != CandleStates.Finished:
return
hv = float(highest)
lv = float(lowest)
if not self._has_prev:
self._prev_high = hv
self._prev_low = lv
self._has_prev = True
return
close = float(candle.ClosePrice)
if close > self._prev_high and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif close < self._prev_low and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_high = hv
self._prev_low = lv
def CreateClone(self):
return maximus_vx_lite_strategy()