This strategy combines the BykovTrend V2 color trend indicator with the ColorX2MA double-smoothed moving average slope filter. Both logic blocks operate on the same symbol and can issue orders independently, which allows the net position to reflect the latest agreement between the two signal sources.
Overview
Market bias: Works on any instrument that supports candlestick data. The default timeframe for both blocks is 4 hours (H4), mirroring the original Expert Advisor.
Indicators:
BykovTrend V2: Uses Williams %R to color candles according to the prevailing trend.
ColorX2MA: Applies two consecutive moving averages to a configurable price source and classifies the slope direction.
Signals: Entries and exits are generated separately by each block. The final position is the sum of all executed trades.
BykovTrend Block
Williams %R is calculated using the configured period (default 9).
Thresholds are shifted by 33 - Risk. When %R rises above -Risk the local trend turns bullish; when it drops below -100 + (33 - Risk) the trend becomes bearish.
Candle colors:
Green/teal (codes 0, 1): bullish trend.
Gray (code 2): neutral, no trend change.
Chocolate/gold (codes 3, 4): bearish trend.
Signals are evaluated on the candle that is SignalBar steps behind the most recent closed bar. A value of 1 means the previous completed candle, which matches the MetaTrader implementation.
Trading logic:
Long entry: Current color < 2 (bullish) and previous color > 1 (was neutral/bearish). Optional via Bykov Allow Long Entries.
Short exit: Current color < 2. Optional via Bykov Allow Short Exits.
Short entry: Current color > 2 (bearish) and previous color < 3 (was neutral/bullish). Optional via Bykov Allow Short Entries.
Long exit: Current color > 2. Optional via Bykov Allow Long Exits.
ColorX2MA Block
A first moving average smooths the selected applied price (close by default) using the chosen method and length.
A second moving average smooths the first MA output, again with a configurable method and length.
The slope of the second smoothing defines the color stream:
1 (magenta): value increased since the previous candle.
2 (violet): value decreased.
0 (gray): unchanged.
Signals are evaluated on the candle that is SignalBar steps behind the latest close.
Trading logic:
Long entry: Current color = 1 and previous color ≠ 1. Optional via Color Allow Long Entries.
Short exit: Current color = 1. Optional via Color Allow Short Exits.
Short entry: Current color = 2 and previous color ≠ 2. Optional via Color Allow Short Entries.
Long exit: Current color = 2. Optional via Color Allow Long Exits.
Position Management
Orders are market orders. When flipping direction the strategy buys/sells enough contracts to neutralize the existing position and establish a new one of size Volume.
Each block can trigger an exit even if the other block still favors the current side; the net effect is a gradual tug-of-war between the two modules.
No automatic stop-loss or take-profit is applied. Risk management should be handled externally or by tuning the permission flags.
Parameters
Parameter
Description
BykovTrend Candle
Data type (timeframe) for the BykovTrend calculation.
Williams %R Period
Lookback for Williams %R.
Risk Offset
Shifts the Williams %R thresholds (33 - Risk). Larger values tighten bullish thresholds and loosen bearish ones.
Signal Bar
Delay (number of completed candles) before acting on a BykovTrend color.
Allow Long/Short Entries
Enable or disable BykovTrend-driven entries.
Allow Long/Short Exits
Enable or disable BykovTrend-driven exits.
ColorX2MA Candle
Data type (timeframe) for the ColorX2MA block.
First/Second MA Method
Smoothing method for each stage (SMA, EMA, SMMA, LWMA, Jurik).
First/Second MA Length
Period length for each smoothing stage.
First/Second MA Phase
Compatibility parameter retained from the original EA; current implementation keeps it for documentation but Jurik smoothing uses its internal defaults.
Only the moving-average types available in StockSharp are supported. Exotic smoothings from the MetaTrader library (JurX, Parabolic, T3, VIDYA, AMA) are not reproduced; choose among SMA, EMA, SMMA, LWMA, or Jurik.
Phase parameters are preserved for reference but do not alter the built-in StockSharp indicators.
The strategy assumes the Volume property is configured; otherwise entries will not place orders.
Because both modules can trade independently, the resulting order flow may differ from MetaTrader installations that segregate trades by magic numbers.
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>
/// BykovTrend + ColorX2MA strategy (simplified). Uses Williams %R for trend
/// detection combined with double EMA smoothing for entry confirmation.
/// </summary>
public class BykovTrendColorX2MaStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaFastLength;
private readonly StrategyParam<int> _emaSlowLength;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int EmaFastLength
{
get => _emaFastLength.Value;
set => _emaFastLength.Value = value;
}
public int EmaSlowLength
{
get => _emaSlowLength.Value;
set => _emaSlowLength.Value = value;
}
public BykovTrendColorX2MaStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Candles", "General");
_emaFastLength = Param(nameof(EmaFastLength), 9)
.SetGreaterThanZero()
.SetDisplay("EMA Fast", "Fast EMA period", "Indicators");
_emaSlowLength = Param(nameof(EmaSlowLength), 21)
.SetGreaterThanZero()
.SetDisplay("EMA Slow", "Slow EMA period", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var emaFast = new ExponentialMovingAverage { Length = EmaFastLength };
var emaSlow = new ExponentialMovingAverage { Length = EmaSlowLength };
decimal prevFast = 0, prevSlow = 0;
var hasPrev = false;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(emaFast, emaSlow, (ICandleMessage candle, decimal fastVal, decimal slowVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!hasPrev)
{
prevFast = fastVal;
prevSlow = slowVal;
hasPrev = true;
return;
}
if (!IsFormedAndOnlineAndAllowTrading())
{
prevFast = fastVal;
prevSlow = slowVal;
return;
}
// EMA crossover with candle direction confirmation
var bullishCross = prevFast <= prevSlow && fastVal > slowVal;
var bearishCross = prevFast >= prevSlow && fastVal < slowVal;
var close = candle.ClosePrice;
var open = candle.OpenPrice;
if (bullishCross && close > open && Position <= 0)
BuyMarket();
else if (bearishCross && close < open && Position >= 0)
SellMarket();
prevFast = fastVal;
prevSlow = slowVal;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, emaFast);
DrawIndicator(area, emaSlow);
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 ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class bykov_trend_color_x2_ma_strategy(Strategy):
def __init__(self):
super(bykov_trend_color_x2_ma_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Candles", "General")
self._ema_fast_length = self.Param("EmaFastLength", 9) \
.SetDisplay("EMA Fast", "Fast EMA period", "Indicators")
self._ema_slow_length = self.Param("EmaSlowLength", 21) \
.SetDisplay("EMA Slow", "Slow EMA period", "Indicators")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
@property
def CandleType(self):
return self._candle_type.Value
@property
def EmaFastLength(self):
return self._ema_fast_length.Value
@property
def EmaSlowLength(self):
return self._ema_slow_length.Value
def OnReseted(self):
super(bykov_trend_color_x2_ma_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(bykov_trend_color_x2_ma_strategy, self).OnStarted2(time)
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
ema_fast = ExponentialMovingAverage()
ema_fast.Length = self.EmaFastLength
ema_slow = ExponentialMovingAverage()
ema_slow.Length = self.EmaSlowLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(ema_fast, ema_slow, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema_fast)
self.DrawIndicator(area, ema_slow)
self.DrawOwnTrades(area)
def _on_process(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fv = float(fast_value)
sv = float(slow_value)
if not self._has_prev:
self._prev_fast = fv
self._prev_slow = sv
self._has_prev = True
return
close = float(candle.ClosePrice)
open_p = float(candle.OpenPrice)
bullish_cross = self._prev_fast <= self._prev_slow and fv > sv
bearish_cross = self._prev_fast >= self._prev_slow and fv < sv
if bullish_cross and close > open_p and self.Position <= 0:
self.BuyMarket()
elif bearish_cross and close < open_p and self.Position >= 0:
self.SellMarket()
self._prev_fast = fv
self._prev_slow = sv
def CreateClone(self):
return bykov_trend_color_x2_ma_strategy()