Esta estratégia é um port de alto nível do StockSharp do assessor especialista do MetaTrader "Three neural networks". Funciona inteiramente através da API de subscrição de velas do StockSharp e reutiliza indicadores SmoothedMovingAverage integrados para emular as três camadas neurais da implementação original. A estratégia opera em três períodos diferentes (H1, H4, D1) e analisa a inclinação de cada média suavizada para derivar uma decisão de negociação coletiva.
Fluxo de trabalho
Quando a estratégia começa, ela subscreve velas dos períodos H1, H4 e D1 e vincula médias móvias suavizadas que usam o preço mediano, espelhando as chamadas iMA(..., MODE_SMMA, PRICE_MEDIAN) do MetaTrader.
Cada período mantém um histórico contínuo que respeita o deslocamento configurado. Assim que quatro valores deslocados estão disponíveis, o algoritmo calcula três saídas neurais usando exatamente a mesma fórmula de diferença ponderada do EA e arredonda o resultado para quatro casas decimais.
Após o fechamento da vela H1, a estratégia combina as saídas neurais:
Se todos os três valores são positivos → abrir ou manter uma posição comprada.
Se a saída H1 é positiva enquanto as saídas H4 e D1 são negativas → abrir ou manter uma posição vendida.
Os posições são dimensionadas com um lote fixo ou um modelo de porcentagem de risco. No modo de risco, a estratégia aloca VolumeOrRisk por cento do valor do portfólio e o converte em volume dividindo pelo preço atual.
A lógica protetora replica os controles do EA: um stop-loss e take-profit são colocados em variáveis locais imediatamente após a mudança de direção do posição, e um Trailing stop é ajustado cada vez que a barra H1 fecha se o preço avança além da distância de trailing mais o passo configurado.
Cada vela H1 concluída primeiro verifica se os níveis atuais de stop-loss ou take-profit são violados e fecha a posição com uma ordem de mercado se necessário. O registro detalhado opcional reproduz o sinalizador InpPrintLog original.
Parâmetros
Nome
Padrão
Descrição
StopLossPips
50
Distância de stop de proteção em pips. Defina como 0 para desativar o stop-loss.
TakeProfitPips
50
Distância de take-profit em pips. Defina como 0 para desativar o objetivo.
TrailingStopPips
15
Distância entre o preço atual e o Trailing stop.
TrailingStepPips
5
Melhoria mínima necessária antes de mover o Trailing stop novamente.
ManagementMode
RiskPercent
Modo de dimensionamento de volume. FixedLot usa o valor como tamanho de lote direto; RiskPercent como porcentagem do patrimônio do portfólio.
VolumeOrRisk
1
Tamanho de lote ou porcentagem de risco, dependendo do modo de gestão de dinheiro.
H1Period, H1Shift
2, 5
Período e deslocamento da média móvel suavizada H1.
H4Period, H4Shift
2, 5
Período e deslocamento da média móvel suavizada H4.
D1Period, D1Shift
2, 5
Período e deslocamento da média móvel suavizada D1.
P1, P2, P3
0.1
Pesos aplicados aos três componentes neurais H1.
Q1, Q2, Q3
0.1
Pesos aplicados aos três componentes neurais H4.
K1, K2, K3
0.1
Pesos aplicados aos três componentes neurais D1.
EnableDetailedLog
false
Ativa mensagens de diagnóstico detalhadas que espelham a saída de registro do EA.
Gestão de risco
Os níveis de stop-loss e take-profit são traduzidos de distâncias em pips usando o tamanho de pip detectado (com ajuste automático de 3/5 dígitos idêntico ao código original) e aplicados imediatamente após a mudança de direção da posição.
A lógica de trailing segue as condições do MetaTrader: torna-se ativa assim que o preço se move mais de TrailingStopPips + TrailingStepPips do ponto de entrada e avança apenas se a melhoria exceder o passo configurado.
Todas as saídas são executadas com ordens de mercado ClosePosition() porque ordens stop/limite do lado do servidor não estão disponíveis na API de alto nível.
Notas
A validação de nível de congelamento/stop do EA não está disponível no StockSharp, portanto a estratégia depende apenas da conversão de tamanho de pip e normalização de volume através de VolumeStep, VolumeMin e VolumeMax.
O dimensionamento baseado em risco usa o valor atual do portfólio e o preço de entrada para aproximar a verificação de margem do MetaTrader. Isso espelha o comportamento geral sem depender de calculadoras de margem específicas do corretor.
O registro opcional pode ser habilitado através de EnableDetailedLog para diagnósticos passo a passo semelhantes a InpPrintLog no MetaTrader.
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 ThreeNeuralNetworksStrategy : 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 ThreeNeuralNetworksStrategy()
{
_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 three_neural_networks_strategy(Strategy):
def __init__(self):
super(three_neural_networks_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(three_neural_networks_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(three_neural_networks_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 three_neural_networks_strategy()