Start
/
Strategie-Beispiele
Auf GitHub ansehen
ColorMaRsi Trigger MMRec Duplex-Strategie
Übersicht
Diese Strategie ist ein StockSharp High-Level-API-Port des MetaTrader-Experten Exp_ColorMaRsi-Trigger_MMRec_Duplex.mq5 . Sie führt zwei unabhängige MaRsi-Trigger-Blöcke aus – einen für Long-Chancen und einen für Short-Chancen. Jeder Block bewertet ein zusammengesetztes Signal, das durch den Vergleich eines schnellen und langsamen gleitenden Durchschnitts zusammen mit einem schnellen und langsamen RSI generiert wird. Der zusammengesetzte Wert wird auf den Bereich [-1, 1] begrenzt, was das Verhalten des ursprünglichen Indikators reproduziert: +1 markiert bullische Ausrichtung, -1 bearische Ausrichtung und 0 zeigt gemischte Bedingungen an.
Ein Geldverwaltungs-"MMRec"-Modul überwacht die letzten Trades für jede Richtung. Wenn eine konfigurierbare Anzahl von Verlusten innerhalb eines gleitenden Fensters erscheint, wechselt der nächste Trade auf ein reduziertes Volumen bis sich die Performance erholt. Dies reproduziert die adaptive Positionsgrößenlogik der MetaTrader-Bibliothek TradeAlgorithms.mqh des Experten.
Handelslogik
Indikator-Pipeline (pro Block):
Schnellen gleitenden Durchschnitt (MA_fast) und langsamen (MA_slow) auf dem gewählten angewendeten Preis und Zeitrahmen berechnen.
Schnellen RSI (RSI_fast) und langsamen RSI (RSI_slow) auf möglicherweise unterschiedlichen angewendeten Preisen berechnen.
Farbwertung aufbauen: bei 0 starten, +1 addieren wenn MA_fast > MA_slow oder -1 sonst, dann +1 addieren wenn RSI_fast > RSI_slow oder -1 sonst. Ergebnis auf [-1, 1] begrenzen.
Wertungshistorie speichern und mit dem konfigurierten SignalBar-Versatz lesen (der Standardwert entspricht der MetaTrader-Implementierung).
Long-Block :
Einstieg : erlaubt wenn keine Long-Position offen ist (Shorts werden zuerst gedeckt). Die vorherige Farbe (SignalBar + 1) muss +1 sein während die aktuelle Farbe (SignalBar) ≤ 0 ist, was zeigt dass der bullische Block gerade neutralisiert wurde.
Ausstieg : wenn die vorherige Farbe negativ (-1) wird und Ausstiege aktiviert sind.
Short-Block :
Einstieg : erlaubt wenn keine Short-Position offen ist (Longs werden zuerst geschlossen). Die vorherige Farbe muss -1 sein während die aktuelle Farbe ≥ 0 ist, was einen frischen bearischen-zu-neutralen Übergang signalisiert.
Ausstieg : wenn die vorherige Farbe positiv wird und Ausstiege aktiviert sind.
Stops und Ziele : optionale Stop-Loss- und Take-Profit-Abstände werden in Kursschritten ausgedrückt und auf jeder abgeschlossenen Kerze neu bewertet. Das Überschreiten einer Grenze schließt die jeweilige Position sofort.
Geldverwaltung : die Strategie speichert das Ergebnis jedes abgeschlossenen Trades (pro Richtung) und zählt die Anzahl der Verluste in den letzten HistoryDepth Trades. Wenn die Verlustzahl LossTrigger erreicht, verwendet die nächste Order das reduzierte Volumen. Andernfalls wird das normale Volumen verwendet.
Parameter
Gruppe
Name
Beschreibung
Standard
Long-Block
LongCandleType
Zeitrahmen der den Long-MaRsi-Trigger-Block speist.
H4
LongAllowOpen / LongAllowClose
Long-Positionen öffnen / schließen aktivieren.
true
LongStopLossPoints / LongTakeProfitPoints
Schutzabstände in Instrument-Punkten. Auf 0 setzen zum Deaktivieren.
1000 / 2000
LongSignalBar
Anzahl abgeschlossener Kerzen beim Abtasten der Indikatorpuffer zu verschieben.
1
LongRsiPeriod / LongRsiLongPeriod
Schnelle und langsame RSI-Längen.
3 / 13
LongMaPeriod / LongMaLongPeriod
Schnelle und langsame gleitende Durchschnitt-Längen.
5 / 10
LongRsiPrice / LongRsiLongPrice
Angewendeter Preis für schnellen / langsamen RSI (Close, Open, High, Low, Median, Typical, Weighted).
Weighted / Median
LongMaPrice / LongMaLongPrice
Angewendeter Preis für schnellen / langsamen MA.
Close / Close
LongMaType / LongMaLongType
Algorithmen für gleitende Durchschnitte (Simple, Exponential, Smoothed, Weighted).
Exponential / Exponential
Geldverwaltung
LongNormalVolume / LongReducedVolume
Standard- und reduziertes Long-Trade-Volumen.
0.1 / 0.01
LongHistoryDepth
Anzahl jüngster Long-Trades vom Geldverwaltungsfilter beobachtet.
5
LongLossTrigger
Mindest-Verlustzahl innerhalb des Fensters um auf reduziertes Long-Volumen zu wechseln.
3
Gruppe
Name
Beschreibung
Standard
Short-Block
ShortCandleType
Zeitrahmen der den Short-MaRsi-Trigger-Block speist.
H4
ShortAllowOpen / ShortAllowClose
Short-Positionen öffnen / schließen aktivieren.
true
ShortStopLossPoints / ShortTakeProfitPoints
Schutzabstände in Instrument-Punkten. Auf 0 setzen zum Deaktivieren.
1000 / 2000
ShortSignalBar
Anzahl abgeschlossener Kerzen beim Abtasten der Indikatorpuffer zu verschieben.
1
ShortRsiPeriod / ShortRsiLongPeriod
Schnelle und langsame RSI-Längen.
3 / 13
ShortMaPeriod / ShortMaLongPeriod
Schnelle und langsame gleitende Durchschnitt-Längen.
5 / 10
ShortRsiPrice / ShortRsiLongPrice
Angewendeter Preis für schnellen / langsamen RSI.
Weighted / Median
ShortMaPrice / ShortMaLongPrice
Angewendeter Preis für schnellen / langsamen MA.
Close / Close
ShortMaType / ShortMaLongType
Algorithmen für gleitende Durchschnitte (Simple, Exponential, Smoothed, Weighted).
Exponential / Exponential
Geldverwaltung
ShortNormalVolume / ShortReducedVolume
Standard- und reduziertes Short-Trade-Volumen.
0.1 / 0.01
ShortHistoryDepth
Anzahl jüngster Short-Trades vom Geldverwaltungsfilter beobachtet.
5
ShortLossTrigger
Mindest-Verlustzahl innerhalb des Fensters um auf reduziertes Short-Volumen zu wechseln.
3
Hinweise
Angewendete Preisoptionen folgen MetaTrader-Semantik. Zum Beispiel entspricht Weighted (High + Low + 2 * Close) / 4 und Typical (High + Low + Close) / 3.
Wenn Long- und Short-Blöcke denselben Zeitrahmen teilen (Standard), speist eine einzelne Kerzen-Abonnement beide Rechner.
Den Verlust-Trigger auf 0 setzen erzwingt sofort das reduzierte Volumen und spiegelt das Verhalten des ursprünglichen Geldverwaltungs-Helpers wider.
Die Strategie verwendet Marktorders; der MetaTrader-Deviation-Parameter ist daher nicht erforderlich.
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 ColorMaRsiTriggerMmRecDuplexStrategy : 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 ColorMaRsiTriggerMmRecDuplexStrategy()
{
_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 color_ma_rsi_trigger_mm_rec_duplex_strategy(Strategy):
def __init__(self):
super(color_ma_rsi_trigger_mm_rec_duplex_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(color_ma_rsi_trigger_mm_rec_duplex_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(color_ma_rsi_trigger_mm_rec_duplex_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 color_ma_rsi_trigger_mm_rec_duplex_strategy()