La Estrategia de Retroceso Para es una conversión a C# del asesor experto original de MetaTrader 4 Para_Retrace.mq4. Reproduce la idea de usar el indicador Parabolic SAR como ancla dinámica y esperar retrocesos del precio hacia ese nivel antes de entrar al mercado. La conversión aprovecha la API de alto nivel de StockSharp para gestionar suscripciones de datos de mercado, actualizaciones de indicadores y ejecución de órdenes.
Lógica de Trading
Calcular el valor del Parabolic SAR en cada vela terminada usando el paso de aceleración y la aceleración máxima configurados.
Determinar la tendencia predominante comprobando si toda la vela está por debajo o por encima del valor SAR:
Contexto bajista: si tanto el máximo como el mínimo de la vela están por debajo del valor SAR.
Contexto alcista: de lo contrario (el precio está tocando o por encima del nivel SAR).
Derivar un precio desencadenante desplazando el valor SAR un número de pips definido por el usuario:
En un contexto bajista la estrategia resta el desplazamiento, esperando un retroceso hacia arriba.
En un contexto alcista la estrategia suma el desplazamiento, esperando un retroceso hacia abajo.
Una vez que el precio toca el desencadenante (el máximo cruza por encima para cortos, el mínimo cruza por debajo para largos), la estrategia abre una orden de mercado en la dirección de la tendencia.
Las órdenes de stop-loss y take-profit de protección se adjuntan automáticamente usando la facilidad StartProtection de StockSharp, coincidiendo con las distancias del script original.
A diferencia del asesor experto original, la versión de StockSharp continúa operando después de que se abre una posición; no es necesario restablecer manualmente el valor de desplazamiento. Todas las acciones se realizan únicamente en velas completadas para evitar problemas de repintado intrabarra.
Indicadores
Parabolic SAR – impulsa tanto la detección de tendencia como los niveles de entrada.
Parámetros
Parámetro
Descripción
Predeterminado
SarStep
Factor de aceleración inicial para el Parabolic SAR.
0.01
SarMax
Factor de aceleración máximo para el Parabolic SAR.
0.2
RetraceOffsetPips
Distancia (en pips) entre el valor SAR y el desencadenante de entrada.
30
StopLossPips
Distancia de stop-loss en pips (convertida a precio absoluto). Establecer en 0 para deshabilitar.
30
TakeProfitPips
Distancia de take-profit en pips (convertida a precio absoluto). Establecer en 0 para deshabilitar.
30
CandleType
Marco temporal usado para velas y cálculos de indicadores.
5 Minute
Nota: La estrategia estima el tamaño del pip a partir de los metadatos de seguridad. Si el instrumento usa cinco decimales (típico para Forex), un pip equivale a diez pasos mínimos de precio.
Gestión de Órdenes
Las órdenes se colocan a mercado una vez que se satisface la condición de retroceso.
El tamaño de operación predeterminado es un lote (Volume = 1), pero puede ajustarse mediante la propiedad base Strategy.Volume antes de iniciar la estrategia.
StartProtection gestiona automáticamente las colocaciones de stop-loss y take-profit usando desplazamientos de precio absolutos derivados de los ajustes de pips.
Consejos de Uso
Ajuste el desplazamiento de pips, el stop y el objetivo para que coincidan con la volatilidad del instrumento que se está operando.
Considere combinar la estrategia con filtros adicionales (hora del día, volatilidad, etc.) cuando se integre en un marco de trading más amplio.
Siempre realice backtesting antes de desplegar en vivo, ya que la rentabilidad depende fuertemente de las condiciones del mercado y la ejecución del bróker.
Diferencias vs. Script Original
Trading continuo sin variables globales manuales.
Usa velas completadas en lugar de verificaciones tick a tick, lo que proporciona comportamiento determinista para backtests.
Gestión de riesgo integrada a través del módulo de órdenes de protección de StockSharp.
Descargo de Responsabilidad
Esta estrategia se proporciona con fines educativos. Pruebe exhaustivamente en datos históricos y de demostración antes de comprometer capital real.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Para Retrace strategy. Uses WMA crossover (7/21).
/// </summary>
public class ParaRetraceStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private decimal? _prevFast;
private decimal? _prevSlow;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public ParaRetraceStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 7).SetGreaterThanZero().SetDisplay("Fast WMA", "Fast WMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 21).SetGreaterThanZero().SetDisplay("Slow WMA", "Slow WMA period", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = null;
_prevSlow = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = null; _prevSlow = null;
var fast = new WeightedMovingAverage { Length = FastPeriod };
var slow = new WeightedMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fast, slow, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, fast); DrawIndicator(area, slow); DrawOwnTrades(area); }
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished) return;
if (!IsFormedAndOnlineAndAllowTrading()) { _prevFast = fast; _prevSlow = slow; return; }
if (_prevFast == null || _prevSlow == null) { _prevFast = fast; _prevSlow = slow; return; }
var prevAbove = _prevFast.Value > _prevSlow.Value;
var currAbove = fast > slow;
_prevFast = fast; _prevSlow = slow;
if (!prevAbove && currAbove && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
else if (prevAbove && !currAbove && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
}
}
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 WeightedMovingAverage
from StockSharp.Algo.Strategies import Strategy
class para_retrace_strategy(Strategy):
def __init__(self):
super(para_retrace_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._fast_period = self.Param("FastPeriod", 7) \
.SetDisplay("Fast WMA", "Fast WMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 21) \
.SetDisplay("Slow WMA", "Slow WMA period", "Indicators")
self._prev_fast = None
self._prev_slow = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def FastPeriod(self):
return self._fast_period.Value
@property
def SlowPeriod(self):
return self._slow_period.Value
def OnReseted(self):
super(para_retrace_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(para_retrace_strategy, self).OnStarted2(time)
self._prev_fast = None
self._prev_slow = None
fast = WeightedMovingAverage()
fast.Length = self.FastPeriod
slow = WeightedMovingAverage()
slow.Length = self.SlowPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast, slow, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast)
self.DrawIndicator(area, slow)
self.DrawOwnTrades(area)
def _on_process(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fv = float(fast_value)
sv = float(slow_value)
if self._prev_fast is None or self._prev_slow is None:
self._prev_fast = fv
self._prev_slow = sv
return
prev_above = self._prev_fast > self._prev_slow
curr_above = fv > sv
self._prev_fast = fv
self._prev_slow = sv
if not prev_above and curr_above and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif prev_above and not curr_above and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
def CreateClone(self):
return para_retrace_strategy()