Esta estrategia porta la utilidad de MetaTrader 4 "Auto Trading Publish" a StockSharp. En lugar de enviar órdenes de mercado, se centra en controlar cuándo se permite operar. Supervisa el reloj de mercado mediante una suscripción de velas y cambia la bandera AutoTradingActive cuando se alcanza la hora configurada de inicio o parada. La bandera replica el comportamiento de la utilidad original, que alternaba programáticamente el botón "AutoTrading" de MT4.
Lógica de negociación
Suscribirse a un flujo ligero de velas (por defecto, velas de un minuto) para seguir la hora de mercado incluso si no se realizan operaciones.
Cuando una vela terminada informa la StartHour configurada, activar AutoTradingActive y registrar el evento.
Cuando una vela terminada informa la StopHour configurada, desactivar AutoTradingActive y registrar el evento.
Suprimir alternancias duplicadas dentro de la misma hora para que el log no se sature si llegan varias velas o ticks durante esa hora.
Parámetros
Parámetro
Descripción
StartHour
Hora del día (0-23) que activa el trading automático.
StopHour
Hora del día (0-23) que desactiva el trading automático.
CandleType
Marco temporal usado para consultar el reloj de mercado. Marcos menores reaccionan más rápido.
Notas de uso
La estrategia no envía órdenes; solo expone la propiedad AutoTradingActive, que otras estrategias o paneles pueden observar para decidir cuándo enviar operaciones.
Cuando la hora de inicio y parada son iguales, el evento de parada se ejecuta después del inicio, dejando el trading desactivado, idéntico al asesor experto original.
Elija un marco de velas que coincida con la rapidez requerida para el cambio. Un marco de un minuto ofrece buen equilibrio entre respuesta y uso de recursos.
Diferencias frente a MetaTrader
MT4 alternaba un botón global de plataforma mediante mensajes de Windows. StockSharp expone en cambio una bandera a nivel de estrategia, facilitando la integración con configuraciones complejas.
El port StockSharp se ejecuta íntegramente dentro de la API de alto nivel, lo que facilita combinarlo con gráficos u otras estrategias auxiliares sin hooks de mensajes de bajo nivel.
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Auto Trading Publish strategy: SMA crossover + RSI confirmation.
/// Buys when close crosses above SMA and RSI is below 40.
/// Sells when close crosses below SMA and RSI is above 60.
/// </summary>
public class AutoTradingPublishStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _smaPeriod;
private readonly StrategyParam<int> _rsiPeriod;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int SmaPeriod
{
get => _smaPeriod.Value;
set => _smaPeriod.Value = value;
}
public int RsiPeriod
{
get => _rsiPeriod.Value;
set => _rsiPeriod.Value = value;
}
public AutoTradingPublishStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_smaPeriod = Param(nameof(SmaPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("SMA Period", "SMA period", "Indicators");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI period", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var sma = new SimpleMovingAverage { Length = SmaPeriod };
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
decimal? prevClose = null;
decimal? prevSma = null;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(sma, rsi, (candle, smaVal, rsiVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var close = candle.ClosePrice;
if (prevClose.HasValue && prevSma.HasValue)
{
var crossUp = prevClose.Value <= prevSma.Value && close > smaVal;
var crossDown = prevClose.Value >= prevSma.Value && close < smaVal;
if (crossUp && rsiVal < 55m && Position <= 0)
BuyMarket();
else if (crossDown && rsiVal > 45m && Position >= 0)
SellMarket();
}
prevClose = close;
prevSma = smaVal;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, sma);
DrawOwnTrades(area);
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import CandleStates
from StockSharp.Algo.Indicators import SimpleMovingAverage, RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
from datatype_extensions import *
class auto_trading_publish_strategy(Strategy):
"""
Auto Trading Publish strategy: SMA crossover + RSI confirmation.
Buys when close crosses above SMA and RSI is below 55.
Sells when close crosses below SMA and RSI is above 45.
"""
def __init__(self):
super(auto_trading_publish_strategy, self).__init__()
self._candle_type = self.Param("CandleType", tf(15)) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._sma_period = self.Param("SmaPeriod", 20) \
.SetGreaterThanZero() \
.SetDisplay("SMA Period", "SMA period", "Indicators")
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetGreaterThanZero() \
.SetDisplay("RSI Period", "RSI period", "Indicators")
self._prev_close = None
self._prev_sma = None
@property
def CandleType(self): return self._candle_type.Value
@CandleType.setter
def CandleType(self, v): self._candle_type.Value = v
@property
def SmaPeriod(self): return self._sma_period.Value
@SmaPeriod.setter
def SmaPeriod(self, v): self._sma_period.Value = v
@property
def RsiPeriod(self): return self._rsi_period.Value
@RsiPeriod.setter
def RsiPeriod(self, v): self._rsi_period.Value = v
def OnReseted(self):
super(auto_trading_publish_strategy, self).OnReseted()
self._prev_close = None
self._prev_sma = None
def OnStarted2(self, time):
super(auto_trading_publish_strategy, self).OnStarted2(time)
self._prev_close = None
self._prev_sma = None
sma = SimpleMovingAverage()
sma.Length = self.SmaPeriod
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(sma, rsi, self.ProcessCandle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, sma)
self.DrawOwnTrades(area)
def ProcessCandle(self, candle, sma_val, rsi_val):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
if self._prev_close is not None and self._prev_sma is not None:
cross_up = self._prev_close <= self._prev_sma and close > sma_val
cross_down = self._prev_close >= self._prev_sma and close < sma_val
if cross_up and rsi_val < 55 and self.Position <= 0:
self.BuyMarket()
elif cross_down and rsi_val > 45 and self.Position >= 0:
self.SellMarket()
self._prev_close = close
self._prev_sma = sma_val
def CreateClone(self):
"""!! REQUIRED!! Creates a new instance of the strategy."""
return auto_trading_publish_strategy()