Estrategia del Oscilador de Olas de Elliott
Esta estrategia aplica el Oscilador de Olas de Elliott (EWO) sobre los cierres de velas. El EWO se calcula como la diferencia entre una Media Móvil Simple rápida y una lenta (5 y 35 períodos por defecto). La lógica de trading busca puntos de giro en el oscilador para capturar posibles reversiones de tendencia.
Se abre una posición larga cuando el oscilador forma un mínimo local y comienza a subir. Se abre una posición corta cuando el oscilador forma un máximo local y comienza a caer. Las posiciones existentes se invierten en consecuencia. Se admiten take‑profit y stop‑loss basados en porcentaje opcionales a través de StartProtection.
Detalles
- Indicador: Oscilador de Olas de Elliott = SMA(rápida) − SMA(lenta).
- Criterios de entrada:
- Largo: el valor del oscilador estaba bajando y luego gira hacia arriba.
- Corto: el valor del oscilador estaba subiendo y luego gira hacia abajo.
- Largo/Corto: Ambos.
- Criterios de salida: La posición se invierte ante la señal opuesta o sale por stop o take‑profit.
- Stops: Stop‑loss y take‑profit en porcentaje.
- Filtros: Ninguno.
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Elliott Wave Oscillator based strategy.
/// Buys when the oscillator turns upward.
/// Sells when the oscillator turns downward.
/// </summary>
public class ElliottWaveOscillatorStrategy : Strategy
{
private readonly StrategyParam<int> _fastLength;
private readonly StrategyParam<int> _slowLength;
private readonly StrategyParam<decimal> _takeProfitPct;
private readonly StrategyParam<decimal> _stopLossPct;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevEwo;
private decimal _prevPrevEwo;
private bool _isFirstValue;
/// <summary>
/// Fast moving average length.
/// </summary>
public int FastLength
{
get => _fastLength.Value;
set => _fastLength.Value = value;
}
/// <summary>
/// Slow moving average length.
/// </summary>
public int SlowLength
{
get => _slowLength.Value;
set => _slowLength.Value = value;
}
/// <summary>
/// Take profit percentage.
/// </summary>
public decimal TakeProfitPct
{
get => _takeProfitPct.Value;
set => _takeProfitPct.Value = value;
}
/// <summary>
/// Stop loss percentage.
/// </summary>
public decimal StopLossPct
{
get => _stopLossPct.Value;
set => _stopLossPct.Value = value;
}
/// <summary>
/// Candle type to use.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initializes a new instance of the strategy.
/// </summary>
public ElliottWaveOscillatorStrategy()
{
_fastLength = Param(nameof(FastLength), 5)
.SetGreaterThanZero()
.SetDisplay("Fast Length", "Length of the fast SMA", "Indicator")
;
_slowLength = Param(nameof(SlowLength), 35)
.SetGreaterThanZero()
.SetDisplay("Slow Length", "Length of the slow SMA", "Indicator")
;
_takeProfitPct = Param(nameof(TakeProfitPct), 1m)
.SetGreaterThanZero()
.SetDisplay("Take Profit %", "Percentage take profit", "Risk")
;
_stopLossPct = Param(nameof(StopLossPct), 1m)
.SetGreaterThanZero()
.SetDisplay("Stop Loss %", "Percentage stop loss", "Risk")
;
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevEwo = 0m;
_prevPrevEwo = 0m;
_isFirstValue = true;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fastMa = new ExponentialMovingAverage { Length = FastLength };
var slowMa = new ExponentialMovingAverage { Length = SlowLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastMa, slowMa, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fastMa);
DrawIndicator(area, slowMa);
DrawOwnTrades(area);
}
StartProtection(new Unit(TakeProfitPct / 100m, UnitTypes.Percent), new Unit(StopLossPct / 100m, UnitTypes.Percent));
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var ewoValue = fastValue - slowValue;
if (_isFirstValue)
{
_prevEwo = ewoValue;
_prevPrevEwo = ewoValue;
_isFirstValue = false;
return;
}
if (_prevEwo < _prevPrevEwo && ewoValue > _prevEwo)
{
// Oscillator turns upward - open long
if (Position <= 0)
BuyMarket();
}
else if (_prevEwo > _prevPrevEwo && ewoValue < _prevEwo)
{
// Oscillator turns downward - open short
if (Position >= 0)
SellMarket();
}
_prevPrevEwo = _prevEwo;
_prevEwo = ewoValue;
}
}
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, Unit, UnitTypes
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class elliott_wave_oscillator_strategy(Strategy):
def __init__(self):
super(elliott_wave_oscillator_strategy, self).__init__()
self._fast_length = self.Param("FastLength", 5) \
.SetDisplay("Fast Length", "Length of the fast SMA", "Indicator")
self._slow_length = self.Param("SlowLength", 35) \
.SetDisplay("Slow Length", "Length of the slow SMA", "Indicator")
self._take_profit_pct = self.Param("TakeProfitPct", 1.0) \
.SetDisplay("Take Profit %", "Percentage take profit", "Risk")
self._stop_loss_pct = self.Param("StopLossPct", 1.0) \
.SetDisplay("Stop Loss %", "Percentage stop loss", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._prev_ewo = 0.0
self._prev_prev_ewo = 0.0
self._is_first_value = True
@property
def fast_length(self):
return self._fast_length.Value
@property
def slow_length(self):
return self._slow_length.Value
@property
def take_profit_pct(self):
return self._take_profit_pct.Value
@property
def stop_loss_pct(self):
return self._stop_loss_pct.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(elliott_wave_oscillator_strategy, self).OnReseted()
self._prev_ewo = 0.0
self._prev_prev_ewo = 0.0
self._is_first_value = True
def OnStarted2(self, time):
super(elliott_wave_oscillator_strategy, self).OnStarted2(time)
fast_ma = ExponentialMovingAverage()
fast_ma.Length = self.fast_length
slow_ma = ExponentialMovingAverage()
slow_ma.Length = self.slow_length
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(fast_ma, slow_ma, self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast_ma)
self.DrawIndicator(area, slow_ma)
self.DrawOwnTrades(area)
self.StartProtection(
takeProfit=Unit(float(self.take_profit_pct) / 100.0, UnitTypes.Percent),
stopLoss=Unit(float(self.stop_loss_pct) / 100.0, UnitTypes.Percent))
def process_candle(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fast_value = float(fast_value)
slow_value = float(slow_value)
ewo_value = fast_value - slow_value
if self._is_first_value:
self._prev_ewo = ewo_value
self._prev_prev_ewo = ewo_value
self._is_first_value = False
return
if self._prev_ewo < self._prev_prev_ewo and ewo_value > self._prev_ewo:
if self.Position <= 0:
self.BuyMarket()
elif self._prev_ewo > self._prev_prev_ewo and ewo_value < self._prev_ewo:
if self.Position >= 0:
self.SellMarket()
self._prev_prev_ewo = self._prev_ewo
self._prev_ewo = ewo_value
def CreateClone(self):
return elliott_wave_oscillator_strategy()