TugbaGold ist ein gitterbasierter Expertenberater zur Durchschnittsbildung, der aus MetaTrader 5 stammt. Die konvertierte Strategie stellt ihre Martingal-Positionsgrößenbestimmung und Warenkorbverwaltungslogik unter Verwendung der übergeordneten API von StockSharp wieder her. Das System platziert neue Aufträge immer dann, wenn die vorherige Kerze mit Richtungsimpuls schließt, und baut nach und nach ein Raster von Positionen auf, die in einem konfigurierbaren Abstand voneinander angeordnet sind. Durchschnittliche Ausstiege werden je nach ausgewähltem Modus entweder durch die Sicherung von Gewinnen auf den Extrempositionen oder durch die teilweise Schließung des Korbs durchgeführt.
Wie es funktioniert
Die Strategie bewertet abgeschlossene Kerzen anhand des Parameters CandleType. Signale verwenden die vorherige Kerze, entsprechend der ursprünglichen MT5-Logik.
Eine bullische Kerze ermöglicht die Platzierung einer neuen Kauforder. Eine bärische Kerze ermöglicht einen neuen Verkaufsauftrag.
Aufträge werden nur hinzugefügt, wenn der Abstand vom besten bestehenden Preis in dieser Richtung mehr als PointOrderStepPips beträgt.
Die erste Bestellung verwendet StartVolume. Nachfolgende Eingaben verdoppeln das Volumen der günstigsten Position unter Einhaltung der MaxVolume- und Broker-Limits.
Sobald mindestens zwei Positionen vorhanden sind, berechnet die Strategie Zielpreise, die den MinimalProfitPips-Puffer enthalten. Die Berechnung unterscheidet sich je nach Exit-Modus:
Durchschnitt – gewichteter Durchschnitt der Extrempositionen plus Gewinnpuffer.
Teilweise – Kombination der schlechtesten und besten Tickets, wobei das schlechteste Ticket StartVolume und das beste seine tatsächliche Größe verwendet.
Bei Erreichen der Ziele schließt die Strategie die entsprechenden Aufträge:
Durchschnittsmodus – schließt beide Extremeinträge vollständig.
Teilmodus – schließt den schlechtesten Eintrag vollständig und reduziert den besseren Eintrag um StartVolume.
Einzelne eigenständige Positionen verwenden TakeProfitPips, um zu beenden, sobald der Preis den konfigurierten Abstand erreicht.
Parameter
Parameter
Beschreibung
TakeProfitPips
Die Take-Profit-Distanz wird angewendet, wenn nur eine Position offen ist. Zum Deaktivieren auf 0 setzen.
StartVolume
Anfangsvolumen für die erste Ordnung in einer Rastersequenz.
MaxVolume
Maximales Bestellvolumen. 0 hält die Verdopplungssequenz unbegrenzt.
CloseMode
Ausgangsmodus: Average (beide Extreme schließen) oder Partial (teilweises + vollständiges Schließen).
PointOrderStepPips
Mindestabstand in Pips, bevor eine neue Mittelungsreihenfolge hinzugefügt werden kann.
MinimalProfitPips
Zusätzlicher Gewinnpuffer zu den Durchschnittszielen hinzugefügt.
CandleType
Kerzenreihe zur Signalauswertung.
Positionsmanagement
Preisschritte werden von Security.PriceStep abgeleitet. Wenn es nicht verfügbar ist, wird der Standardwert 0.0001 verwendet.
Die Volumina werden automatisch auf die minimalen, maximalen und schrittweisen Einschränkungen des Brokers normalisiert.
Die Strategie verfolgt gefüllte Positionen intern und gibt Marktaufträge (BuyMarket / SellMarket) aus, wenn Teile des Warenkorbs geschlossen werden.
Der Schutz wird automatisch durch StartProtection() aktiviert, sobald die Strategie startet.
Hinweise und Einschränkungen
Die Implementierung geht davon aus, dass Marktaufträge sofort ausgeführt werden, ähnlich wie in der MT5-Umgebung.
Mittelungssignale basieren auf den aktuell besten Geld-/Briefkursen. Stellen Sie sicher, dass Level-1-Daten für eine genaue Ausführung verfügbar sind.
Da Ausstiege von der Strategielogik gesteuert werden, werden die Stop-Loss-Werte des ursprünglichen Experten nicht wiederhergestellt.
Gehen Sie vorsichtig mit dem Risikomanagement um: Die Martingal-Größe kann zu einem großen Risiko führen, wenn die Trends anhalten.
Konvertierungsdetails
Die Durchschnittsformeln und Korbanpassungen spiegeln den ursprünglichen Quellcode wider.
Die Positionsauswahl (beste/schlechteste Tickets) wird durch die Verfolgung der höchsten und niedrigsten Eröffnungspreise in jeder Richtung reproduziert.
Die gesamte Logik wird innerhalb des Kerzenabonnements mithilfe des High-Level-API von StockSharp ausgeführt, ohne auf Low-Level-Datenzugriff zurückgreifen zu müssen.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// TugbaGold strategy: candle direction + EMA trend filter with martingale-style averaging.
/// Buys on bullish candle above EMA, sells on bearish candle below EMA.
/// </summary>
public class TugbaGoldStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaPeriod;
private bool _wasBullishSignal;
private bool _hasPrevSignal;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
public TugbaGoldStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_emaPeriod = Param(nameof(EmaPeriod), 50)
.SetGreaterThanZero()
.SetDisplay("EMA Period", "EMA trend filter period", "Indicators");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_wasBullishSignal = false;
_hasPrevSignal = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_wasBullishSignal = false;
_hasPrevSignal = false;
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ema, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal emaValue)
{
if (candle.State != CandleStates.Finished) return;
var bullish = candle.ClosePrice > candle.OpenPrice;
var bearish = candle.ClosePrice < candle.OpenPrice;
var bullishSignal = bullish && candle.ClosePrice > emaValue;
var bearishSignal = bearish && candle.ClosePrice < emaValue;
var crossedUp = bullishSignal && (!_hasPrevSignal || !_wasBullishSignal);
var crossedDown = bearishSignal && (!_hasPrevSignal || _wasBullishSignal);
if (crossedUp && Position <= 0)
BuyMarket();
else if (crossedDown && Position >= 0)
SellMarket();
if (bullishSignal || bearishSignal)
{
_wasBullishSignal = bullishSignal;
_hasPrevSignal = true;
}
}
}
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 tugba_gold_strategy(Strategy):
def __init__(self):
super(tugba_gold_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60)))
self._ema_period = self.Param("EmaPeriod", 50)
self._was_bullish_signal = False
self._has_prev_signal = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def EmaPeriod(self):
return self._ema_period.Value
@EmaPeriod.setter
def EmaPeriod(self, value):
self._ema_period.Value = value
def OnReseted(self):
super(tugba_gold_strategy, self).OnReseted()
self._was_bullish_signal = False
self._has_prev_signal = False
def OnStarted2(self, time):
super(tugba_gold_strategy, self).OnStarted2(time)
self._was_bullish_signal = False
self._has_prev_signal = False
ema = ExponentialMovingAverage()
ema.Length = self.EmaPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(ema, self._process_candle).Start()
def _process_candle(self, candle, ema_value):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
open_price = float(candle.OpenPrice)
ema_val = float(ema_value)
bullish = close > open_price
bearish = close < open_price
bullish_signal = bullish and close > ema_val
bearish_signal = bearish and close < ema_val
crossed_up = bullish_signal and (not self._has_prev_signal or not self._was_bullish_signal)
crossed_down = bearish_signal and (not self._has_prev_signal or self._was_bullish_signal)
if crossed_up and self.Position <= 0:
self.BuyMarket()
elif crossed_down and self.Position >= 0:
self.SellMarket()
if bullish_signal or bearish_signal:
self._was_bullish_signal = bullish_signal
self._has_prev_signal = True
def CreateClone(self):
return tugba_gold_strategy()