This strategy reproduces the MetaTrader expert Exp_CandlesticksBW_Tm on top of the StockSharp high-level API. It relies on Bill Williams' Candlesticks BW indicator, which paints candle colors by combining the Awesome Oscillator (AO) and the Accelerator Oscillator (AC). Momentum acceleration and deceleration are detected via candle color transitions, while an optional trading-session filter restricts entries to specific intraday hours.
How it works
Subscribes to the configured time-frame (default H4) and feeds every finished candle into an Awesome Oscillator (5/34). The AO series is smoothed with a 5-period simple moving average to produce the Accelerator component.
Each candle is classified into one of six color states: two bullish momentum colors (AO and AC rising), two bearish momentum colors (AO and AC falling), and two neutral colors (mixed AO/AC direction). The candle body direction decides between the darker or lighter shade in each pair.
A circular buffer stores the recent color indices alongside their open times. The SignalBar parameter selects which historical bar to evaluate (default = previous candle, i.e., offset 1). One bar further back is used as context.
Long entries are enabled when the older bar belonged to a bullish momentum zone and the signal bar leaves that zone. Short entries mirror the logic with bearish zones. Exit signals use the same momentum filters to close the opposite direction.
Optional session filtering (UseTimeFilter) keeps a trade log between StartHour:StartMinute and EndHour:EndMinute. Leaving the window immediately liquidates open positions, preventing overnight exposure.
Stop-loss and take-profit protections are registered through StartProtection, translating point-based distances into instrument price steps.
Trading rules
Open long: previous color index < 2 (AO and AC accelerating upwards) and the signal bar color index > 1. Long entries are skipped if already long or if longs are disabled.
Open short: previous color index > 3 (AO and AC accelerating downwards) and the signal bar color index < 4.
Close long: triggered when the older color index > 3 (bearish acceleration) and long exits are enabled.
Close short: triggered when the older color index < 2 (bullish acceleration) and short exits are enabled.
When the time filter is active, positions are force-closed outside of the allowed session even without color-based exit signals.
Parameters
Name
Description
Default
CandleType
Time-frame used for AO/AC calculations.
TimeSpan.FromHours(4).TimeFrame()
Volume
Order size for new entries.
1m
SignalBar
Number of finished candles to skip before evaluating signals (1 = previous candle).
1
StopLossPoints
Protective stop distance in instrument points. Set 0 to disable.
1000m
TakeProfitPoints
Profit target distance in instrument points. Set 0 to disable.
2000m
EnableLongEntries, EnableShortEntries
Allow opening trades in the respective direction.
true
EnableLongExits, EnableShortExits
Allow closing trades in the respective direction.
true
UseTimeFilter
Enable trading-session restrictions.
true
StartHour, StartMinute, EndHour, EndMinute
Session boundaries (inclusive start, exclusive end for identical hours).
0/0/23/59
Notes
The strategy automatically synchronizes the stop-loss and take-profit distances with the instrument price step.
Signals are timestamped using the close time of the evaluated bar so that repeated trades within the same bar are suppressed.
No Python version is provided, matching the source MQL package structure.
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()