A Estratégia de Linhas de Encontro Stochastic é uma implementação StockSharp do especialista MetaTrader Expert_AML_Stoch. Ele combina os padrões de reversão do castiçal das Linhas de Reunião de Alta/Baixa com a confirmação da linha de sinal %D do oscilador Stochastic. A estratégia foi projetada para traders discricionários que desejam uma abordagem baseada em regras para reconhecimento de padrões com confirmação adicional de impulso. Ao usar o StockSharp API de alto nível, o código permanece conciso, testável e fácil de estender para gerenciamento de portfólio ou automação adicional.
Lógica de negociação
Filtro de padrão de vela
A estratégia avalia continuamente as duas últimas velas concluídas para detectar a formação de Linhas de Encontro.
Uma configuração de alta requer uma vela preta longa seguida por uma vela branca longa cujo preço de fechamento esteja dentro de 10% do fechamento anterior.
Uma configuração de baixa requer uma vela branca longa seguida por uma vela preta longa com o mesmo alinhamento próximo de 10%.
O tamanho médio do corpo da vela é calculado com uma média móvel simples configurável para filtrar corpos fracos.
Stochastic Confirmação
A linha de sinal %D do oscilador Stochastic deve confirmar o sinal da vela.
As entradas de alta exigem que %D esteja abaixo do limite de sobrevenda configurável (padrão 30).
As entradas de baixa exigem que %D esteja acima do limite de sobrecompra configurável (padrão 70).
Regras de saída
As posições curtas são fechadas quando %D cruza para cima através do nível de saída inferior (padrão 20) ou do nível de saída superior (padrão 80).
As posições longas são fechadas quando %D cruza os mesmos níveis para baixo.
As ordens de reversão fecham automaticamente a exposição existente e abrem uma nova posição na direção oposta.
Manuseio de Volume
A estratégia utiliza a propriedade base Volume quando esta é positiva; caso contrário, o padrão é um único lote para compatibilidade com o comportamento de lote fixo de MetaTrader.
Parâmetros
Nome
Descrição
Padrão
Notas
CandleType
Série de velas primárias usadas para análise.
Período de 15 minutos
Aceita qualquer DataType compatível com StockSharp.
StochasticLength
Período de lookback para o cálculo %K bruto.
3
Espelha o MetaTrader %K period.
StochasticSmoothing
Suavização aplicada a %K (MetaTrader slowing).
25
Define o comprimento de suavização interna do oscilador.
StochasticSignal
Período de suavização para a linha de sinal %D.
36
Espelha o MetaTrader %D period.
BodyAveragePeriod
Número de velas usadas para calcular a média do tamanho do corpo da vela.
3
Filtra corpos menores ao detectar Linhas de Reunião.
LongEntryLevel
Valor máximo de %D que ainda permite uma entrada de alta.
30
Equivalente ao limite de sobrevenda.
ShortEntryLevel
Valor mínimo de %D necessário para uma entrada de baixa.
70
Equivalente ao limite de sobrecompra.
ExitLowerLevel
Limite inferior que aciona saídas em cruzamentos ascendentes.
20
Usado para decisões de saída longas e curtas.
ExitUpperLevel
Limite superior que aciona saídas em cruzamentos descendentes.
80
Usado para decisões de saída longas e curtas.
Todos os parâmetros são expostos por meio do StrategyParam<T> e podem ser otimizados diretamente no StockSharp Designer ou programaticamente.
Geração de Sinal
Entrada longa: Linhas de reunião de alta + %D abaixo de LongEntryLevel sem exposição longa existente (as posições vendidas são invertidas).
Entrada curta: Linhas de reunião de baixa + %D acima de ShortEntryLevel sem exposição curta existente (as posições compradas são revertidas).
Saída longa: %D cruza abaixo de ExitUpperLevel ou ExitLowerLevel.
Saída curta: %D cruza acima de ExitLowerLevel ou ExitUpperLevel.
Notas de implementação
Os dados dos indicadores são tratados via BindEx, evitando o gerenciamento manual de coleta de indicadores.
A média do corpo da vela usa um SimpleMovingAverage alimentado com tamanhos absolutos de corpo por meio de DecimalIndicatorValue, correspondendo ao auxiliar MetaTrader AvgBody.
Todos os comentários no código são escritos em inglês e o recuo depende de caracteres de tabulação de acordo com as diretrizes do projeto.
A estratégia desenha automaticamente velas e o oscilador estocástico quando uma área do gráfico está disponível, simplificando o monitoramento ao vivo.
Dicas de uso
Otimização: Use os parâmetros expostos para testes walk-forward para alinhar os limites com o instrumento negociado.
Gerenciamento de riscos: coloque a estratégia em camadas com o StartProtection integrado do StartProtection ou controles de risco externos em nível de portfólio para implantações de produção.
Qualidade dos dados: Os padrões das Linhas de Reunião são sensíveis a preços precisos de abertura/fechamento; garantir o alinhamento do feed e a filtragem de sessões ilíquidas.
Períodos: embora o padrão seja 15 minutos, dados intradiários ou diários podem ser usados modificando CandleType.
A estratégia oferece uma abordagem disciplinada para traders que dependem de formações de velas, mas exigem a confirmação do oscilador para reduzir falsos positivos.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Meeting Lines + Stochastic strategy.
/// Buys on bullish meeting lines with low stochastic, sells on bearish meeting lines with high stochastic.
/// </summary>
public class MeetingLinesStochasticStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _stochPeriod;
private readonly StrategyParam<decimal> _stochLow;
private readonly StrategyParam<decimal> _stochHigh;
private ICandleMessage _prevCandle;
private ICandleMessage _prevPrevCandle;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int StochPeriod { get => _stochPeriod.Value; set => _stochPeriod.Value = value; }
public decimal StochLow { get => _stochLow.Value; set => _stochLow.Value = value; }
public decimal StochHigh { get => _stochHigh.Value; set => _stochHigh.Value = value; }
public MeetingLinesStochasticStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_stochPeriod = Param(nameof(StochPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("Stochastic Period", "Stochastic K period", "Indicators");
_stochLow = Param(nameof(StochLow), 30m)
.SetDisplay("Stoch Low", "Stochastic oversold level", "Signals");
_stochHigh = Param(nameof(StochHigh), 70m)
.SetDisplay("Stoch High", "Stochastic overbought level", "Signals");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevCandle = null;
_prevPrevCandle = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevCandle = null;
_prevPrevCandle = null;
var stoch = new StochasticOscillator { K = { Length = StochPeriod }, D = { Length = 3 } };
var subscription = SubscribeCandles(CandleType);
subscription.BindEx(stoch, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue stochValue)
{
if (candle.State != CandleStates.Finished) return;
var stochTyped = stochValue as StochasticOscillatorValue;
if (stochTyped?.K is not decimal kValue) { UpdateState(candle); return; }
if (_prevCandle != null && _prevPrevCandle != null)
{
var avgBody = (Math.Abs(_prevCandle.ClosePrice - _prevCandle.OpenPrice) +
Math.Abs(_prevPrevCandle.ClosePrice - _prevPrevCandle.OpenPrice)) / 2m;
if (avgBody > 0)
{
// Bullish meeting lines: prev bearish, current bullish, closes near
var prevBearish = _prevCandle.OpenPrice > _prevCandle.ClosePrice &&
(_prevCandle.OpenPrice - _prevCandle.ClosePrice) > avgBody * 0.5m;
var currBullish = candle.ClosePrice > candle.OpenPrice &&
(candle.ClosePrice - candle.OpenPrice) > avgBody * 0.5m;
var closesNear = Math.Abs(candle.ClosePrice - _prevCandle.ClosePrice) < avgBody * 0.3m;
if (prevBearish && currBullish && closesNear && kValue < StochLow && Position <= 0)
BuyMarket();
// Bearish meeting lines: prev bullish, current bearish, closes near
var prevBullish = _prevCandle.ClosePrice > _prevCandle.OpenPrice &&
(_prevCandle.ClosePrice - _prevCandle.OpenPrice) > avgBody * 0.5m;
var currBearish = candle.OpenPrice > candle.ClosePrice &&
(candle.OpenPrice - candle.ClosePrice) > avgBody * 0.5m;
var closesNear2 = Math.Abs(candle.ClosePrice - _prevCandle.ClosePrice) < avgBody * 0.3m;
if (prevBullish && currBearish && closesNear2 && kValue > StochHigh && Position >= 0)
SellMarket();
}
}
UpdateState(candle);
}
private void UpdateState(ICandleMessage candle)
{
_prevPrevCandle = _prevCandle;
_prevCandle = candle;
}
}
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 StochasticOscillator
from StockSharp.Algo.Strategies import Strategy
class meeting_lines_stochastic_strategy(Strategy):
def __init__(self):
super(meeting_lines_stochastic_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5)))
self._stoch_period = self.Param("StochPeriod", 14)
self._stoch_low = self.Param("StochLow", 30.0)
self._stoch_high = self.Param("StochHigh", 70.0)
self._prev_candle = None
self._prev_prev_candle = None
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def StochPeriod(self):
return self._stoch_period.Value
@StochPeriod.setter
def StochPeriod(self, value):
self._stoch_period.Value = value
@property
def StochLow(self):
return self._stoch_low.Value
@StochLow.setter
def StochLow(self, value):
self._stoch_low.Value = value
@property
def StochHigh(self):
return self._stoch_high.Value
@StochHigh.setter
def StochHigh(self, value):
self._stoch_high.Value = value
def OnReseted(self):
super(meeting_lines_stochastic_strategy, self).OnReseted()
self._prev_candle = None
self._prev_prev_candle = None
def OnStarted2(self, time):
super(meeting_lines_stochastic_strategy, self).OnStarted2(time)
self._prev_candle = None
self._prev_prev_candle = None
stoch = StochasticOscillator()
stoch.K.Length = self.StochPeriod
stoch.D.Length = 3
subscription = self.SubscribeCandles(self.CandleType)
subscription.BindEx(stoch, self._process_candle).Start()
def _process_candle(self, candle, stoch_value):
if candle.State != CandleStates.Finished:
return
k_val = stoch_value.K
if k_val is None:
self._update_state(candle)
return
k_value = float(k_val)
if self._prev_candle is not None and self._prev_prev_candle is not None:
avg_body = (abs(float(self._prev_candle.ClosePrice) - float(self._prev_candle.OpenPrice))
+ abs(float(self._prev_prev_candle.ClosePrice) - float(self._prev_prev_candle.OpenPrice))) / 2.0
if avg_body > 0:
# Bullish meeting lines
prev_bearish = (float(self._prev_candle.OpenPrice) > float(self._prev_candle.ClosePrice)
and (float(self._prev_candle.OpenPrice) - float(self._prev_candle.ClosePrice)) > avg_body * 0.5)
curr_bullish = (float(candle.ClosePrice) > float(candle.OpenPrice)
and (float(candle.ClosePrice) - float(candle.OpenPrice)) > avg_body * 0.5)
closes_near = abs(float(candle.ClosePrice) - float(self._prev_candle.ClosePrice)) < avg_body * 0.3
if prev_bearish and curr_bullish and closes_near and k_value < self.StochLow and self.Position <= 0:
self.BuyMarket()
# Bearish meeting lines
prev_bullish = (float(self._prev_candle.ClosePrice) > float(self._prev_candle.OpenPrice)
and (float(self._prev_candle.ClosePrice) - float(self._prev_candle.OpenPrice)) > avg_body * 0.5)
curr_bearish = (float(candle.OpenPrice) > float(candle.ClosePrice)
and (float(candle.OpenPrice) - float(candle.ClosePrice)) > avg_body * 0.5)
closes_near2 = abs(float(candle.ClosePrice) - float(self._prev_candle.ClosePrice)) < avg_body * 0.3
if prev_bullish and curr_bearish and closes_near2 and k_value > self.StochHigh and self.Position >= 0:
self.SellMarket()
self._update_state(candle)
def _update_state(self, candle):
self._prev_prev_candle = self._prev_candle
self._prev_candle = candle
def CreateClone(self):
return meeting_lines_stochastic_strategy()