Prop Firm Helper Strategy é um sistema de breakout de canal Donchian convertido do consultor especialista MetaTrader "Prop Firm Helper". A estratégia envia ordens de stop acima do intervalo recente para entradas longas e abaixo do intervalo para entradas curtas. Ele aplica automaticamente as regras de desafio da prop firme, interrompendo a negociação depois que o patrimônio alvo é atingido ou quando o limite de perda diária é violado.
Lógica de negociação
Assine velas definidas pelo parâmetro Candle Type.
Calcule dois canais Donchian:
Entry Period/Entry Shift para detectar interrupções.
Exit Period/Exit Shift para rastrear negociações abertas.
Coloque ordens de compra stop um tick acima da máxima superior deslocada Donchian quando estiver estável ou vendido.
Coloque ordens de stop de venda um tick abaixo da mínima inferior deslocada Donchian quando estiver plana ou longa.
Use a suavização Average True Range (ATR Period) para decidir quando avançar as ordens de stop.
Feche as posições longas se a vela ficar abaixo da mínima final Donchian. Feche as posições vendidas quando a vela fechar acima da máxima final de Donchian.
Gestão de risco
Risk Per Trade % calcula o volume do pedido a partir do patrimônio atual do portfólio, tamanho do passo do instrumento e preço do passo. O volume é arredondado para a etapa de volume de troca e limitado pelo volume mínimo/máximo.
As ordens de stop protetora rastreiam a posição usando o canal de saída Donchian mais um buffer ATR para evitar a rotatividade excessiva de ordens.
Regras do Desafio da Prop Firm
Use Challenge Rules permite verificações de desafio.
A negociação é interrompida quando Pass Criteria patrimônio é alcançado. Todas as ordens são canceladas e a posição fechada.
Rebaixamentos diários maiores que Daily Loss Limit acionam uma liquidação completa e desativam novos pedidos pelo restante da sessão. O patrimônio de referência é zerado no início de cada dia de negociação.
Parâmetros
Nome
Descrição
Entry Period
Lookback do canal de breakout Donchian.
Entry Shift
Número de velas finalizadas ignoradas ao usar o canal de breakout.
Exit Period
Lookback do canal Donchian final.
Exit Shift
Número de velas concluídas ignoradas para trailing stops.
Risk Per Trade %
Porcentagem do patrimônio do portfólio em relação ao risco em cada entrada.
ATR Period
Lookback para filtro ATR usado ao mover paradas.
Use Challenge Rules
Permite condições de desafio firmes.
Pass Criteria
Nível de patrimônio que interrompe negociações adicionais.
Daily Loss Limit
Rebaixamento diário permitido antes da interrupção da negociação.
Candle Type
Assinatura de vela usada para cálculos.
Notas
A estratégia requer uma conexão de portfólio para calcular tamanhos de posição baseados em risco e métricas de desafio.
Os pedidos são cancelados e reenviados em cada vela concluída para manter os preços de gatilho alinhados com os níveis Donchian mais recentes.
Os parâmetros padrão reproduzem o comportamento do consultor especialista MetaTrader original.
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Breakout strategy that recreates the MetaTrader "Prop Firm Helper" expert advisor.
/// Uses Donchian channel breakouts for entry signals with market orders.
/// </summary>
public class PropFirmHelperStrategy : Strategy
{
private readonly StrategyParam<int> _entryPeriod;
private readonly StrategyParam<int> _exitPeriod;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _signalCooldownBars;
private DonchianChannels _entryChannel;
private DonchianChannels _exitChannel;
private decimal _entryUpper;
private decimal _entryLower;
private decimal _exitLower;
private decimal _exitUpper;
private decimal _prevEntryUpper;
private decimal _prevEntryLower;
private bool _hasValues;
private decimal _entryPrice;
private int _cooldownRemaining;
/// <summary>
/// Initializes a new instance of <see cref="PropFirmHelperStrategy"/>.
/// </summary>
public PropFirmHelperStrategy()
{
_entryPeriod = Param(nameof(EntryPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("Entry Period", "Number of candles used for breakout Donchian channel", "Entries");
_exitPeriod = Param(nameof(ExitPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("Exit Period", "Number of candles used for trailing Donchian channel", "Exits");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Timeframe used for Donchian calculations", "General");
_signalCooldownBars = Param(nameof(SignalCooldownBars), 4)
.SetNotNegative()
.SetDisplay("Signal Cooldown Bars", "Closed candles to wait before a new breakout entry", "General");
}
/// <summary>
/// Donchian breakout lookback length.
/// </summary>
public int EntryPeriod
{
get => _entryPeriod.Value;
set => _entryPeriod.Value = value;
}
/// <summary>
/// Donchian trailing lookback length.
/// </summary>
public int ExitPeriod
{
get => _exitPeriod.Value;
set => _exitPeriod.Value = value;
}
/// <summary>
/// Candle type used for indicator subscriptions.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int SignalCooldownBars
{
get => _signalCooldownBars.Value;
set => _signalCooldownBars.Value = value;
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_entryChannel = null;
_exitChannel = null;
_entryUpper = 0m;
_entryLower = 0m;
_exitLower = 0m;
_exitUpper = 0m;
_prevEntryUpper = 0m;
_prevEntryLower = 0m;
_hasValues = false;
_entryPrice = 0m;
_cooldownRemaining = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasValues = false;
_cooldownRemaining = 0;
_entryChannel = new DonchianChannels { Length = EntryPeriod };
_exitChannel = new DonchianChannels { Length = ExitPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _entryChannel);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
if (_cooldownRemaining > 0)
_cooldownRemaining--;
var entryValue = _entryChannel.Process(new CandleIndicatorValue(_entryChannel, candle));
var exitValue = _exitChannel.Process(new CandleIndicatorValue(_exitChannel, candle));
if (!_entryChannel.IsFormed || !_exitChannel.IsFormed)
return;
if (entryValue is not DonchianChannelsValue entryBands || exitValue is not DonchianChannelsValue exitBands)
return;
if (entryBands.UpperBand is not decimal entryUpper || entryBands.LowerBand is not decimal entryLower)
return;
if (exitBands.UpperBand is not decimal exitUpper || exitBands.LowerBand is not decimal exitLower)
return;
_prevEntryUpper = _entryUpper;
_prevEntryLower = _entryLower;
_entryUpper = entryUpper;
_entryLower = entryLower;
_exitUpper = exitUpper;
_exitLower = exitLower;
if (!_hasValues)
{
_hasValues = true;
return;
}
if (!IsFormedAndOnlineAndAllowTrading())
return;
ProcessSignal(candle);
}
private void ProcessSignal(ICandleMessage candle)
{
var close = candle.ClosePrice;
// Exit logic
if (Position > 0 && close < _exitLower)
{
SellMarket(Position);
_cooldownRemaining = SignalCooldownBars;
return;
}
else if (Position < 0 && close > _exitUpper)
{
BuyMarket(-Position);
_cooldownRemaining = SignalCooldownBars;
return;
}
// Entry logic - breakout above previous entry channel upper
if (_cooldownRemaining == 0 && _prevEntryUpper > 0 && close > _prevEntryUpper && Position <= 0)
{
BuyMarket(Volume + (Position < 0 ? -Position : 0m));
_entryPrice = close;
_cooldownRemaining = SignalCooldownBars;
}
else if (_cooldownRemaining == 0 && _prevEntryLower > 0 && close < _prevEntryLower && Position >= 0)
{
SellMarket(Volume + (Position > 0 ? Position : 0m));
_entryPrice = close;
_cooldownRemaining = SignalCooldownBars;
}
}
}