Esta estrategia emula el experto BuySell de MetaTrader. Combina una media móvil con el Average True Range (ATR) para detectar reversiones de tendencia.
Cuando la media móvil se orienta hacia arriba, el sistema considera el mercado alcista; cuando se orienta hacia abajo, lo considera bajista.
Una operación se abre solo si la vela anterior estaba en el estado contrario, confirmando una reversión. Los niveles opcionales de stop-loss y take-profit se expresan en puntos de precio.
Detalles
Lógica de entrada
Largo: la media móvil pasa de caer a subir y la vela anterior era bajista.
Corto: la media móvil pasa de subir a caer y la vela anterior era alcista.
Lógica de salida
Largo: la media móvil se gira a la baja o se activa el stop-loss / take-profit.
Corto: la media móvil se gira al alza o se activa el stop-loss / take-profit.
Indicadores: Media Móvil Simple (SMA) y ATR.
Stops: Stop-loss y take-profit en puntos.
Permisos: indicadores separados permiten o prohíben abrir/cerrar posiciones largas y cortas.
Marco temporal predeterminado: velas de 4 horas.
Parámetros
Nombre
Predeterminado
Descripción
MaPeriod
14
Período de la media móvil.
AtrPeriod
60
Período del ATR.
StopLoss
1000
Stop-loss en puntos de precio.
TakeProfit
2000
Take-profit en puntos de precio.
AllowLongEntry
true
Permiso para abrir posiciones largas.
AllowShortEntry
true
Permiso para abrir posiciones cortas.
AllowLongExit
true
Permiso para cerrar posiciones largas.
AllowShortExit
true
Permiso para cerrar posiciones cortas.
CandleType
H4
Marco temporal utilizado para los cálculos.
Uso
Añade la estrategia a tu solución StockSharp.
Configura los parámetros según sea necesario.
Ejecuta la estrategia en modo en vivo o de backtesting. Las operaciones se ejecutan mediante órdenes BuyMarket y SellMarket.
El enfoque es adecuado para mercados donde las reversiones de tendencia van acompañadas de cambios de volatilidad capturados por el ATR.
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>
/// Buy/Sell strategy based on EMA crossover.
/// </summary>
public class BuySellStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFast;
private decimal _prevSlow;
private bool _hasPrev;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public BuySellStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("Fast Period", "Fast EMA period", "Indicator");
_slowPeriod = Param(nameof(SlowPeriod), 28)
.SetGreaterThanZero()
.SetDisplay("Slow Period", "Slow EMA period", "Indicator");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle type", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0;
_prevSlow = 0;
_hasPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
SubscribeCandles(CandleType)
.Bind(fast, slow, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fastVal, decimal slowVal)
{
if (candle.State != CandleStates.Finished) return;
if (!_hasPrev)
{
_prevFast = fastVal;
_prevSlow = slowVal;
_hasPrev = true;
return;
}
var crossUp = _prevFast <= _prevSlow && fastVal > slowVal;
var crossDown = _prevFast >= _prevSlow && fastVal < slowVal;
if (crossUp && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (crossDown && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
_prevFast = fastVal;
_prevSlow = slowVal;
}
}