在 GitHub 上查看

机器学习 SuperTrend 止盈止损

基于 SuperTrend 指标,并设置跟踪止盈与止损的策略。

止盈与止损随 SuperTrend 线移动,尝试抓住趋势同时在动能减弱时锁定利润。

详情

  • 入场条件: 价格穿越 SuperTrend 线。
  • 多空方向: 双向。
  • 退出条件: 相反信号或触发跟踪止盈/止损。
  • 止损: 是,依据 SuperTrend 跟踪。
  • 默认值:
    • AtrPeriod = 4
    • AtrFactor = 2.94m
    • StopLossMultiplier = 0.0025m
    • TakeProfitMultiplier = 0.022m
    • CandleType = TimeSpan.FromMinutes(5)
  • 过滤器:
    • 类型: 趋势
    • 方向: 双向
    • 指标: ATR, SuperTrend
    • 止损: 是
    • 复杂度: 中等
    • 时间框架: 日内 (5m)
    • 季节性: 无
    • 神经网络: 无
    • 背离: 无
    • 风险等级: 中等
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>
	/// SuperTrend strategy with trailing take profit and stop loss.
	/// </summary>
	public class MachineLearningSuperTrendStrategy : Strategy
	{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _atrPeriod;
	private readonly StrategyParam<decimal> _atrFactor;
	private readonly StrategyParam<decimal> _stopLossMultiplier;
	private readonly StrategyParam<decimal> _takeProfitMultiplier;
	private readonly StrategyParam<int> _cooldownBars;
	
	private SuperTrend _superTrend;
	private int _prevDirection;
	private decimal _stopLoss;
	private decimal _takeProfit;
	private int _barsFromSignal;
	
	/// <summary>
	/// Candle type for strategy calculation.
	/// </summary>
	public DataType CandleType
	{
	get => _candleType.Value;
	set => _candleType.Value = value;
	}
	
	/// <summary>
	/// ATR period for SuperTrend calculation.
	/// </summary>
	public int AtrPeriod
	{
	get => _atrPeriod.Value;
	set => _atrPeriod.Value = value;
	}
	
	/// <summary>
	/// ATR multiplier for SuperTrend.
	/// </summary>
	public decimal AtrFactor
	{
	get => _atrFactor.Value;
	set => _atrFactor.Value = value;
	}
	
	/// <summary>
	/// Stop loss multiplier relative to SuperTrend value.
	/// </summary>
	public decimal StopLossMultiplier
	{
	get => _stopLossMultiplier.Value;
	set => _stopLossMultiplier.Value = value;
	}
	
	/// <summary>
	/// Take profit multiplier relative to SuperTrend value.
	/// </summary>
	public decimal TakeProfitMultiplier
	{
	get => _takeProfitMultiplier.Value;
	set => _takeProfitMultiplier.Value = value;
	}

	/// <summary>
	/// Minimum bars between trade actions.
	/// </summary>
	public int CooldownBars
	{
		get => _cooldownBars.Value;
		set => _cooldownBars.Value = value;
	}
	
	/// <summary>
	/// Initialize strategy parameters.
	/// </summary>
	public MachineLearningSuperTrendStrategy()
	{
	_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(10).TimeFrame())
	.SetDisplay("Candle Type", "Type of candles to use", "General");
	
	_atrPeriod = Param(nameof(AtrPeriod), 4)
	.SetGreaterThanZero()
	.SetDisplay("ATR Period", "ATR length for SuperTrend", "SuperTrend")
	
	.SetOptimize(3, 20, 1);
	
	_atrFactor = Param(nameof(AtrFactor), 2.94m)
	.SetRange(0.5m, 10m)
	.SetDisplay("Multiplier", "ATR multiplier for SuperTrend", "SuperTrend")
	
	.SetOptimize(1m, 5m, 0.5m);
	
	_stopLossMultiplier = Param(nameof(StopLossMultiplier), 0.01m)
	.SetRange(0m, 0.05m)
	.SetDisplay("Stop Loss Mult", "Percentage from SuperTrend", "Risk Management");
	
	_takeProfitMultiplier = Param(nameof(TakeProfitMultiplier), 0.03m)
	.SetRange(0m, 0.1m)
	.SetDisplay("Take Profit Mult", "Percentage from SuperTrend", "Risk Management");

	_cooldownBars = Param(nameof(CooldownBars), 8)
		.SetGreaterThanZero()
		.SetDisplay("Cooldown Bars", "Bars between trade actions", "Risk Management");
	}
	
	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
	return [(Security, CandleType)];
	}
	
	/// <inheritdoc />
	protected override void OnReseted()
	{
	base.OnReseted();
	_superTrend = null;
	_prevDirection = 0;
	_stopLoss = 0;
	_takeProfit = 0;
	_barsFromSignal = CooldownBars;
	}
	
	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
	base.OnStarted2(time);
	_barsFromSignal = CooldownBars;
	
	_superTrend = new SuperTrend
	{
	Length = AtrPeriod,
	Multiplier = AtrFactor
	};
	
	var dummyEma1 = new ExponentialMovingAverage { Length = 10 };
	var dummyEma2 = new ExponentialMovingAverage { Length = 20 };

	var subscription = SubscribeCandles(CandleType);
	subscription
	.Bind(dummyEma1, dummyEma2, ProcessCandle)
	.Start();
	
	var area = CreateChartArea();
	if (area != null)
	{
	DrawCandles(area, subscription);
	DrawIndicator(area, _superTrend);
	DrawOwnTrades(area);
	}
	}
	
	private void ProcessCandle(ICandleMessage candle, decimal d1, decimal d2)
	{
	if (candle.State != CandleStates.Finished)
	return;

	var stResult = _superTrend.Process(new CandleIndicatorValue(_superTrend, candle));
	if (!_superTrend.IsFormed || stResult.IsEmpty)
	return;

	var superTrendValue = stResult.GetValue<decimal>();
	var direction = candle.ClosePrice > superTrendValue ? 1 : -1;
	var directionChanged = _prevDirection != 0 && direction != _prevDirection;
	_barsFromSignal++;
	var canTradeNow = _barsFromSignal >= CooldownBars;
	
	_stopLoss = direction == 1
	? superTrendValue - superTrendValue * StopLossMultiplier
	: superTrendValue + superTrendValue * StopLossMultiplier;
	
	_takeProfit = direction == 1
	? superTrendValue + superTrendValue * TakeProfitMultiplier
	: superTrendValue - superTrendValue * TakeProfitMultiplier;
	
	if (canTradeNow && directionChanged)
	{
	if (direction == 1 && Position <= 0)
	BuyMarket();
	else if (direction == -1 && Position >= 0)
	SellMarket();
	_barsFromSignal = 0;
	}
	
	if (canTradeNow && Position > 0)
	{
	if (candle.ClosePrice <= _stopLoss || candle.ClosePrice >= _takeProfit)
	{
	SellMarket();
	_barsFromSignal = 0;
	}
	}
	else if (canTradeNow && Position < 0)
	{
	if (candle.ClosePrice >= _stopLoss || candle.ClosePrice <= _takeProfit)
	{
	BuyMarket();
	_barsFromSignal = 0;
	}
	}
	
	_prevDirection = direction;
	}
	}