Convertido do MetaTrader 4 especialista original "Billy_expert.mq4".
Estratégia de momentum longo que espera por quatro máximas descendentes consecutivas e abre antes de entrar.
Usa dois osciladores estocásticos (rápido no período de negociação, lento em um período de tempo mais alto) para confirmar que o impulso está mudando para cima.
Projetado para pares spot FX, mas pode ser aplicado a qualquer instrumento que forneça velas baseadas em minutos.
Lógica de sinal
Filtro de ação de preço
Avalie as velas concluídas no primeiro período.
São necessárias quatro velas consecutivas onde tanto a máxima quanto a abertura diminuem. Isso recria as verificações MT4 High[0] < High[1] < High[2] < High[3] e Open[0] < Open[1] < Open[2] < Open[3].
O padrão sugere um movimento de baixa exausto e prepara a estratégia para uma negociação de reversão.
Confirmação do oscilador
Calcule um oscilador estocástico rápido no período de negociação e um estocástico lento no período de confirmação.
Para cada oscilador, exija que a linha %K esteja acima da linha %D na vela concluída atual e anterior (%K(0) > %D(0) e %K(1) > %D(1)).
A negociação é acionada apenas quando ambos os osciladores confirmam simultaneamente a dinâmica de alta.
Gerenciamento de pedidos
Entradas: compras de mercado dimensionadas pelo parâmetro da estratégia Volume (caso exista posição vendida ela é fechada e revertida automaticamente).
Stop loss: distância fixa abaixo do preço de preenchimento usando o parâmetro Stop Loss (pts). Um valor de 0 desativa a parada.
Take Profit: distância fixa acima do preço de preenchimento usando o parâmetro Take Profit (pts). Um valor de 0 desativa o destino.
Limite de posição: Max Orders limita quantas entradas longas podem estar ativas ao mesmo tempo. Como StockSharp mantém uma posição líquida, a estratégia aproxima o comportamento do MT4 contando quantos blocos Volume estão abertos no momento.
Parada móvel: o EA original declarou uma entrada de parada móvel, mas não a implementou. A versão convertida também omite a lógica final para paridade.
Parâmetros
Nome
Descrição
Padrão
Trading Candle
Período primário para padrão de preço e estocástico rápido.
1 minuto
Slow Stochastic Candle
Prazo maior utilizado para confirmação estocástica.
5 minutos
Stochastic Length
Janela de lookback para %K.
5
%K Smoothing
Suavização aplicada à linha %K.
3
%D Period
Suavização aplicada à linha %D.
3
Slowing
Fator de suavização adicional para %K.
3
Stop Loss (pts)
Pare a distância de perda nas etapas de preço.
0
Take Profit (pts)
Calcule a distância do lucro nas etapas de preço.
12
Max Orders
Máximo de entradas longas simultâneas.
1
Notas de uso
Defina a propriedade Volume antes de iniciar a estratégia; StockSharp é padronizado como 0, o que bloquearia a colocação de pedidos.
A etapa de preço é lida em Security.PriceStep (volta para Security.Step ou 1). Certifique-se de que os metadados do seu instrumento estejam configurados corretamente para obter níveis precisos de parada/alvo.
Quando o período de confirmação difere do período de negociação, a vela lenta concluída mais recentemente é reutilizada até que uma nova apareça, correspondendo ao comportamento do script MT4 original.
O EA não administrou saídas além do stop loss e do take-profit do lado da corretora. A conversão reflete esse comportamento, enviando ordens de mercado protetoras quando os níveis são atingidos.
Como StockSharp agrega posições, Max Orders > 1 funciona melhor quando cada entrada usa o mesmo tamanho de Volume.
Diferenças da versão MT4
Verificação de segurança para informações ausentes de etapas de preço com um aviso de registro em vez de usar silenciosamente Point.
Adicionadas cláusulas de guarda para garantir que a estratégia seja negociada somente quando todos os dados necessários (histórico de preços e ambos os osciladores estocásticos) estiverem disponíveis.
A estratégia é executada apenas em velas finalizadas, enquanto o MT4 processa ticks, mas é acelerado pelo tempo da barra. Essa alteração evita avaliações duplicadas e mantém a lógica determinística.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Long-only reversal strategy that looks for consecutive descending highs
/// and enters when RSI confirms oversold conditions with momentum turning up.
/// </summary>
public class BillyExpertReversalStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiLength;
private decimal _prevHigh1, _prevHigh2, _prevHigh3;
private int _barCount;
private decimal _prevRsi;
private bool _hasPrevRsi;
private decimal _entryPrice;
public BillyExpertReversalStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for analysis.", "General");
_rsiLength = Param(nameof(RsiLength), 14)
.SetDisplay("RSI Length", "Length for RSI indicator.", "Indicators");
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int RsiLength
{
get => _rsiLength.Value;
set => _rsiLength.Value = value;
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevHigh1 = 0;
_prevHigh2 = 0;
_prevHigh3 = 0;
_barCount = 0;
_prevRsi = 50;
_hasPrevRsi = false;
_entryPrice = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevHigh1 = 0;
_prevHigh2 = 0;
_prevHigh3 = 0;
_barCount = 0;
_prevRsi = 50;
_hasPrevRsi = false;
_entryPrice = 0;
var rsi = new RelativeStrengthIndex { Length = RsiLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(rsi, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, rsi);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal rsiValue)
{
if (candle.State != CandleStates.Finished)
return;
_barCount++;
var high = candle.HighPrice;
var close = candle.ClosePrice;
// Check descending highs pattern (3 consecutive lower highs)
var descendingHighs = _barCount >= 4 &&
high < _prevHigh1 &&
_prevHigh1 < _prevHigh2 &&
_prevHigh2 < _prevHigh3;
// RSI turning up from oversold
var rsiBullish = _hasPrevRsi && _prevRsi < 40 && rsiValue > _prevRsi;
// Manage long position
if (Position > 0)
{
// Exit on take-profit, stop-loss, or RSI overbought
if (_entryPrice > 0 && close >= _entryPrice * 1.015m)
{
SellMarket();
}
else if (_entryPrice > 0 && close <= _entryPrice * 0.985m)
{
SellMarket();
}
else if (rsiValue > 75)
{
SellMarket();
}
}
// Manage short position (exit only, this is mostly long-only)
if (Position < 0)
{
if (rsiValue < 30)
{
BuyMarket();
}
}
// Entry: descending highs (selling exhaustion) + RSI confirms reversal
if (Position == 0)
{
if (descendingHighs && rsiBullish)
{
_entryPrice = close;
BuyMarket();
}
// Also allow short on ascending lows pattern with overbought RSI
else if (_barCount >= 4 && rsiValue > 70 && _prevRsi > 70)
{
_entryPrice = close;
SellMarket();
}
}
// Update history
_prevHigh3 = _prevHigh2;
_prevHigh2 = _prevHigh1;
_prevHigh1 = high;
_prevRsi = rsiValue;
_hasPrevRsi = 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.Strategies import Strategy
from StockSharp.Algo.Indicators import RelativeStrengthIndex
class billy_expert_reversal_strategy(Strategy):
def __init__(self):
super(billy_expert_reversal_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30))) \
.SetDisplay("Candle Type", "Timeframe for analysis", "General")
self._rsi_length = self.Param("RsiLength", 14) \
.SetDisplay("RSI Length", "Length for RSI indicator", "Indicators")
self._prev_high1 = 0.0
self._prev_high2 = 0.0
self._prev_high3 = 0.0
self._bar_count = 0
self._prev_rsi = 50.0
self._has_prev_rsi = False
self._entry_price = 0.0
@property
def CandleType(self):
return self._candle_type.Value
@property
def RsiLength(self):
return self._rsi_length.Value
def OnStarted2(self, time):
super(billy_expert_reversal_strategy, self).OnStarted2(time)
self._prev_high1 = 0.0
self._prev_high2 = 0.0
self._prev_high3 = 0.0
self._bar_count = 0
self._prev_rsi = 50.0
self._has_prev_rsi = False
self._entry_price = 0.0
self._rsi = RelativeStrengthIndex()
self._rsi.Length = self.RsiLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._rsi, self.ProcessCandle).Start()
def ProcessCandle(self, candle, rsi_value):
if candle.State != CandleStates.Finished:
return
self._bar_count += 1
high = float(candle.HighPrice)
close = float(candle.ClosePrice)
rsi_val = float(rsi_value)
# Check descending highs pattern (3 consecutive lower highs)
descending_highs = (self._bar_count >= 4 and
high < self._prev_high1 and
self._prev_high1 < self._prev_high2 and
self._prev_high2 < self._prev_high3)
# RSI turning up from oversold
rsi_bullish = self._has_prev_rsi and self._prev_rsi < 40 and rsi_val > self._prev_rsi
# Manage long position
if self.Position > 0:
if self._entry_price > 0 and close >= self._entry_price * 1.015:
self.SellMarket()
elif self._entry_price > 0 and close <= self._entry_price * 0.985:
self.SellMarket()
elif rsi_val > 75:
self.SellMarket()
# Manage short position (exit only)
if self.Position < 0:
if rsi_val < 30:
self.BuyMarket()
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_high3 = self._prev_high2
self._prev_high2 = self._prev_high1
self._prev_high1 = high
self._prev_rsi = rsi_val
self._has_prev_rsi = True
return
# Entry
if self.Position == 0:
if descending_highs and rsi_bullish:
self._entry_price = close
self.BuyMarket()
elif self._bar_count >= 4 and rsi_val > 70 and self._prev_rsi > 70:
self._entry_price = close
self.SellMarket()
# Update history
self._prev_high3 = self._prev_high2
self._prev_high2 = self._prev_high1
self._prev_high1 = high
self._prev_rsi = rsi_val
self._has_prev_rsi = True
def OnReseted(self):
super(billy_expert_reversal_strategy, self).OnReseted()
self._prev_high1 = 0.0
self._prev_high2 = 0.0
self._prev_high3 = 0.0
self._bar_count = 0
self._prev_rsi = 50.0
self._has_prev_rsi = False
self._entry_price = 0.0
def CreateClone(self):
return billy_expert_reversal_strategy()