Die Währungsstärke v1.1-Strategie repliziert den MetaTrader Expert Advisor Currency Strength v1.1. Sie misst die relative Stärke der acht wichtigsten Währungen (USD, EUR, JPY, CAD, AUD, NZD, GBP, CHF) anhand täglicher prozentualer Veränderungen für 26 liquide FX-Paare. Wenn die Stärke zweier Währungen einen konfigurierbaren Schwellenwert überschreitet, öffnet die Strategie eine Position im entsprechenden Währungspaar in Richtung der stärkeren Währung.
CHF-Stärke = Durchschnitt von CHFJPY, –USDCHF, –EURCHF, –AUDCHF, –GBPCHF, –CADCHF
Jeder Durchschnitt verwendet dieselbe Anzahl von Komponenten wie im ursprünglichen Expert Advisor, um das Gewichtungsschema zu erhalten.
Handelslogik
Nachdem alle 26 Paare eine neue abgeschlossene Tageskerze melden, werden die Stärken neu berechnet.
Für jedes Paar vergleicht die Strategie die zwei relevanten Währungsstärken. Wenn die absolute Differenz den Parameter DifferenceThreshold überschreitet, wird ein Handelssignal generiert.
Die Signalrichtung folgt der stärkeren Währung:
Wenn Basiswährungsstärke > Notierungswährungsstärke → Paar kaufen.
Wenn Basiswährungsstärke < Notierungswährungsstärke → Paar verkaufen.
Trades sind nur erlaubt, wenn die Tageskerze des Paares mit dem Signal übereinstimmt (Schluss über Eröffnung für Käufe, Schluss unter Eröffnung für Verkäufe), was den Trendfilter des ursprünglichen EA widerspiegelt.
Bestehende Nettopositionen werden respektiert. Wenn ein Umkehrsignal erscheint, während eine entgegengesetzte Position offen ist, schließt die Strategie die aktuelle Position und dreht in die neue Richtung mit einer einzigen Marktorder.
Wenn TradeOncePerDay aktiviert ist, kann jedes Paar maximal einmal pro Handelstag Long einsteigen und maximal einmal pro Handelstag Short einsteigen.
Risikomanagement und Ausstiege
Die optionale UseSlTp-Flag aktiviert Stop-Loss- und Take-Profit-Logik, die auf der Tageskerze jedes Paares ausgeführt wird. Die Abstände werden in Pips definiert (StopLossPips, TakeProfitPips).
Die Schutzlogik wertet das Tageshoch/-tief der jüngsten Kerze aus. Wenn diese Extreme die jeweiligen Ziele erreichen, wird die Position beim nächsten Auswertungsschritt zum Marktpreis geschlossen.
Ohne SL/TP bleiben Positionen offen, bis ein entgegengesetztes Signal eine Umkehrung erzwingt oder die Strategie manuell gestoppt wird, was das Verhalten des Quell-EA widerspiegelt.
Strategieparameter
Parameter
Beschreibung
CandleType
Zeitrahmen für Kerzen (Standard: täglich).
DifferenceThreshold
Minimale Stärkelücke (in Prozentpunkten), die erforderlich ist, um einen Trade auszulösen.
TradeOncePerDay
Wenn true, begrenzt jedes Paar auf einen Long- und einen Short-Einstieg pro Tag.
UseSlTp
Aktiviert die tägliche Auswertung von Stop-Loss- und Take-Profit-Niveaus.
TakeProfitPips
Take-Profit-Abstand in Pips gemessen.
StopLossPips
Stop-Loss-Abstand in Pips gemessen.
Paar-Parameter
Individuelle Security-Eingaben für die 26 FX-Paare. Jedes muss vor dem Starten der Strategie zugewiesen werden.
Volume
Basisklasseneigenschaft, die die Handelsgröße definiert (Standard 0.01 Lot).
Implementierungshinweise
Die Strategie abonniert jedes Paar separat über die High-Level-Kerzenabonnement-API (SubscribeCandles).
Die Kerzenbehandlung ignoriert strikt unvollständige Kerzen und erfüllt die StockSharp-Konvertierungsrichtlinien.
Stärkeberechnungen und Signalgenerierung laufen nur, wenn alle Paare dasselbe Handelsdatum melden, was synchronisierte Währungskörbe garantiert.
Interne Wörterbücher verfolgen die letzten Handelsdaten pro Richtung und speichern Einstiegsinformationen für Schutzausstiege.
Verwendungstipps
Alle 26 Wertpapiere vor dem Starten der Strategie zuweisen; fehlende Eingaben werfen eine Ausnahme, um Teilberechnungen zu verhindern.
Sicherstellen, dass der Datenprovider Tageskerzen für jedes konfigurierte Paar liefert, damit die Währungsstärken synchron bleiben.
DifferenceThreshold anpassen, um die Signalhäufigkeit zu kontrollieren. Kleinere Schwellenwerte führen zu häufigeren Trades, aber auch mehr Umkehrungen.
Die pip-basierten Stops an die Quotierungsgenauigkeit des eigenen Brokers kalibrieren; der Standard geht von Bruchpip-Preisen aus.
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Strategy that trades based on percentage change momentum of candles.
/// Simplified from the original multi-pair currency strength approach to single-security.
/// </summary>
public class CurrencyStrengthV11Strategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<decimal> _differenceThreshold;
private decimal? _prevChange;
private decimal? _prevMomentum;
private decimal _entryPrice;
private DateTimeOffset? _lastTradeTime;
/// <summary>
/// Candle type for analysis.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Minimum percentage change to trigger trades.
/// </summary>
public decimal DifferenceThreshold
{
get => _differenceThreshold.Value;
set => _differenceThreshold.Value = value;
}
/// <summary>
/// Initializes a new instance of the strategy.
/// </summary>
public CurrencyStrengthV11Strategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for strength calculation", "General");
_differenceThreshold = Param(nameof(DifferenceThreshold), 0.2m)
.SetDisplay("Threshold", "Minimum percentage change to trigger trade", "Parameters")
.SetOptimize(0.05m, 1m, 0.05m);
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
yield return (Security, CandleType);
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevChange = null;
_prevMomentum = null;
_entryPrice = 0m;
_lastTradeTime = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
SubscribeCandles(CandleType)
.Bind(ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormed)
return;
var change = candle.OpenPrice != 0m
? (candle.ClosePrice - candle.OpenPrice) / candle.OpenPrice * 100m
: 0m;
if (_prevChange == null)
{
_prevChange = change;
return;
}
var momentum = change - _prevChange.Value;
var cooldownPassed = _lastTradeTime is null || candle.CloseTime - _lastTradeTime >= TimeSpan.FromHours(24);
var longSignal = _prevMomentum is decimal prevMomentum && prevMomentum <= DifferenceThreshold && momentum > DifferenceThreshold;
var shortSignal = _prevMomentum is decimal prevMomentum2 && prevMomentum2 >= -DifferenceThreshold && momentum < -DifferenceThreshold;
if (cooldownPassed && longSignal && Position <= 0)
{
if (Position < 0)
BuyMarket(Math.Abs(Position));
BuyMarket(Volume > 0m ? Volume : 1m);
_entryPrice = candle.ClosePrice;
_lastTradeTime = candle.CloseTime;
}
else if (cooldownPassed && shortSignal && Position >= 0)
{
if (Position > 0)
SellMarket(Position);
SellMarket(Volume > 0m ? Volume : 1m);
_entryPrice = candle.ClosePrice;
_lastTradeTime = candle.CloseTime;
}
_prevChange = change;
_prevMomentum = momentum;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates, Unit, UnitTypes
from StockSharp.Algo.Strategies import Strategy
class currency_strength_v11_strategy(Strategy):
def __init__(self):
super(currency_strength_v11_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1)))
self._difference_threshold = self.Param("DifferenceThreshold", 0.2)
self._prev_change = None
self._prev_momentum = None
self._entry_price = 0.0
self._last_trade_time = None
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def DifferenceThreshold(self):
return self._difference_threshold.Value
@DifferenceThreshold.setter
def DifferenceThreshold(self, value):
self._difference_threshold.Value = value
def OnStarted2(self, time):
super(currency_strength_v11_strategy, self).OnStarted2(time)
self._prev_change = None
self._prev_momentum = None
self._entry_price = 0.0
self._last_trade_time = None
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self.ProcessCandle).Start()
def ProcessCandle(self, candle):
if candle.State != CandleStates.Finished:
return
open_price = float(candle.OpenPrice)
close = float(candle.ClosePrice)
change = (close - open_price) / open_price * 100.0 if open_price != 0.0 else 0.0
if self._prev_change is None:
self._prev_change = change
return
momentum = change - self._prev_change
threshold = float(self.DifferenceThreshold)
long_signal = (self._prev_momentum is not None and
self._prev_momentum <= threshold and
momentum > threshold)
short_signal = (self._prev_momentum is not None and
self._prev_momentum >= -threshold and
momentum < -threshold)
cooldown_passed = (self._last_trade_time is None or
candle.CloseTime - self._last_trade_time >= TimeSpan.FromHours(24))
if cooldown_passed and long_signal and self.Position <= 0:
if self.Position < 0:
self.BuyMarket(abs(self.Position))
vol = float(self.Volume) if float(self.Volume) > 0 else 1.0
self.BuyMarket(vol)
self._entry_price = float(candle.ClosePrice)
self._last_trade_time = candle.CloseTime
elif cooldown_passed and short_signal and self.Position >= 0:
if self.Position > 0:
self.SellMarket(self.Position)
vol = float(self.Volume) if float(self.Volume) > 0 else 1.0
self.SellMarket(vol)
self._entry_price = float(candle.ClosePrice)
self._last_trade_time = candle.CloseTime
self._prev_change = change
self._prev_momentum = momentum
def OnReseted(self):
super(currency_strength_v11_strategy, self).OnReseted()
self._prev_change = None
self._prev_momentum = None
self._entry_price = 0.0
self._last_trade_time = None
def CreateClone(self):
return currency_strength_v11_strategy()