Diese Strategie portiert den klassischen MetaTrader CCFp-Expertenberater in die High-Level-API von StockSharp. Sie berechnet eine relative Stärke-Punktzahl für die acht wichtigsten Währungen (USD, EUR, GBP, CHF, JPY, AUD, CAD, NZD) anhand von Verhältnissen zwischen schnellen und langsamen einfachen gleitenden Durchschnitten auf den sieben USD-basierten Hauptpaaren (EURUSD, GBPUSD, AUDUSD, NZDUSD, USDCAD, USDCHF, USDJPY). Wenn die Differenz zwischen zwei Währungsstärken einen konfigurierbaren Schwellenwert überschreitet, öffnet die Strategie Marktpositionen, die die stärkere Währung gegen die schwächere ausdrücken.
Die Implementierung folgt der empfohlenen High-Level-Architektur: Jedes Instrument hat sein eigenes Kerzenabonnement, Indikatoren werden über Bind gebunden, und die Auftragsverwaltung verwendet RegisterOrder mit Marktaufträgen. Kommentare zu ausgeführten Aufträgen verwenden das ursprüngliche (TOPDOWN)-Format, um denselben Buchführungsstil wie die MQL-Version beizubehalten.
Erforderliche Instrumente
Folgende Wertpapiere an die Strategieparameter anhängen:
EURUSD
GBPUSD
AUDUSD
NZDUSD
USDCAD
USDCHF
USDJPY
Alle sieben Paare müssen denselben Zeitrahmen teilen, der über den Parameter Candle Type eingestellt wird.
Parameter
Parameter
Beschreibung
Fast MA
Schnelle Moving-Average-Periode für die Stärkeberechnung.
Slow MA
Langsame Moving-Average-Periode für die Stärkeberechnung.
Strength Step
Minimale Differenz zwischen zwei Währungen, die überschritten werden muss, um ein neues Signal auszulösen.
Close Opposite
Bei Aktivierung schließt die Strategie gegenläufige Positionen vor dem Senden einer neuen Order.
Candle Type
Von den Indikatoren verarbeitete Kerzenserie.
Basis-Volume
Wird von der Standard-Strategy.Volume-Eigenschaft übernommen und für jeden gesendeten Marktauftrag verwendet.
Handelslogik
Jedes der sieben USD-Hauptpaare wird mit seinem eigenen Paar einfacher gleitender Durchschnitte (schnell und langsam) abonniert.
Jedes Mal, wenn eine abgeschlossene Kerze eintrifft, konvertiert die Strategie das Verhältnis der langsamen und schnellen Durchschnitte in dieselben synthetischen Stärkewerte, die vom ursprünglichen CCFp-Indikator erzeugt werden.
Nachdem alle sieben Paare aktualisiert wurden, werden die acht Währungsstärke-Punktzahlen neu berechnet.
Wenn die Differenz zwischen einer "Top"- und einer "Down"-Währung das Strength Step-Niveau aufwärts kreuzt, während die Top-Währung steigt und die Down-Währung fällt, wird eine Gelegenheit erkannt.
Die Strategie öffnet Marktaufträge, die Long-Exposition zur starken Währung und Short-Exposition zur schwachen Währung ausdrücken:
Wenn USD die starke Währung ist, wird nur ein Auftrag auf dem Gegenpaar platziert (zum Beispiel Short EURUSD).
Wenn USD die schwache Währung ist, kauft die Strategie das Paar, wo die starke Währung die Basis ist (zum Beispiel Long EURUSD).
Wenn beide Währungen Nicht-USD sind, sendet die Strategie zwei Aufträge: Long die Top-Währung gegen USD und Short die Down-Währung gegen USD.
Wenn Close Opposite aktiviert ist und eine gegenläufige Position auf einem Zielpaar noch offen ist, sendet die Strategie zuerst einen schließenden Marktauftrag, bevor sie in einen neuen Trade einsteigt.
Risikomanagement
Die Strategie fügt keine expliziten Stop-Loss- oder Take-Profit-Aufträge hinzu; die Risikokontrolle wird durch das Close Opposite-Flag zusammen mit manuellen Portfolio-Verwaltungstools gehandhabt.
Die Einstiegsgröße wird durch die Volume-Eigenschaft kontrolliert. Entsprechend der Kontogröße und des gewünschten Exposures pro Segment konfigurieren.
Unterschiede zur ursprünglichen MQL-Implementierung
Die Währungsstärkeberechnung verwendet StockSharp-SimpleMovingAverage-Indikatoren auf einem einzigen Zeitrahmen. Multi-Zeitrahmen-Koeffizientenstapelung aus dem MQL-Indikator kann durch Anpassen der Fast MA- und Slow MA-Perioden emuliert werden.
Schützende Stops werden nicht automatisch nachgezogen; stattdessen konzentriert sich die Strategie auf die Reproduktion der Einstiegs-/Ausstiegslogik und überlässt die erweiterte Risikokontrolle der Portfolio-Ebene von StockSharp.
Die Auftragsweiterleitung verwendet den High-Level-RegisterOrder-Helfer und StockSharp-Sicherheitsreferenzen anstelle von MetaTrader-Handelsobjekten.
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;
/// <summary>
/// CCFp Currency Strength strategy (simplified). Uses fast/slow EMA crossover
/// to detect momentum shifts, inspired by currency strength comparison.
/// </summary>
public class CcfpCurrencyStrengthStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastLength;
private readonly StrategyParam<int> _slowLength;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int FastLength
{
get => _fastLength.Value;
set => _fastLength.Value = value;
}
public int SlowLength
{
get => _slowLength.Value;
set => _slowLength.Value = value;
}
public CcfpCurrencyStrengthStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Candles", "General");
_fastLength = Param(nameof(FastLength), 5)
.SetGreaterThanZero()
.SetDisplay("Fast Length", "Fast EMA period", "Indicators");
_slowLength = Param(nameof(SlowLength), 20)
.SetGreaterThanZero()
.SetDisplay("Slow Length", "Slow EMA period", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var emaFast = new ExponentialMovingAverage { Length = FastLength };
var emaSlow = new ExponentialMovingAverage { Length = SlowLength };
decimal prevFast = 0, prevSlow = 0;
var hasPrev = false;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(emaFast, emaSlow, (ICandleMessage candle, decimal fastVal, decimal slowVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!hasPrev)
{
prevFast = fastVal;
prevSlow = slowVal;
hasPrev = true;
return;
}
if (!IsFormedAndOnlineAndAllowTrading())
{
prevFast = fastVal;
prevSlow = slowVal;
return;
}
// Fast EMA crosses above slow - bullish
if (prevFast <= prevSlow && fastVal > slowVal && Position <= 0)
BuyMarket();
// Fast EMA crosses below slow - bearish
else if (prevFast >= prevSlow && fastVal < slowVal && Position >= 0)
SellMarket();
prevFast = fastVal;
prevSlow = slowVal;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, emaFast);
DrawIndicator(area, emaSlow);
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 ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class ccfp_currency_strength_strategy(Strategy):
def __init__(self):
super(ccfp_currency_strength_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Candles", "General")
self._fast_length = self.Param("FastLength", 5) \
.SetDisplay("Fast Length", "Fast EMA period", "Indicators")
self._slow_length = self.Param("SlowLength", 20) \
.SetDisplay("Slow Length", "Slow EMA period", "Indicators")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
@property
def CandleType(self):
return self._candle_type.Value
@property
def FastLength(self):
return self._fast_length.Value
@property
def SlowLength(self):
return self._slow_length.Value
def OnReseted(self):
super(ccfp_currency_strength_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(ccfp_currency_strength_strategy, self).OnStarted2(time)
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
fast_ema = ExponentialMovingAverage()
fast_ema.Length = self.FastLength
slow_ema = ExponentialMovingAverage()
slow_ema.Length = self.SlowLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast_ema, slow_ema, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast_ema)
self.DrawIndicator(area, slow_ema)
self.DrawOwnTrades(area)
def _on_process(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fv = float(fast_value)
sv = float(slow_value)
if not self._has_prev:
self._prev_fast = fv
self._prev_slow = sv
self._has_prev = True
return
if self._prev_fast <= self._prev_slow and fv > sv and self.Position <= 0:
self.BuyMarket()
elif self._prev_fast >= self._prev_slow and fv < sv and self.Position >= 0:
self.SellMarket()
self._prev_fast = fv
self._prev_slow = sv
def CreateClone(self):
return ccfp_currency_strength_strategy()