Estrategia de Ejecución Instantánea
Esta estrategia entra inmediatamente en una única posición en la primera vela completada y la gestiona con reglas simples de beneficio y riesgo. La dirección de la posición es seleccionable mediante parámetros. Una vez que se abre una operación, el algoritmo rastrea el beneficio y la pérdida y puede seguir el precio para proteger las ganancias.
La lógica reproduce el comportamiento del script MQL original que permitía la ejecución instantánea de órdenes de mercado con valores opcionales de take profit, stop loss y trailing stop.
Detalles
- Criterios de entrada: abre una posición de mercado en la primera vela finalizada tras el inicio. La dirección está definida por el parámetro
Direction.
- Largo/Corto: Ambos lados soportados.
- Criterios de salida:
- Take profit alcanzado.
- Stop loss alcanzado.
- Trailing stop activado y el precio alcanza el nivel de trailing.
- Stops: Están disponibles take profit, stop loss y trailing stop.
- Valores predeterminados:
TakeProfit = 70 unidades de precio.
StopLoss = 0 (deshabilitado).
TrailingStart = 5 unidades de precio.
TrailingSize = 5 unidades de precio.
- Filtros:
- Categoría: Utilidad
- Dirección: Ambos
- Indicadores: Ninguno
- Stops: Sí
- Complejidad: Simple
- Marco temporal: Cualquiera
- Estacionalidad: No
- Redes neuronales: No
- Divergencia: No
- Nivel de riesgo: Medio
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>
/// Strategy that opens a position based on EMA direction and manages it with
/// take profit, stop loss and trailing stop rules.
/// </summary>
public class InstantExecutionStrategy : Strategy
{
private readonly StrategyParam<decimal> _takeProfitPct;
private readonly StrategyParam<decimal> _stopLossPct;
private readonly StrategyParam<int> _emaPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal? _prevEma;
public decimal TakeProfitPct
{
get => _takeProfitPct.Value;
set => _takeProfitPct.Value = value;
}
public decimal StopLossPct
{
get => _stopLossPct.Value;
set => _stopLossPct.Value = value;
}
public int EmaPeriod
{
get => _emaPeriod.Value;
set => _emaPeriod.Value = value;
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public InstantExecutionStrategy()
{
_takeProfitPct = Param(nameof(TakeProfitPct), 3m)
.SetDisplay("Take Profit %", "Take profit percentage", "Risk");
_stopLossPct = Param(nameof(StopLossPct), 2m)
.SetDisplay("Stop Loss %", "Stop loss percentage", "Risk");
_emaPeriod = Param(nameof(EmaPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("EMA Period", "EMA trend filter period", "Indicator");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(8).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevEma = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ema, (candle, emaValue) =>
{
if (candle.State != CandleStates.Finished)
return;
if (_prevEma.HasValue)
{
var rising = emaValue > _prevEma.Value;
var falling = emaValue < _prevEma.Value;
if (rising && candle.ClosePrice > emaValue && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (falling && candle.ClosePrice < emaValue && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
}
_prevEma = emaValue;
}).Start();
StartProtection(
takeProfit: new Unit(TakeProfitPct, UnitTypes.Percent),
stopLoss: new Unit(StopLossPct, UnitTypes.Percent),
isStopTrailing: true,
useMarketOrders: true);
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ema);
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 DataType, CandleStates, Unit, UnitTypes
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class instant_execution_strategy(Strategy):
def __init__(self):
super(instant_execution_strategy, self).__init__()
self._take_profit_pct = self.Param("TakeProfitPct", 3.0) \
.SetDisplay("Take Profit %", "Take profit percentage", "Risk")
self._stop_loss_pct = self.Param("StopLossPct", 2.0) \
.SetDisplay("Stop Loss %", "Stop loss percentage", "Risk")
self._ema_period = self.Param("EmaPeriod", 20) \
.SetDisplay("EMA Period", "EMA trend filter period", "Indicator")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(8))) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._prev_ema = None
@property
def take_profit_pct(self):
return self._take_profit_pct.Value
@property
def stop_loss_pct(self):
return self._stop_loss_pct.Value
@property
def ema_period(self):
return self._ema_period.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(instant_execution_strategy, self).OnReseted()
self._prev_ema = None
def OnStarted2(self, time):
super(instant_execution_strategy, self).OnStarted2(time)
ema = ExponentialMovingAverage()
ema.Length = self.ema_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(ema, self.process_candle).Start()
self.StartProtection(
takeProfit=Unit(self.take_profit_pct, UnitTypes.Percent),
stopLoss=Unit(self.stop_loss_pct, UnitTypes.Percent),
isStopTrailing=True,
useMarketOrders=True)
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema)
self.DrawOwnTrades(area)
def process_candle(self, candle, ema_value):
if candle.State != CandleStates.Finished:
return
ema_value = float(ema_value)
if self._prev_ema is not None:
rising = ema_value > self._prev_ema
falling = ema_value < self._prev_ema
if rising and float(candle.ClosePrice) > ema_value and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif falling and float(candle.ClosePrice) < ema_value and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_ema = ema_value
def CreateClone(self):
return instant_execution_strategy()