Ver no GitHub

Estratégia de Fraktrak XonaX Advanced

Visão geral

Esta estratégia é uma conversão em C# do consultor especialista do MetaTrader 5 Fraktrak xonax.mq5. O robô original rastreia fractais de Williams e abre operações quando o preço rompe o nível fractal mais recente. A versão StockSharp mantém a mesma ideia aproveitando recursos da API de alto nível como assinaturas de velas, helpers integrados de gestão monetária e proteção automática de operações.

Lógica de trading

  1. Detecção de fractais – o algoritmo mantém uma janela de cinco velas. Quando a vela do meio cria uma máxima mais alta (ou mínima mais baixa) do que seus vizinhos, o preço é salvo como o último fractal superior (ou inferior).
  2. Sinais de rompimento – quando uma vela concluída toca ou ultrapassa o nível fractal atual, a estratégia se prepara para operar:
    • Rompimento de fractal superior → abrir posição comprada (ou posição vendida quando o Modo Reversão está habilitado).
    • Rompimento de fractal inferior → abrir posição vendida (ou posição comprada quando o Modo Reversão está habilitado).
  3. Gestão de posições – a estratégia convertida reproduz o comportamento do MetaTrader:
    • Fechamento opcional da posição oposta antes de abrir uma nova.
    • Stop-loss e take-profit iniciais são definidos de acordo com as distâncias em pips configuradas.
    • Um trailing stop de dois estágios move o nível protetor após o preço avançar pelo Passo de Trailing especificado.
  4. Gestão monetária – escolher entre lote fixo ou percentual de risco baseado em patrimônio. Quando o modo de risco está ativo, o algoritmo estima o volume usando o patrimônio do portfólio, o tamanho do passo de preço e a distância de stop configurada.

Parâmetros

Parâmetro Descrição
StopLossPips Distância de stop-loss expressa em pips. Definir como zero para desabilitar o nível de stop-loss.
TakeProfitPips Distância de take-profit em pips. Zero desabilita o alvo.
TrailingStopPips Distância base do trailing stop. Requer que TrailingStepPips seja maior que zero.
TrailingStepPips Distância adicional que o preço deve percorrer antes do trailing stop avançar.
ReverseMode Inverter as regras de rompimento (vender fractais superiores, comprar fractais inferiores).
CloseOpposite Quando verdadeiro, qualquer posição oposta é fechada antes de abrir uma nova operação.
ManagementMode Selecionar entre gestão monetária FixedLot ou RiskPercent.
ManagementValue Valor usado pelo modo de gestão monetária ativo (tamanho de lote ou percentual).
CandleType Série de velas usada para detecção de fractais e decisões de trading.

Notas de uso

  • O tamanho do pip é derivado automaticamente do passo de preço do instrumento. Ativos com três ou cinco dígitos decimais são tratados como instrumentos de pip fracionário (0.1 pip). Ajustar os parâmetros pip adequadamente.
  • A lógica do trailing stop corresponde ao expert original: requer que tanto a distância de trailing quanto o passo adicional sejam positivos. Caso contrário, o trailing é ignorado.
  • A gestão monetária no modo de risco assume que o custo do passo de preço está disponível. Se não estiver, a estratégia recorre a um cálculo simplificado baseado na distância de preço bruta.
  • Habilitar Fechar Oposto para emular o comportamento do consultor especialista onde um novo rompimento fecha a operação em andamento antes de entrar na direção oposta.

Arquivos

  • CS/FraktrakXonaxAdvancedStrategy.cs – implementação da estratégia.
  • README.md – documento atual.
  • README_ru.md – descrição em russo.
  • README_zh.md – descrição em chinês.
using System;
using System.Collections.Generic;

using Ecng.Common;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

public class FraktrakXonaxAdvancedStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _stopLossPoints;
	private readonly StrategyParam<int> _takeProfitPoints;

	private ExponentialMovingAverage _fast;
	private ExponentialMovingAverage _slow;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;
	private int _cooldown;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
	public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }

	public FraktrakXonaxAdvancedStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 14).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
		_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
		_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
		_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
	}

	protected override void OnReseted()
	{
		base.OnReseted();
		_fast = null; _slow = null;
		_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_fast = new ExponentialMovingAverage { Length = FastPeriod };
		_slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
		subscription.Bind(_fast, _slow, ProcessCandle);
		subscription.Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
		if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }

		var close = candle.ClosePrice;
		var step = Security?.PriceStep ?? 1m;

		if (Position > 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}
		else if (Position < 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}

		if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
		{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
		else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
		{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }

		_prevFast = fastValue; _prevSlow = slowValue;
	}
}