A WPR Custom Cloud Simple Strategy é uma versão StockSharp do MetaTrader consultor especialista WPR Custom Cloud Simple.mq5. O EA monitora o oscilador %R de Larry Williams e abre negociações quando o indicador sai do território de sobrevenda ou sobrecompra. Esta versão C# mantém o design original de negociação apenas em novas velas, revertendo a posição quando um sinal oposto aparece e evita quaisquer ordens de stop-loss ou take-profit exatamente como a implementação de referência.
Lógica de negociação
Assine o período configurado (CandleType) e alimente um indicador WilliamsR com as velas recebidas.
Espere até que a vela acabe; a estratégia nunca atua em barras incompletas.
Armazene os dois últimos valores %R concluídos. Eles espelham as leituras wpr[1] e wpr[2] de MetaTrader.
Gere sinais em cruzamentos:
Configuração longa: a barra anterior fecha acima de OversoldLevel enquanto a barra anterior estava abaixo do nível. Isso recria a condição de "saída de sobrevenda" (wpr[2] < level e wpr[1] > level) do EA.
Configuração curta: a barra anterior fecha abaixo de OverboughtLevel enquanto a barra anterior estava acima dela, correspondendo à verificação original wpr[2] > level e wpr[1] < level.
Quando uma configuração longa aparecer, nivele qualquer exposição curta e compre um volume líquido. Quando uma configuração curta for acionada, alise o lado comprado e venda um volume líquido. Como StockSharp funciona com posições líquidas, enviar BuyMarket/SellMarket com Volume + |Position| replica perfeitamente o fluxo de fechamento e reversão da conta de hedge de MetaTrader.
Nenhuma saída adicional é usada; um novo cruzamento oposto é a única maneira de fechar negociações, assim como no consultor original.
Parâmetros
Nome
Tipo
Padrão
MetaTrader contraparte
Descrição
WprPeriod
int
14
Inp_WPR_Period
Comprimento de lookback para o cálculo de Williams %R.
OverboughtLevel
decimal
-20
Inp_WPR_Level1
Limite que define o território de sobrecompra. Cruzar abaixo desencadeia shorts.
OversoldLevel
decimal
-80
Inp_WPR_Level2
Limite que define o território de sobrevenda. Cruzar acima desencadeia compras.
CandleType
DataType
Período de 1 hora
InpWorkingPeriod
Série de velas usada para atualizar o indicador e avaliar sinais.
Volume
decimal
Volume base da estratégia
InpLots
Tamanho do lote para ordens de mercado. A estratégia compensa automaticamente a posição líquida atual antes de abrir uma nova negociação.
Diferenças do original EA
StockSharp opera com posições líquidas. O fechamento da exposição oposta é feito aumentando o volume de ordens de mercado, de forma que o comportamento corresponda ao modelo de hedge sem estruturas contábeis extras como STRUCT_POSITION.
Todas as classes auxiliares de gerenciamento de pedidos (CTrade, CPositionInfo, verificações de margem, etc.) são substituídas pelos controles de risco integrados do StockSharp. A estratégia depende de Strategy.Volume e dos metadados da exchange em vez de cálculos manuais de margem livre.
O registro é simplificado. A versão StockSharp evita instruções Print detalhadas porque o API de alto nível já fornece atualizações de status do pedido.
As ordens de proteção são omitidas intencionalmente para refletir o design de "fechamento no sinal oposto" da fonte EA.
Dicas de uso
Ajuste CandleType para o mesmo período de tempo usado em MetaTrader para manter a frequência de cruzamento comparável.
Williams %R limites são valores negativos. Mover OverboughtLevel para mais perto de zero torna as entradas curtas mais raras, enquanto empurrar OversoldLevel em direção a -100 torna as entradas longas mais raras.
A estratégia assume que Volume já está alinhado com o passo mínimo e as regras de compensação do corretor. Ajuste o volume base na interface do usuário ou por meio de código antes de iniciar a negociação ao vivo.
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Williams %R cloud breakout strategy converted from the MetaTrader expert advisor.
/// Looks for %R crossings above -80 to go long and below -20 to go short.
/// Positions are reversed when an opposite signal appears.
/// </summary>
public class WprCustomCloudSimpleStrategy : Strategy
{
private readonly StrategyParam<int> _wprPeriod;
private readonly StrategyParam<decimal> _overboughtLevel;
private readonly StrategyParam<decimal> _oversoldLevel;
private readonly StrategyParam<DataType> _candleType;
private WilliamsR _williamsR;
private decimal? _previousWpr;
private decimal? _olderWpr;
public int WprPeriod
{
get => _wprPeriod.Value;
set => _wprPeriod.Value = value;
}
public decimal OverboughtLevel
{
get => _overboughtLevel.Value;
set => _overboughtLevel.Value = value;
}
public decimal OversoldLevel
{
get => _oversoldLevel.Value;
set => _oversoldLevel.Value = value;
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public WprCustomCloudSimpleStrategy()
{
_wprPeriod = Param(nameof(WprPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("WPR Period", "Williams %R lookback length", "Williams %R");
_overboughtLevel = Param(nameof(OverboughtLevel), -10m)
.SetDisplay("Overbought Level", "%R level that marks overbought conditions", "Williams %R");
_oversoldLevel = Param(nameof(OversoldLevel), -90m)
.SetDisplay("Oversold Level", "%R level that marks oversold conditions", "Williams %R");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Timeframe used for Williams %R", "Data");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_williamsR = new WilliamsR { Length = WprPeriod };
_previousWpr = null;
_olderWpr = null;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_williamsR, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _williamsR);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal wprValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!_williamsR.IsFormed)
{
_olderWpr = _previousWpr;
_previousWpr = wprValue;
return;
}
if (_previousWpr is not null && _olderWpr is not null)
{
var prev = _previousWpr.Value;
var prevPrev = _olderWpr.Value;
var crossedAboveOversold = prevPrev < OversoldLevel && prev > OversoldLevel;
var crossedBelowOverbought = prevPrev > OverboughtLevel && prev < OverboughtLevel;
var volume = Volume;
if (volume <= 0)
volume = 1;
if (crossedAboveOversold)
{
if (Position <= 0)
BuyMarket(Position < 0 ? Math.Abs(Position) + volume : volume);
}
else if (crossedBelowOverbought)
{
if (Position >= 0)
SellMarket(Position > 0 ? Math.Abs(Position) + volume : volume);
}
}
_olderWpr = _previousWpr;
_previousWpr = wprValue;
}
/// <inheritdoc />
protected override void OnReseted()
{
_williamsR = null;
_previousWpr = null;
_olderWpr = null;
base.OnReseted();
}
}