Port do especialista MetaTrader 5 MySystem.mq5 localizado em MQL/22016.
Detecta reversões de momentum calculando a média dos valores de Elder Bulls Power e Bears Power calculados a partir dos extremos das velas e uma EMA.
Entra comprado quando a média aumenta enquanto ainda está abaixo de zero (a pressão baixista está diminuindo) e vendido quando a média diminui enquanto ainda está acima de zero (a pressão altista está diminuindo).
Projetado para uma posição aberta de cada vez; stop-loss e take-profit são opcionais e expressos em pips.
Lógica do indicador
Componente
Descrição
Exponential Moving Average (EMA)
Aplicado aos preços de fechamento das velas. O parâmetro MaPeriod controla a janela de suavização (padrão 5).
Bulls Power (derivado)
Calculado como High - EMA. Mede a força altista relativa à EMA.
Bears Power (derivado)
Calculado como Low - EMA. Mede a força baixista relativa à EMA.
Potência média
(Bulls Power + Bears Power) / 2. Este oscilador sintético é comparado com seu valor anterior para detectar mudanças de momentum.
A estratégia avalia as últimas duas velas finalizadas. Novos negócios são avaliados apenas quando uma vela está completamente completada para evitar ruído intrabar.
Regras de entrada
Aguardar a EMA estar completamente formada (isto é, processou pelo menos MaPeriod velas).
Calcular Bulls Power e Bears Power para a vela recém-fechada usando seu high/low e o valor da EMA.
Calcular a média de ambas as forças para obter a leitura atual do oscilador.
Comparar com a média anterior:
Configuração comprada: média anterior < média atual e média atual < 0. Entrar comprado se não houver posição existente.
Configuração vendida: média anterior > média atual e média atual > 0. Entrar vendido se plano.
Uma vez em um negócio, depender de ordens de proteção opcionais ou gestão manual. O algoritmo não gera sinais de saída além do stop-loss/take-profit.
Gestão de risco
StopLossPips: Distância de stop absoluta opcional em pips (0 desabilita o stop). Convertido usando o PriceStep do instrumento.
TakeProfitPips: Objetivo de lucro absoluto opcional em pips (0 desabilita o objetivo).
Ordens de proteção são registradas assim que a posição é aberta via StartProtection com execução de mercado.
Parâmetros
Nome
Padrão
Descrição
OrderVolume
0.1
Tamanho de ordem para entradas de mercado.
StopLossPips
15
Distância de stop-loss em pips. Definir como 0 para desabilitar.
TakeProfitPips
95
Distância de take-profit em pips. Definir como 0 para desabilitar.
MaPeriod
5
Comprimento da EMA usado para o cálculo de Bulls/Bears Power.
CandleType
Período de 1 hora
Série de velas usada para todos os cálculos (alterar para corresponder ao seu feed de dados).
Notas de uso
Vincular a estratégia a um instrumento e garantir que CandleType corresponda ao período pretendido.
Ajustar OrderVolume, StopLossPips e TakeProfitPips para atender aos requisitos do corretor.
Executar a estratégia; ela se inscreve automaticamente em velas, atualiza a EMA e emite ordens de mercado em sinais qualificados.
Apenas uma posição pode existir de cada vez. Quando um negócio está ativo, novos sinais são ignorados até que as ordens de proteção fechem a posição ou ela seja fechada manualmente.
Como a versão MQL original usou InpBarCurrent = 1, este port sempre trabalha em velas completamente fechadas e compara valores consecutivos; nenhum recálculo intrabar é realizado.
Diferenças vs. Especialista MQL Original
Usa a API Strategy de alto nível do StockSharp com inscrições de velas e vinculação de indicadores em vez de acesso manual a buffers.
Deriva automaticamente os pips de PriceStep em vez de ajustes manuais de dígitos.
Ignora o gerenciamento de ordens comentado original e depende da proteção de posição incorporada.
Mantém a restrição de posição única da fonte ignorando sinais enquanto uma posição existe.
Recomendações de teste
Backtest no símbolo/período pretendido com dados históricos que incluam preços high/low para cálculo preciso de Bulls/Bears.
Validar o comportamento das ordens de proteção com o tamanho do tick e o passo de volume do seu corretor antes de executar ao vivo.
Experimentar com diferentes valores de MaPeriod para adaptar a sensibilidade à volatilidade do instrumento.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Bulls Bears Power Average strategy. Uses EMA with bulls/bears power crossover.
/// </summary>
public class BullsBearsPowerAverageStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaPeriod;
private decimal? _prevPower;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
public BullsBearsPowerAverageStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
_emaPeriod = Param(nameof(EmaPeriod), 13).SetGreaterThanZero().SetDisplay("EMA Period", "EMA lookback for power calc", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevPower = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevPower = null;
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ema, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, ema); DrawOwnTrades(area); }
}
private void ProcessCandle(ICandleMessage candle, decimal emaVal)
{
if (candle.State != CandleStates.Finished) return;
var bullsPower = candle.HighPrice - emaVal;
var bearsPower = candle.LowPrice - emaVal;
var avgPower = (bullsPower + bearsPower) / 2m;
if (!IsFormedAndOnlineAndAllowTrading()) { _prevPower = avgPower; return; }
if (_prevPower == null) { _prevPower = avgPower; return; }
if (_prevPower.Value < 0m && avgPower >= 0m && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
else if (_prevPower.Value > 0m && avgPower <= 0m && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
_prevPower = avgPower;
}
}
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 bulls_bears_power_average_strategy(Strategy):
"""
Bulls Bears Power Average strategy. Uses EMA with bulls/bears power crossover.
"""
def __init__(self):
super(bulls_bears_power_average_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._ema_period = self.Param("EmaPeriod", 13) \
.SetDisplay("EMA Period", "EMA lookback for power calc", "Indicators")
self._prev_power = None
@property
def candle_type(self):
return self._candle_type.Value
@candle_type.setter
def candle_type(self, value):
self._candle_type.Value = value
@property
def ema_period(self):
return self._ema_period.Value
@ema_period.setter
def ema_period(self, value):
self._ema_period.Value = value
def OnReseted(self):
super(bulls_bears_power_average_strategy, self).OnReseted()
self._prev_power = None
def OnStarted2(self, time):
super(bulls_bears_power_average_strategy, self).OnStarted2(time)
self._prev_power = None
ema = ExponentialMovingAverage()
ema.Length = self.ema_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(ema, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema)
self.DrawOwnTrades(area)
def on_process(self, candle, ema_val):
if candle.State != CandleStates.Finished:
return
bulls_power = candle.HighPrice - ema_val
bears_power = candle.LowPrice - ema_val
avg_power = (bulls_power + bears_power) / 2.0
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_power = avg_power
return
if self._prev_power is None:
self._prev_power = avg_power
return
if self._prev_power < 0.0 and avg_power >= 0.0 and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif self._prev_power > 0.0 and avg_power <= 0.0 and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_power = avg_power
def CreateClone(self):
return bulls_bears_power_average_strategy()