Die TenPips-Strategie ist ein StockSharp-Port des MetaTrader-Expert Advisors "10PIPS". Sie kombiniert schnelle/langsame linear gewichtete gleitende Durchschnitte, die auf dem Handelszeitrahmen berechnet werden, mit einer Multi-Zeitrahmen-Momentum-Bestätigung und einem makro (monatlichen) MACD-Filter. Die Konvertierung spiegelt das ursprüngliche Geldverwaltungsmodul wider, einschließlich Break-Even-Schutz, pip-basiertem Trailing und Eigenkapital-/absoluten Gewinnzielen.
Signallogik
Primärer Zeitrahmen (Parameter CandleType, Standard 15 Minuten) liefert den Preisstrom, der für die schnellen und langsamen LWMAs verwendet wird, berechnet auf dem typischen Preis (H + L + C) / 3.
Höherer Zeitrahmen-Momentum (MomentumCandleType, Standard 1 Stunde) konvertiert den StockSharp-Momentum-Unterschied in die MetaTrader-Verhältnis. Der absolute Abstand von 100 über die letzten drei abgeschlossenen Bars muss MomentumThreshold überschreiten, damit ein Trade ausgelöst wird.
Makro-MACD-Filter (MacdCandleType, Standard 30-Tages-Kerzen, die den monatlichen MetaTrader-Zeitraum approximieren) erfordert, dass die MACD-Hauptlinie über der Signallinie liegt für Käufe und darunter für Verkäufe.
Eine Long-Position wird eröffnet, wenn die vorherige Kerze:
über der schnellen LWMA schloss, nachdem sie darunter getaucht war,
die schnelle LWMA über der langsamen LWMA liegt,
eine der letzten drei Momentum-Lesungen MomentumThreshold erfüllt,
der Makro-MACD bullisch ist.
Eine Short-Position verwendet die symmetrischen Bedingungen (vorheriger Schlusskurs unter der schnellen LWMA, schnell unter langsam, Momentum über dem Schwellenwert, MACD bearisch).
Da StockSharp mit einem Netto-Positionsmodell arbeitet, öffnet der Port höchstens eine aggregierte Position pro Seite. Das Senden eines Kaufs bei Short-Position schließt automatisch den Short-Anteil und hinterlässt das angeforderte Long-Volumen.
Risiko- und Geldverwaltung
Schutzabstände – StopLossPips und TakeProfitPips übersetzen MetaTrader-Pips in Preisoffsets unter Verwendung des PriceStep des Instruments. Wenn eine Grenze getroffen wird, schließt die Strategie die gesamte Position mit einer Marktorder.
Trailing Stop – TrailingStopPips folgt dem höchsten (Long) oder niedrigsten (Short) Preis seit dem Einstieg.
Break-Even – wenn aktiviert, bewaffnet BreakEvenTriggerPips den Stop und verschiebt ihn auf den Einstieg plus den optionalen BreakEvenOffsetPips.
Geldziele – das Trio UseMoneyTakeProfit, UsePercentTakeProfit und EnableMoneyTrailing repliziert das TP_In_Money, TP_In_Percent des EAs und die Balance-basierte Trailing-Sperre. Unrealisierter PnL wird pro Kerzenschluss gemessen.
Eigenkapital-Stop – UseEquityStop mit EquityRiskPercent implementiert den ursprünglichen UseEquityStop/TotalEquityRisk-Schutz, indem Positionen geschlossen werden, sobald der Drawdown vom Eigenkapitalhöchststand den Schwellenwert überschreitet.
MACD-Exit-Flag – UseMacdExit spiegelt den Exit-Schalter des EAs wider und schließt Positionen frühzeitig, wenn der Makro-MACD gegen den Trade dreht.
Parameter
Parameter
Standard
Beschreibung
TradeVolume
0.01
Netto-Positionsvolumen für Marktorders (MetaTrader-Lotgrößen-Äquivalent).
CandleType
15m Zeitrahmen
Primärer Zeitrahmen für die schnellen/langsamen LWMAs und Trade-Ausführung.
MomentumCandleType
1h Zeitrahmen
Höherer Zeitrahmen-Kerzen für die Momentum-Bestätigung.
MacdCandleType
30d Zeitrahmen
Makro-Zeitrahmen (monatliche Approximation) für MACD-Bestätigung.
FastMaPeriod
8
Periode des schnellen linear gewichteten gleitenden Durchschnitts.
SlowMaPeriod
50
Periode des langsamen linear gewichteten gleitenden Durchschnitts.
MomentumPeriod
14
Lookback für das Momentum-Verhältnis.
MomentumThreshold
0.3
Mindestabsolutabstand von 100 (MetaTrader-Momentum) erforderlich über die letzten drei Bars des höheren Zeitrahmens.
StopLossPips
20
Schutz-Stop-Loss in MetaTrader-Pips. Auf null setzen zum Deaktivieren.
TakeProfitPips
50
Schutz-Take-Profit in MetaTrader-Pips. Auf null setzen zum Deaktivieren.
TrailingStopPips
40
Trailing-Stop-Abstand in Pips (null deaktiviert das Trailing).
UseBreakEven
true
Aktiviert das Break-Even-Verhalten.
BreakEvenTriggerPips
30
Gewinn (Pips) erforderlich, bevor Break-Even aktiviert wird.
BreakEvenOffsetPips
30
Zusätzliche Pips, die zum Break-Even-Stop nach Aktivierung hinzugefügt werden.
UseMoneyTakeProfit
false
Positionen schließen nach Erreichen des absoluten Gewinnziels MoneyTakeProfit.
MoneyTakeProfit
10
Gewinnziel in Kontowährung ausgedrückt.
UsePercentTakeProfit
false
Positionen schließen nach Verdienen von PercentTakeProfit Prozent des Anfangskapitals.
PercentTakeProfit
10
Prozentziel basierend auf Startkapital.
EnableMoneyTrailing
true
Balance-basierter Trailing-Stop aktivieren mit MoneyTrailTarget / MoneyTrailStop.
MoneyTrailTarget
40
Gewinn (Währung) erforderlich, bevor der Money-Trail bewaffnet wird.
MoneyTrailStop
10
Erlaubter Rückgang nach Bewaffnen des Money-Trails.
UseEquityStop
true
Eigenkapital-Drawdown-Schutz aktivieren.
EquityRiskPercent
1
Maximaler Drawdown vom Eigenkapitalhöchststand vor erzwungener Flat-Position.
UseMacdExit
false
Positionen bei entgegengesetztem MACD-Signal des Makro-Zeitrahmens schließen.
Implementierungshinweise
Die Pip-Konvertierung folgt der EA-Logik: wenn der Broker-Tick-Size 0.00001 oder 0.001 ist, entspricht ein Pip zehn Ticks; andernfalls wird der rohe PriceStep verwendet.
StockSharp's Momentum-Indikator gibt eine Preisdifferenz aus. Die Strategie konvertiert diese in das MetaTrader-Verhältnis (Close / Close(period) * 100) vor der Anwendung von MomentumThreshold.
Der Port arbeitet in einer Netting-Umgebung und repliziert daher nicht das Multi-Ticket-Martingal des EAs (IncreaseFactor, LotExponent, Max_Trades). Stattdessen passt er das Order-Volumen automatisch an, wenn zwischen Long- und Short-Positionen gewechselt wird.
Schutzende Exits und Gewinnverwaltung senden Marktorders, entsprechend dem ursprünglichen Advisor-Verhalten beim Modifizieren offener Tickets.
Diagramme zeigen die verarbeiteten Indikatoren (schnelle LWMA, langsame LWMA, Momentum, MACD) wenn Visualisierung verfügbar ist.
Verwendung
Konfiguriere die Kerzen-Zeitrahmen so, dass sie zum MetaTrader-Chart und dem höheren Zeitrahmen des EAs passen.
Passe die pip-basierten Risikoparameter an die Instrument-Punktgröße an. Null deaktiviert die entsprechende Komponente.
Aktiviere oder deaktiviere Geld-/Prozentziele, Eigenkapital-Stop und MACD-Exit entsprechend deinen Risikopräferenzen.
Starte die Strategie; sie abonniert die drei erforderlichen Zeitrahmen, verwaltet Positionen nach den ursprünglichen Regeln und protokolliert jegliche durch Balance- oder Eigenkapitalschutz ausgelöste Schutzausstiege.
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;
public class TenPipsMomentumStrategy : 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 TenPipsMomentumStrategy()
{
_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 ten_pips_momentum_strategy(Strategy):
def __init__(self):
super(ten_pips_momentum_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(ten_pips_momentum_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(ten_pips_momentum_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 ten_pips_momentum_strategy()