Die Above Below MA Strategie bildet den MetaTrader-Expert-Advisor Above Below MA (barabashkakvn's edition) nach. Sie überwacht, wie weit aktuelle Preise im Verhältnis zu einem konfigurierbaren gleitenden Durchschnitt handeln, und erlaubt Trades nur, wenn der Preis auf der „falschen" Seite des Durchschnitts liegt — mindestens um eine definierte Distanz — während der Durchschnitt selbst in die erwartete Richtung tendiert. Die Logik wurde auf die StockSharp High-Level-API portiert und wird ausschließlich auf abgeschlossenen Kerzen ausgeführt.
Übersicht
Marktregime: Funktioniert am besten bei Instrumenten, die einen gleitenden Durchschnitt häufig retesten, bevor sie den Trend fortsetzen.
Instrumente: Jedes von Ihrer StockSharp-Verbindung unterstützte Instrument. Forex-Paare profitieren am meisten, da das Originalskript die Distanz in Pips maß.
Zeitrahmen: Über den Parameter Candle Type einstellbar (Standard: 1-Minuten-Zeitrahmen).
Positionsrichtung: Sowohl Long- als auch Short-Trades werden unterstützt, aber es kann zu jedem Zeitpunkt nur eine Nettoposition bestehen.
Strategie-Logik
Es wird ein gleitender Durchschnitt auf der ausgewählten Kerzenserie berechnet. Die Mittelungsmethode (SMA, EMA, SMMA, WMA), der angewandte Preis (close, open, high, low, median, typical, weighted) und die Vorwärtsverschiebung replizieren die MetaTrader-Eingaben.
Die in Pips ausgedrückte Mindestdistanz wird mit dem PriceStep des Instruments in einen tatsächlichen Preisversatz umgerechnet. Wenn der Broker keinen Preisschritt veröffentlicht, wird der Distanzfilter automatisch übersprungen.
Bei jeder abgeschlossenen Kerze:
Long-Setup:
Eröffnung und Schluss der Kerze müssen mindestens die konfigurierte Distanz unterhalb des verschobenen gleitenden Durchschnitts liegen.
Der gleitende Durchschnitt muss gegenüber der vorherigen Kerze steigen.
Short-Setup:
Eröffnung und Schluss der Kerze müssen mindestens die konfigurierte Distanz oberhalb des verschobenen gleitenden Durchschnitts liegen.
Der gleitende Durchschnitt muss gegenüber der vorherigen Kerze fallen.
Die Strategie schließt jede entgegengesetzte Position, bevor eine neue Marktorder in der Signalrichtung gesendet wird. Gleichzeitige Long/Short-Exposition ist nicht erlaubt.
Alle Handelsentscheidungen werden auf abgeschlossenen Kerzen getroffen, um wiederholte Einstiege innerhalb eines sich formierenden Balkens zu vermeiden. Orders werden über BuyMarket oder SellMarket mit dem konfigurierten Volumen ausgeführt.
Parameter
Parameter
Beschreibung
MaPeriod
Länge des gleitenden Durchschnitts. Standard 6.
MaShift
Anzahl der Kerzen, um die der gleitende Durchschnitt vorwärts verschoben wird. Ein Wert von 0 verwendet den aktuellen Balken, n verwendet den Wert von vor n Balken. Standard 0.
MaMethod
Typ des gleitenden Durchschnitts: Simple, Exponential, Smoothed oder Weighted. Standard Exponential.
AppliedPrice
Preisquelle: close, open, high, low, median, typical oder weighted. Standard Typical.
MinimumDistancePips
Erforderliche Distanz in Pips zwischen den Kerzenpreisen und dem gleitenden Durchschnitt. Wird mit PriceStep umgerechnet. Standard 5.
CandleType
Kerzentyp, der Indikatoraktualisierungen antreibt. Standard: 1-Minuten-Zeitrahmen.
TradeVolume
Ordervolumen für neue Einstiege. Standard 1.
Zusätzliche Hinweise
Keine Stop-Loss- oder Take-Profit-Logik ist enthalten. Das Risikomanagement muss über Portfolio-Einstellungen oder externe Module implementiert werden.
Der Verschiebungs-Puffer des gleitenden Durchschnitts wird minimal gehalten und respektiert die „keine Sammlungen"-Richtlinie, indem nur die für die angegebene Verschiebung erforderlichen Werte gespeichert werden.
Wenn PriceStep nicht verfügbar ist, kann der Mindestdistanzfilter nicht ausgewertet werden, sodass Einstiege ausschließlich von den Bedingungen des gleitenden Durchschnitts abhängen.
Die Strategie zeichnet die Kerzenserie, den gleitenden Durchschnittsindikator und Ihre Trades im Standard-Chartbereich, wenn ein Chart-Container verfügbar ist.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Above/Below MA strategy. Trades when price crosses above or below a moving average.
/// </summary>
public class AboveBelowMaStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _maPeriod;
private decimal? _prevClose;
private decimal? _prevMa;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int MaPeriod
{
get => _maPeriod.Value;
set => _maPeriod.Value = value;
}
public AboveBelowMaStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_maPeriod = Param(nameof(MaPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("MA Period", "Moving average period", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevClose = null;
_prevMa = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevClose = null;
_prevMa = null;
var sma = new SimpleMovingAverage { Length = MaPeriod };
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 maVal)
{
if (candle.State != CandleStates.Finished)
return;
var close = candle.ClosePrice;
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevClose = close;
_prevMa = maVal;
return;
}
if (_prevClose == null || _prevMa == null)
{
_prevClose = close;
_prevMa = maVal;
return;
}
// Price crosses above MA → buy
if (_prevClose.Value <= _prevMa.Value && close > maVal && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
// Price crosses below MA → sell
else if (_prevClose.Value >= _prevMa.Value && close < maVal && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
_prevClose = close;
_prevMa = maVal;
}
}
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 CandleStates
from StockSharp.Algo.Indicators import SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
from datatype_extensions import *
class above_below_ma_strategy(Strategy):
"""
Above/Below MA strategy. Trades when price crosses above or below a moving average.
"""
def __init__(self):
super(above_below_ma_strategy, self).__init__()
self._candle_type = self.Param("CandleType", tf(5)) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._ma_period = self.Param("MaPeriod", 20) \
.SetGreaterThanZero() \
.SetDisplay("MA Period", "Moving average period", "Indicators")
self._prev_close = None
self._prev_ma = 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(above_below_ma_strategy, self).OnReseted()
self._prev_close = None
self._prev_ma = None
def OnStarted2(self, time):
super(above_below_ma_strategy, self).OnStarted2(time)
self._prev_close = None
self._prev_ma = None
sma = SimpleMovingAverage()
sma.Length = self.MaPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(sma, self.ProcessCandle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, sma)
self.DrawOwnTrades(area)
def ProcessCandle(self, candle, ma_val):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
if self._prev_close is None or self._prev_ma is None:
self._prev_close = close
self._prev_ma = ma_val
return
# Price crosses above MA -> buy
if self._prev_close <= self._prev_ma and close > ma_val and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
# Price crosses below MA -> sell
elif self._prev_close >= self._prev_ma and close < ma_val and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_close = close
self._prev_ma = ma_val
def CreateClone(self):
"""!! REQUIRED!! Creates a new instance of the strategy."""
return above_below_ma_strategy()