Die Day Trading PAMXA-Strategie reproduziert den MetaTrader 5-Expertenberater, der Bill Williams' Awesome-Oscillator-Momentum-Umkehrungen mit einem stochastischen Filter kombiniert. Der StockSharp-Port behält das originale Multi-Timeframe-Design:
Die Hauptentscheidungsschleife läuft auf dem Signal Candles-Zeitrahmen (Standard 1 Stunde).
Der Awesome Oscillator wird auf einem separaten AO Candles-Zeitrahmen (Standard 1 Tag) ausgewertet, um Momentum auf höherem Zeitrahmen zu erhalten.
Der stochastische Oszillator verwendet seinen eigenen Stochastic Candles-Zeitrahmen (Standard 1 Stunde), sodass %K/%D-Niveaus mit den Originaleinstellungen übereinstimmen.
Die Strategie hält maximal eine Position gleichzeitig. Wenn ein bullisches Setup erscheint, werden zuerst aktive Shorts gedeckt bevor Long eingegangen wird, und umgekehrt für bärische Setups.
Einstiegslogik
Die neuesten abgeschlossenen Werte des Awesome Oscillators auf dem AO-Zeitrahmen berechnen.
Die neuesten abgeschlossenen %K- und %D-Werte des stochastischen Oszillators auf dem Stochastic-Zeitrahmen berechnen.
Bei jeder abgeschlossenen Signal-Kerze:
Bullisches Setup: ausgelöst, wenn der vorherige AO-Balken unter null war und der letzte Balken über null schloss (Momentum-Umkehr), während entweder %K oder %D unter dem Stochastic Level Down-Schwellenwert liegt (überverkaufte Bedingung). Jeder offene Short wird gedeckt und ein neuer Long wird eröffnet, wenn keine Position verbleibt.
Bärisches Setup: ausgelöst, wenn der vorherige AO-Balken über null war und der letzte Balken unter null schloss, während entweder %K oder %D über dem Stochastic Level Up-Schwellenwert liegt (überkaufte Bedingung). Jeder offene Long wird geschlossen und, wenn flat, wird eine neue Short-Position eröffnet.
Ausstieg und Risikomanagement
Ein pip-basierter Stop-Loss und Take-Profit werden beim Einstieg angehängt. Wenn das Tief der Kerze (für Longs) oder das Hoch (für Shorts) den Stop-Level durchbricht, wird die Position sofort liquidiert. Dieselbe Logik gilt für das Gewinnziel.
Ein optionaler Trailing Stop aktiviert sich, sobald sich der Preis um Trailing Stop + Trailing Step Pips zugunsten der Position bewegt hat. Für Longs folgt der Stop dem höchsten Hoch minus der Trailing-Distanz; für Shorts folgt er dem niedrigsten Tief plus der Trailing-Distanz. Die Trailing-Anpassung erfolgt nur, wenn die Bewegung den Trailing-Schritt übersteigt.
Das Geldmanagement kann in zwei Modi betrieben werden:
FixedVolume: verwendet den Parameter Order Volume direkt.
RiskPercent: berechnet das Volumen so, dass der konfigurierte Prozentsatz des Portfolio-Werts verloren gehen würde, wenn der Stop-Loss getroffen wird.
Die Strategie pyramidisiert nie – sobald eine Position existiert, wird das nächste entgegengesetzte Signal sie abflachen, bevor ein neuer Einstieg in Betracht gezogen wird.
Parameter
Parameter
Beschreibung
Stop Loss
Stop-Loss-Abstand in Pips. Null deaktiviert den Schutz-Stop.
Take Profit
Take-Profit-Abstand in Pips. Null deaktiviert das Gewinnziel.
Trailing Stop
Aktivierungsdistanz des Trailing Stops in Pips. Null deaktiviert den Trailing.
Trailing Step
Zusätzliche Pips erforderlich, bevor der Trailing Stop vorrückt. Muss positiv sein, wenn Trailing aktiviert ist.
Money Mode
Wählt zwischen FixedVolume- und RiskPercent-Dimensionierung.
Money Value
Als Lotgröße bei festem Volumen oder als Risikoprozentsatz bei risikobasierter Dimensionierung interpretiert.
Order Volume
Basisvolumen, das verwendet wird, wenn Money ModeFixedVolume ist.
Stochastic %K
Berechnungslänge für den stochastischen %K.
Stochastic %D
Glättungslänge für die stochastische %D-Linie.
Stochastic Slow
Abschließender Glättungsfaktor des stochastischen Oszillators.
Level Up
Oberer stochastischer Schwellenwert, der Short-Einstiege ermöglicht.
Level Down
Unterer stochastischer Schwellenwert, der Long-Einstiege ermöglicht.
Signal Candles
Zeitrahmen, der die Haupthandelsschleife antreibt.
Stochastic Candles
Zeitrahmen, der den stochastischen Oszillator speist.
AO Candles
Zeitrahmen, der den Awesome Oscillator speist.
AO Fast / AO Slow
Perioden für die internen gleitenden Durchschnitte des Awesome Oscillators.
Implementierungshinweise
Die Pip-Wert-Berechnung emuliert die MetaTrader-Logik: Wenn das Instrument 3 oder 5 Dezimalstellen verwendet, entspricht ein Pip zehn Preisschritten; andernfalls entspricht er einem Preisschritt.
Der stochastische Oszillator von StockSharp stellt keine dedizierte "Preisfeld"-Auswahl bereit; der Port verwendet die Standard-Close-basierte Berechnung, während konfigurierbare Glättungsparameter beibehalten werden.
Trailing-Stop-Handling wird als virtuelle Prüfung auf Kerzenhochs/-tiefs implementiert. Dies repliziert die serverseitigen Stop-Anpassungen in MetaTrader ohne explizite Stop-Orders zu registrieren.
Der Code abonniert alle erforderlichen Kerzenzeitrahmen über GetWorkingSecurities.
Englische Inline-Kommentare dokumentieren die wichtigsten Kontrollfluss-Entscheidungen.
Nutzungstipps
Richten Sie den Signal Candles-Zeitrahmen auf den Zeitrahmen aus, auf dem Sie backtesten oder handeln möchten. Behalten Sie Stochastic Candles und AO Candles gleich den originalen Standards bei, wenn Sie den MQL5-Experten genau nachahmen möchten.
Wenn Sie zu RiskPercent-Dimensionierung wechseln, stellen Sie sicher, dass die Stop-Loss-Distanz ungleich null ist; andernfalls fällt die Strategie auf Order Volume zurück.
Die Standard-Trailing-Konfiguration spiegelt den originalen EA wider (25-Pip-Trailing-Stop mit 5-Pip-Schritt). Setzen Sie Trailing Stop auf null, wenn Sie einen statischen Stop-Loss bevorzugen.
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>
/// Day Trading PAMXA strategy using EMA crossover.
/// Buys when fast EMA crosses above slow EMA, sells on reverse.
/// </summary>
public class DayTradingPamxaStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _stopLossPoints;
private readonly StrategyParam<int> _takeProfitPoints;
private ExponentialMovingAverage _fast;
private ExponentialMovingAverage _slow;
private decimal _prevFast;
private decimal _prevSlow;
private decimal _entryPrice;
private int _cooldown;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }
public DayTradingPamxaStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 14).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
}
protected override void OnReseted()
{
base.OnReseted();
_fast = null; _slow = null;
_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_fast = new ExponentialMovingAverage { Length = FastPeriod };
_slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
subscription.Bind(_fast, _slow, ProcessCandle);
subscription.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished) return;
if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }
var close = candle.ClosePrice;
var step = Security?.PriceStep ?? 1m;
if (Position > 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
else if (Position < 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }
_prevFast = fastValue; _prevSlow = slowValue;
}
}
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 day_trading_pamxa_strategy(Strategy):
def __init__(self):
super(day_trading_pamxa_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 14) \
.SetDisplay("Fast Period", "Fast MA period", "Indicator")
self._slow_period = self.Param("SlowPeriod", 50) \
.SetDisplay("Slow Period", "Slow MA period", "Indicator")
self._stop_loss_points = self.Param("StopLossPoints", 200) \
.SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk")
self._take_profit_points = self.Param("TakeProfitPoints", 400) \
.SetDisplay("Take Profit", "Take-profit in price steps", "Risk")
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
@property
def fast_period(self):
return self._fast_period.Value
@property
def slow_period(self):
return self._slow_period.Value
@property
def stop_loss_points(self):
return self._stop_loss_points.Value
@property
def take_profit_points(self):
return self._take_profit_points.Value
def OnReseted(self):
super(day_trading_pamxa_strategy, self).OnReseted()
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
def OnStarted2(self, time):
super(day_trading_pamxa_strategy, self).OnStarted2(time)
self._fast = ExponentialMovingAverage()
self._fast.Length = self.fast_period
self._slow = ExponentialMovingAverage()
self._slow.Length = self.slow_period
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(5)))
subscription.Bind(self._fast, self._slow, self._process_candle)
subscription.Start()
def _process_candle(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fast_val = float(fast_value)
slow_val = float(slow_value)
if not self._fast.IsFormed or not self._slow.IsFormed:
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_fast = fast_val
self._prev_slow = slow_val
return
close = float(candle.ClosePrice)
step = float(self.Security.PriceStep) if self.Security is not None and self.Security.PriceStep is not None else 1.0
if self.Position > 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close <= self._entry_price - self.stop_loss_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close >= self._entry_price + self.take_profit_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
elif self.Position < 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close >= self._entry_price + self.stop_loss_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close <= self._entry_price - self.take_profit_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._prev_fast <= self._prev_slow and fast_val > slow_val and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._entry_price = close
self._cooldown = 100
elif self._prev_fast >= self._prev_slow and fast_val < slow_val and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._entry_price = close
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return day_trading_pamxa_strategy()