Flat 001a é um sistema de scalping projetado para o gráfico horário EURUSD. Ele verifica as velas de três horas mais recentes e mede a distância entre a máxima mais alta e a mínima mais baixa. Quando o intervalo desta janela de três velas permanece dentro de um número configurável de pontos, a estratégia prevê que o preço permanecerá preso dentro da linha plana. Em seguida, procura atenuar excursões de curto prazo no quarto superior ou inferior do canal e imediatamente atribui ordens de proteção.
O consultor especialista original MQL4 negociou apenas EURUSD no primeiro semestre e rejeitou a negociação se o símbolo ou período de tempo estivesse incorreto. Esta porta mantém os mesmos padrões (EURUSD, velas de 60 minutos) e reproduz todos os cálculos de entrada, stop-loss, take-profit e trailing-stop em StockSharp.
Indicadores e dados
Os indicadores Highest e Lowest (período = 3) rastreiam a parte superior e inferior das últimas três velas concluídas.
Um parâmetro de período de tempo tem como padrão velas de 60 minutos para espelhar o requisito H1 do código-fonte.
Não são utilizados osciladores adicionais ou filtros de suavização, pelo que a estratégia reage apenas aos extremos do preço bruto.
Lógica de entrada
Aguarde o fechamento da vela de assinatura. Apenas velas prontas são processadas.
Verifique se o código de segurança atual corresponde ao código configurado (padrão: EURUSD). Caso contrário, a estratégia permanece ociosa.
Avalie a janela de negociação opcional. Por padrão, as entradas são permitidas durante as duas horas a partir da meia-noite do horário da plataforma (horas 0 e 1). O filtro pode ser desativado.
Calcule o intervalo de três velas range = highest - lowest e converta-o em pontos por meio do instrumento PriceStep.
Continue apenas se o número de pontos estiver entre DiffMinPoints e DiffMaxPoints.
Se o preço de fechamento estiver dentro do quarto mais baixo do intervalo e nenhuma posição estiver aberta, entre em uma negociação longa.
Se o preço de fechamento estiver dentro do quarto mais alto do intervalo e nenhuma posição estiver aberta, entre em uma negociação curta.
Gerenciamento de pedidos
Stop-loss inicial
Negociações longas: lowest - range / 3.
Negociações curtas: highest + range / 3.
Realização de lucro
Negociações longas: preço de entrada + TakeProfitPoints * PriceStep.
Negociações curtas: preço de entrada − TakeProfitPoints * PriceStep.
Parada final
Assim que o lucro não realizado exceder TrailingStopPoints * PriceStep, o stop-loss é seguido vela por vela.
As negociações longas movem o stop para closePrice - TrailingDistance se for maior que o stop atual.
As negociações curtas movem o stop para closePrice + TrailingDistance se for inferior ao stop atual.
Todas as saídas são executadas com ordens de mercado. A estratégia fecha a posição completa quando o nível de stop-loss ou de take-profit é tocado pela vela subsequente.
Parâmetros
Grupo
Nome
Descrição
Padrão
Geral
CandleType
Tipo de vela usado para cálculos. Deve ser definido para um período de 60 minutos para corresponder ao sistema original.
TimeFrame(60m)
Geral
SecurityCode
Código de segurança esperado. Deixe em branco para negociar qualquer instrumento.
EURUSD
Filtro de intervalo
DiffMinPoints
Faixa mínima de três velas em pontos necessários para negociar.
18
Filtro de intervalo
DiffMaxPoints
Faixa máxima de três velas em pontos permitidos para negociação.
28
Janela de negociação
EnableTimeFilter
Ativa ou desativa o filtro de hora.
true
Janela de negociação
OpenHour
Hora de início (0–23) da janela de negociação. A estratégia também permite a próxima hora imediata.
0
Gestão de Risco
TakeProfitPoints
Distância de lucro expressa em pontos. Defina como zero para desativar.
8
Gestão de Risco
TrailingStopPoints
Distância do trailing-stop expressa em pontos. Defina como zero para desativar o rastreamento.
6
Notas práticas
A propriedade StockSharp Strategy.Volume controla o tamanho do pedido. Ajuste-o de acordo com o tamanho do seu contrato de corretor.
Certifique-se de que o instrumento selecionado exponha um PriceStep válido. Se PriceStep estiver faltando, a estratégia volta para 1 e registra um aviso.
O consultor especialista MQL4 ofereceu gerenciamento de dinheiro opcional, escalonando os lotes de acordo com o saldo da conta. A amostra de StockSharp mantém o tamanho da posição constante; você pode criar scripts para seu próprio gerenciamento de volume, se necessário.
Sempre teste a estratégia em simulação antes de executá-la ao vivo. A lógica final pressupõe que o corretor atenderá às ordens de proteção quando os extremos das velas cruzarem o nível; em mercados rápidos, a derrapagem pode aumentar o risco realizado.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Flat 001a: RSI reversal with EMA filter and ATR stops.
/// </summary>
public class Flat001aStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiLength;
private readonly StrategyParam<int> _emaLength;
private readonly StrategyParam<int> _atrLength;
private decimal _prevRsi;
private decimal _entryPrice;
public Flat001aStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Timeframe.", "General");
_rsiLength = Param(nameof(RsiLength), 14)
.SetDisplay("RSI Length", "RSI period.", "Indicators");
_emaLength = Param(nameof(EmaLength), 20)
.SetDisplay("EMA Length", "Trend filter.", "Indicators");
_atrLength = Param(nameof(AtrLength), 14)
.SetDisplay("ATR Length", "ATR period.", "Indicators");
}
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int RsiLength { get => _rsiLength.Value; set => _rsiLength.Value = value; }
public int EmaLength { get => _emaLength.Value; set => _emaLength.Value = value; }
public int AtrLength { get => _atrLength.Value; set => _atrLength.Value = value; }
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevRsi = 0; _entryPrice = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevRsi = 0; _entryPrice = 0;
var rsi = new RelativeStrengthIndex { Length = RsiLength };
var ema = new ExponentialMovingAverage { Length = EmaLength };
var atr = new AverageTrueRange { Length = AtrLength };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(rsi, ema, atr, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, ema); DrawOwnTrades(area); }
}
private void ProcessCandle(ICandleMessage candle, decimal rsiVal, decimal emaVal, decimal atrVal)
{
if (candle.State != CandleStates.Finished) return;
if (_prevRsi == 0 || atrVal <= 0) { _prevRsi = rsiVal; return; }
var close = candle.ClosePrice;
if (Position > 0)
{
if (close >= _entryPrice + atrVal * 2.5m || close <= _entryPrice - atrVal * 1.5m || rsiVal > 70) { SellMarket(); _entryPrice = 0; }
}
else if (Position < 0)
{
if (close <= _entryPrice - atrVal * 2.5m || close >= _entryPrice + atrVal * 1.5m || rsiVal < 30) { BuyMarket(); _entryPrice = 0; }
}
if (Position == 0)
{
if (rsiVal > 55 && _prevRsi <= 55 && close > emaVal) { _entryPrice = close; BuyMarket(); }
else if (rsiVal < 45 && _prevRsi >= 45 && close < emaVal) { _entryPrice = close; SellMarket(); }
}
_prevRsi = rsiVal;
}
}
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, ExponentialMovingAverage, AverageTrueRange
class flat001a_strategy(Strategy):
def __init__(self):
super(flat001a_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe.", "General")
self._rsi_length = self.Param("RsiLength", 14) \
.SetDisplay("RSI Length", "RSI period.", "Indicators")
self._ema_length = self.Param("EmaLength", 20) \
.SetDisplay("EMA Length", "Trend filter.", "Indicators")
self._atr_length = self.Param("AtrLength", 14) \
.SetDisplay("ATR Length", "ATR period.", "Indicators")
self._prev_rsi = 0.0
self._entry_price = 0.0
@property
def CandleType(self):
return self._candle_type.Value
@property
def RsiLength(self):
return self._rsi_length.Value
@property
def EmaLength(self):
return self._ema_length.Value
@property
def AtrLength(self):
return self._atr_length.Value
def OnStarted2(self, time):
super(flat001a_strategy, self).OnStarted2(time)
self._prev_rsi = 0.0
self._entry_price = 0.0
self._rsi = RelativeStrengthIndex()
self._rsi.Length = self.RsiLength
self._ema = ExponentialMovingAverage()
self._ema.Length = self.EmaLength
self._atr = AverageTrueRange()
self._atr.Length = self.AtrLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._rsi, self._ema, self._atr, self.ProcessCandle).Start()
def ProcessCandle(self, candle, rsi_val, ema_val, atr_val):
if candle.State != CandleStates.Finished:
return
rv = float(rsi_val)
ev = float(ema_val)
av = float(atr_val)
if self._prev_rsi == 0 or av <= 0:
self._prev_rsi = rv
return
close = float(candle.ClosePrice)
if self.Position > 0:
if close >= self._entry_price + av * 2.5 or close <= self._entry_price - av * 1.5 or rv > 70:
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 < 30:
self.BuyMarket()
self._entry_price = 0.0
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_rsi = rv
return
if self.Position == 0:
if rv > 55 and self._prev_rsi <= 55 and close > ev:
self._entry_price = close
self.BuyMarket()
elif rv < 45 and self._prev_rsi >= 45 and close < ev:
self._entry_price = close
self.SellMarket()
self._prev_rsi = rv
def OnReseted(self):
super(flat001a_strategy, self).OnReseted()
self._prev_rsi = 0.0
self._entry_price = 0.0
def CreateClone(self):
return flat001a_strategy()