AIS5 Trade Machine transporta o MetaTrader 4 consultor especialista AIS5TM.mq4 para a StockSharp estratégia de alto nível API. O original
programa focado na construção de histogramas de perfil de mercado em dois intervalos de tempo e oferecendo um console de execução semiautomático. O
A versão StockSharp mantém a ideia de destacar zonas de preços fortes e fracas a partir da agregação do volume de ticks e a transforma em um
sistema de breakout automatizado com controle de risco adaptativo baseado no Average True Range (ATR).
A estratégia assina dois fluxos de velas:
Um período de perfil (padrão 15 minutos) que acumula volume para detectar zonas fortes e fracas.
Um período de negociação (padrão 1 minuto) que procura rompimentos confirmados por volume fora dessas zonas.
As posições são protegidas por paradas proporcionais ATR e metas escaláveis. As contrações de volume desencadeiam saídas precoces para imitar o
disciplina de monitoramento encontrada no código MT4.
Lógica estratégica
Detecção de zona de volume (período de perfil)
Cada vela finalizada de período superior atualiza duas médias móveis simples (SMA) do volume de ticks.
Uma vela é rotulada como zona forte quando seu volume excede a média do multiplicador configurável (Strong Volume Mult).
O preço de fechamento da vela torna-se o nível forte mais recente.
Uma vela é rotulada como zona fraca quando seu volume cai abaixo da média dividida pelo divisor configurado
(Weak Volume Divider). O preço de fechamento dessa vela torna-se o último nível fraco.
Participam apenas velas acabadas. A estratégia ignora zonas até que o perfil SMA esteja totalmente formado para evitar
sinais durante o período de aquecimento.
Entradas de breakout (período de negociação)
O período inferior aguarda que seu volume SMA e o indicador ATR terminem de se formar.
Uma configuração longa exige que o fechamento exceda o nível forte mais recente pela soma dos Pontos Base da Zona e
Zone Step Points buffers (convertidos por meio da etapa de preço do instrumento). A vela também deve fornecer um pico de volume relativo
à média intradiária.
Uma configuração curta reflete a lógica em torno do último nível fraco, exigindo uma quebra além do buffer combinado e confirmando
expansão volumétrica.
O especialista MT4 original permitia comandos manuais e grades de múltiplas ordens. A porta StockSharp mantém um modelo de posição única, então um
o rompimento só é acionado quando a posição líquida atual é estável.
Gerenciamento de saída
Na entrada, a estratégia armazena o preço de preenchimento, calcula um stop de proteção baseado em ATR (ATR multiplicado por ATR Multiplier e
fixado pelo buffer da zona base) e define o alvo como a distância de parada multiplicada pelo divisor de volume fraco. Isso mantém
risco e recompensa alinhados com a estrutura de volume.
Enquanto uma posição está aberta, a estratégia monitora cada vela de negociação concluída:
Se o preço atingir a meta de lucro ou o stop de proteção, a posição será achatada imediatamente.
Se o volume de ticks contrair abaixo do limite de volume fraco antes de qualquer nível ser atingido, a negociação será fechada mais cedo para evitar
permanecendo em zonas inativas.
Quando a posição líquida retorna a zero, o estado interno é redefinido, permitindo que o próximo rompimento seja avaliado do zero.
Parâmetros
Vela de Perfil – tipo de vela que alimenta o perfil de volume (padrão: velas de 15 minutos).
Vela de negociação – período de tempo inferior usado para rompimentos e saídas (padrão: velas de 1 minuto).
Volume Lookback – número de velas para SMAs de volume e período ATR.
Strong Volume Mult – multiplicador acima do volume médio que marca uma zona forte (mapeia para Parameter.1 em MQL).
Divisor de Volume Fraco – divisor abaixo do volume médio que marca zonas fracas e dimensiona a meta de lucro (mapeia para
Parameter.2).
ATR Multiplicador – fator de escala aplicado a ATR ao calcular a distância de parada adaptativa (mapeia para Parameter.3).
Pontos base da zona – buffer mínimo em pontos adicionados ao nível da zona antes de verificar os rompimentos (mapeia para ZoneBasePoints).
Zone Step Points – buffer de breakout adicional em pontos que amplia a distância da zona antes que as entradas sejam
acionado (mapeia para ZoneStepPoints).
Volume – herdado da classe base Strategy; define o tamanho da ordem para entradas no mercado.
Notas adicionais
A estratégia volta automaticamente para uma etapa de preço padrão de 0.0001 se o título não especificar uma. Isto mantém o
parâmetros baseados em pontos compatíveis com a maioria dos símbolos FX.
Todos os cálculos dos indicadores dependem de velas finalizadas para corresponder à implementação do MT4 que funcionou em barras totalmente fechadas.
Ao contrário do EA original, não há painel de controle manual ou carregador de perfil baseado em arquivo. As zonas são reconstruídas puramente a partir de live
dados da vela para manter a porta independente.
A versão StockSharp não inclui uma tradução Python.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// AIS5 Trade Machine: EMA breakout with RSI filter and ATR stops.
/// </summary>
public class Ais5TradeMachineStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaLength;
private readonly StrategyParam<int> _rsiLength;
private readonly StrategyParam<int> _atrLength;
private decimal _prevClose;
private decimal _entryPrice;
public Ais5TradeMachineStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(8).TimeFrame())
.SetDisplay("Candle Type", "Timeframe.", "General");
_emaLength = Param(nameof(EmaLength), 20)
.SetDisplay("EMA Length", "Trend filter.", "Indicators");
_rsiLength = Param(nameof(RsiLength), 14)
.SetDisplay("RSI Length", "RSI period.", "Indicators");
_atrLength = Param(nameof(AtrLength), 14)
.SetDisplay("ATR Length", "ATR period.", "Indicators");
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int EmaLength
{
get => _emaLength.Value;
set => _emaLength.Value = value;
}
public int RsiLength
{
get => _rsiLength.Value;
set => _rsiLength.Value = value;
}
public int AtrLength
{
get => _atrLength.Value;
set => _atrLength.Value = value;
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevClose = 0;
_entryPrice = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevClose = 0;
_entryPrice = 0;
var ema = new ExponentialMovingAverage { Length = EmaLength };
var rsi = new RelativeStrengthIndex { Length = RsiLength };
var atr = new AverageTrueRange { Length = AtrLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ema, rsi, atr, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ema);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal emaVal, decimal rsiVal, decimal atrVal)
{
if (candle.State != CandleStates.Finished)
return;
var close = candle.ClosePrice;
if (_prevClose == 0 || atrVal <= 0)
{
_prevClose = close;
return;
}
if (Position > 0)
{
if (close >= _entryPrice + atrVal * 2.5m || close <= _entryPrice - atrVal * 1.5m || rsiVal > 75)
{
SellMarket();
_entryPrice = 0;
}
}
else if (Position < 0)
{
if (close <= _entryPrice - atrVal * 2.5m || close >= _entryPrice + atrVal * 1.5m || rsiVal < 25)
{
BuyMarket();
_entryPrice = 0;
}
}
if (Position == 0)
{
if (close > emaVal && _prevClose <= emaVal && rsiVal > 50)
{
_entryPrice = close;
BuyMarket();
}
else if (close < emaVal && _prevClose >= emaVal && rsiVal < 50)
{
_entryPrice = close;
SellMarket();
}
}
_prevClose = close;
}
}
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 ExponentialMovingAverage, RelativeStrengthIndex, AverageTrueRange
class ais5_trade_machine_strategy(Strategy):
def __init__(self):
super(ais5_trade_machine_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(8))) \
.SetDisplay("Candle Type", "Timeframe.", "General")
self._ema_length = self.Param("EmaLength", 20) \
.SetDisplay("EMA Length", "Trend filter.", "Indicators")
self._rsi_length = self.Param("RsiLength", 14) \
.SetDisplay("RSI Length", "RSI period.", "Indicators")
self._atr_length = self.Param("AtrLength", 14) \
.SetDisplay("ATR Length", "ATR period.", "Indicators")
self._prev_close = 0.0
self._entry_price = 0.0
@property
def CandleType(self):
return self._candle_type.Value
@property
def EmaLength(self):
return self._ema_length.Value
@property
def RsiLength(self):
return self._rsi_length.Value
@property
def AtrLength(self):
return self._atr_length.Value
def OnStarted2(self, time):
super(ais5_trade_machine_strategy, self).OnStarted2(time)
self._prev_close = 0.0
self._entry_price = 0.0
self._ema = ExponentialMovingAverage()
self._ema.Length = self.EmaLength
self._rsi = RelativeStrengthIndex()
self._rsi.Length = self.RsiLength
self._atr = AverageTrueRange()
self._atr.Length = self.AtrLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._ema, self._rsi, self._atr, self.ProcessCandle).Start()
def ProcessCandle(self, candle, ema_val, rsi_val, atr_val):
if candle.State != CandleStates.Finished:
return
ev = float(ema_val)
rv = float(rsi_val)
av = float(atr_val)
close = float(candle.ClosePrice)
if self._prev_close == 0 or av <= 0:
self._prev_close = close
return
if self.Position > 0:
if close >= self._entry_price + av * 2.5 or close <= self._entry_price - av * 1.5 or rv > 75:
self.SellMarket()
self._entry_price = 0.0
elif self.Position < 0:
if close <= self._entry_price - av * 2.5 or close >= self._entry_price + av * 1.5 or rv < 25:
self.BuyMarket()
self._entry_price = 0.0
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_close = close
return
if self.Position == 0:
if close > ev and self._prev_close <= ev and rv > 50:
self._entry_price = close
self.BuyMarket()
elif close < ev and self._prev_close >= ev and rv < 50:
self._entry_price = close
self.SellMarket()
self._prev_close = close
def OnReseted(self):
super(ais5_trade_machine_strategy, self).OnReseted()
self._prev_close = 0.0
self._entry_price = 0.0
def CreateClone(self):
return ais5_trade_machine_strategy()