Стратегия переносит эксперт Exp_CandlesticksBW_Tm из MetaTrader 5 на платформу StockSharp. В основе лежит индикатор Bill Williams Candlesticks BW, который раскрашивает свечи в зависимости от сочетания Awesome Oscillator (AO) и Accelerator Oscillator (AC). Логика строится на смене цветов свечей (ускорение/замедление импульса), а дополнительный фильтр торгового времени ограничивает сделки заданным временным окном.
Как работает
Выполняется подписка на выбранный таймфрейм (по умолчанию H4). Каждая завершённая свеча передаётся в Awesome Oscillator с периодами 5/34. Значения AO сглаживаются простой скользящей средней с периодом 5 для получения компоненты AC.
Свеча получает один из шести цветовых кодов: две «бычьи» зоны (AO и AC растут), две «медвежьи» зоны (AO и AC падают) и две нейтральные зоны (индикаторы движутся в разные стороны). Направление тела свечи определяет, какая из двух оттеночных меток будет присвоена.
В кольцевом буфере хранятся индексы цветов и время открытия свечей. Параметр SignalBar задаёт, какую по счёту завершённую свечу анализировать (1 — предыдущая свеча). Ещё одна свеча используется как контекст.
Длинный вход появляется, когда более старая свеча окрашена в «бычью» зону, а анализируемая свеча выходит из неё. Короткий вход зеркален и использует «медвежьи» цвета. Сигналы закрытия работают по тем же зонам, что и входы, только в противоположную сторону.
Фильтр торгового времени (UseTimeFilter) удерживает сделки между парами StartHour:StartMinute и EndHour:EndMinute. Выход за границы окна приводит к немедленному закрытию позиции.
Защитные стоп-приказы и тейк-профит выставляются через StartProtection, где дистанция в пунктах переводится в шаг цены инструмента.
Правила торговли
Открытие длинной позиции: цвет свечи SignalBar + 1 меньше 2 (ускорение вверх), а цвет свечи SignalBar больше 1. Вход возможен только при отсутствии текущей длинной позиции и при включённом разрешении на лонги.
Открытие короткой позиции: цвет свечи SignalBar + 1 больше 3 (ускорение вниз), а цвет свечи SignalBar меньше 4.
Закрытие длинной позиции: цвет свечи SignalBar + 1 больше 3 и включено разрешение на выход из лонга.
Закрытие короткой позиции: цвет свечи SignalBar + 1 меньше 2 и включено разрешение на выход из шорта.
При активном временном фильтре все позиции закрываются сразу после выхода из торгового интервала, даже если цветовых сигналов нет.
Параметры
Имя
Описание
Значение по умолчанию
CandleType
Таймфрейм для расчёта AO/AC.
TimeSpan.FromHours(4).TimeFrame()
Volume
Объём заявки при открытии.
1m
SignalBar
Смещение по числу завершённых свечей (1 = предыдущая).
1
StopLossPoints
Расстояние стоп-лосса в пунктах (0 отключает).
1000m
TakeProfitPoints
Расстояние тейк-профита в пунктах (0 отключает).
2000m
EnableLongEntries, EnableShortEntries
Разрешение на открытие длинных/коротких позиций.
true
EnableLongExits, EnableShortExits
Разрешение на закрытие длинных/коротких позиций по сигналу.
true
UseTimeFilter
Включение фильтра торговой сессии.
true
StartHour, StartMinute, EndHour, EndMinute
Границы торгового окна (начало включительно, окончание исключается при равных часах).
0/0/23/59
Дополнительно
Защитные уровни автоматически масштабируются в зависимости от шага цены торгуемого инструмента.
Метки времени сигналов берутся по моменту закрытия рассматриваемой свечи, что исключает повторные сделки в рамках одного бара.
Версия на Python не предоставляется, чтобы сохранить структуру пакета, аналогичную исходному MQL.
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>
/// Bill Williams Candlesticks BW strategy (simplified).
/// Uses candle body direction with SMA trend filter.
/// </summary>
public class ExpCandlesticksBwTimeStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _smaLength;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int SmaLength
{
get => _smaLength.Value;
set => _smaLength.Value = value;
}
public ExpCandlesticksBwTimeStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candles", "General");
_smaLength = Param(nameof(SmaLength), 34)
.SetGreaterThanZero()
.SetDisplay("SMA Length", "Bill Williams median line proxy", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var sma = new SimpleMovingAverage { Length = SmaLength };
int bullCount = 0, bearCount = 0;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(sma, (ICandleMessage candle, decimal smaValue) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var isBullish = candle.ClosePrice > candle.OpenPrice;
var isBearish = candle.ClosePrice < candle.OpenPrice;
if (isBullish)
{
bullCount++;
bearCount = 0;
}
else if (isBearish)
{
bearCount++;
bullCount = 0;
}
// 3 consecutive bullish candles above SMA
if (bullCount >= 3 && candle.ClosePrice > smaValue && Position <= 0)
{
BuyMarket();
bullCount = 0;
}
// 3 consecutive bearish candles below SMA
else if (bearCount >= 3 && candle.ClosePrice < smaValue && Position >= 0)
{
SellMarket();
bearCount = 0;
}
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, sma);
DrawOwnTrades(area);
}
}
}
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
from StockSharp.Algo.Strategies import Strategy
class exp_candlesticks_bw_time_strategy(Strategy):
"""
Bill Williams Candlesticks BW strategy (simplified).
Uses candle body direction with SMA trend filter.
Buys after 3 consecutive bullish candles above SMA, sells after 3 bearish below SMA.
"""
def __init__(self):
super(exp_candlesticks_bw_time_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Candles", "General")
self._sma_length = self.Param("SmaLength", 34) \
.SetDisplay("SMA Length", "Bill Williams median line proxy", "Indicators")
self._bull_count = 0
self._bear_count = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(exp_candlesticks_bw_time_strategy, self).OnReseted()
self._bull_count = 0
self._bear_count = 0
def OnStarted2(self, time):
super(exp_candlesticks_bw_time_strategy, self).OnStarted2(time)
self._bull_count = 0
self._bear_count = 0
sma = SimpleMovingAverage()
sma.Length = self._sma_length.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
close = float(candle.ClosePrice)
open_p = float(candle.OpenPrice)
sma_val = float(sma_val)
is_bullish = close > open_p
is_bearish = close < open_p
if is_bullish:
self._bull_count += 1
self._bear_count = 0
elif is_bearish:
self._bear_count += 1
self._bull_count = 0
if self._bull_count >= 3 and close > sma_val and self.Position <= 0:
self.BuyMarket()
self._bull_count = 0
elif self._bear_count >= 3 and close < sma_val and self.Position >= 0:
self.SellMarket()
self._bear_count = 0
def CreateClone(self):
return exp_candlesticks_bw_time_strategy()