Стратегия Bullish Reversal
Стратегия ищет классические бычьи разворотные свечные модели. При появлении любого из этих паттернов ниже 50‑периодной простой скользящей средней открывается длинная позиция. Опциональный трейлинг‑стоп защищает прибыль.
Паттерны
- Abandoned Baby – две медвежьи свечи подряд, затем бычья свеча, закрывающаяся выше открытия первой, при этом вторая свеча имеет гэп вниз.
- Morning Doji Star – медвежья свеча, свеча‑доджи или малая свеча, затем бычья свеча, закрывающаяся внутри тела первой.
- Three Inside Up – медвежья свеча, меньшая бычья свеча внутри её диапазона и третья бычья свеча, закрывающаяся выше открытия первой.
- Three Outside Up – медвежья свеча, за которой следует большая бычья свеча, поглощающая её, и третья бычья свеча для подтверждения разворота.
- Three White Soldiers – три последовательные бычьи свечи с растущими ценами закрытия.
Детали
- Условия входа: любой из перечисленных паттернов и открытие последней свечи ниже скользящей средней
- Длинная/Короткая: Длинная
- Условия выхода: опциональный трейлинг‑стоп
- Стопы: Трейлинг
- Значения по умолчанию:
MaPeriod= 50TrailingStop= 50UseTrailingStop= true
- Фильтры:
- Категория: Паттерн
- Направление: Long
- Индикаторы: SMA
- Стопы: Трейлинг
- Сложность: Базовая
- Таймфрейм: Внутридневной
- Сезонность: Нет
- Нейросети: Нет
- Дивергенция: Нет
- Уровень риска: Средний
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()