A Estratégia FiboChannel Line é uma conversão do consultor especialista MetaTrader "FIBOCHANNEL". O robô original dependia da direção de um canal de Fibonacci desenhado manualmente, oscilações de Momentum em um período superior e uma combinação de médias móvias ponderadas linearmente e sinais MACD. O porte StockSharp mantém o mesmo espírito aproveitando vínculos de indicadores de alto nível e gestão de risco integrada.
Ideias-chave:
Seguir a tendência dominante usando um par de médias móvias ponderadas linearmente (LWMA).
Confirmar picos de Momentum ao redor do nível neutro do oscilador Momentum.
Filtrar trades com a relação linha MACD vs. linha de sinal.
Verificar a inclinação de um canal de regressão linear em vez de ler objetos do gráfico.
Gerenciar posições via proteção percentual automática.
A estratégia funciona em qualquer instrumento que suporte agregação de candles. O período padrão são candles de 30 minutos, que fornecem um equilíbrio entre responsividade e estabilidade do indicador.
Lógica de trading
Filtro de tendência – quando a LWMA rápida fecha acima da LWMA lenta, o mercado é considerado altista e apenas trades longos são avaliados. Quando está abaixo, apenas os curtos são considerados.
Requisito de Momentum – uma janela deslizante das três leituras de Momentum mais recentes deve mostrar que pelo menos um valor se desviou do nível neutro 100 pelo limiar configurado. Isso replica as verificações de força de Momentum de múltiplas barras da versão MQL.
Filtro MACD – trades longos requerem que a linha MACD esteja acima da linha de sinal; trades curtos requerem o oposto.
Direção do canal – a inclinação da regressão linear deve ser positiva (para longos) ou negativa (para curtos) além do Slope Threshold. Isso imita a validação de canal ascendente/descendente do especialista original.
Entradas e reversões – se todas as condições se alinham e não há posição existente nessa direção, a estratégia cancela ordens ativas e envia uma ordem de mercado com tamanho Volume + |Position|. Isso permite reversões suaves.
Saídas – se a direção do canal ou o filtro MACD parar de suportar o trade aberto, a posição é fechada após cancelar ordens pendentes. Adicionalmente, as regras de stop-loss protetor, take-profit e drawdown máximo são configuradas através de StartProtection.
Parâmetros
Parâmetro
Descrição
Padrão
Candle Type
Agregação de candles usada para todos os indicadores.
Período de 30 minutos
Fast LWMA
Comprimento da média móvel ponderada linearmente rápida.
6
Slow LWMA
Comprimento da média móvel ponderada linearmente lenta.
85
Momentum Period
Número de barras para o indicador Momentum.
14
Momentum Threshold
Desvio absoluto mínimo de 100 necessário dentro do buffer de Momentum.
0.3
Channel Length
Barras usadas para calcular a inclinação da regressão linear.
50
Slope Threshold
Valor mínimo de inclinação absoluta para confirmar a direção da tendência.
0.0
MACD Fast
Período EMA rápida dentro do cálculo MACD.
12
MACD Slow
Período EMA lenta dentro do cálculo MACD.
26
MACD Signal
Período da linha de sinal do MACD.
9
Take Profit %
Distância do take-profit protetor em percentual.
2
Stop Loss %
Distância do stop-loss protetor em percentual.
1
Equity Risk %
Drawdown máximo de capital da conta permitido antes de fechar todas as posições.
3
Todos os parâmetros numéricos expõem dicas de otimização que refletem os intervalos típicos das entradas MQL.
Gestão de risco
StartProtection é configurado para aplicar:
Stop-loss e take-profit baseados em percentual relativos ao preço de entrada.
Proteção de drawdown de capital que fecha a estratégia se a perda exceder o percentual configurado.
Essas proteções substituem as numerosas rotinas de balanço, trailing e ponto de equilíbrio do especialista original, fornecendo um comportamento mais claro e seguro dentro do StockSharp.
Diferenças da versão MetaTrader
As leituras de objetos do gráfico foram substituídas por um filtro de inclinação de regressão porque as estratégias StockSharp não interagem com canais de Fibonacci manuais.
Em vez de uma mistura de lógica de trailing baseada em dinheiro, a estratégia depende de StartProtection.
O conjunto de indicadores permanece o mesmo (LWMA, Momentum, MACD), mas é implementado usando vínculos de alto nível e sem sondagem direta de valores de indicadores.
Alertas, e-mails e notificações push foram removidos, pois o ambiente StockSharp já fornece logging consolidado.
Notas de uso
Anexe a estratégia a um portfólio e ativo, configure o tamanho do lote através da propriedade Volume e ajuste os parâmetros conforme necessário.
Certifique-se de que os dados históricos estejam disponíveis para o tipo de candle selecionado para que o buffer de Momentum e o indicador de inclinação possam se formar corretamente.
Execute primeiro em paper trading para ajustar o limiar de Momentum e os parâmetros de risco de acordo com a volatilidade do instrumento negociado.
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 FiboChannelLineStrategy : 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 FiboChannelLineStrategy()
{
_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;
}
}
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 fibo_channel_line_strategy(Strategy):
def __init__(self):
super(fibo_channel_line_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 14) \
.SetDisplay("Fast Period", "Fast MA period", "Indicator")
self._slow_period = self.Param("SlowPeriod", 50) \
.SetDisplay("Slow Period", "Slow MA period", "Indicator")
self._stop_loss_points = self.Param("StopLossPoints", 200) \
.SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk")
self._take_profit_points = self.Param("TakeProfitPoints", 400) \
.SetDisplay("Take Profit", "Take-profit in price steps", "Risk")
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
@property
def fast_period(self):
return self._fast_period.Value
@property
def slow_period(self):
return self._slow_period.Value
@property
def stop_loss_points(self):
return self._stop_loss_points.Value
@property
def take_profit_points(self):
return self._take_profit_points.Value
def OnReseted(self):
super(fibo_channel_line_strategy, self).OnReseted()
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
def OnStarted2(self, time):
super(fibo_channel_line_strategy, self).OnStarted2(time)
self._fast = ExponentialMovingAverage()
self._fast.Length = self.fast_period
self._slow = ExponentialMovingAverage()
self._slow.Length = self.slow_period
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(5)))
subscription.Bind(self._fast, self._slow, self._process_candle)
subscription.Start()
def _process_candle(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fast_val = float(fast_value)
slow_val = float(slow_value)
if not self._fast.IsFormed or not self._slow.IsFormed:
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_fast = fast_val
self._prev_slow = slow_val
return
close = float(candle.ClosePrice)
step = float(self.Security.PriceStep) if self.Security is not None and self.Security.PriceStep is not None else 1.0
if self.Position > 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close <= self._entry_price - self.stop_loss_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close >= self._entry_price + self.take_profit_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
elif self.Position < 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close >= self._entry_price + self.stop_loss_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close <= self._entry_price - self.take_profit_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._prev_fast <= self._prev_slow and fast_val > slow_val and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._entry_price = close
self._cooldown = 100
elif self._prev_fast >= self._prev_slow and fast_val < slow_val and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._entry_price = close
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return fibo_channel_line_strategy()