Estrategia que busca formaciones clásicas de velas de reversión alcista. Cuando cualquiera de estos patrones aparece por debajo de una media móvil simple de 50 períodos, la estrategia abre una posición larga. Un trailing stop opcional protege las ganancias abiertas.
Patrones
Abandoned Baby – dos velas bajistas consecutivas seguidas de una vela alcista que cierra por encima de la apertura de la primera vela, mientras que la segunda vela tiene una brecha hacia abajo.
Morning Doji Star – una vela bajista, una vela doji o de cuerpo pequeño, y luego una vela alcista que cierra de nuevo dentro del cuerpo de la primera vela.
Three Inside Up – una vela bajista, una vela alcista más pequeña dentro de su rango, y luego una vela alcista que cierra por encima de la apertura de la primera vela.
Three Outside Up – una vela bajista seguida de una vela alcista más grande que la envuelve y una tercera vela alcista que confirma la reversión.
Three White Soldiers – tres velas alcistas consecutivas con cierres ascendentes.
Detalles
Criterios de entrada: cualquier patrón listado y la última vela abrió por debajo de la media móvil
Largo/Corto: Largo
Criterios de salida: trailing stop opcional
Stops: Trailing
Valores predeterminados:
MaPeriod = 50
TrailingStop = 50
UseTrailingStop = true
Filtros:
Categoría: Patrón
Dirección: Solo largos
Indicadores: SMA
Stops: Trailing
Complejidad: Básico
Marco temporal: Intradía
Estacionalidad: No
Redes neuronales: No
Divergencia: No
Nivel de riesgo: Medio
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>
/// Strategy looking for bullish/bearish reversal candlestick patterns with MA filter.
/// </summary>
public class BullishReversalStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _maPeriod;
private decimal _prevOpen1, _prevClose1, _prevLow1;
private decimal _prevOpen2, _prevClose2, _prevLow2;
private decimal _prevOpen3, _prevClose3, _prevLow3;
private int _candleCount;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int MaPeriod { get => _maPeriod.Value; set => _maPeriod.Value = value; }
public BullishReversalStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
_maPeriod = Param(nameof(MaPeriod), 50)
.SetDisplay("MA Period", "EMA length", "Parameters")
.SetGreaterThanZero();
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_prevOpen1 = 0; _prevClose1 = 0; _prevLow1 = 0;
_prevOpen2 = 0; _prevClose2 = 0; _prevLow2 = 0;
_prevOpen3 = 0; _prevClose3 = 0; _prevLow3 = 0;
_candleCount = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var ema = new ExponentialMovingAverage { Length = MaPeriod };
SubscribeCandles(CandleType).Bind(ema, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal ma)
{
if (candle.State != CandleStates.Finished) return;
_candleCount++;
if (_candleCount < 4)
{
ShiftCandles(candle);
return;
}
// Bullish patterns using stored values
var threeWhiteSoldiers = _prevOpen3 < _prevClose3 && _prevOpen2 < _prevClose2 && _prevOpen1 < _prevClose1 &&
_prevClose3 < _prevClose2 && _prevClose2 < _prevClose1;
var threeInsideUp = _prevOpen3 > _prevClose3 &&
Math.Abs(_prevClose2 - _prevOpen2) <= 0.6m * Math.Abs(_prevOpen3 - _prevClose3) &&
_prevClose2 > _prevOpen2 && _prevClose1 > _prevOpen1 && _prevClose1 > _prevOpen3;
// Bearish patterns
var threeBlackCrows = _prevOpen3 > _prevClose3 && _prevOpen2 > _prevClose2 && _prevOpen1 > _prevClose1 &&
_prevClose3 > _prevClose2 && _prevClose2 > _prevClose1;
var threeInsideDown = _prevOpen3 < _prevClose3 &&
Math.Abs(_prevClose2 - _prevOpen2) <= 0.6m * Math.Abs(_prevOpen3 - _prevClose3) &&
_prevClose2 < _prevOpen2 && _prevClose1 < _prevOpen1 && _prevClose1 < _prevOpen3;
var bullSignal = threeWhiteSoldiers || threeInsideUp;
var bearSignal = threeBlackCrows || threeInsideDown;
if (bullSignal && candle.ClosePrice > ma && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (bearSignal && candle.ClosePrice < ma && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
ShiftCandles(candle);
}
private void ShiftCandles(ICandleMessage candle)
{
_prevOpen3 = _prevOpen2; _prevClose3 = _prevClose2; _prevLow3 = _prevLow2;
_prevOpen2 = _prevOpen1; _prevClose2 = _prevClose1; _prevLow2 = _prevLow1;
_prevOpen1 = candle.OpenPrice; _prevClose1 = candle.ClosePrice; _prevLow1 = candle.LowPrice;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class bullish_reversal_strategy(Strategy):
def __init__(self):
super(bullish_reversal_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._ma_period = self.Param("MaPeriod", 50) \
.SetDisplay("MA Period", "EMA length", "Parameters")
self._prev_open1 = 0.0
self._prev_close1 = 0.0
self._prev_low1 = 0.0
self._prev_open2 = 0.0
self._prev_close2 = 0.0
self._prev_low2 = 0.0
self._prev_open3 = 0.0
self._prev_close3 = 0.0
self._prev_low3 = 0.0
self._candle_count = 0
@property
def candle_type(self):
return self._candle_type.Value
@property
def ma_period(self):
return self._ma_period.Value
def OnReseted(self):
super(bullish_reversal_strategy, self).OnReseted()
self._prev_open1 = 0.0
self._prev_close1 = 0.0
self._prev_low1 = 0.0
self._prev_open2 = 0.0
self._prev_close2 = 0.0
self._prev_low2 = 0.0
self._prev_open3 = 0.0
self._prev_close3 = 0.0
self._prev_low3 = 0.0
self._candle_count = 0
def OnStarted2(self, time):
super(bullish_reversal_strategy, self).OnStarted2(time)
ema = ExponentialMovingAverage()
ema.Length = self.ma_period
self.SubscribeCandles(self.candle_type).Bind(ema, self.process_candle).Start()
def process_candle(self, candle, ma):
if candle.State != CandleStates.Finished:
return
self._candle_count += 1
if self._candle_count < 4:
self._shift_candles(candle)
return
mv = float(ma)
three_white_soldiers = (self._prev_open3 < self._prev_close3 and
self._prev_open2 < self._prev_close2 and
self._prev_open1 < self._prev_close1 and
self._prev_close3 < self._prev_close2 and
self._prev_close2 < self._prev_close1)
three_inside_up = (self._prev_open3 > self._prev_close3 and
abs(self._prev_close2 - self._prev_open2) <= 0.6 * abs(self._prev_open3 - self._prev_close3) and
self._prev_close2 > self._prev_open2 and
self._prev_close1 > self._prev_open1 and
self._prev_close1 > self._prev_open3)
three_black_crows = (self._prev_open3 > self._prev_close3 and
self._prev_open2 > self._prev_close2 and
self._prev_open1 > self._prev_close1 and
self._prev_close3 > self._prev_close2 and
self._prev_close2 > self._prev_close1)
three_inside_down = (self._prev_open3 < self._prev_close3 and
abs(self._prev_close2 - self._prev_open2) <= 0.6 * abs(self._prev_open3 - self._prev_close3) and
self._prev_close2 < self._prev_open2 and
self._prev_close1 < self._prev_open1 and
self._prev_close1 < self._prev_open3)
bull_signal = three_white_soldiers or three_inside_up
bear_signal = three_black_crows or three_inside_down
close = float(candle.ClosePrice)
if bull_signal and close > mv and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif bear_signal and close < mv and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._shift_candles(candle)
def _shift_candles(self, candle):
self._prev_open3 = self._prev_open2
self._prev_close3 = self._prev_close2
self._prev_low3 = self._prev_low2
self._prev_open2 = self._prev_open1
self._prev_close2 = self._prev_close1
self._prev_low2 = self._prev_low1
self._prev_open1 = float(candle.OpenPrice)
self._prev_close1 = float(candle.ClosePrice)
self._prev_low1 = float(candle.LowPrice)
def CreateClone(self):
return bullish_reversal_strategy()