Diese Beispielstrategie ist ein vereinfachter Port des MQL4-Skripts "Tester v0.14", das ursprünglich für EURUSD auf dem H4-Zeitrahmen entwickelt wurde.
Logik
Berechnet einen einfachen gleitenden Durchschnitt mit 14 Perioden und MACD.
Generiert ein Kaufsignal, wenn der Schlusskurs über dem SMA liegt und MACD positiv ist.
Generiert ein Verkaufssignal, wenn der Schlusskurs unter dem SMA liegt und MACD negativ ist.
Nach dem Öffnen einer Order wird die Position nach einer konfigurierbaren Anzahl von Bars geschlossen.
Dieser Port verwendet die High-Level-StockSharp-API und basiert auf SubscribeCandles und Bind zum Empfangen von Indikatorwerten.
Parameter
MinSignSum – Mindestzahl der erforderlichen Signale, um eine Position zu eröffnen.
Risk – Prozentsatz des Kontosaldos für das Money Management.
TakeProfit / StopLoss – feste Levels in Punkten.
BarsNumber – Anzahl der Bars, für die eine Position offen bleibt.
Die originale MQL-Datei enthielt Hunderte von Regelkombinationen. Dieses C#-Beispiel veranschaulicht die Struktur anhand eines reduzierten Regelsatzes zur besseren Übersichtlichkeit.
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>
/// Tester strategy using SMA and MACD for entries.
/// Closes after specified number of bars.
/// </summary>
public class TesterV014Strategy : Strategy
{
private readonly StrategyParam<int> _barsNumber;
private readonly StrategyParam<DataType> _candleType;
private int _barsCounter;
private bool _positionOpened;
public int BarsNumber { get => _barsNumber.Value; set => _barsNumber.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public TesterV014Strategy()
{
_barsNumber = Param(nameof(BarsNumber), 3)
.SetGreaterThanZero()
.SetDisplay("Bars Number", "Holding period in bars", "General");
_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 OnReseted()
{
base.OnReseted();
_barsCounter = 0;
_positionOpened = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var sma = new SimpleMovingAverage { Length = 14 };
var macd = new MovingAverageConvergenceDivergence();
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(sma, macd, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal smaVal, decimal macdVal)
{
if (candle.State != CandleStates.Finished)
return;
// Close after specified bars
if (_positionOpened)
{
_barsCounter++;
if (_barsCounter >= BarsNumber)
{
if (Position > 0)
SellMarket();
else if (Position < 0)
BuyMarket();
_positionOpened = false;
_barsCounter = 0;
}
}
// Entry
if (Position == 0 && !_positionOpened)
{
if (candle.ClosePrice > smaVal && macdVal > 0)
{
BuyMarket();
_barsCounter = 0;
_positionOpened = true;
}
else if (candle.ClosePrice < smaVal && macdVal < 0)
{
SellMarket();
_barsCounter = 0;
_positionOpened = true;
}
}
}
}
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 MovingAverageConvergenceDivergence, SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class tester_v014_strategy(Strategy):
def __init__(self):
super(tester_v014_strategy, self).__init__()
self._bars_number = self.Param("BarsNumber", 3) \
.SetDisplay("Bars Number", "Holding period in bars", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._bars_counter = 0
self._position_opened = False
@property
def bars_number(self):
return self._bars_number.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(tester_v014_strategy, self).OnReseted()
self._bars_counter = 0
self._position_opened = False
def OnStarted2(self, time):
super(tester_v014_strategy, self).OnStarted2(time)
sma = SimpleMovingAverage()
sma.Length = 14
macd = MovingAverageConvergenceDivergence()
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(sma, macd, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def on_process(self, candle, sma_val, macd_val):
if candle.State != CandleStates.Finished:
return
# Close after specified bars
if self._position_opened:
self._bars_counter += 1
if self._bars_counter >= self.bars_number:
if self.Position > 0:
self.SellMarket()
elif self.Position < 0:
self.BuyMarket()
self._position_opened = False
self._bars_counter = 0
# Entry
if self.Position == 0 and not self._position_opened:
if candle.ClosePrice > sma_val and macd_val > 0:
self.BuyMarket()
self._bars_counter = 0
self._position_opened = True
elif candle.ClosePrice < sma_val and macd_val < 0:
self.SellMarket()
self._bars_counter = 0
self._position_opened = True
def CreateClone(self):
return tester_v014_strategy()