Esta estratégia é uma versão StockSharp do consultor especialista MetaTrader “Farhad Hill Version 2”.
Ele combina vários filtros de indicadores para negociar reversões de tendências em símbolos Forex. O
a lógica convertida retém a pilha de indicadores original (MACD, Stochastic, Parabolic SAR,
Momentum e cruzamento de média móvel opcional) e sua gestão de dinheiro mais
comportamento.
A estratégia funciona em um único período (velas padrão de 30 minutos) e abre apenas um
posição de cada vez. Stop-loss protetor, take-profit e três estilos de trailing-stop são
suportado para espelhar a versão MQL. Todos os comentários no código são fornecidos em inglês como
solicitado.
Lógica de negociação
MACD filtro – quando ativado, os longos requerem MACD linha principal abaixo da linha de sinal;
shorts requerem MACD principal acima da linha de sinal.
Stochastic filtro de nível – demanda de posições compradas %K abaixo do limite inferior, demanda de posições vendidas
%K acima do limite superior. Quando o filtro cruzado opcional está ativado, uma tendência de alta
A linha %K/%D (de baixo para cima) é necessária para posições compradas e uma linha de baixa para posições vendidas.
Parabolic SAR filtro – posições compradas exigem SAR abaixo do preço com um degrau descendente
(anterior SAR maior que o atual); shorts exigem SAR acima do preço com um aumento
passo. A conversão usa preços de velas fechadas como referência.
Filtro de impulso – calculado com base nos preços de abertura das velas, correspondendo às configurações de MQL.
Os comprados precisam de impulso abaixo do limite inferior, os vendidos precisam de impulso acima do limite superior
limite.
Média móvel cruzada (opcional) – tipo de MA configurável, preço aplicado e períodos.
Os comprados precisam do MA rápido acima do MA lento; shorts precisam da relação inversa.
A estratégia avalia apenas sinais em velas concluídas e ignora novas entradas quando um
existe posição aberta. As entradas são feitas com ordens de mercado utilizando o lote calculado
tamanho.
Gerenciamento de posição
Stop-loss / Take-profit – especificado em pips. Um pip é derivado do instrumento
PriceStep, voltando para 0.0001 se não estiver disponível.
Tipos de trailing stop
Imediato – quando o preço ultrapassa a distância do stop, o stop segue o preço.
Atrasado – espera que o preço se mova pela distância final da entrada antes
seguindo em um deslocamento fixo.
Três estágios – reproduz a lógica original de três níveis com duas etapas de ponto de equilíbrio
e uma distância final de fuga.
Ordens de proteção são colocadas com SellStop/BuyStop (para stop-loss) e
SellLimit/BuyLimit (para obter lucro) para que permaneçam visíveis na bolsa.
Gestão de capital
Lote Fixo – negocia o volume fixo configurado. Se AccountIsMini estiver ativado, muitos
são convertidos para dimensionamento de minilote com mínimo de 0,1.
Risco percentual – replica a fórmula original
floor(FreeMargin * percent / 10000) / 10, limitado pelo limite MaxLots e ajustado
para mini contas quando necessário. Se o valor do portfólio não estiver disponível, a estratégia
volta para o lote fixo.
Parâmetros
Todos os parâmetros são expostos através de objetos StrategyParam<T> e podem ser otimizados ou
alterado na IU. Grupos principais:
Parabolic SAR comparações usam o preço de fechamento da vela para aproximar verificações de compra/venda
do MT4. Isso mantém a lógica determinística em dados históricos.
A gestão de dinheiro requer uma carteira conectada para obter patrimônio atual; caso contrário
o volume fixo é usado.
As combinações de indicadores são processadas apenas em velas concluídas, evitando
sinais em dados parciais.
Arquivos
CS/FarhadHillVersion2Strategy.cs – Implementação da estratégia em C#.
README.md – Este documento.
README_ru.md – Tradução russa.
README_zh.md – tradução chinesa.
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>
/// Farhad Hill V2 strategy - EMA + Momentum trend follower.
/// Buys when fast EMA crosses above slow EMA with positive momentum.
/// Sells on bearish crossover with negative momentum.
/// </summary>
public class FarhadHillVersion2Strategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _momentumPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFast;
private decimal _prevSlow;
private bool _hasPrev;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int MomentumPeriod { get => _momentumPeriod.Value; set => _momentumPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public FarhadHillVersion2Strategy()
{
_fastPeriod = Param(nameof(FastPeriod), 8)
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 21)
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
_momentumPeriod = Param(nameof(MomentumPeriod), 10)
.SetDisplay("Momentum", "Momentum period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
protected override void OnReseted() { base.OnReseted(); _prevFast = 0m; _prevSlow = 0m; _hasPrev = false; }
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var momentum = new Momentum { Length = MomentumPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, slow, momentum, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow, decimal momentum)
{
if (candle.State != CandleStates.Finished)
return;
if (!_hasPrev)
{
_prevFast = fast;
_prevSlow = slow;
_hasPrev = true;
return;
}
var crossUp = _prevFast <= _prevSlow && fast > slow;
var crossDown = _prevFast >= _prevSlow && fast < slow;
if (crossUp && momentum > 0 && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
else if (crossDown && momentum < 0 && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
_prevFast = fast;
_prevSlow = slow;
}
}