This strategy replicates the functionality of the original Shuriken Lite MQL tool. It tracks executed trades on the account and groups them by numerical identifiers known as magic numbers. For each group the strategy calculates:
Number of trades
Winning and losing trades
Total profit or loss in pips
Profit factor
The statistics are logged after every new trade when score display is enabled.
Parameters
Magic Numbers — comma-separated list of identifiers used to group trades. Each identifier should match the numeric value placed in the order comment.
Show Scores — enable or disable logging of statistics.
Usage
Set the desired magic numbers in the parameter.
Run the strategy alongside other strategies that set numeric comments on their orders.
Check the log for the aggregated performance metrics.
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>
/// Shuriken Lite - fast EMA/RSI scalping strategy.
/// </summary>
public class ShurikenLiteStrategy : Strategy
{
private readonly StrategyParam<int> _emaLength;
private readonly StrategyParam<int> _rsiLength;
private readonly StrategyParam<DataType> _candleType;
public int EmaLength { get => _emaLength.Value; set => _emaLength.Value = value; }
public int RsiLength { get => _rsiLength.Value; set => _rsiLength.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public ShurikenLiteStrategy()
{
_emaLength = Param(nameof(EmaLength), 14)
.SetGreaterThanZero()
.SetDisplay("EMA", "EMA period", "Indicators");
_rsiLength = Param(nameof(RsiLength), 7)
.SetGreaterThanZero()
.SetDisplay("RSI", "RSI period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var ema = new ExponentialMovingAverage { Length = EmaLength };
var rsi = new RelativeStrengthIndex { Length = RsiLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ema, rsi, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal emaVal, decimal rsi)
{
if (candle.State != CandleStates.Finished)
return;
var close = candle.ClosePrice;
// Buy when RSI oversold
if (rsi < 30 && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
// Sell when RSI overbought
else if (rsi > 70 && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
}
}
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, RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class shuriken_lite_strategy(Strategy):
def __init__(self):
super(shuriken_lite_strategy, self).__init__()
self._ema_length = self.Param("EmaLength", 14) \
.SetDisplay("EMA", "EMA period", "Indicators")
self._rsi_length = self.Param("RsiLength", 7) \
.SetDisplay("RSI", "RSI period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
@property
def ema_length(self):
return self._ema_length.Value
@property
def rsi_length(self):
return self._rsi_length.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnStarted2(self, time):
super(shuriken_lite_strategy, self).OnStarted2(time)
ema = ExponentialMovingAverage()
ema.Length = self.ema_length
rsi = RelativeStrengthIndex()
rsi.Length = self.rsi_length
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(ema, rsi, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def on_process(self, candle, ema_val, rsi):
if candle.State != CandleStates.Finished:
return
close = candle.ClosePrice
# Buy when RSI oversold
if rsi < 30 and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
# Sell when RSI overbought
elif rsi > 70 and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
def CreateClone(self):
return shuriken_lite_strategy()