Estrategia Simple XAUUSD con 20 de Beneficio y 100 de Pérdida
Esta estrategia abre una posición larga cuando no hay posición abierta y ambos temporizadores de enfriamiento están inactivos. Cierra la posición cuando el beneficio no realizado alcanza $20 o la pérdida llega a $100. Después de una salida rentable, la estrategia espera 15 minutos antes de volver a entrar, y después de una salida con pérdida espera 12 horas.
Parámetros
ProfitTarget– objetivo de beneficio en USD.LossLimit– pérdida máxima en USD.TradeCooldown– tiempo de espera tras una pérdida.EntryCooldown– tiempo de espera tras un beneficio.CandleType– marco temporal de velas.
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Simple XAUUSD strategy with fixed profit and loss targets.
/// Buys and holds until hitting percent-based TP or SL, then waits cooldown.
/// </summary>
public class XauusdSimple20Profit100LossStrategy : Strategy
{
private readonly StrategyParam<decimal> _tpPct;
private readonly StrategyParam<decimal> _slPct;
private readonly StrategyParam<int> _cooldownBars;
private readonly StrategyParam<DataType> _candleType;
private int _barsSinceExit;
private decimal _entryPrice;
public decimal TpPct { get => _tpPct.Value; set => _tpPct.Value = value; }
public decimal SlPct { get => _slPct.Value; set => _slPct.Value = value; }
public int CooldownBars { get => _cooldownBars.Value; set => _cooldownBars.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public XauusdSimple20Profit100LossStrategy()
{
_tpPct = Param(nameof(TpPct), 0.3m)
.SetGreaterThanZero()
.SetDisplay("TP %", "Take profit percent", "Risk");
_slPct = Param(nameof(SlPct), 1.5m)
.SetGreaterThanZero()
.SetDisplay("SL %", "Stop loss percent", "Risk");
_cooldownBars = Param(nameof(CooldownBars), 100)
.SetGreaterThanZero()
.SetDisplay("Cooldown", "Bars between trades", "Risk");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
protected override void OnReseted()
{
base.OnReseted();
_barsSinceExit = 100;
_entryPrice = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var sma = new SimpleMovingAverage { Length = 10 };
_barsSinceExit = 100;
_entryPrice = 0;
var subscription = SubscribeCandles(CandleType);
subscription.Bind(sma, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal _dummy)
{
if (candle.State != CandleStates.Finished)
return;
_barsSinceExit++;
if (Position == 0 && _barsSinceExit >= CooldownBars)
{
BuyMarket();
_entryPrice = candle.ClosePrice;
return;
}
if (Position > 0 && _entryPrice > 0)
{
var tp = _entryPrice * (1 + TpPct / 100m);
var sl = _entryPrice * (1 - SlPct / 100m);
if (candle.ClosePrice >= tp || candle.ClosePrice <= sl)
{
SellMarket();
_barsSinceExit = 0;
_entryPrice = 0;
}
}
}
}
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 xauusd_simple20_profit100_loss_strategy(Strategy):
def __init__(self):
super(xauusd_simple20_profit100_loss_strategy, self).__init__()
self._tp_pct = self.Param("TpPct", 0.3) \
.SetDisplay("TP %", "Take profit percent", "Risk")
self._sl_pct = self.Param("SlPct", 1.5) \
.SetDisplay("SL %", "Stop loss percent", "Risk")
self._cooldown_bars = self.Param("CooldownBars", 100) \
.SetDisplay("Cooldown", "Bars between trades", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._bars_since_exit = 0
self._entry_price = 0.0
@property
def tp_pct(self):
return self._tp_pct.Value
@property
def sl_pct(self):
return self._sl_pct.Value
@property
def cooldown_bars(self):
return self._cooldown_bars.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(xauusd_simple20_profit100_loss_strategy, self).OnReseted()
self._bars_since_exit = 0
self._entry_price = 0.0
def OnStarted2(self, time):
super(xauusd_simple20_profit100_loss_strategy, self).OnStarted2(time)
sma = SimpleMovingAverage()
sma.Length = 10
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, _dummy):
if candle.State != CandleStates.Finished:
return
self._bars_since_exit += 1
if self.Position == 0 and self._bars_since_exit >= self.cooldown_bars:
self.BuyMarket()
self._entry_price = candle.ClosePrice
return
if self.Position > 0 and self._entry_price > 0:
tp = self._entry_price * (1 + self.tp_pct / 100)
sl = self._entry_price * (1 - self.sl_pct / 100)
if candle.ClosePrice >= tp or candle.ClosePrice <= sl:
self.SellMarket()
self._bars_since_exit = 0
self._entry_price = 0
def CreateClone(self):
return xauusd_simple20_profit100_loss_strategy()