La estrategia Smart Forex System es una versión StockSharp del asesor experto MetaTrader "Smart Forex System". El robot combina un filtro de impulso de una sola vela con una cuadrícula de promedio estilo martingala. La primera operación se abre cuando la vela anterior muestra un cierre direccional fuerte y el precio actual se ha alejado lo suficiente del cierre de referencia. Se agregan entradas adicionales a intervalos de pips fijos en la dirección adversa, y el tamaño de la posición aumenta mediante un multiplicador configurable. La estrategia gestiona las salidas a través de niveles promedio de toma de ganancias y un stop-loss de seguridad vinculado a la última orden de la red.
Lógica de trading
Generación de señal
Evalúe la última vela completa en el período de tiempo seleccionado.
Calcule una relación de impulso: (current close - previous close) / previous close * 10,000.
Si la vela anterior es bajista y el impulso es inferior al umbral negativo, puede comenzar una cesta larga.
Si la vela anterior es alcista y el impulso supera el umbral positivo, puede comenzar una cesta corta.
El comercio puede limitarse a solo largo, solo corto, en ambas direcciones o deshabilitarse por completo a través del parámetro Trading Mode.
Expansión de la red
Una vez que existe una cesta, se agregan nuevas entradas cada vez que el precio se mueve contra la posición por al menos Grid Step pips desde el precio de la última orden.
Cada nuevo volumen de pedido se multiplica por Lot Multiplier. Los volúmenes están sujetos a los límites del corredor y al Max Volume configurado.
La cesta deja de crecer cuando el número de pedidos llega a Max Trades.
Gestión de salida
Se coloca un stop-loss estricto a Stop Loss pips del precio de la última orden. Al superar esa distancia se cierra toda la canasta.
Los niveles de obtención de beneficios dependen del tamaño de la cesta:
Una sola orden utiliza First Take Profit pips del precio de entrada promedio ponderado por volumen.
Varias órdenes utilizan Grid Take Profit pips del mismo precio de entrada promedio para capturar rebotes más pequeños.
Las salidas se procesan en velas terminadas para garantizar que los indicadores tengan valores finales.
Notas de gestión de riesgos
El tamaño de la posición tipo martingala aumenta drásticamente la exposición a tendencias adversas. Utilice multiplicadores y tamaños de cesta conservadores en instrumentos altamente volátiles.
El stop-loss predeterminado (400 pips) es intencionalmente amplio para reflejar el EA original. Considere alinearlo con el ATR del instrumento si se requieren pérdidas menores.
El comercio en red consume margen rápidamente. Asegúrese de que el apalancamiento de la cuenta, el tamaño del contrato y los parámetros Start Volume sean consistentes con las especificaciones del corredor.
Parámetros
Nombre
Descripción
Predeterminado
Modo de negociación
Dirección comercial permitida (solo larga, solo corta, ambas o deshabilitada).
Largo y corto
Umbral de impulso
Impulso mínimo en pseudo-pips necesario para activar una señal.
1
Volumen inicial
Volumen del primer pedido en una cesta nueva.
0,01
Volumen máximo
Límite estricto aplicado a cualquier volumen de pedido único.
2
Multiplicador de lote
Multiplicador utilizado al dimensionar pedidos de cuadrícula posteriores.
1.5
Paso de cuadrícula
Distancia mínima en pips antes de agregar la siguiente orden.
26
Operaciones máximas
Número máximo de pedidos permitidos por dirección.
12
Primera toma de ganancias
Distancia de obtención de beneficios en pips cuando solo hay una orden abierta.
30
Toma de ganancias de la red
Distancia de obtención de beneficios en pips una vez que la cesta contiene varias órdenes.
7
Detener pérdidas
Distancia de parada en pips desde el último precio de la orden.
400
Tipo de vela
Plazo utilizado para la evaluación de la señal.
velas de 1 hora
Uso recomendado
Adjunte la estrategia a un símbolo de divisas con suficiente liquidez y un diferencial predecible.
Configure el Candle Type para que coincida con el período operativo del EA original (H1 por defecto) o adáptelo a su horizonte preferido.
Optimice el filtro de espacio, multiplicador y impulso de la red en datos históricos antes de la implementación en vivo.
Supervise de cerca el uso del margen. La canasta puede crecer rápidamente, así que considere combinar la estrategia con una protección de capital en toda la cuenta.
Evite la superposición con otros sistemas basados en redes en el mismo instrumento para reducir el riesgo de caídas compuestas.
Diferencias en comparación con la versión MetaTrader
El puerto StockSharp funciona con velas terminadas en lugar de actualizaciones paso a paso, lo que reduce el ruido y hace que la lógica sea determinista.
Los volúmenes de pedidos se ajustan utilizando metadatos de seguridad StockSharp (mínimo, máximo y paso), lo que garantiza la compatibilidad con una amplia gama de corredores.
Las comprobaciones de toma de ganancias y límite de pérdidas se manejan dentro de la lógica de la estrategia en lugar de enviar modificaciones de órdenes individuales para cada nivel de la red.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Smart Forex System strategy: Triple EMA alignment.
/// Enters when fast > mid > slow (buy) or fast < mid < slow (sell).
/// </summary>
public class SmartForexSystemStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _midPeriod;
private readonly StrategyParam<int> _slowPeriod;
private bool _wasBullishAlignment;
private bool _hasPrevAlignment;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int MidPeriod { get => _midPeriod.Value; set => _midPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public SmartForexSystemStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_midPeriod = Param(nameof(MidPeriod), 25)
.SetGreaterThanZero()
.SetDisplay("Mid EMA", "Mid EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 50)
.SetGreaterThanZero()
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_wasBullishAlignment = false;
_hasPrevAlignment = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_wasBullishAlignment = false;
_hasPrevAlignment = false;
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var mid = new ExponentialMovingAverage { Length = MidPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fast, mid, slow, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal midValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished) return;
var bullishAlignment = fastValue > midValue && midValue > slowValue;
var bearishAlignment = fastValue < midValue && midValue < slowValue;
var crossedUp = bullishAlignment && (!_hasPrevAlignment || !_wasBullishAlignment);
var crossedDown = bearishAlignment && (!_hasPrevAlignment || _wasBullishAlignment);
if (crossedUp && Position <= 0)
BuyMarket();
else if (crossedDown && Position >= 0)
SellMarket();
if (bullishAlignment || bearishAlignment)
{
_wasBullishAlignment = bullishAlignment;
_hasPrevAlignment = true;
}
}
}
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 smart_forex_system_strategy(Strategy):
def __init__(self):
super(smart_forex_system_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60)))
self._fast_period = self.Param("FastPeriod", 10)
self._mid_period = self.Param("MidPeriod", 25)
self._slow_period = self.Param("SlowPeriod", 50)
self._was_bullish_alignment = False
self._has_prev_alignment = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def FastPeriod(self):
return self._fast_period.Value
@FastPeriod.setter
def FastPeriod(self, value):
self._fast_period.Value = value
@property
def MidPeriod(self):
return self._mid_period.Value
@MidPeriod.setter
def MidPeriod(self, value):
self._mid_period.Value = value
@property
def SlowPeriod(self):
return self._slow_period.Value
@SlowPeriod.setter
def SlowPeriod(self, value):
self._slow_period.Value = value
def OnReseted(self):
super(smart_forex_system_strategy, self).OnReseted()
self._was_bullish_alignment = False
self._has_prev_alignment = False
def OnStarted2(self, time):
super(smart_forex_system_strategy, self).OnStarted2(time)
self._was_bullish_alignment = False
self._has_prev_alignment = False
fast = ExponentialMovingAverage()
fast.Length = self.FastPeriod
mid = ExponentialMovingAverage()
mid.Length = self.MidPeriod
slow = ExponentialMovingAverage()
slow.Length = self.SlowPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast, mid, slow, self._process_candle).Start()
def _process_candle(self, candle, fast_value, mid_value, slow_value):
if candle.State != CandleStates.Finished:
return
fast_val = float(fast_value)
mid_val = float(mid_value)
slow_val = float(slow_value)
bullish_alignment = fast_val > mid_val and mid_val > slow_val
bearish_alignment = fast_val < mid_val and mid_val < slow_val
crossed_up = bullish_alignment and (not self._has_prev_alignment or not self._was_bullish_alignment)
crossed_down = bearish_alignment and (not self._has_prev_alignment or self._was_bullish_alignment)
if crossed_up and self.Position <= 0:
self.BuyMarket()
elif crossed_down and self.Position >= 0:
self.SellMarket()
if bullish_alignment or bearish_alignment:
self._was_bullish_alignment = bullish_alignment
self._has_prev_alignment = True
def CreateClone(self):
return smart_forex_system_strategy()