A estratégia Forex Fraus M1 replica o assessor especializado MetaTrader 5 "Forex Fraus M1" no framework StockSharp. É um sistema contrário que monitora um oscilador Williams %R de longo período (período 360) em velas de um minuto. Sempre que o oscilador toca valores extremos, a estratégia tenta desaparecer do movimento, visando uma rápida reversão ao ponto médio do intervalo recente. A implementação mantém o gerenciamento de dinheiro do especialista original, incluindo horas de trading opcionais, níveis estáticos de stop-loss e take-profit medidos em pips e um trailing stop baseado em pips.
Lógica de trading
Indicador: Williams %R com um período de 360.
Sinal de compra: Quando Williams %R cai abaixo de -99.9, o mercado é considerado extremamente sobrevendido. A estratégia envia uma ordem de compra a mercado se não há posição comprada existente. Se CloseOppositePositions está habilitado, qualquer exposição vendida é fechada na mesma solicitação de ordem.
Sinal de venda: Quando Williams %R sobe acima de -0.1, o mercado está extremamente sobrecomprado. A estratégia emite uma ordem de venda a mercado, opcionalmente fechando primeiro qualquer exposição comprada aberta.
Filtro de tempo: Quando UseTimeControl está habilitado, a estratégia só avalia sinais entre StartHour (inclusive) e EndHour (exclusive). Se a sessão ultrapassa a meia-noite (StartHour > EndHour), o trading é permitido de StartHour a 23 e de 0 a EndHour - 1.
Gestão de risco
Stop-loss: Calculado como StopLossPips * PipSize abaixo (para comprados) ou acima (para vendidos) do preço de entrada. Quando o mínimo da vela toca o nível de stop, a posição é fechada a mercado.
Take-profit: Calculado como TakeProfitPips * PipSize acima (para comprados) ou abaixo (para vendidos) do preço de entrada. Quando o máximo/mínimo da vela atinge este nível, a posição é fechada para garantir lucros.
Trailing stop: Se tanto TrailingStopPips quanto TrailingStepPips são positivos, o stop é apertado quando o preço se move pelo menos TrailingStopPips + TrailingStepPips pips a favor da operação. Para comprados, o stop acompanha o fechamento menos TrailingStopPips; para vendidos, acompanha o fechamento mais TrailingStopPips.
Tamanho do pip: PipSize define o valor monetário de um pip. Para símbolos Forex de cinco dígitos, defina PipSize como 0.0001, para pares JPY de três dígitos use 0.01, etc.
A estratégia verifica as condições de stop-loss e take-profit usando máximos/mínimos das velas. Quando ambos são tocados dentro da mesma vela, o stop de proteção tem prioridade, refletindo o comportamento conservador do especialista original.
Parâmetros
Nome
Padrão
Descrição
OrderVolume
0.1
Volume de operação usado para novas posições.
StopLossPips
50
Distância do stop-loss em pips do preço de entrada. Defina como zero para desabilitar.
TakeProfitPips
150
Distância do take-profit em pips do preço de entrada. Defina como zero para desabilitar.
TrailingStopPips
1
Distância base do trailing stop em pips. Defina como zero para desabilitar o rastreamento.
TrailingStepPips
1
Ganho mínimo adicional em pips antes que o trailing stop se mova.
UseTimeControl
true
Habilita o filtro de sessão intradiária.
StartHour
7
Hora de início da sessão de trading (0-23).
EndHour
17
Hora de fim da sessão de trading (1-24, exclusive).
CloseOppositePositions
true
Se habilitado, reverte as posições existentes em uma única ordem.
WilliamsPeriod
360
Período de retrospectiva para o indicador Williams %R.
CandleType
1 minute
Tipo de vela usado para avaliar Williams %R e as regras de trading.
PipSize
0.0001
Valor de um único pip em unidades de preço.
Notas adicionais
A estratégia usa a API de subscrição de velas de alto nível do StockSharp e a vinculação de indicadores para lógica concisa sem gerenciamento manual de buffers.
Os cálculos de stop-loss, take-profit e rastreamento ocorrem em velas completadas para evitar agir sobre dados de preço incompletos.
A implementação chama StartProtection() uma vez na inicialização para se alinhar com as diretrizes do projeto, enquanto o gerenciamento real de risco é feito dentro da lógica da estratégia.
Ajuste o parâmetro PipSize para corresponder ao instrumento negociado para que as distâncias baseadas em pips sejam mapeadas corretamente para movimentos de preço.
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>
/// Forex Fraus M1 strategy using fast EMA crossover on short timeframes.
/// </summary>
public class ForexFrausM1Strategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private decimal? _prevFast;
private decimal? _prevSlow;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int FastPeriod
{
get => _fastPeriod.Value;
set => _fastPeriod.Value = value;
}
public int SlowPeriod
{
get => _slowPeriod.Value;
set => _slowPeriod.Value = value;
}
public ForexFrausM1Strategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 5)
.SetGreaterThanZero()
.SetDisplay("Fast Period", "Fast EMA", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 15)
.SetGreaterThanZero()
.SetDisplay("Slow Period", "Slow EMA", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = null;
_prevSlow = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = null;
_prevSlow = null;
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, slow, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fast);
DrawIndicator(area, slow);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal fastVal, decimal slowVal)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevFast = fastVal;
_prevSlow = slowVal;
return;
}
if (_prevFast == null || _prevSlow == null)
{
_prevFast = fastVal;
_prevSlow = slowVal;
return;
}
var prevAbove = _prevFast.Value > _prevSlow.Value;
var currAbove = fastVal > slowVal;
_prevFast = fastVal;
_prevSlow = slowVal;
if (!prevAbove && currAbove)
{
if (Position < 0)
BuyMarket();
if (Position <= 0)
BuyMarket();
}
else if (prevAbove && !currAbove)
{
if (Position > 0)
SellMarket();
if (Position >= 0)
SellMarket();
}
}
}
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 forex_fraus_m1_strategy(Strategy):
def __init__(self):
super(forex_fraus_m1_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._fast_period = self.Param("FastPeriod", 5) \
.SetDisplay("Fast Period", "Fast EMA", "Indicators")
self._slow_period = self.Param("SlowPeriod", 15) \
.SetDisplay("Slow Period", "Slow EMA", "Indicators")
self._prev_fast = None
self._prev_slow = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def FastPeriod(self):
return self._fast_period.Value
@property
def SlowPeriod(self):
return self._slow_period.Value
def OnReseted(self):
super(forex_fraus_m1_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(forex_fraus_m1_strategy, self).OnStarted2(time)
self._prev_fast = None
self._prev_slow = None
fast = ExponentialMovingAverage()
fast.Length = self.FastPeriod
slow = ExponentialMovingAverage()
slow.Length = self.SlowPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast, slow, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast)
self.DrawIndicator(area, slow)
self.DrawOwnTrades(area)
def _on_process(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fv = float(fast_value)
sv = float(slow_value)
if self._prev_fast is None or self._prev_slow is None:
self._prev_fast = fv
self._prev_slow = sv
return
prev_above = self._prev_fast > self._prev_slow
curr_above = fv > sv
self._prev_fast = fv
self._prev_slow = sv
if not prev_above and curr_above:
if self.Position < 0:
self.BuyMarket()
if self.Position <= 0:
self.BuyMarket()
elif prev_above and not curr_above:
if self.Position > 0:
self.SellMarket()
if self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return forex_fraus_m1_strategy()