Estrategia de Mínimo de 3 Barras
La estrategia de Mínimo de 3 Barras compra cuando el precio de cierre cae por debajo del cierre mínimo de las tres barras anteriores y sale cuando el precio cierra por encima del cierre máximo de las siete barras anteriores. Un filtro EMA opcional puede requerir que el precio se mantenga por encima de una media de largo plazo antes de permitir entradas.
Detalles
- Criterios de entrada:
- El precio de cierre está por debajo del cierre mínimo de las tres barras anteriores.
- Opcional: el precio de cierre está por encima de la EMA cuando el filtro está activado.
- Largo/Corto: Solo largos.
- Criterios de salida:
- El precio de cierre está por encima del cierre máximo de las siete barras anteriores.
- Stops: Ninguno.
- Valores predeterminados:
MaPeriod= 200LowestLength= 3HighestLength= 7UseEmaFilter= false
- Filtros:
- Categoría: Ruptura
- Dirección: Long
- Indicadores: EMA, Highest/Lowest
- Stops: No
- Complejidad: Bajo
- Marco temporal: Cualquiera
- Estacionalidad: No
- Redes neuronales: No
- Divergencia: No
- Nivel de riesgo: Bajo
namespace StockSharp.Samples.Strategies;
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
/// <summary>
/// Three Bar Low Strategy.
/// A long opens when the close falls below the lowest close of the previous LowestLength candles and, with UseEmaFilter,
/// the close is above the MaPeriod EMA. The long closes when the close rises above the highest close of the previous
/// HighestLength candles.
/// </summary>
public class ThreeBarLowStrategy : Strategy
{
private readonly StrategyParam<int> _maPeriod;
private readonly StrategyParam<int> _lowestLength;
private readonly StrategyParam<int> _highestLength;
private readonly StrategyParam<bool> _useEmaFilter;
private readonly StrategyParam<DataType> _candleType;
private Lowest _lowestClose;
private Highest _highestClose;
private decimal? _prevLowest;
private decimal? _prevHighest;
/// <summary>
/// EMA period of the filter.
/// </summary>
public int MaPeriod
{
get => _maPeriod.Value;
set => _maPeriod.Value = value;
}
/// <summary>
/// Previous candles of the lowest close.
/// </summary>
public int LowestLength
{
get => _lowestLength.Value;
set => _lowestLength.Value = value;
}
/// <summary>
/// Previous candles of the highest close.
/// </summary>
public int HighestLength
{
get => _highestLength.Value;
set => _highestLength.Value = value;
}
/// <summary>
/// Require the close above the EMA for entries.
/// </summary>
public bool UseEmaFilter
{
get => _useEmaFilter.Value;
set => _useEmaFilter.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public ThreeBarLowStrategy()
{
_maPeriod = Param(nameof(MaPeriod), 200)
.SetGreaterThanZero()
.SetDisplay("MA Period", "EMA period of the filter", "Indicators");
_lowestLength = Param(nameof(LowestLength), 3)
.SetGreaterThanZero()
.SetDisplay("Lowest Length", "Previous candles of the lowest close", "Indicators");
_highestLength = Param(nameof(HighestLength), 7)
.SetGreaterThanZero()
.SetDisplay("Highest Length", "Previous candles of the highest close", "Indicators");
_useEmaFilter = Param(nameof(UseEmaFilter), false)
.SetDisplay("Use EMA Filter", "Require the close above the EMA for entries", "Filters");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevLowest = null;
_prevHighest = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevLowest = null;
_prevHighest = null;
var ema = new ExponentialMovingAverage { Length = MaPeriod };
_lowestClose = new Lowest { Length = LowestLength };
_highestClose = new Highest { Length = HighestLength };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(ema, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ema);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue emaValue)
{
if (candle.State != CandleStates.Finished)
return;
var close = candle.ClosePrice;
// Both levels are measured on the candles before this one.
var lowest = _prevLowest;
var highest = _prevHighest;
var currentLowest = _lowestClose.Process(close, candle.OpenTime, true).ToDecimal();
var currentHighest = _highestClose.Process(close, candle.OpenTime, true).ToDecimal();
if (_lowestClose.IsFormed)
_prevLowest = currentLowest;
if (_highestClose.IsFormed)
_prevHighest = currentHighest;
if (lowest is not decimal lowLevel || highest is not decimal highLevel)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (Position > 0)
{
if (close > highLevel)
SellMarket(Position);
return;
}
var emaOk = !UseEmaFilter || (emaValue.IsFormed && close > emaValue.GetValue<decimal>());
if (Position == 0 && close < lowLevel && emaOk)
BuyMarket(Volume);
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Decimal
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage, Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
from indicator_extensions import *
class three_bar_low_strategy(Strategy):
"""
Three Bar Low Strategy.
A long opens when the close falls below the lowest close of the previous LowestLength candles and, with UseEmaFilter,
the close is above the MaPeriod EMA. The long closes when the close rises above the highest close of the previous
HighestLength candles.
"""
def __init__(self):
super(three_bar_low_strategy, self).__init__()
self._ma_period = self.Param("MaPeriod", 200).SetGreaterThanZero().SetDisplay("MA Period", "EMA period of the filter", "Indicators")
self._lowest_length = self.Param("LowestLength", 3).SetGreaterThanZero().SetDisplay("Lowest Length", "Previous candles of the lowest close", "Indicators")
self._highest_length = self.Param("HighestLength", 7).SetGreaterThanZero().SetDisplay("Highest Length", "Previous candles of the highest close", "Indicators")
self._use_ema_filter = self.Param("UseEmaFilter", False).SetDisplay("Use EMA Filter", "Require the close above the EMA for entries", "Filters")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._lowest_close = None
self._highest_close = None
self._prev_lowest = None
self._prev_highest = None
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(three_bar_low_strategy, self).OnReseted()
self._prev_lowest = None
self._prev_highest = None
def OnStarted2(self, time):
super(three_bar_low_strategy, self).OnStarted2(time)
self._prev_lowest = None
self._prev_highest = None
ema = ExponentialMovingAverage()
ema.Length = self._ma_period.Value
self._lowest_close = Lowest()
self._lowest_close.Length = self._lowest_length.Value
self._highest_close = Highest()
self._highest_close.Length = self._highest_length.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(ema, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema)
self.DrawOwnTrades(area)
def _process_candle(self, candle, ema_value):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
# Both levels are measured on the candles before this one.
lowest = self._prev_lowest
highest = self._prev_highest
current_lowest = float(process_float(self._lowest_close, candle.ClosePrice, candle.OpenTime, True).GetValue[Decimal](None))
current_highest = float(process_float(self._highest_close, candle.ClosePrice, candle.OpenTime, True).GetValue[Decimal](None))
if self._lowest_close.IsFormed:
self._prev_lowest = current_lowest
if self._highest_close.IsFormed:
self._prev_highest = current_highest
if lowest is None or highest is None:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
if self.Position > 0:
if close > highest:
self.SellMarket(self.Position)
return
ema_ok = not self._use_ema_filter.Value or (ema_value.IsFormed and close > float(ema_value.GetValue[Decimal](None)))
if self.Position == 0 and close < lowest and ema_ok:
self.BuyMarket(self.Volume)
def CreateClone(self):
return three_bar_low_strategy()