La Estrategia de muestra de TradePad es una adaptación del ejemplo MetaTrader "TradePad". El asesor experto original presentó una cuadrícula de
Botones que mostraban la tendencia a corto plazo para múltiples símbolos coloreando cada celda con el oscilador Stochastic actual.
leyendo. Esta implementación StockSharp mantiene el núcleo analítico de la muestra y se centra en monitorear una lista de instrumentos.
sin replicar la interfaz de usuario en el gráfico. La estrategia se suscribe a los datos de velas para cada símbolo configurado, calcula un
Stochastic oscilador y clasifica cada instrumento en estados Tendencia alcista, Tendencia bajista o Plano. Cada vez que cambia la clase,
la estrategia escribe un mensaje de registro similar al cambio de color realizado por el TradePad original.
La estrategia no realiza pedidos. Su objetivo es ayudar a los operadores discrecionales a realizar un seguimiento de varios mercados a la vez y detectar
cambios de impulso que requieren acciones manuales (por ejemplo, cambiar de gráfico o preparar operaciones).
Cómo funciona
Descubrimiento de símbolos: el parámetro SymbolList acepta una lista de tickers separados por comas. Si no se proporciona ninguna lista, el
La estrategia vuelve al Security principal asignado en el corredor.
Suscripción de vela: cada símbolo utiliza el mismo período de tiempo configurado a través de CandleType.
Procesamiento de indicadores: una instancia StochasticOscillator dedicada está vinculada al flujo de velas. Cuando la vela está
terminado, el indicador produce el valor %K utilizado para la clasificación de tendencias.
Clasificación de tendencias: una lectura por encima de UpperLevel se asigna a Tendencia alcista, una lectura por debajo de LowerLevel se asigna a Tendencia a la baja,
todo lo que hay en el medio es Plano. El último valor del oscilador se almacena en LatestKValues.
Intervalo de actualización: la estrategia imita el comportamiento del temporizador del TradePad original. Un cambio se registra como máximo una vez por
TimerPeriodSeconds para cada símbolo incluso si llegan varias velas dentro del intervalo.
Parámetros
Parámetro
Descripción
SymbolList
Lista separada por comas de instrumentos para monitorear. Una cadena vacía significa "usar la seguridad principal".
TimerPeriodSeconds
Número mínimo de segundos entre actualizaciones de estado por símbolo. Evita el spam de registros cuando las velas son muy cortas.
StochasticLength
Período retrospectivo utilizado para calcular la línea %K sin procesar.
StochasticKPeriod
Período de suavizado aplicado a la línea %K.
StochasticDPeriod
Período de suavizado aplicado a la línea %D (se mantiene para que esté completo, aunque la estrategia solo dice %K).
UpperLevel
Umbral por encima del cual se considera que el símbolo está en tendencia alcista.
LowerLevel
Umbral por debajo del cual se considera que el símbolo está en tendencia bajista.
CandleType
Periodo de tiempo de las velas utilizadas para el cálculo del indicador.
Notas de uso
Asegúrese de que los tickers especificados estén disponibles en el conector; Los símbolos faltantes se informan en el registro y se omiten.
La propiedad TrendStates expone la clasificación más reciente para paneles externos o bloques de Designer.
Utilice la estrategia dentro de Designer o Runner para adjuntar sus propios elementos visuales (paneles, gráficos) que reaccionen al AddInfoLog
mensajes o los diccionarios públicos.
Debido a que no se envían órdenes, es seguro ejecutar la estrategia en proveedores de datos en vivo únicamente con fines de monitoreo.
Comportamiento original de MQL frente a la versión StockSharp
MQL5 Característica
StockSharp Implementación
Cuadrícula gráfica de botones.
Expuestos como entradas de registro y diccionarios públicos para que se pueda crear una interfaz de usuario personalizada en Designer.
Botones manuales de COMPRAR/VENDER
No implementado; la estrategia permanece intencionalmente pasiva.
Lógica de arrastre de gráficos
No aplicable en StockSharp y omitido.
Actualizaciones de colores de tendencia
Reemplazado con cambios de estado de tendencia activados cada TimerPeriodSeconds por símbolo.
Ampliando la estrategia
Conecte el diccionario TrendStates a los widgets de Designer para reconstruir el panel de color mediante controles XAML.
Agregue alertas o notificaciones cuando un símbolo pase de Plano a Tendencia alcista o Tendencia bajista.
Combine la clasificación con la lógica de orden si desea automatizar las entradas después de identificar un fuerte 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()