El asesor experto ZigZag Climber generado por fxDreema contiene solo tres bloques: un filtro No trade seguido de acciones Buy now y Sell now. Cuando el terminal detecta que no hay posiciones abiertas, lanza de inmediato una orden de compra a mercado con niveles predefinidos de stop-loss y take-profit y, sin más comprobaciones, coloca una orden de venta a mercado simétrica. Ambas operaciones heredan los mismos parámetros de riesgo y están pensadas para coexistir como un par cubierto.
Este port C# reproduce ese comportamiento en StockSharp esperando la primera vela terminada del marco elegido y enviando después las patas de compra y venta una tras otra con distancias protectoras idénticas. No hay generación adicional de señales, trailing ni gestión de posición, exactamente como en el proyecto MQL original.
Lógica de negociación
Esperar a que la primera vela del marco configurado se forme por completo.
Si la estrategia puede operar y aún no se han colocado órdenes, enviar una compra a mercado con el volumen fijo.
Adjuntar órdenes de stop-loss y take-profit al largo usando distancias en pips estilo MetaTrader (convertidas mediante PriceStep del instrumento).
Enviar inmediatamente una venta a mercado con el mismo volumen y adjuntar niveles protectores reflejados.
No abrir más órdenes durante el resto de la ejecución.
Importante: MetaTrader 4 trabaja en modo hedging, por lo que ambos lados pueden permanecer abiertos simultáneamente. StockSharp usa el modelo de ejecución del broker; en cuentas netting, la segunda orden compensará la primera y la estrategia terminará plana. Use un conector con hedging (por ejemplo, gateway MetaTrader configurado para cuentas hedge) si desea mantener vivas ambas patas.
Parámetros
Nombre
Predeterminado
Descripción
Candle Type
1 minuto
Marco temporal que dispara la secuencia de entrada única.
Trade Volume
0.01
Volumen fijo aplicado a ambas órdenes de mercado.
Stop-Loss (pips)
99.9
Distancia del stop protector en pips MetaTrader (maneja automáticamente símbolos de 4/5 dígitos).
Take-Profit (pips)
100
Distancia objetivo en pips MetaTrader.
Todas las distancias se convierten a puntos de precio mediante PriceStep y precisión decimal del instrumento antes de pasarse a SetStopLoss/SetTakeProfit.
Gestión de riesgo
La estrategia se apoya en el servicio integrado StartProtection() y los métodos auxiliares SetStopLoss/SetTakeProfit para colocar órdenes protectoras justo después de cada orden de mercado. No hay lógica de trailing ni break-even.
Notas de uso
Asigne el instrumento y la cartera deseados antes de iniciar la estrategia. Asegúrese de que el símbolo exponga PriceStep y Decimals para que la conversión de pips funcione correctamente.
Como la lógica de entrada se ejecuta solo una vez, reiniciar la estrategia es la única forma de crear un nuevo ciclo hedge.
Al probar en un simulador netting, el comportamiento realizado diferirá de MetaTrader: la orden de venta neutralizará la compra casi de inmediato.
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// ZigZag Climber strategy: Highest/Lowest channel breakout.
/// Buys when close >= highest, sells when close <= lowest.
/// </summary>
public class ZigZagClimberStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _channelPeriod;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int ChannelPeriod
{
get => _channelPeriod.Value;
set => _channelPeriod.Value = value;
}
public ZigZagClimberStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_channelPeriod = Param(nameof(ChannelPeriod), 12)
.SetGreaterThanZero()
.SetDisplay("Channel Period", "Highest/Lowest lookback", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var high = new Highest { Length = ChannelPeriod };
var low = new Lowest { Length = ChannelPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(high, low, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal high, decimal low)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (candle.ClosePrice >= high && Position <= 0)
{
BuyMarket();
}
else if (candle.ClosePrice <= low && 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 Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
class zig_zag_climber_strategy(Strategy):
def __init__(self):
super(zig_zag_climber_strategy, self).__init__()
self._channel_period = self.Param("ChannelPeriod", 12) \
.SetDisplay("Channel Period", "Highest/Lowest lookback", "Indicators")
self._highest = None
self._lowest = None
@property
def channel_period(self):
return self._channel_period.Value
def OnReseted(self):
super(zig_zag_climber_strategy, self).OnReseted()
self._highest = None
self._lowest = None
def OnStarted2(self, time):
super(zig_zag_climber_strategy, self).OnStarted2(time)
self._highest = Highest()
self._highest.Length = self.channel_period
self._lowest = Lowest()
self._lowest.Length = self.channel_period
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(5)))
subscription.Bind(self._highest, self._lowest, self._process_candle)
subscription.Start()
def _process_candle(self, candle, high_val, low_val):
if candle.State != CandleStates.Finished:
return
if not self._highest.IsFormed or not self._lowest.IsFormed:
return
close = float(candle.ClosePrice)
h = float(high_val)
l = float(low_val)
if close >= h and self.Position <= 0:
self.BuyMarket()
elif close <= l and self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return zig_zag_climber_strategy()