CSPA-1.43-Strategie
Diese Strategie ist eine Adaption des MQL-Expertenberaters CSPA-1_43. Sie misst die Stärke eines Währungspaares mit dem Relative Strength Index (RSI). Wenn das Paar ausreichend stark oder schwach wird, eröffnet die Strategie eine Position in Richtung des vorherrschenden Momentums und schließt sie, wenn das Momentum nachlässt.
Logik
- Kerzen des ausgewählten Wertpapiers abonnieren.
- Den RSI-Wert für jede abgeschlossene Kerze berechnen.
- Eine Long-Position öffnen, wenn RSI über den oberen Schwellenwert steigt.
- Eine Short-Position öffnen, wenn RSI unter den unteren Schwellenwert fällt.
- Die aktuelle Position schließen, wenn RSI in die neutrale Zone zurückkehrt.
Parameter
| Name | Beschreibung | Standard |
|---|---|---|
StrengthPeriod |
Periode des RSI-Indikators. | 14 |
Threshold |
Abstand vom neutralen RSI-Niveau von 50 zur Signalgenerierung. | 10 |
CandleType |
Zeitrahmen der Kerzen. | 1 Stunde |
Hinweise
- Die Strategie verwendet die High-Level-API mit automatischer Indikatorbindung.
- Orders werden mit Market-Orders ausgeführt (
BuyMarketundSellMarket). - Nur abgeschlossene Kerzen werden verarbeitet.
using System;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Simplified currency strength strategy based on RSI.
/// </summary>
public class Cspa143Strategy : Strategy
{
private readonly StrategyParam<int> _strengthPeriod;
private readonly StrategyParam<decimal> _threshold;
private readonly StrategyParam<int> _cooldownBars;
private readonly StrategyParam<DataType> _candleType;
private decimal _previousRsi;
private bool _isInitialized;
private int _barsSinceTrade;
/// <summary>
/// RSI period.
/// </summary>
public int StrengthPeriod
{
get => _strengthPeriod.Value;
set => _strengthPeriod.Value = value;
}
/// <summary>
/// RSI distance from 50.
/// </summary>
public decimal Threshold
{
get => _threshold.Value;
set => _threshold.Value = value;
}
/// <summary>
/// Bars to wait after a completed trade.
/// </summary>
public int CooldownBars
{
get => _cooldownBars.Value;
set => _cooldownBars.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initializes a new instance of the strategy.
/// </summary>
public Cspa143Strategy()
{
_strengthPeriod = Param(nameof(StrengthPeriod), 14)
.SetDisplay("Strength Period", "RSI period", "Parameters");
_threshold = Param(nameof(Threshold), 18m)
.SetDisplay("Threshold", "RSI distance from 50", "Parameters")
.SetGreaterThanZero();
_cooldownBars = Param(nameof(CooldownBars), 2)
.SetDisplay("Cooldown Bars", "Bars to wait after a completed trade", "Parameters");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_previousRsi = 0m;
_isInitialized = false;
_barsSinceTrade = CooldownBars;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi = new RelativeStrengthIndex { Length = StrengthPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(rsi, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal rsi)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (_barsSinceTrade < CooldownBars)
_barsSinceTrade++;
var upper = 50m + Threshold;
var lower = 50m - Threshold;
if (!_isInitialized)
{
_previousRsi = rsi;
_isInitialized = true;
return;
}
var longEntry = _previousRsi <= upper && rsi > upper;
var shortEntry = _previousRsi >= lower && rsi < lower;
var longExit = Position > 0 && _previousRsi >= 55m && rsi < 55m;
var shortExit = Position < 0 && _previousRsi <= 45m && rsi > 45m;
if (longExit)
{
SellMarket(Position);
_barsSinceTrade = 0;
}
else if (shortExit)
{
BuyMarket(-Position);
_barsSinceTrade = 0;
}
else if (_barsSinceTrade >= CooldownBars)
{
if (longEntry && Position <= 0)
{
BuyMarket(Volume + Math.Abs(Position));
_barsSinceTrade = 0;
}
else if (shortEntry && Position >= 0)
{
SellMarket(Volume + Math.Abs(Position));
_barsSinceTrade = 0;
}
}
_previousRsi = rsi;
}
}
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
from StockSharp.Algo.Indicators import RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class cspa143_strategy(Strategy):
def __init__(self):
super(cspa143_strategy, self).__init__()
self._strength_period = self.Param("StrengthPeriod", 14) \
.SetDisplay("Strength Period", "RSI period", "Parameters")
self._threshold = self.Param("Threshold", 18.0) \
.SetDisplay("Threshold", "RSI distance from 50", "Parameters")
self._cooldown_bars = self.Param("CooldownBars", 2) \
.SetDisplay("Cooldown Bars", "Bars to wait after a completed trade", "Parameters")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._previous_rsi = 0.0
self._is_initialized = False
self._bars_since_trade = 0
@property
def StrengthPeriod(self):
return self._strength_period.Value
@StrengthPeriod.setter
def StrengthPeriod(self, value):
self._strength_period.Value = value
@property
def Threshold(self):
return self._threshold.Value
@Threshold.setter
def Threshold(self, value):
self._threshold.Value = value
@property
def CooldownBars(self):
return self._cooldown_bars.Value
@CooldownBars.setter
def CooldownBars(self, value):
self._cooldown_bars.Value = value
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
def OnStarted2(self, time):
super(cspa143_strategy, self).OnStarted2(time)
rsi = RelativeStrengthIndex()
rsi.Length = self.StrengthPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(rsi, self.ProcessCandle).Start()
def ProcessCandle(self, candle, rsi_value):
if candle.State != CandleStates.Finished:
return
rsi = float(rsi_value)
if self._bars_since_trade < self.CooldownBars:
self._bars_since_trade += 1
upper = 50.0 + float(self.Threshold)
lower = 50.0 - float(self.Threshold)
if not self._is_initialized:
self._previous_rsi = rsi
self._is_initialized = True
return
long_entry = self._previous_rsi <= upper and rsi > upper
short_entry = self._previous_rsi >= lower and rsi < lower
long_exit = self.Position > 0 and self._previous_rsi >= 55.0 and rsi < 55.0
short_exit = self.Position < 0 and self._previous_rsi <= 45.0 and rsi > 45.0
if long_exit:
self.SellMarket(self.Position)
self._bars_since_trade = 0
elif short_exit:
self.BuyMarket(-self.Position)
self._bars_since_trade = 0
elif self._bars_since_trade >= self.CooldownBars:
pos = self.Position
if long_entry and pos <= 0:
self.BuyMarket(self.Volume + abs(pos))
self._bars_since_trade = 0
elif short_entry and pos >= 0:
self.SellMarket(self.Volume + abs(pos))
self._bars_since_trade = 0
self._previous_rsi = rsi
def OnReseted(self):
super(cspa143_strategy, self).OnReseted()
self._previous_rsi = 0.0
self._is_initialized = False
self._bars_since_trade = self.CooldownBars
def CreateClone(self):
return cspa143_strategy()