Estrategia Evaluadora de Osciladores
Esta estrategia combina el Índice de Fuerza Relativa (RSI) y el Oscilador Estocástico para identificar puntos de entrada y salida. Se abre una posición larga cuando ambos osciladores caen por debajo del umbral de sobrevendido, mientras que se abre una posición corta cuando ambos suben por encima del umbral de sobrecomprado. Las posiciones se cierran una vez que ambos indicadores regresan a la zona neutral. La estrategia también admite protección de take-profit y stop-loss configurables.
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class OscillatorEvaluatorStrategy : Strategy
{
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<DataType> _candleType;
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public OscillatorEvaluatorStrategy()
{
_rsiPeriod = Param(nameof(RsiPeriod), 14).SetGreaterThanZero();
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame());
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fast = new ExponentialMovingAverage { Length = 14 };
var slow = new ExponentialMovingAverage { Length = 40 };
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var prevF = 0m;
var prevS = 0m;
var init = false;
var lastSignal = DateTimeOffset.MinValue;
var cooldown = TimeSpan.FromMinutes(360);
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, slow, rsi, (candle, f, s, r) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!fast.IsFormed || !slow.IsFormed || !rsi.IsFormed)
return;
if (!init)
{
prevF = f;
prevS = s;
init = true;
return;
}
if (candle.OpenTime - lastSignal >= cooldown)
{
if (prevF <= prevS && f > s && r > 50 && Position <= 0)
{
BuyMarket();
lastSignal = candle.OpenTime;
}
else if (prevF >= prevS && f < s && r < 50 && Position >= 0)
{
SellMarket();
lastSignal = candle.OpenTime;
}
}
prevF = f;
prevS = s;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fast);
DrawIndicator(area, slow);
DrawOwnTrades(area);
}
}
}
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, RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class oscillator_evaluator_strategy(Strategy):
def __init__(self):
super(oscillator_evaluator_strategy, self).__init__()
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetGreaterThanZero()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5)))
self._prev_fast = 0.0
self._prev_slow = 0.0
self._initialized = False
self._last_signal_ticks = 0
@property
def candle_type(self):
return self._candle_type.Value
@candle_type.setter
def candle_type(self, value):
self._candle_type.Value = value
def OnReseted(self):
super(oscillator_evaluator_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._initialized = False
self._last_signal_ticks = 0
def OnStarted2(self, time):
super(oscillator_evaluator_strategy, self).OnStarted2(time)
self._prev_fast = 0.0
self._prev_slow = 0.0
self._initialized = False
self._last_signal_ticks = 0
self._fast = ExponentialMovingAverage()
self._fast.Length = 14
self._slow = ExponentialMovingAverage()
self._slow.Length = 40
self._rsi = RelativeStrengthIndex()
self._rsi.Length = self._rsi_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._fast, self._slow, self._rsi, self.OnProcess).Start()
def OnProcess(self, candle, f, s, r):
if candle.State != CandleStates.Finished:
return
if not self._fast.IsFormed or not self._slow.IsFormed or not self._rsi.IsFormed:
return
fv = float(f)
sv = float(s)
rv = float(r)
if not self._initialized:
self._prev_fast = fv
self._prev_slow = sv
self._initialized = True
return
cooldown_ticks = TimeSpan.FromMinutes(360).Ticks
current_ticks = candle.OpenTime.Ticks
if current_ticks - self._last_signal_ticks >= cooldown_ticks:
if self._prev_fast <= self._prev_slow and fv > sv and rv > 50 and self.Position <= 0:
self.BuyMarket()
self._last_signal_ticks = current_ticks
elif self._prev_fast >= self._prev_slow and fv < sv and rv < 50 and self.Position >= 0:
self.SellMarket()
self._last_signal_ticks = current_ticks
self._prev_fast = fv
self._prev_slow = sv
def CreateClone(self):
return oscillator_evaluator_strategy()