Diese Strategie ist ein StockSharp-Port des MetaTrader TimerEA-Roboters. Der Schwerpunkt liegt auf der Eröffnung und Schließung von Geschäften zu geplanten Terminen
mit optionalem Pending Orders, Trailing Protection und Break-Even-Handling.
Handelslogik
Zeitplan
OpenTime löst die Auftragserteilung aus, sobald die erste fertige Kerze die konfigurierte Minute erreicht.
CloseTime erzwingt die Positionsauflösung und storniert optional verbleibende ausstehende Aufträge.
Bestellmodi
Es können Markt-, Stop- oder Limiteinträge ausgewählt werden. Ausstehende Aufträge werden in einem konfigurierbaren Abstand (in Preisschritten) platziert und können
verfallen nach der angegebenen Anzahl von Minuten.
Richtungskontrolle
Separate Schalter ermöglichen die Aktivierung von Long- und/oder Short-Trades. Jede Seite gibt pro Lauf einen Auftrag ab.
Risikomanagement
Die Größenbestimmung mit festem Volumen oder auf Gleichgewichtsbasis (unter Verwendung von RiskFactor) ahmt die ursprüngliche Losauswahl nach.
Stop-Loss- und Take-Profit-Abstände werden in Preisschritten ausgedrückt und nach jedem Eintrag neu erstellt.
Die Trailing-Stop-Logik hält den Stop auf einem konstanten Offset, sobald der Gewinn den BreakEvenSteps-Puffer überschreitet. Der Weg wird aktiviert
nur, wenn der Stopp bereits über dem anfänglichen Versatz plus TrailingStep liegt.
Schutzmaßnahmen
Die optionale Break-Even-Anforderung verhindert ein Nachlaufen, bis die Mindestgewinnschwelle erreicht ist.
Ausstehende Bestellungen, deren Ablaufdatum abgelaufen ist, werden automatisch storniert.
Standardparameter
Bestellmodus: Markt.
Offener Kauf/Verkauf: deaktiviert.
Take Profit / Stop Loss: jeweils 10 Schritte.
Trailing Stop und Break-Even: deaktiviert.
Ausstehende Distanz: 10 Schritte mit Ablauf von 60 Minuten.
Losgröße: Manuelles Volumen = 1,0 (Risikofaktor = 1,0 für Balance-Modus).
Kerzentyp: 1-Minuten-Zeitrahmen.
Notizen
Die Strategie arbeitet mit fertigen Kerzen und reagiert daher mit bis zu einem Balken Latenz.
StockSharp verwendet ein Netting-Positionsmodell, sodass ein gleichzeitiges Long- und Short-Engagement nicht unterstützt wird, selbst wenn beide Umschaltmöglichkeiten vorhanden sind
aktiviert.
Preisstufen werden mit Security.PriceStep berechnet. Instrumente ohne konfigurierten Schritt behandeln Entfernungen als Rohpreis
Punkte.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Timer EA strategy: SMA crossover with time-of-day filter.
/// Trades only during active session hours.
/// </summary>
public class TimerEaStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public TimerEaStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("Fast Period", "Fast SMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 30)
.SetGreaterThanZero()
.SetDisplay("Slow Period", "Slow SMA period", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fast = new SimpleMovingAverage { Length = FastPeriod };
var slow = new SimpleMovingAverage { Length = SlowPeriod };
decimal? prevFast = null;
decimal? prevSlow = null;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, slow, (candle, fastVal, slowVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (prevFast.HasValue && prevSlow.HasValue)
{
if (prevFast.Value <= prevSlow.Value && fastVal > slowVal && Position <= 0)
BuyMarket();
else if (prevFast.Value >= prevSlow.Value && fastVal < slowVal && Position >= 0)
SellMarket();
}
prevFast = fastVal;
prevSlow = slowVal;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fast);
DrawIndicator(area, slow);
DrawOwnTrades(area);
}
}
}
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 SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class timer_ea_strategy(Strategy):
def __init__(self):
super(timer_ea_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._fast_period = self.Param("FastPeriod", 10) \
.SetGreaterThanZero() \
.SetDisplay("Fast Period", "Fast SMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 30) \
.SetGreaterThanZero() \
.SetDisplay("Slow Period", "Slow SMA period", "Indicators")
self._prev_fast = None
self._prev_slow = None
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(timer_ea_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(timer_ea_strategy, self).OnStarted2(time)
self._fast_ind = SimpleMovingAverage()
self._fast_ind.Length = self._fast_period.Value
self._slow_ind = SimpleMovingAverage()
self._slow_ind.Length = self._slow_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._fast_ind, self._slow_ind, self._process_candle).Start()
def _process_candle(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
fast_val = float(fast_value)
slow_val = float(slow_value)
if self._prev_fast is not None and self._prev_slow is not None:
if self._prev_fast <= self._prev_slow and fast_val > slow_val and self.Position <= 0:
self.BuyMarket()
elif self._prev_fast >= self._prev_slow and fast_val < slow_val and self.Position >= 0:
self.SellMarket()
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return timer_ea_strategy()