Die MA Price Cross-Strategie ist eine direkte Umwandlung des MetaTrader 4-Expertenberaters „MA Price Cross“ in den StockSharp High-Level-API. Es wartet darauf, dass der ausgewählte gleitende Durchschnitt den aktuellen Preis kreuzt, während der Handel innerhalb eines konfigurierbaren Zeitfensters zulässig ist. Wenn die Kreuzung von unten erfolgt, eröffnet der Algorithmus eine Long-Position; Wenn die Kreuzung von oben erfolgt, wird eine Short-Position eröffnet. Schützende Stop-Loss- und Take-Profit-Abstände werden in MetaTrader Punkten definiert und mithilfe des PriceStep des Instruments automatisch in absolute Preisversätze umgerechnet.
Im Gegensatz zur ursprünglichen MQL-Implementierung, die auf jeden Tick reagiert, arbeitet die StockSharp-Version mit fertigen Kerzen und verwendet das High-Level-Abonnement SubscribeCandles. Dadurch wird sichergestellt, dass Handelsentscheidungen einmal pro Balken ausgeführt werden und mit der Indikatorbindungspipeline kompatibel bleiben. Der gleitende Durchschnitt kann so konfiguriert werden, dass er allen vier MetaTrader-Modi entspricht, und akzeptiert verschiedene Preisquellen (Schlusskurs, Eröffnungstag, Höchstkurs, Tiefstkurs, Medianwert, typisch, gewichtet).
Handelslogik
Warten Sie, bis die aktuelle Zeit in das Handelsfenster [StartTime, StopTime) fällt. Nachtfenster werden dadurch unterstützt, dass sie um Mitternacht gewickelt werden.
Verarbeiten Sie nur fertige Kerzen. Füttere den konfigurierten gleitenden Durchschnitt mit dem gewählten angewandten Preis.
Speichern Sie den vorherigen gleitenden Durchschnittswert, um die in MetaTrader verwendete iMA-Verschiebungslogik zu emulieren.
Wenn der vorherige Durchschnitt unter dem letzten Preis und der neue Durchschnitt über dem Preis liegt, eröffnen Sie eine Long-Position (oder kehren Sie diese um).
Wenn der vorherige Durchschnitt über dem letzten Preis liegt und der neue Durchschnitt unter dem Preis, eröffnen Sie eine Short-Position (oder gehen Sie eine Short-Position ein).
Bevor Sie eine neue Position auf der gegenüberliegenden Seite öffnen, reduzieren Sie alle vorhandenen Belichtungen, um die OrdersTotal() == 0-Beschränkung des ursprünglichen Codes widerzuspiegeln.
Starten Sie einen virtuellen Stop-Loss und Take-Profit mit Distanzen ausgedrückt in MetaTrader Punkten multipliziert mit dem aktuellen Instrument PriceStep.
Standardparameter
Parameter
Standard
Beschreibung
CandleType
TimeFrame(1m)
Kerzenserie, die alle Berechnungen vorantreibt.
MaPeriod
160
Anzahl der vom gleitenden Durchschnitt verwendeten Balken.
MaMethod
Simple
Typ des gleitenden Durchschnitts: Einfach, Exponentiell, Geglättet oder LinearGewichtet.
PriceType
Close
Preisquelle, die an den gleitenden Durchschnitt weitergeleitet wird (Schluss/Eröffnung/Hoch/Tief/Median/typisch/gewichtet).
StartTime
01:00
Tageszeit, zu der der Handel aktiv wird.
StopTime
22:00
Tageszeit, zu der neue Einträge enden.
StopLossPoints
200
MetaTrader Punkte umgerechnet in einen absoluten Schutzstoppabstand.
TakeProfitPoints
600
MetaTrader Punkte werden in eine absolute Gewinnzieldistanz umgewandelt.
OrderVolume
0.1
Mit Marktaufträgen übermitteltes Standardvolumen.
Notizen
Wenn StartTime gleich StopTime ist, ist der Zeitfilter deaktiviert und der Handel ist den ganzen Tag über zulässig.
Wenn StopLossPoints oder TakeProfitPoints gleich Null ist, wird die entsprechende Schutzstufe nicht registriert.
Der Zeitfilter verwendet die Kerzenschlusszeit (candle.CloseTime.TimeOfDay), sodass er sich an die von MarketDataConnector bereitgestellte Börsenzeitzone anpasst.
Wenn die Sicherheit PriceStep nicht verfügbar macht, werden punktbasierte Entfernungen direkt ohne Skalierung verwendet.
Ursprüngliche Strategiereferenz
Quelle: MQL/44133/MA Price Cross.mq4
Autor: JBlanked (2023)
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Simplified from "MA Price Cross" MetaTrader expert.
/// Enters when SMA crosses above/below the current close price.
/// </summary>
public class MaPriceCrossStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _maPeriod;
private ExponentialMovingAverage _sma;
private decimal? _prevAverage;
private decimal? _prevClose;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int MaPeriod
{
get => _maPeriod.Value;
set => _maPeriod.Value = value;
}
public MaPriceCrossStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for MA cross detection", "General");
_maPeriod = Param(nameof(MaPeriod), 100)
.SetGreaterThanZero()
.SetDisplay("MA Period", "SMA period", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_sma = new ExponentialMovingAverage { Length = MaPeriod };
_prevAverage = null;
_prevClose = null;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_sma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _sma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal smaValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!_sma.IsFormed)
{
_prevAverage = smaValue;
_prevClose = candle.ClosePrice;
return;
}
if (_prevAverage is null || _prevClose is null)
{
_prevAverage = smaValue;
_prevClose = candle.ClosePrice;
return;
}
var close = candle.ClosePrice;
var volume = Volume;
if (volume <= 0)
volume = 1;
// MA was below price, now crosses above -> sell signal (price goes under MA)
var sellSignal = _prevClose.Value >= _prevAverage.Value && close < smaValue;
// MA was above price, now crosses below -> buy signal (price goes above MA)
var buySignal = _prevClose.Value <= _prevAverage.Value && close > smaValue;
if (buySignal)
{
if (Position <= 0)
BuyMarket(Position < 0 ? Math.Abs(Position) + volume : volume);
}
else if (sellSignal)
{
if (Position >= 0)
SellMarket(Position > 0 ? Math.Abs(Position) + volume : volume);
}
_prevAverage = smaValue;
_prevClose = close;
}
/// <inheritdoc />
protected override void OnReseted()
{
_sma = null;
_prevAverage = null;
_prevClose = null;
base.OnReseted();
}
}
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 ma_price_cross_strategy(Strategy):
def __init__(self):
super(ma_price_cross_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60)))
self._ma_period = self.Param("MaPeriod", 100)
self._prev_average = None
self._prev_close = None
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def MaPeriod(self):
return self._ma_period.Value
@MaPeriod.setter
def MaPeriod(self, value):
self._ma_period.Value = value
def OnReseted(self):
super(ma_price_cross_strategy, self).OnReseted()
self._prev_average = None
self._prev_close = None
def OnStarted2(self, time):
super(ma_price_cross_strategy, self).OnStarted2(time)
self._prev_average = None
self._prev_close = None
sma = ExponentialMovingAverage()
sma.Length = self.MaPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(sma, self._process_candle).Start()
def _process_candle(self, candle, sma_value):
if candle.State != CandleStates.Finished:
return
sma_val = float(sma_value)
close = float(candle.ClosePrice)
if self._prev_average is None or self._prev_close is None:
self._prev_average = sma_val
self._prev_close = close
return
# Price crosses above MA -> buy
buy_signal = self._prev_close <= self._prev_average and close > sma_val
# Price crosses below MA -> sell
sell_signal = self._prev_close >= self._prev_average and close < sma_val
if buy_signal:
if self.Position <= 0:
self.BuyMarket()
elif sell_signal:
if self.Position >= 0:
self.SellMarket()
self._prev_average = sma_val
self._prev_close = close
def CreateClone(self):
return ma_price_cross_strategy()