Estrategia SAR Automatizada
Este ejemplo demuestra un enfoque de trading simple basado en el indicador Parabolic SAR. La estrategia abre una posición larga cuando el precio actual está por encima del valor SAR y abre una posición corta cuando el precio está por debajo del SAR. Las características adicionales de gestión de riesgos incluyen stop-loss fijo, take-profit y un trailing stop opcional.
Parámetros
SarStep– factor de aceleración para el cálculo del SAR.SarMax– factor de aceleración máximo para el SAR.StopLoss– distancia del stop-loss en unidades de precio.TakeProfit– distancia del take-profit en unidades de precio.TrailingStop– distancia del trailing stop en unidades de precio.CandleType– tipo de velas utilizadas para los cálculos del indicador.
Lógica de trading
- Suscribirse a las velas y calcular los valores del Parabolic SAR.
- Entrada:
- Ir largo cuando SAR esté por debajo del precio de cierre y no exista posición.
- Ir corto cuando SAR esté por encima del precio de cierre y no exista posición.
- Salida:
- Cerrar la posición cuando el precio alcance el nivel SAR opuesto.
- Aplicar las reglas de stop-loss, take-profit y trailing stop.
Esta estrategia está destinada a fines educativos y muestra cómo usar indicadores y controles de riesgo con la API de alto nivel de StockSharp.
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 Parabolic SAR based strategy with optional stop-loss,
/// take-profit and trailing stop management.
/// </summary>
public class SarAutomatedStrategy : Strategy
{
private readonly StrategyParam<decimal> _sarStep;
private readonly StrategyParam<decimal> _sarMax;
private readonly StrategyParam<decimal> _stopLoss;
private readonly StrategyParam<decimal> _takeProfit;
private readonly StrategyParam<decimal> _trailingStop;
private readonly StrategyParam<DataType> _candleType;
private decimal _entryPrice;
private decimal _highestPrice;
private decimal _lowestPrice;
/// <summary>
/// Parabolic SAR acceleration step.
/// </summary>
public decimal SarStep
{
get => _sarStep.Value;
set => _sarStep.Value = value;
}
/// <summary>
/// Parabolic SAR maximum acceleration.
/// </summary>
public decimal SarMax
{
get => _sarMax.Value;
set => _sarMax.Value = value;
}
/// <summary>
/// Stop loss in price units.
/// </summary>
public decimal StopLoss
{
get => _stopLoss.Value;
set => _stopLoss.Value = value;
}
/// <summary>
/// Take profit in price units.
/// </summary>
public decimal TakeProfit
{
get => _takeProfit.Value;
set => _takeProfit.Value = value;
}
/// <summary>
/// Trailing stop in price units.
/// </summary>
public decimal TrailingStop
{
get => _trailingStop.Value;
set => _trailingStop.Value = value;
}
/// <summary>
/// Candle type for calculations.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initialize <see cref="SarAutomatedStrategy"/>.
/// </summary>
public SarAutomatedStrategy()
{
_sarStep = Param(nameof(SarStep), 0.002m)
.SetDisplay("SAR Step", "Acceleration factor for SAR", "Indicators");
_sarMax = Param(nameof(SarMax), 0.02m)
.SetDisplay("SAR Max", "Maximum acceleration for SAR", "Indicators");
_stopLoss = Param(nameof(StopLoss), 3500m)
.SetDisplay("Stop Loss", "Stop loss in price units", "Risk Management");
_takeProfit = Param(nameof(TakeProfit), 6500m)
.SetDisplay("Take Profit", "Take profit in price units", "Risk Management");
_trailingStop = Param(nameof(TrailingStop), 800m)
.SetDisplay("Trailing Stop", "Trailing stop in price units", "Risk Management");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(8).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_entryPrice = 0m;
_highestPrice = 0m;
_lowestPrice = 0m;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var sar = new ParabolicSar
{
Acceleration = SarStep,
AccelerationMax = SarMax
};
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(sar, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, sar);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal sarValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (Position == 0)
{
if (sarValue < candle.ClosePrice)
{
BuyMarket();
_entryPrice = candle.ClosePrice;
_highestPrice = candle.ClosePrice;
_lowestPrice = candle.ClosePrice;
}
else if (sarValue > candle.ClosePrice)
{
SellMarket();
_entryPrice = candle.ClosePrice;
_highestPrice = candle.ClosePrice;
_lowestPrice = candle.ClosePrice;
}
}
else if (Position > 0)
{
_highestPrice = Math.Max(_highestPrice, candle.HighPrice);
if (candle.HighPrice - _entryPrice >= TakeProfit)
{
SellMarket();
return;
}
if (_entryPrice - candle.LowPrice >= StopLoss)
{
SellMarket();
return;
}
if (TrailingStop > 0m && _highestPrice - candle.ClosePrice >= TrailingStop)
{
SellMarket();
return;
}
if (sarValue > candle.ClosePrice)
{
SellMarket();
}
}
else if (Position < 0)
{
_lowestPrice = Math.Min(_lowestPrice, candle.LowPrice);
if (_entryPrice - candle.LowPrice >= TakeProfit)
{
BuyMarket();
return;
}
if (candle.HighPrice - _entryPrice >= StopLoss)
{
BuyMarket();
return;
}
if (TrailingStop > 0m && candle.ClosePrice - _lowestPrice >= TrailingStop)
{
BuyMarket();
return;
}
if (sarValue < candle.ClosePrice)
{
BuyMarket();
}
}
}
}
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 ParabolicSar
from StockSharp.Algo.Strategies import Strategy
class sar_automated_strategy(Strategy):
def __init__(self):
super(sar_automated_strategy, self).__init__()
self._sar_step = self.Param("SarStep", 0.002) \
.SetDisplay("SAR Step", "Acceleration factor for SAR", "Indicators")
self._sar_max = self.Param("SarMax", 0.02) \
.SetDisplay("SAR Max", "Maximum acceleration for SAR", "Indicators")
self._stop_loss = self.Param("StopLoss", 3500.0) \
.SetDisplay("Stop Loss", "Stop loss in price units", "Risk Management")
self._take_profit = self.Param("TakeProfit", 6500.0) \
.SetDisplay("Take Profit", "Take profit in price units", "Risk Management")
self._trailing_stop = self.Param("TrailingStop", 800.0) \
.SetDisplay("Trailing Stop", "Trailing stop in price units", "Risk Management")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(8))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._entry_price = 0.0
self._highest_price = 0.0
self._lowest_price = 0.0
@property
def sar_step(self):
return self._sar_step.Value
@property
def sar_max(self):
return self._sar_max.Value
@property
def stop_loss(self):
return self._stop_loss.Value
@property
def take_profit(self):
return self._take_profit.Value
@property
def trailing_stop(self):
return self._trailing_stop.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(sar_automated_strategy, self).OnReseted()
self._entry_price = 0.0
self._highest_price = 0.0
self._lowest_price = 0.0
def OnStarted2(self, time):
super(sar_automated_strategy, self).OnStarted2(time)
sar = ParabolicSar()
sar.Acceleration = self.sar_step
sar.AccelerationMax = self.sar_max
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(sar, self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, sar)
self.DrawOwnTrades(area)
def process_candle(self, candle, sar_value):
if candle.State != CandleStates.Finished:
return
sar_value = float(sar_value)
close_price = float(candle.ClosePrice)
high_price = float(candle.HighPrice)
low_price = float(candle.LowPrice)
tp = float(self.take_profit)
sl = float(self.stop_loss)
ts = float(self.trailing_stop)
if self.Position == 0:
if sar_value < close_price:
self.BuyMarket()
self._entry_price = close_price
self._highest_price = close_price
self._lowest_price = close_price
elif sar_value > close_price:
self.SellMarket()
self._entry_price = close_price
self._highest_price = close_price
self._lowest_price = close_price
elif self.Position > 0:
self._highest_price = max(self._highest_price, high_price)
if high_price - self._entry_price >= tp:
self.SellMarket()
return
if self._entry_price - low_price >= sl:
self.SellMarket()
return
if ts > 0 and self._highest_price - close_price >= ts:
self.SellMarket()
return
if sar_value > close_price:
self.SellMarket()
elif self.Position < 0:
self._lowest_price = min(self._lowest_price, low_price)
if self._entry_price - low_price >= tp:
self.BuyMarket()
return
if high_price - self._entry_price >= sl:
self.BuyMarket()
return
if ts > 0 and close_price - self._lowest_price >= ts:
self.BuyMarket()
return
if sar_value < close_price:
self.BuyMarket()
def CreateClone(self):
return sar_automated_strategy()