Die Cryptos-Strategie ist eine High-Level-StockSharp-Portierung des ursprünglichen MetaTrader4-Expertenberaters cryptos.mq4. Es konzentriert sich auf das ETH/USD-Paar und kombiniert Bollinger-Bänder mit einem linear gewichteten gleitenden Durchschnitt (LWMA), um Ausbrüche aus der Volatilitätskompression zu erfassen. Die Strategie verfolgt Swing-Hochs und -Tiefs über eine konfigurierbare Anzahl von Kerzen und berechnet dynamisch Take-Profit-Ziele als Vielfaches der erkannten Spanne.
Handelslogik
Trenderkennung – wenn der Schlusskurs das obere Bollinger-Band berührt, wechselt die Strategie in eine Short-Tendenz, und wenn das untere Band berührt wird, wechselt sie in eine Long-Tendenz. Die Bandberührung friert außerdem die aktuellen Swing-Werte ein, indem die automatische Hoch-/Tiefaktualisierung deaktiviert wird.
Eintrittsbedingungen –
Eröffnen Sie eine Short-Position, wenn der Schlusskurs unter den LWMA fällt, die Tendenz Short ist und keine aktive Short-Position besteht.
Eröffnen Sie eine Long-Position, wenn der Schlusskurs über den LWMA steigt, die Tendenz long ist und keine aktive Long-Position besteht.
Bereichsprojektion – Swing-Hochs und -Tiefs (entweder automatisch oder manuell eingefroren) definieren den Abstand vom LWMA. Dieser in Ticks ausgedrückte Abstand wird mit der Take-Profit-Quote multipliziert, um Gewinnziele und die risikobasierte Positionsgröße zu berechnen.
Risikokontrolle – die Strategie legt Take-Profit- und Stop-Loss-Niveaus pro Trade fest. Bei Long-Positionen wird der Stop unterhalb des Swing-Tiefs platziert; für Shorts, oberhalb der Swing-Höhe. Stopps und Ziele werden für jeden Eintrag neu berechnet und innerhalb der Strategieschleife durchgesetzt.
Trailing-Exits – wenn eine Long-Position unterhalb des unteren Bollinger-Bandes (oder eine Short-Position über dem oberen Band) schließt, wird die offene Position sofort abgeflacht, wodurch das Trailing-Verhalten des ursprünglichen EA nachgeahmt wird.
Parameter
Parameter
Beschreibung
CandleType
Datentyp der Kerzenserie, der für alle Indikatorberechnungen verwendet wird.
BollingerPeriod, BollingerWidth
Länge und Standardabweichungsmultiplikator der Bollinger-Bänder.
MaPeriod
Zeitraum des linear gewichteten gleitenden Durchschnitts basierend auf Medianpreisen.
LookbackCandles
Anzahl der untersuchten Kerzen, um den automatischen Hoch-/Tiefschwung zu bestimmen.
TakeProfitRatio
Bereichsmultiplikator, der für Gewinnziele beim Handel mit ETH/USD verwendet wird.
AlternativeTakeProfitRatio
Bereichsmultiplikator wird auf alle anderen Symbole angewendet.
RiskPerTrade
Kapitalbetrag (in Quotierungswährung), den der Volumenrechner bei jedem Trade zu riskieren versucht.
ValueIndex, CryptoValueIndex
Multiplikatoren, die das Risiko in Volumen für Nicht-Krypto- bzw. Krypto-Symbole umwandeln.
MinVolume, MaxVolume
Feste Grenzen für die Positionsgröße nach der Ausrichtung, um Volumenschritte auszutauschen.
MinRangeTicks
Minimal zulässiger projizierter Bereich in Ticks, um Null-Distanz-Stopps zu vermeiden.
SpreadPoints
Manuelle Überschreibung des Spreads in Ticks (wird automatisch anhand des besten Geld-/Briefkurses ermittelt, sofern verfügbar).
GlobalTrend
Manuelle Bias-Überschreibung: 1 erzwingt eine kurze Einrichtung, 2 erzwingt eine lange Einrichtung, 0 lässt die Strategie entscheiden.
AutoHighLow
Wenn diese Option aktiviert ist, werden die Swing-Punkte bei jeder Kerze neu berechnet; Wenn sie deaktiviert sind, bleiben sie bis zur nächsten Bandberührung eingefroren.
ManualBuyTrigger, ManualSellTrigger
Auf true setzen, um einen sofortigen Long- oder Short-Eintrag anzufordern (nach der Ausführung zurückgesetzt).
SkipBuys, SkipSells
Deaktivieren Sie die Eröffnung neuer Long- oder Short-Positionen.
Positionsgrößen
Die Strategie repliziert die MT4-Logik: volume = RiskPerTrade / rangeTicks * valueIndex. Das Ergebnis wird an VolumeStep angepasst und dann zwischen MinVolume/MaxVolume und den durch die Börse auferlegten Limits des Instruments begrenzt.
Nutzungshinweise
Die Strategie prüft den Portfoliowert beim Start. Wenn der Kontostand unter RiskPerTrade * 3 liegt, wird der Handel deaktiviert und eine Warnung wird protokolliert, die der Sicherheitsüberprüfung von EA entspricht.
Manuelle Trigger und Bias-Kontrollen ermöglichen die Synchronisierung mit Ermessensentscheidungen während des Live-Handels.
ETH/USD verwendet automatisch CryptoValueIndex und TakeProfitRatio; andere Instrumente greifen auf die alternativen Parameter zurück.
Stopps und Ziele werden innerhalb der Strategieschleife durchgesetzt, sodass kein zusätzliches Schutzmodul erforderlich ist.
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Simplified from "Cryptos" MetaTrader expert.
/// Uses Bollinger Bands with a WMA trend filter. Buys when price is below WMA
/// and touches lower band; sells when price is above WMA and touches upper band.
/// </summary>
public class CryptosStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _wmaPeriod;
private readonly StrategyParam<int> _bollingerPeriod;
private readonly StrategyParam<decimal> _bollingerWidth;
private ExponentialMovingAverage _bandEma;
private ExponentialMovingAverage _trendEma;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int WmaPeriod
{
get => _wmaPeriod.Value;
set => _wmaPeriod.Value = value;
}
public int BollingerPeriod
{
get => _bollingerPeriod.Value;
set => _bollingerPeriod.Value = value;
}
public decimal BollingerWidth
{
get => _bollingerWidth.Value;
set => _bollingerWidth.Value = value;
}
public CryptosStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for signals", "General");
_wmaPeriod = Param(nameof(WmaPeriod), 55)
.SetGreaterThanZero()
.SetDisplay("WMA Period", "Weighted moving average period", "Indicators");
_bollingerPeriod = Param(nameof(BollingerPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("BB Period", "Bollinger Bands period", "Indicators");
_bollingerWidth = Param(nameof(BollingerWidth), 2m)
.SetGreaterThanZero()
.SetDisplay("BB Width", "Bollinger Bands deviation", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_bandEma = new ExponentialMovingAverage { Length = BollingerPeriod };
_trendEma = new ExponentialMovingAverage { Length = WmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_bandEma, _trendEma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _bandEma);
DrawIndicator(area, _trendEma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal bandValue, decimal trendValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!_bandEma.IsFormed || !_trendEma.IsFormed)
return;
var close = candle.ClosePrice;
var bandOffset = bandValue * (BollingerWidth / 100m);
var upperBand = bandValue + bandOffset;
var lowerBand = bandValue - bandOffset;
var volume = Volume;
if (volume <= 0)
volume = 1;
// Buy: price below WMA, touches lower band
if (close < trendValue && close <= lowerBand)
{
if (Position <= 0)
BuyMarket(Position < 0 ? Math.Abs(Position) + volume : volume);
}
// Sell: price above WMA, touches upper band
else if (close > trendValue && close >= upperBand)
{
if (Position >= 0)
SellMarket(Position > 0 ? Math.Abs(Position) + volume : volume);
}
// Exit at WMA cross
if (Position > 0 && close >= upperBand)
SellMarket(Position);
else if (Position < 0 && close <= lowerBand)
BuyMarket(Math.Abs(Position));
}
/// <inheritdoc />
protected override void OnReseted()
{
_bandEma = null;
_trendEma = null;
base.OnReseted();
}
}
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 cryptos_strategy(Strategy):
def __init__(self):
super(cryptos_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60)))
self._wma_period = self.Param("WmaPeriod", 55)
self._bollinger_period = self.Param("BollingerPeriod", 20)
self._bollinger_width = self.Param("BollingerWidth", 2.0)
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def WmaPeriod(self):
return self._wma_period.Value
@WmaPeriod.setter
def WmaPeriod(self, value):
self._wma_period.Value = value
@property
def BollingerPeriod(self):
return self._bollinger_period.Value
@BollingerPeriod.setter
def BollingerPeriod(self, value):
self._bollinger_period.Value = value
@property
def BollingerWidth(self):
return self._bollinger_width.Value
@BollingerWidth.setter
def BollingerWidth(self, value):
self._bollinger_width.Value = value
def OnReseted(self):
super(cryptos_strategy, self).OnReseted()
def OnStarted2(self, time):
super(cryptos_strategy, self).OnStarted2(time)
band_ema = ExponentialMovingAverage()
band_ema.Length = self.BollingerPeriod
trend_ema = ExponentialMovingAverage()
trend_ema.Length = self.WmaPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(band_ema, trend_ema, self._process_candle).Start()
def _process_candle(self, candle, band_value, trend_value):
if candle.State != CandleStates.Finished:
return
band_val = float(band_value)
trend_val = float(trend_value)
close = float(candle.ClosePrice)
band_offset = band_val * (float(self.BollingerWidth) / 100.0)
upper_band = band_val + band_offset
lower_band = band_val - band_offset
# Buy: price below WMA, touches lower band
if close < trend_val and close <= lower_band:
if self.Position <= 0:
self.BuyMarket()
# Sell: price above WMA, touches upper band
elif close > trend_val and close >= upper_band:
if self.Position >= 0:
self.SellMarket()
# Exit at opposite band
if self.Position > 0 and close >= upper_band:
self.SellMarket()
elif self.Position < 0 and close <= lower_band:
self.BuyMarket()
def CreateClone(self):
return cryptos_strategy()