A TradePad Sample Strategy é uma versão do exemplo MetaTrader "TradePad". O consultor especialista original apresentou uma grade de
botões que exibiam a tendência de curto prazo para vários símbolos, colorindo cada célula com o oscilador Stochastic atual
lendo. Esta implementação StockSharp mantém o núcleo analítico da amostra e se concentra no monitoramento de uma lista de instrumentos
sem replicar a interface do usuário na carta. A estratégia assina dados de velas para cada símbolo configurado, calcula um
Stochastic oscilador e classifica cada instrumento em estados Uptrend, Downtrend ou Flat. Cada vez que a classe muda,
a estratégia grava uma mensagem de log semelhante à mudança de cor realizada pelo TradePad original.
A estratégia não faz pedidos. Seu objetivo é ajudar os traders discricionários a acompanhar vários mercados ao mesmo tempo e detectar
mudanças de impulso que exigem ações manuais (por exemplo, troca de gráficos ou preparação de negociações).
Como funciona
Descoberta de símbolos – o parâmetro SymbolList aceita uma lista de tickers separados por vírgula. Se nenhuma lista for fornecida, o
a estratégia recorre ao Security principal atribuído no executor.
Assinatura de vela – cada símbolo usa o mesmo período de tempo configurado por meio de CandleType.
Processamento de indicador – uma instância StochasticOscillator dedicada está vinculada ao fluxo de vela. Quando a vela estiver
concluído, o indicador produz o valor %K usado para classificação de tendência.
Classificação de tendência – uma leitura acima de UpperLevel mapeia para Tendência de alta, uma leitura abaixo de LowerLevel mapeia para Tendência de baixa,
tudo no meio é plano. O último valor do oscilador é armazenado em LatestKValues.
Intervalo de atualização – a estratégia imita o comportamento do temporizador do TradePad original. Uma alteração é registrada no máximo uma vez por
TimerPeriodSeconds para cada símbolo, mesmo que várias velas cheguem dentro do intervalo.
Parâmetros
Parâmetro
Descrição
SymbolList
Lista separada por vírgulas de instrumentos a serem monitorados. String vazia significa "usar a segurança principal".
TimerPeriodSeconds
Número mínimo de segundos entre atualizações de estado por símbolo. Evita spam de log quando as velas são muito curtas.
StochasticLength
Período de lookback usado para calcular a linha %K bruta.
StochasticKPeriod
Período de suavização aplicado à linha %K.
StochasticDPeriod
Período de suavização aplicado à linha %D (mantido para fins de integridade, embora a estratégia leia apenas %K).
UpperLevel
Limite acima do qual o símbolo é considerado em tendência de alta.
LowerLevel
Limite abaixo do qual o símbolo é considerado em tendência de baixa.
CandleType
Prazo das velas utilizadas para cálculo do indicador.
Notas de uso
Certifique-se de que os tickers especificados estejam disponíveis no conector; símbolos ausentes são relatados no log e ignorados.
A propriedade TrendStates expõe a classificação mais recente para painéis externos ou blocos do Designer.
Use a estratégia dentro do Designer ou Runner para anexar seus próprios recursos visuais (painéis, gráficos) que reagem ao AddInfoLog
mensagens ou os dicionários públicos.
Como nenhum pedido é enviado, a estratégia pode ser executada com segurança em provedores de dados ativos apenas para fins de monitoramento.
Comportamento MQL original vs. versão StockSharp
MQL5 Recurso
StockSharp Implementação
Grade gráfica de botões
Exposto como entradas de log e dicionários públicos para que a UI personalizada possa ser criada no Designer.
Botões manuais de COMPRA/VENDA
Não implementado; a estratégia permanece intencionalmente passiva.
Lógica de arrastar gráfico
Não aplicável em StockSharp e omitido.
Atualizações de cores de tendência
Substituído por mudanças de estado de tendência acionadas a cada TimerPeriodSeconds por símbolo.
Estendendo a Estratégia
Conecte o dicionário TrendStates aos widgets do Designer para reconstruir o bloco colorido usando controles XAML.
Adicione alertas ou notificações quando um símbolo transitar de Flat para Uptrend ou Downtrend.
Combine a classificação com a lógica do pedido se quiser automatizar as entradas após identificar um forte impulso.
namespace StockSharp.Samples.Strategies;
using System;
using StockSharp.Algo;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// TradePad Sample strategy.
/// Classifies market state using Stochastic oscillator and trades on state transitions.
/// Buys when stochastic crosses up from oversold, sells when it crosses down from overbought.
/// </summary>
public class TradePadSampleStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _stochasticKPeriod;
private readonly StrategyParam<int> _stochasticDPeriod;
private readonly StrategyParam<decimal> _upperLevel;
private readonly StrategyParam<decimal> _lowerLevel;
private decimal _prevK;
private bool _hasPrev;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int StochasticKPeriod { get => _stochasticKPeriod.Value; set => _stochasticKPeriod.Value = value; }
public int StochasticDPeriod { get => _stochasticDPeriod.Value; set => _stochasticDPeriod.Value = value; }
public decimal UpperLevel { get => _upperLevel.Value; set => _upperLevel.Value = value; }
public decimal LowerLevel { get => _lowerLevel.Value; set => _lowerLevel.Value = value; }
public TradePadSampleStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_stochasticKPeriod = Param(nameof(StochasticKPeriod), 10)
.SetDisplay("Stochastic %K", "%K period", "Indicators");
_stochasticDPeriod = Param(nameof(StochasticDPeriod), 3)
.SetDisplay("Stochastic %D", "%D period", "Indicators");
_upperLevel = Param(nameof(UpperLevel), 75m)
.SetDisplay("Upper Threshold", "Overbought level", "Signals");
_lowerLevel = Param(nameof(LowerLevel), 25m)
.SetDisplay("Lower Threshold", "Oversold level", "Signals");
}
/// <inheritdoc />
public override System.Collections.Generic.IEnumerable<(StockSharp.BusinessEntities.Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevK = 0;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var stochastic = new StochasticOscillator();
stochastic.K.Length = StochasticKPeriod;
stochastic.D.Length = StochasticDPeriod;
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(stochastic, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue stochVal)
{
if (candle.State != CandleStates.Finished)
return;
if (!stochVal.IsFinal || !stochVal.IsFormed)
return;
var stoch = (StochasticOscillatorValue)stochVal;
if (stoch.K is not decimal kValue)
return;
if (!_hasPrev)
{
_prevK = kValue;
_hasPrev = true;
return;
}
// Buy: stochastic crosses up through lower level (leaving oversold)
var crossUp = _prevK <= LowerLevel && kValue > LowerLevel;
// Sell: stochastic crosses down through upper level (leaving overbought)
var crossDown = _prevK >= UpperLevel && kValue < UpperLevel;
if (crossUp && Position <= 0)
{
BuyMarket();
}
else if (crossDown && Position >= 0)
{
SellMarket();
}
_prevK = kValue;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import StochasticOscillator
from StockSharp.Algo.Strategies import Strategy
class trade_pad_sample_strategy(Strategy):
"""Stochastic crossover strategy. Buys when %K crosses up from oversold, sells when it crosses down from overbought."""
def __init__(self):
super(trade_pad_sample_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._stochastic_k_period = self.Param("StochasticKPeriod", 10) \
.SetDisplay("Stochastic %K", "%K period", "Indicators")
self._stochastic_d_period = self.Param("StochasticDPeriod", 3) \
.SetDisplay("Stochastic %D", "%D period", "Indicators")
self._upper_level = self.Param("UpperLevel", 75.0) \
.SetDisplay("Upper Threshold", "Overbought level", "Signals")
self._lower_level = self.Param("LowerLevel", 25.0) \
.SetDisplay("Lower Threshold", "Oversold level", "Signals")
self._prev_k = 0.0
self._has_prev = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def StochasticKPeriod(self):
return self._stochastic_k_period.Value
@property
def StochasticDPeriod(self):
return self._stochastic_d_period.Value
@property
def UpperLevel(self):
return self._upper_level.Value
@property
def LowerLevel(self):
return self._lower_level.Value
def OnReseted(self):
super(trade_pad_sample_strategy, self).OnReseted()
self._prev_k = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(trade_pad_sample_strategy, self).OnStarted2(time)
self._has_prev = False
stochastic = StochasticOscillator()
stochastic.K.Length = self.StochasticKPeriod
stochastic.D.Length = self.StochasticDPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.BindEx(stochastic, self._process_candle).Start()
def _process_candle(self, candle, stoch_val):
if candle.State != CandleStates.Finished:
return
if not stoch_val.IsFinal or not stoch_val.IsFormed:
return
k_raw = stoch_val.K
if k_raw is None:
return
k_value = float(k_raw)
if not self._has_prev:
self._prev_k = k_value
self._has_prev = True
return
lower = float(self.LowerLevel)
upper = float(self.UpperLevel)
cross_up = self._prev_k <= lower and k_value > lower
cross_down = self._prev_k >= upper and k_value < upper
if cross_up and self.Position <= 0:
self.BuyMarket()
elif cross_down and self.Position >= 0:
self.SellMarket()
self._prev_k = k_value
def CreateClone(self):
return trade_pad_sample_strategy()