La estrategia Forex Fraus M1 replica el asesor experto MetaTrader 5 "Forex Fraus M1" en el framework StockSharp. Es un sistema contrario que monitorea un oscilador Williams %R de largo período (período 360) en velas de un minuto. Cada vez que el oscilador toca valores extremos, la estrategia intenta desvanecerse del movimiento, apuntando a una rápida reversión hacia el punto medio del rango reciente. La implementación mantiene la gestión de dinero del experto original, incluyendo horas de trading opcionales, niveles estáticos de stop-loss y take-profit medidos en pips y un trailing stop basado en pips.
Lógica de trading
Indicador: Williams %R con un período de 360.
Señal de compra: Cuando Williams %R cae por debajo de -99.9, el mercado se considera extremadamente sobrevendido. La estrategia envía una orden de compra al mercado si no hay posición larga existente. Si CloseOppositePositions está habilitado, cualquier exposición corta se cierra en la misma solicitud de orden.
Señal de venta: Cuando Williams %R sube por encima de -0.1, el mercado está extremadamente sobrecomprado. La estrategia emite una orden de venta al mercado, opcionalmente cerrando primero cualquier exposición larga abierta.
Filtro de tiempo: Cuando UseTimeControl está habilitado, la estrategia solo evalúa señales entre StartHour (inclusive) y EndHour (exclusive). Si la sesión cruza la medianoche (StartHour > EndHour), el trading se permite de StartHour a 23 y de 0 a EndHour - 1.
Gestión de riesgo
Stop-loss: Calculado como StopLossPips * PipSize por debajo (para largos) o por encima (para cortos) del precio de entrada. Cuando el mínimo de la vela toca el nivel de stop, la posición se cierra al mercado.
Take-profit: Calculado como TakeProfitPips * PipSize por encima (para largos) o por debajo (para cortos) del precio de entrada. Cuando el máximo/mínimo de la vela alcanza este nivel, la posición se cierra para asegurar ganancias.
Trailing stop: Si tanto TrailingStopPips como TrailingStepPips son positivos, el stop se aprieta una vez que el precio se mueve al menos TrailingStopPips + TrailingStepPips pips a favor de la operación. Para largos el stop sigue el cierre menos TrailingStopPips; para cortos sigue el cierre más TrailingStopPips.
Tamaño de pip: PipSize define el valor monetario de un pip. Para símbolos Forex de cinco dígitos establezca PipSize en 0.0001, para pares JPY de tres dígitos use 0.01, etc.
La estrategia verifica las condiciones de stop-loss y take-profit usando los máximos/mínimos de las velas. Cuando ambos se tocan dentro de la misma vela, el stop de protección tiene prioridad, reflejando el comportamiento conservador del experto original.
Parámetros
Nombre
Predeterminado
Descripción
OrderVolume
0.1
Volumen de operación usado para nuevas posiciones.
StopLossPips
50
Distancia del stop-loss en pips desde el precio de entrada. Establezca en cero para deshabilitar.
TakeProfitPips
150
Distancia del take-profit en pips desde el precio de entrada. Establezca en cero para deshabilitar.
TrailingStopPips
1
Distancia base del trailing stop en pips. Establezca en cero para deshabilitar el seguimiento.
TrailingStepPips
1
Ganancia mínima adicional en pips antes de que el trailing stop se mueva.
UseTimeControl
true
Habilita el filtro de sesión intradiaria.
StartHour
7
Hora de inicio de la sesión de trading (0-23).
EndHour
17
Hora de fin de la sesión de trading (1-24, exclusive).
CloseOppositePositions
true
Si está habilitado, revierte las posiciones existentes en una sola orden.
WilliamsPeriod
360
Período de retrospectiva para el indicador Williams %R.
CandleType
1 minute
Tipo de vela utilizado para evaluar Williams %R y las reglas de trading.
PipSize
0.0001
Valor de un solo pip en unidades de precio.
Notas adicionales
La estrategia usa la API de suscripción de velas de alto nivel de StockSharp y la vinculación de indicadores para una lógica concisa sin gestión manual de buffers.
Los cálculos de stop-loss, take-profit y seguimiento ocurren en velas completadas para evitar actuar sobre datos de precio no terminados.
La implementación llama a StartProtection() una vez al arranque para alinearse con las directrices del proyecto, mientras que el manejo real del riesgo se gestiona dentro de la lógica de la estrategia.
Ajuste el parámetro PipSize para que coincida con el instrumento negociado para que las distancias basadas en pips se mapeen correctamente a los movimientos de precio.
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>
/// Forex Fraus M1 strategy using fast EMA crossover on short timeframes.
/// </summary>
public class ForexFrausM1Strategy : 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 ForexFrausM1Strategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 5)
.SetGreaterThanZero()
.SetDisplay("Fast Period", "Fast EMA", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 15)
.SetGreaterThanZero()
.SetDisplay("Slow Period", "Slow EMA", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(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 ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { 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 fastVal, decimal slowVal)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevFast = fastVal;
_prevSlow = slowVal;
return;
}
if (_prevFast == null || _prevSlow == null)
{
_prevFast = fastVal;
_prevSlow = slowVal;
return;
}
var prevAbove = _prevFast.Value > _prevSlow.Value;
var currAbove = fastVal > slowVal;
_prevFast = fastVal;
_prevSlow = slowVal;
if (!prevAbove && currAbove)
{
if (Position < 0)
BuyMarket();
if (Position <= 0)
BuyMarket();
}
else if (prevAbove && !currAbove)
{
if (Position > 0)
SellMarket();
if (Position >= 0)
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 ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class forex_fraus_m1_strategy(Strategy):
def __init__(self):
super(forex_fraus_m1_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", 5) \
.SetDisplay("Fast Period", "Fast EMA", "Indicators")
self._slow_period = self.Param("SlowPeriod", 15) \
.SetDisplay("Slow Period", "Slow EMA", "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(forex_fraus_m1_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(forex_fraus_m1_strategy, self).OnStarted2(time)
self._prev_fast = None
self._prev_slow = None
fast = ExponentialMovingAverage()
fast.Length = self.FastPeriod
slow = ExponentialMovingAverage()
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:
if self.Position < 0:
self.BuyMarket()
if self.Position <= 0:
self.BuyMarket()
elif prev_above and not curr_above:
if self.Position > 0:
self.SellMarket()
if self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return forex_fraus_m1_strategy()