Esta estrategia implementa un enfoque de reversión a la media intradía utilizando dos conjuntos de Bandas de Bollinger. Las bandas externas (desviación 2.4) definen las zonas de entrada, mientras que las bandas internas (desviación 1) gestionan las salidas. Niveles opcionales de stop-loss y take-profit cierran posiciones cuando el precio se mueve en contra de la operación en un monto configurable.
Detalles
Criterios de entrada:
Largo: El precio de cierre cae por debajo de la banda inferior externa.
Corto: El precio de cierre sube por encima de la banda superior externa.
Largo/Corto: Ambos.
Criterios de salida:
Largo: El precio cruza hacia arriba la banda inferior interna o toca el stop-loss/take-profit.
Corto: El precio cruza hacia abajo la banda superior interna o toca el stop-loss/take-profit.
Stops: Stop-loss y take-profit absolutos configurables.
Filtros: Ninguno.
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>
/// Intraday mean reversion strategy using SMA and standard deviation bands.
/// Buys when price touches lower band, sells when touching upper band.
/// </summary>
public class IntradayV2Strategy : Strategy
{
private readonly StrategyParam<int> _bandLength;
private readonly StrategyParam<DataType> _candleType;
private readonly List<decimal> _closes = new();
public int BandLength { get => _bandLength.Value; set => _bandLength.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public IntradayV2Strategy()
{
_bandLength = Param(nameof(BandLength), 20)
.SetGreaterThanZero()
.SetDisplay("Band Length", "Band period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_closes.Clear();
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var sma = new SimpleMovingAverage { Length = BandLength };
var stdev = new StandardDeviation { Length = BandLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(sma, stdev, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal smaVal, decimal stdevVal)
{
if (candle.State != CandleStates.Finished)
return;
if (stdevVal <= 0)
return;
var close = candle.ClosePrice;
var upper = smaVal + 2m * stdevVal;
var lower = smaVal - 2m * stdevVal;
// Mean reversion: buy at lower band
if (close < lower && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
// Mean reversion: sell at upper band
else if (close > upper && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
// Exit long at middle (SMA)
if (Position > 0 && close > smaVal)
{
SellMarket();
}
// Exit short at middle (SMA)
else if (Position < 0 && close < smaVal)
{
BuyMarket();
}
}
}
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, StandardDeviation
from StockSharp.Algo.Strategies import Strategy
class intraday_v2_strategy(Strategy):
def __init__(self):
super(intraday_v2_strategy, self).__init__()
self._band_length = self.Param("BandLength", 20) \
.SetDisplay("Band Length", "Band period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
@property
def band_length(self):
return self._band_length.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(intraday_v2_strategy, self).OnReseted()
def OnStarted2(self, time):
super(intraday_v2_strategy, self).OnStarted2(time)
sma = SimpleMovingAverage()
sma.Length = self.band_length
stdev = StandardDeviation()
stdev.Length = self.band_length
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(sma, stdev, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def on_process(self, candle, sma_val, stdev_val):
if candle.State != CandleStates.Finished:
return
if stdev_val <= 0:
return
close = candle.ClosePrice
upper = sma_val + 2 * stdev_val
lower = sma_val - 2 * stdev_val
# Mean reversion: buy at lower band
if close < lower and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
# Mean reversion: sell at upper band
elif close > upper and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
# Exit long at middle (SMA)
if self.Position > 0 and close > sma_val:
self.SellMarket()
# Exit short at middle (SMA)
elif self.Position < 0 and close < sma_val:
self.BuyMarket()
def CreateClone(self):
return intraday_v2_strategy()