Multicurrency Trading Panel Strategy
This strategy emulates the behavior of the original MQL "Multicurrency trading panel" expert advisor. It monitors three currency pairs (EURUSD, USDJPY, GBPUSD) and compares the latest candle with the previous one using seven simple metrics (open, high, low, (high+low)/2, close, (high+low+close)/3, (high+low+close+close)/4). For each comparison, a BUY or SELL score is increased. When automatic trading is enabled, the strategy opens or reverses positions on a pair if BUY score exceeds SELL score or vice versa.
Parameters
- EURUSD – first security.
- USDJPY – second security.
- GBPUSD – third security.
- Candle Type – timeframe of candles.
- Auto Trade – toggle to allow automatic order placement.
The strategy is a simplified demo and is not intended for real trading.
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Strategy that compares consecutive candle metrics and trades based on majority direction.
/// </summary>
public class MulticurrencyTradingPanelStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleTypeParam;
private ICandleMessage _prev;
/// <summary>
/// Candle type used for signal calculation.
/// </summary>
public DataType CandleType
{
get => _candleTypeParam.Value;
set => _candleTypeParam.Value = value;
}
/// <summary>
/// Initializes a new instance of the strategy.
/// </summary>
public MulticurrencyTradingPanelStrategy()
{
_candleTypeParam = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for analysis", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
if (CandleType != null)
yield return (Security, CandleType);
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var warmup = new ExponentialMovingAverage { Length = 5 };
SubscribeCandles(CandleType)
.Bind(warmup, ProcessCandle)
.Start();
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prev = null;
}
private void ProcessCandle(ICandleMessage candle, decimal _warmupVal)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (_prev == null)
{
_prev = candle;
return;
}
var buy = 0;
var sell = 0;
void Compare(decimal current, decimal previous)
{
if (current > previous)
buy++;
else
sell++;
}
Compare(candle.OpenPrice, _prev.OpenPrice);
Compare(candle.HighPrice, _prev.HighPrice);
Compare(candle.LowPrice, _prev.LowPrice);
Compare((candle.HighPrice + candle.LowPrice) / 2m, (_prev.HighPrice + _prev.LowPrice) / 2m);
Compare(candle.ClosePrice, _prev.ClosePrice);
Compare((candle.HighPrice + candle.LowPrice + candle.ClosePrice) / 3m,
(_prev.HighPrice + _prev.LowPrice + _prev.ClosePrice) / 3m);
Compare((candle.HighPrice + candle.LowPrice + candle.ClosePrice + candle.ClosePrice) / 4m,
(_prev.HighPrice + _prev.LowPrice + _prev.ClosePrice + _prev.ClosePrice) / 4m);
if (buy > sell && Position <= 0)
BuyMarket();
else if (sell > buy && Position >= 0)
SellMarket();
_prev = 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
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class multicurrency_trading_panel_strategy(Strategy):
def __init__(self):
super(multicurrency_trading_panel_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe for analysis", "General")
self._prev = None
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(multicurrency_trading_panel_strategy, self).OnReseted()
self._prev = None
def OnStarted2(self, time):
super(multicurrency_trading_panel_strategy, self).OnStarted2(time)
warmup = ExponentialMovingAverage()
warmup.Length = 5
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(warmup, self.process_candle).Start()
def process_candle(self, candle, warmup_val):
if candle.State != CandleStates.Finished:
return
if self._prev is None:
self._prev = candle
return
buy = 0
sell = 0
cur_open = float(candle.OpenPrice)
cur_high = float(candle.HighPrice)
cur_low = float(candle.LowPrice)
cur_close = float(candle.ClosePrice)
prev_open = float(self._prev.OpenPrice)
prev_high = float(self._prev.HighPrice)
prev_low = float(self._prev.LowPrice)
prev_close = float(self._prev.ClosePrice)
if cur_open > prev_open:
buy += 1
else:
sell += 1
if cur_high > prev_high:
buy += 1
else:
sell += 1
if cur_low > prev_low:
buy += 1
else:
sell += 1
if (cur_high + cur_low) / 2.0 > (prev_high + prev_low) / 2.0:
buy += 1
else:
sell += 1
if cur_close > prev_close:
buy += 1
else:
sell += 1
if (cur_high + cur_low + cur_close) / 3.0 > (prev_high + prev_low + prev_close) / 3.0:
buy += 1
else:
sell += 1
if (cur_high + cur_low + cur_close + cur_close) / 4.0 > (prev_high + prev_low + prev_close + prev_close) / 4.0:
buy += 1
else:
sell += 1
if buy > sell and self.Position <= 0:
self.BuyMarket()
elif sell > buy and self.Position >= 0:
self.SellMarket()
self._prev = candle
def CreateClone(self):
return multicurrency_trading_panel_strategy()