La Estrategia Cryptos es una versión StockSharp de alto nivel del asesor experto MetaTrader4 original cryptos.mq4. Se centra en el par ETH/USD, combinando Bollinger bandas con un promedio móvil ponderado lineal (LWMA) para capturar rupturas de la compresión de la volatilidad. La estrategia rastrea los máximos y mínimos a lo largo de un número configurable de velas y calcula dinámicamente los objetivos de obtención de beneficios como un múltiplo del rango detectado.
Lógica de trading
Detección de tendencias: cuando el precio de cierre toca la banda superior Bollinger, la estrategia cambia a un sesgo corto, y cuando se toca la banda inferior, cambia a un sesgo largo. El toque de banda también congela los valores de swing actuales al desactivar las actualizaciones automáticas de altos/bajos.
Condiciones de entrada –
Abra una posición corta cuando el precio de cierre caiga por debajo de la LWMA, el sesgo sea corto y no haya una posición corta activa.
Abra una posición larga cuando el precio de cierre suba por encima de la LWMA, el sesgo sea largo y no haya una posición larga activa.
Proyección de rango: los máximos y mínimos de oscilación (ya sea automático o congelado manualmente) definen la distancia desde el LWMA. Esta distancia, expresada en ticks, se multiplica por el índice de obtención de beneficios para calcular los objetivos de beneficios y el tamaño de la posición basada en el riesgo.
Control de riesgos: la estrategia establece niveles de obtención de beneficios y limitación de pérdidas por operación. Para posiciones largas, el stop se coloca por debajo del mínimo de oscilación; para pantalones cortos, por encima del máximo del swing. Las paradas y los objetivos se recalculan para cada entrada y se aplican dentro del ciclo de estrategia.
Salidas finales: si una posición larga se cierra por debajo de la banda inferior Bollinger (o una posición corta por encima de la banda superior), la posición abierta se aplana inmediatamente, imitando el comportamiento final de la EA original.
Parámetros
Parámetro
Descripción
CandleType
Tipo de datos de la serie de velas utilizada para todos los cálculos del indicador.
BollingerPeriod, BollingerWidth
Multiplicador de longitud y desviación estándar de las Bollinger Bandas.
MaPeriod
Período de la media móvil lineal ponderada en función de los precios medianos.
LookbackCandles
Número de velas examinadas para determinar la oscilación automática alto/bajo.
TakeProfitRatio
Multiplicador de rango utilizado para objetivos de ganancias al operar con ETH/USD.
AlternativeTakeProfitRatio
Multiplicador de rango aplicado a todos los demás símbolos.
RiskPerTrade
Cantidad de capital (en moneda cotizada) que la calculadora de volumen intenta arriesgar en cada operación.
ValueIndex, CryptoValueIndex
Multiplicadores que convierten el riesgo en volumen para símbolos criptográficos y no criptográficos, respectivamente.
MinVolume, MaxVolume
Límites estrictos para el tamaño de la posición después de la alineación para intercambiar pasos de volumen.
MinRangeTicks
Rango proyectado mínimo permitido en ticks para evitar paradas de distancia cero.
SpreadPoints
Anulación manual del diferencial en ticks (detectado automáticamente desde la mejor oferta/demanda, si está disponible).
GlobalTrend
Anulación de sesgo manual: 1 fuerza una configuración corta, 2 fuerza una configuración larga, 0 deja que la estrategia decida.
AutoHighLow
Cuando está habilitado, los puntos de oscilación se recalculan en cada vela; cuando están deshabilitados, se congelan hasta el siguiente toque de banda.
ManualBuyTrigger, ManualSellTrigger
Establezca en true para solicitar una entrada larga o corta inmediata (restablecer después de la ejecución).
SkipBuys, SkipSells
Deshabilite la apertura de nuevas posiciones largas o cortas.
Dimensionamiento de posiciones
La estrategia replica la lógica MT4: volume = RiskPerTrade / rangeTicks * valueIndex. El resultado se alinea con VolumeStep y luego se recorta entre MinVolume/MaxVolume y los límites impuestos por el intercambio del instrumento.
Notas de uso
La estrategia verifica el valor de la cartera al inicio. Si el saldo es inferior a RiskPerTrade * 3, el comercio se desactiva y se registra una advertencia que coincide con la verificación de seguridad de EA.
Los activadores manuales y los controles de sesgo hacen posible la sincronización con decisiones discrecionales durante las operaciones en vivo.
ETH/USD utiliza automáticamente CryptoValueIndex y TakeProfitRatio; otros instrumentos recurren a los parámetros alternativos.
Las paradas y los objetivos se aplican dentro del bucle de estrategia, por lo que no se requiere ningún módulo de protección adicional.
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()