This strategy is a StockSharp port of the Advanced EA Panel utility from MQL5. The original expert advisor provided a manual trading dashboard with multi-timeframe analytics, pivot management, and quick trade buttons. The C# implementation re-creates those analytical capabilities inside an automated strategy so they remain available without an on-chart control panel.
Key features
Aggregates nine timeframes (M1 … MN1) and tracks EMA(3/6/9), SMA(50/200), CCI(14) and RSI(21) votes for each horizon.
Calculates floor-trader, Woodie or Camarilla pivot levels on a configurable candle series.
Monitors volatility with an ATR feed and logs every significant change.
Keeps an internal risk panel by computing stop distance, reward distance and live risk/reward ratio for the active position.
Supports automatic order execution when the multi-timeframe vote exceeds a configurable threshold. Opposite trades are flattened before reversing, exactly like pressing the panel buttons.
Leverages StartProtection so stop-loss and take-profit guards survive restarts, mirroring the protection logic of the original panel.
Trading logic
Each timeframe subscription produces indicator values for EMA(3/6/9), SMA(50/200), CCI(14) and RSI(21). A bullish vote is added when the close is above the moving averages, CCI is above +100, and RSI is above 60. Bearish votes are produced for the opposite conditions. Neutral readings do not contribute to the score.
The total score across ready timeframes is compared against DirectionalThreshold. Scores ≥ threshold generate a Buy signal; scores ≤ –threshold generate a Sell signal.
When auto trading is enabled the strategy:
Closes the opposite position with ClosePosition() before sending the reversing order.
Sends a market order sized according to Volume, rounded to the nearest Security.VolumeStep.
Relies on StartProtection to attach stop-loss/take-profit brackets expressed in pips.
ATR from the primary candle series is logged. Any change beyond the rounding precision prints a fresh volatility report.
Pivot levels are recomputed whenever the pivot timeframe produces a finished candle. The log shows PP, R1–R4 and S1–S4 so they can be used as discretionary levels or exported to dashboards.
Parameters
Name
Description
Group
Default
Volume
Trading volume in lots. Rounded to VolumeStep before sending orders.
Trading
1.0
StopLossPips
Distance from entry to stop-loss expressed in price steps. 0 disables the stop.
Risk
50
TakeProfitPips
Distance from entry to take-profit in price steps. 0 disables the take.
Risk
100
VolatilityPeriod
ATR lookback length used for volatility logging.
Volatility
14
PrimaryCandleType
Candle type driving ATR calculations and chart drawing.
General
15 minute candles
PivotCandleType
Candle type used for pivot level recalculation.
General
1 hour candles
DirectionalThreshold
Absolute score required to trigger a Buy/Sell signal.
Signals
3
AutoTradingEnabled
Enables automatic execution of detected signals.
Signals
true
PivotFormula
Pivot preset (Classic, Woodie, Camarilla).
General
Classic
Risk management
StartProtection attaches price-based brackets calculated from StopLossPips and TakeProfitPips (converted to absolute price using PriceStep).
_entryPrice, _stopPrice and _takePrice are updated on fills so the strategy can log risk, reward and risk/reward ratio in pips.
If auto trading is disabled the risk monitor still works for manual entries executed outside the strategy.
Differences from the MQL5 panel
The original EA displayed buttons and draggable lines on the chart; the StockSharp version exposes the same analytics through logs and strategy parameters. All comments inside the code explain how to extend or hook the results into a UI if required.
Position management is automated. Clicking Buy, Sell, Reverse or Close is replaced by RequestExecution, SendOrder and ClosePosition() in reaction to the multi-timeframe score.
Points of interest, manual tab edits and chart object manipulation are not ported. Instead, pivots are recalculated programmatically and logged. Traders can consume the log or extend the strategy to draw objects if desired.
Volatility, risk metrics and pivots persist across restarts because they are recalculated from live data instead of relying on chart objects.
Usage notes
Attach the strategy to a symbol and ensure the connector provides all candle types listed in PanelTimeFrames. Missing data will delay signal generation until at least one candle per timeframe is finished.
Adjust DirectionalThreshold to control sensitivity. Higher thresholds demand more agreement across timeframes before trading.
Set AutoTradingEnabled = false to use the module as an informational dashboard while placing orders manually from another tool.
The class adds default chart rendering for primary candles, ATR and own trades. Remove or extend these calls if a custom visualization is required.
Conversion summary
UI actions → Strategy methods. Panel button handlers (EAPanelClickHandler, T0ClickHandler, etc.) are mapped to order execution helpers that preserve the buy/sell/reverse/close flow.
Pivot formulas. The MQL5 spinners allowed independent formulas per level; this port keeps the preset combinations (Classic, Woodie, Camarilla) that the panel offered via its quick-select buttons.
Indicator tracking. Native MQL5 indicator handles are replaced by ExponentialMovingAverage, SimpleMovingAverage, CommodityChannelIndex and RelativeStrengthIndex from StockSharp with Bind callbacks.
Risk panel. All risk/rward calculations that were previously rendered in edit boxes are now logged and can be consumed by any monitoring component.
The strategy therefore preserves the intent of the Advanced EA Panel—centralized situational awareness with quick reaction logic—while presenting it as a fully automated StockSharp strategy ready for optimization or discretionary monitoring.
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>
/// Advanced EA Panel strategy using EMA crossover.
/// Buys when fast EMA crosses above slow EMA, sells on reverse.
/// </summary>
public class AdvancedEaPanelStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _stopLossPoints;
private readonly StrategyParam<int> _takeProfitPoints;
private ExponentialMovingAverage _fast;
private ExponentialMovingAverage _slow;
private decimal _prevFast;
private decimal _prevSlow;
private decimal _entryPrice;
private int _cooldown;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }
public AdvancedEaPanelStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 14).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
}
protected override void OnReseted()
{
base.OnReseted();
_fast = null; _slow = null;
_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_fast = new ExponentialMovingAverage { Length = FastPeriod };
_slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
subscription.Bind(_fast, _slow, ProcessCandle);
subscription.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished) return;
if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }
var close = candle.ClosePrice;
var step = Security?.PriceStep ?? 1m;
if (Position > 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
else if (Position < 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }
_prevFast = fastValue; _prevSlow = slowValue;
}
}
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 advanced_ea_panel_strategy(Strategy):
def __init__(self):
super(advanced_ea_panel_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 14) \
.SetDisplay("Fast Period", "Fast MA period", "Indicator")
self._slow_period = self.Param("SlowPeriod", 50) \
.SetDisplay("Slow Period", "Slow MA period", "Indicator")
self._stop_loss_points = self.Param("StopLossPoints", 200) \
.SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk")
self._take_profit_points = self.Param("TakeProfitPoints", 400) \
.SetDisplay("Take Profit", "Take-profit in price steps", "Risk")
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
@property
def fast_period(self):
return self._fast_period.Value
@property
def slow_period(self):
return self._slow_period.Value
@property
def stop_loss_points(self):
return self._stop_loss_points.Value
@property
def take_profit_points(self):
return self._take_profit_points.Value
def OnReseted(self):
super(advanced_ea_panel_strategy, self).OnReseted()
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
def OnStarted2(self, time):
super(advanced_ea_panel_strategy, self).OnStarted2(time)
self._fast = ExponentialMovingAverage()
self._fast.Length = self.fast_period
self._slow = ExponentialMovingAverage()
self._slow.Length = self.slow_period
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(5)))
subscription.Bind(self._fast, self._slow, self._process_candle)
subscription.Start()
def _process_candle(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fast_val = float(fast_value)
slow_val = float(slow_value)
if not self._fast.IsFormed or not self._slow.IsFormed:
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_fast = fast_val
self._prev_slow = slow_val
return
close = float(candle.ClosePrice)
step = float(self.Security.PriceStep) if self.Security is not None and self.Security.PriceStep is not None else 1.0
if self.Position > 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close <= self._entry_price - self.stop_loss_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close >= self._entry_price + self.take_profit_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
elif self.Position < 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close >= self._entry_price + self.stop_loss_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close <= self._entry_price - self.take_profit_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._prev_fast <= self._prev_slow and fast_val > slow_val and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._entry_price = close
self._cooldown = 100
elif self._prev_fast >= self._prev_slow and fast_val < slow_val and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._entry_price = close
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return advanced_ea_panel_strategy()