La estrategia de comercio diario más sencilla jamás creada
Descripción general
Conversión del MetaTrader 4 asesor experto "El más fácil de todos: robot de comercio diario" al API de alto nivel de StockSharp.
Diseñado para operaciones intradía simples: cada sesión abre como máximo una posición de mercado que sigue la dirección de la vela diaria anterior.
Utiliza únicamente datos de velas, sin indicadores técnicos ni osciladores. Toda la gestión de órdenes se realiza mediante órdenes de mercado.
Lógica de trading
Recopile velas diarias (DailyCandleType, predeterminado TimeSpan.FromDays(1)) y almacene los precios de apertura y cierre del último día completo.
Suscríbase a velas intradía (IntradayCandleType, predeterminado TimeSpan.FromMinutes(1)) para impulsar la ejecución.
Durante las primeras horas de la sesión (mientras la hora de apertura de la vela es estrictamente inferior a EntryHourLimit, por defecto 1):
Si el cierre diario anterior está por encima de la apertura diaria anterior, ingrese una posición larga usando BuyMarket(TradeVolume).
Si el cierre diario anterior está por debajo de la apertura diaria anterior, ingrese una posición corta usando SellMarket(TradeVolume).
Si la vela diaria cerró plana (apertura es igual a cierre), no se abre ninguna operación.
Mantenga la posición durante todo el día. Cuando la hora de la vela intradiaria sea mayor o igual a MarketCloseHour (predeterminado 20), cierre cualquier exposición abierta con una orden de mercado (SellMarket para largos, BuyMarket para cortos).
La estrategia sólo abre una nueva posición cuando no existe ninguna posición activa, lo que garantiza una operación por día como máximo.
Parámetros
Parámetro
Descripción
Predeterminado
TradeVolume
Volumen de pedidos tanto para entradas largas como cortas. Debe ser positivo.
1
EntryHourLimit
Última hora (exclusiva) en la que se puede iniciar una nueva operación. Los valores fuera de [0, 23] se fijan mediante validación.
1
MarketCloseHour
Hora en la que la estrategia cierra con fuerza cualquier posición abierta. Aplica diariamente.
20
IntradayCandleType
Marco de tiempo utilizado para la lógica de ejecución comercial y la gestión de posiciones.
TimeSpan.FromMinutes(1).TimeFrame()
DailyCandleType
Marco de tiempo utilizado para leer los precios de apertura y cierre del día anterior.
TimeSpan.FromMinutes(5).TimeFrame()
Todos los parámetros se registran a través de Param() y se pueden optimizar en el optimizador StockSharp.
Gestión del riesgo
La estrategia no utiliza niveles de stop-loss o take-profit; El riesgo está controlado por la salida diaria en MarketCloseHour.
StartProtection() está habilitado al inicio para protegerse contra posiciones inesperadas no planas durante la negociación.
Debido a que solo puede haber una posición activa por día, la exposición máxima está definida por TradeVolume.
Notas de uso
Ejecute la estrategia en instrumentos que proporcionen historiales de velas tanto intradía como diarias. La configuración predeterminada requiere velas minuciosas y diarias.
Alinee EntryHourLimit y MarketCloseHour con la sesión de negociación del instrumento seleccionado.
El algoritmo espera la hora local del intercambio en las marcas de tiempo de las velas; ajustar las fuentes de datos en consecuencia.
La lógica refleja el asesor experto MQL original, lo que permite replicar el comportamiento dentro del entorno StockSharp sin componentes de Python.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Easiest Ever Daytrade: EMA trend following with ATR stops.
/// </summary>
public class EasiestEverDaytradeStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaLength;
private readonly StrategyParam<int> _atrLength;
private decimal _prevClose;
private decimal _entryPrice;
public EasiestEverDaytradeStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(8).TimeFrame())
.SetDisplay("Candle Type", "Timeframe.", "General");
_emaLength = Param(nameof(EmaLength), 20)
.SetDisplay("EMA Length", "Trend filter.", "Indicators");
_atrLength = Param(nameof(AtrLength), 14)
.SetDisplay("ATR Length", "ATR period.", "Indicators");
}
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int EmaLength { get => _emaLength.Value; set => _emaLength.Value = value; }
public int AtrLength { get => _atrLength.Value; set => _atrLength.Value = value; }
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevClose = 0; _entryPrice = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevClose = 0; _entryPrice = 0;
var ema = new ExponentialMovingAverage { Length = EmaLength };
var atr = new AverageTrueRange { Length = AtrLength };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ema, atr, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, ema); DrawOwnTrades(area); }
}
private void ProcessCandle(ICandleMessage candle, decimal emaVal, decimal atrVal)
{
if (candle.State != CandleStates.Finished) return;
var close = candle.ClosePrice;
if (_prevClose == 0 || atrVal <= 0) { _prevClose = close; return; }
if (Position > 0)
{
if (close >= _entryPrice + atrVal * 2.5m || close <= _entryPrice - atrVal * 1.5m || close < emaVal) { SellMarket(); _entryPrice = 0; }
}
else if (Position < 0)
{
if (close <= _entryPrice - atrVal * 2.5m || close >= _entryPrice + atrVal * 1.5m || close > emaVal) { BuyMarket(); _entryPrice = 0; }
}
if (Position == 0)
{
if (close > emaVal && _prevClose <= emaVal) { _entryPrice = close; BuyMarket(); }
else if (close < emaVal && _prevClose >= emaVal) { _entryPrice = close; SellMarket(); }
}
_prevClose = close;
}
}
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 DataType, CandleStates
from StockSharp.Algo.Strategies import Strategy
from StockSharp.Algo.Indicators import ExponentialMovingAverage, AverageTrueRange
class easiest_ever_daytrade_strategy(Strategy):
def __init__(self):
super(easiest_ever_daytrade_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(8))) \
.SetDisplay("Candle Type", "Timeframe.", "General")
self._ema_length = self.Param("EmaLength", 20) \
.SetDisplay("EMA Length", "Trend filter.", "Indicators")
self._atr_length = self.Param("AtrLength", 14) \
.SetDisplay("ATR Length", "ATR period.", "Indicators")
self._prev_close = 0.0
self._entry_price = 0.0
@property
def CandleType(self):
return self._candle_type.Value
@property
def EmaLength(self):
return self._ema_length.Value
@property
def AtrLength(self):
return self._atr_length.Value
def OnStarted2(self, time):
super(easiest_ever_daytrade_strategy, self).OnStarted2(time)
self._prev_close = 0.0
self._entry_price = 0.0
self._ema = ExponentialMovingAverage()
self._ema.Length = self.EmaLength
self._atr = AverageTrueRange()
self._atr.Length = self.AtrLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._ema, self._atr, self.ProcessCandle).Start()
def ProcessCandle(self, candle, ema_val, atr_val):
if candle.State != CandleStates.Finished:
return
ev = float(ema_val)
av = float(atr_val)
close = float(candle.ClosePrice)
if self._prev_close == 0 or av <= 0:
self._prev_close = close
return
if self.Position > 0:
if close >= self._entry_price + av * 2.5 or close <= self._entry_price - av * 1.5 or close < ev:
self.SellMarket()
self._entry_price = 0.0
elif self.Position < 0:
if close <= self._entry_price - av * 2.5 or close >= self._entry_price + av * 1.5 or close > ev:
self.BuyMarket()
self._entry_price = 0.0
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_close = close
return
if self.Position == 0:
if close > ev and self._prev_close <= ev:
self._entry_price = close
self.BuyMarket()
elif close < ev and self._prev_close >= ev:
self._entry_price = close
self.SellMarket()
self._prev_close = close
def OnReseted(self):
super(easiest_ever_daytrade_strategy, self).OnReseted()
self._prev_close = 0.0
self._entry_price = 0.0
def CreateClone(self):
return easiest_ever_daytrade_strategy()