La estrategia Line Order es una traducción del script MQL4 "LineOrder" (10715). La estrategia abre una posición cuando el precio de mercado alcanza una línea de entrada predefinida y luego gestiona la posición con stop-loss, take-profit y un trailing stop opcional.
Parámetros
Entry Price – nivel de precio que activa una posición.
Stop Loss (pips) – distancia desde la entrada hasta el stop loss inicial.
Take Profit (pips) – distancia desde la entrada hasta el take profit.
Trailing Stop (pips) – distancia opcional del trailing stop. Cuando se establece en cero, el trailing se desactiva.
Candle Type – tipo de velas utilizadas para el procesamiento.
Lógica de Operación
La estrategia se suscribe a la serie de velas seleccionada.
Cuando una vela completada cierra por encima del precio de entrada, se abre una posición larga. Cuando cierra por debajo del precio de entrada, se abre una posición corta.
Tras la entrada, los niveles de stop-loss y take-profit se calculan usando el paso de precio del instrumento.
Si el trailing stop está habilitado, el nivel del stop se mueve en la dirección del trade.
La posición se cierra cuando el precio alcanza el nivel de stop-loss o take-profit.
Esta es una adaptación simplificada del script MQL original, enfocada en la ejecución automatizada de órdenes en una línea definida por el usuario.
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Line order strategy that enters when price crosses a predefined level.
/// Uses SMA as the dynamic entry line.
/// </summary>
public class LineOrderSingleEntryStrategy : Strategy
{
private readonly StrategyParam<int> _smaLength;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevClose;
private decimal _prevSma;
private bool _hasPrev;
public int SmaLength { get => _smaLength.Value; set => _smaLength.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public LineOrderSingleEntryStrategy()
{
_smaLength = Param(nameof(SmaLength), 20)
.SetGreaterThanZero()
.SetDisplay("SMA Length", "Moving average period", "Parameters");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_prevClose = 0;
_prevSma = 0;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var sma = new SimpleMovingAverage { Length = SmaLength };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(sma, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal smaValue)
{
if (candle.State != CandleStates.Finished)
return;
var close = candle.ClosePrice;
if (_hasPrev)
{
// Cross above SMA
if (_prevClose <= _prevSma && close > smaValue && Position <= 0)
{
BuyMarket();
}
// Cross below SMA
else if (_prevClose >= _prevSma && close < smaValue && Position >= 0)
{
SellMarket();
}
}
_prevClose = close;
_prevSma = smaValue;
_hasPrev = true;
}
}
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.Indicators import SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class line_order_single_entry_strategy(Strategy):
def __init__(self):
super(line_order_single_entry_strategy, self).__init__()
self._sma_length = self.Param("SmaLength", 20) \
.SetDisplay("SMA Length", "Moving average period", "Parameters")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._prev_close = 0.0
self._prev_sma = 0.0
self._has_prev = False
@property
def sma_length(self):
return self._sma_length.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(line_order_single_entry_strategy, self).OnReseted()
self._prev_close = 0.0
self._prev_sma = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(line_order_single_entry_strategy, self).OnStarted2(time)
sma = SimpleMovingAverage()
sma.Length = self.sma_length
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(sma, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def on_process(self, candle, sma_value):
if candle.State != CandleStates.Finished:
return
close = candle.ClosePrice
if self._has_prev:
# Cross above SMA
if self._prev_close <= self._prev_sma and close > sma_value and self.Position <= 0:
self.BuyMarket()
# Cross below SMA
elif self._prev_close >= self._prev_sma and close < sma_value and self.Position >= 0:
self.SellMarket()
self._prev_close = close
self._prev_sma = sma_value
self._has_prev = True
def CreateClone(self):
return line_order_single_entry_strategy()