O expert advisor ZigZag Climber gerado pelo fxDreema contém apenas três blocos: um filtro No trade seguido das ações Buy now e Sell now. Quando o terminal detecta que não há posições abertas, ele dispara imediatamente uma ordem de compra a mercado com níveis predefinidos de stop-loss e take-profit e, sem verificações adicionais, coloca uma ordem de venda a mercado simétrica. Ambas as operações herdam os mesmos parâmetros de risco e foram pensadas para coexistir como um par protegido por hedge.
Este port C# reproduz esse comportamento no StockSharp aguardando o primeiro candle concluído do timeframe escolhido e então enviando as pernas de compra e venda em sequência com distâncias protetoras idênticas. Não há geração adicional de sinal, trailing ou gestão de posição, exatamente como no projeto MQL de origem.
Lógica de negociação
Aguardar até que o primeiro candle do timeframe configurado esteja completamente formado.
Se a estratégia puder operar e nenhuma ordem tiver sido colocada, enviar uma compra a mercado usando o volume fixo.
Anexar ordens de stop-loss e take-profit à compra usando distâncias em pips no estilo MetaTrader (convertidas pelo PriceStep do instrumento).
Enviar imediatamente uma venda a mercado com o mesmo volume e anexar níveis protetores espelhados.
Não abrir novas ordens pelo restante da execução.
Importante: MetaTrader 4 trabalha em modo hedging, portanto os dois lados podem permanecer abertos simultaneamente. StockSharp usa o modelo de execução da corretora; em contas netting, a segunda ordem compensará a primeira e a estratégia terminará zerada. Use um conector compatível com hedge (por exemplo, gateway MetaTrader configurado para contas hedge) se quiser manter as duas pernas ativas.
Parâmetros
Nome
Padrão
Descrição
Candle Type
1 minuto
Timeframe que dispara a sequência única de entrada.
Trade Volume
0.01
Volume fixo aplicado às duas ordens a mercado.
Stop-Loss (pips)
99.9
Distância do stop protetor em pips MetaTrader (trata símbolos de 4/5 dígitos automaticamente).
Take-Profit (pips)
100
Distância do alvo em pips MetaTrader.
Todas as distâncias são convertidas para pontos de preço via PriceStep e precisão decimal do instrumento antes de serem passadas para SetStopLoss/SetTakeProfit.
Gestão de risco
A estratégia depende do serviço integrado StartProtection() e dos métodos auxiliares SetStopLoss/SetTakeProfit para colocar ordens protetoras logo após cada ordem a mercado. Não há lógica de trailing ou break-even.
Notas de uso
Atribua o ativo e a carteira desejados antes de iniciar a estratégia. Garanta que o símbolo exponha PriceStep e Decimals para que a conversão de pips funcione corretamente.
Como a lógica de entrada roda apenas uma vez, reiniciar a estratégia é a única forma de criar um novo ciclo de hedge.
Ao testar em um simulador netting, o comportamento realizado será diferente do MetaTrader: a ordem de venda neutralizará a compra quase imediatamente.
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()