Стратегия по модели "Вечерняя звезда"
Паттерн "Вечерняя звезда" является зеркальным отражением "Утренней звезды" и указывает на возможное формирование вершины. Он начинается с сильной бычьей свечи, за которой следует небольшая свеча неопределенности, и заканчивается медвежьей свечой, закрывающейся ниже середины первой.
Тестирование показывает среднегодичную доходность около 100%. Стратегию лучше запускать на рынке Форекс.
Алгоритм следит за последовательностями из трех свечей. Когда формируется шаблон, открывается короткая позиция со стопом выше максимума маленькой средней свечи. Позиции закрываются, когда цена падает ниже минимума подтверждающей свечи или если сработает стоп.
Так как сетап подразумевает быстрое разворотное движение от перекупленных условий, сделки обычно нацелены на короткие импульсные движения вниз.
Детали
- Условия входа: Паттерн "Вечерняя звезда" из трех свечей.
- Лонг/Шорт: Только шорт.
- Условия выхода: Цена ниже минимума подтверждающей свечи или стоп‑лосс.
- Стопы: Да, выше максимума средней свечи.
- Значения по умолчанию:
CandleType= 5 минутStopLossPercent= 1
- Фильтры:
- Категория: Паттерн
- Направление: Шорт
- Индикаторы: Свечные модели
- Стопы: Да
- Сложность: Средняя
- Таймфрейм: Внутридневной
- Сезонность: Нет
- Нейронные сети: Нет
- Дивергенция: Нет
- Уровень риска: Средний
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>
/// Evening Star candle pattern strategy.
/// Evening Star: 1st bullish, 2nd small body (doji), 3rd bearish closing below midpoint of 1st.
/// Morning Star (reverse): 1st bearish, 2nd small body, 3rd bullish closing above midpoint of 1st.
/// Uses SMA for exit signals.
/// </summary>
public class EveningStarStrategy : Strategy
{
private readonly StrategyParam<int> _maPeriod;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _cooldownBars;
private ICandleMessage _bar1;
private ICandleMessage _bar2;
private int _cooldown;
/// <summary>
/// MA Period.
/// </summary>
public int MAPeriod
{
get => _maPeriod.Value;
set => _maPeriod.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Cooldown bars.
/// </summary>
public int CooldownBars
{
get => _cooldownBars.Value;
set => _cooldownBars.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public EveningStarStrategy()
{
_maPeriod = Param(nameof(MAPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("MA Period", "Period for SMA", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
_cooldownBars = Param(nameof(CooldownBars), 500)
.SetRange(1, 1000)
.SetDisplay("Cooldown Bars", "Bars to wait between trades", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_bar1 = null;
_bar2 = null;
_cooldown = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_bar1 = null;
_bar2 = null;
_cooldown = 0;
var sma = new SimpleMovingAverage { Length = MAPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(sma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, sma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal smaValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (_cooldown > 0)
{
_cooldown--;
_bar1 = _bar2;
_bar2 = candle;
return;
}
if (_bar1 != null && _bar2 != null)
{
var firstBody = Math.Abs(_bar1.OpenPrice - _bar1.ClosePrice);
var secondBody = Math.Abs(_bar2.OpenPrice - _bar2.ClosePrice);
var secondSmall = firstBody > 0 && secondBody < firstBody * 0.5m;
var firstMid = (_bar1.HighPrice + _bar1.LowPrice) / 2;
// Evening Star (bearish reversal) - primary
var firstBullish = _bar1.ClosePrice > _bar1.OpenPrice;
var thirdBearish = candle.ClosePrice < candle.OpenPrice;
var eveningStar = firstBullish && secondSmall && thirdBearish && candle.ClosePrice < firstMid;
// Morning Star (bullish reversal) - secondary
var firstBearish = _bar1.ClosePrice < _bar1.OpenPrice;
var thirdBullish = candle.ClosePrice > candle.OpenPrice;
var morningStar = firstBearish && secondSmall && thirdBullish && candle.ClosePrice > firstMid;
if (Position == 0 && eveningStar)
{
SellMarket();
_cooldown = CooldownBars;
}
else if (Position == 0 && morningStar)
{
BuyMarket();
_cooldown = CooldownBars;
}
else if (Position > 0 && candle.ClosePrice < smaValue)
{
SellMarket();
_cooldown = CooldownBars;
}
else if (Position < 0 && candle.ClosePrice > smaValue)
{
BuyMarket();
_cooldown = CooldownBars;
}
}
_bar1 = _bar2;
_bar2 = candle;
}
}
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 SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class evening_star_strategy(Strategy):
"""
Evening Star candle pattern strategy.
Evening Star: 1st bullish, 2nd small body (doji), 3rd bearish closing below midpoint of 1st.
Morning Star (reverse): 1st bearish, 2nd small body, 3rd bullish closing above midpoint of 1st.
Uses SMA for exit signals.
"""
def __init__(self):
super(evening_star_strategy, self).__init__()
self._ma_period = self.Param("MAPeriod", 20).SetDisplay("MA Period", "Period for SMA", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(1))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._cooldown_bars = self.Param("CooldownBars", 500).SetDisplay("Cooldown Bars", "Bars to wait between trades", "General")
self._bar1 = None
self._bar2 = None
self._cooldown = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(evening_star_strategy, self).OnReseted()
self._bar1 = None
self._bar2 = None
self._cooldown = 0
def OnStarted2(self, time):
super(evening_star_strategy, self).OnStarted2(time)
self._bar1 = None
self._bar2 = None
self._cooldown = 0
sma = SimpleMovingAverage()
sma.Length = self._ma_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(sma, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, sma)
self.DrawOwnTrades(area)
def _process_candle(self, candle, sma_val):
if candle.State != CandleStates.Finished:
return
if self._cooldown > 0:
self._cooldown -= 1
self._bar1 = self._bar2
self._bar2 = candle
return
if self._bar1 is not None and self._bar2 is not None:
first_body = abs(float(self._bar1.OpenPrice) - float(self._bar1.ClosePrice))
second_body = abs(float(self._bar2.OpenPrice) - float(self._bar2.ClosePrice))
second_small = first_body > 0 and second_body < first_body * 0.5
first_mid = (float(self._bar1.HighPrice) + float(self._bar1.LowPrice)) / 2.0
# Evening Star (bearish reversal) - primary
first_bullish = self._bar1.ClosePrice > self._bar1.OpenPrice
third_bearish = candle.ClosePrice < candle.OpenPrice
evening_star = first_bullish and second_small and third_bearish and float(candle.ClosePrice) < first_mid
# Morning Star (bullish reversal) - secondary
first_bearish = self._bar1.ClosePrice < self._bar1.OpenPrice
third_bullish = candle.ClosePrice > candle.OpenPrice
morning_star = first_bearish and second_small and third_bullish and float(candle.ClosePrice) > first_mid
sv = float(sma_val)
close = float(candle.ClosePrice)
cd = self._cooldown_bars.Value
if self.Position == 0 and evening_star:
self.SellMarket()
self._cooldown = cd
elif self.Position == 0 and morning_star:
self.BuyMarket()
self._cooldown = cd
elif self.Position > 0 and close < sv:
self.SellMarket()
self._cooldown = cd
elif self.Position < 0 and close > sv:
self.BuyMarket()
self._cooldown = cd
self._bar1 = self._bar2
self._bar2 = candle
def CreateClone(self):
return evening_star_strategy()