Supertrend 反转策略
Supertrend 指标结合 ATR 和价格生成跟随式支撑/阻力。当该线从价格上方翻到下方或相反时,可能预示趋势转换。本策略交易这种翻转。
测试表明年均收益约为 151%,该策略在股票市场表现最佳。
每根K线根据 ATR 计算更新 Supertrend 水平。当指标从价格上方转至下方时做多;从下方转至上方时做空。示例代码未设置明确止损,因此离场需手动或由其他风险模块控制。
由于该指标对波动反应较快,交易者常配合其他过滤器减少假信号。
细节
- 入场条件:Supertrend 相对于价格翻转。
- 多/空:双向。
- 退出条件:手动或外部止损。
- 止损:未定义。
- 默认值:
Period= 10Multiplier= 3.0CandleType= 15 分钟
- 过滤条件:
- 类别: 趋势跟随
- 方向: 双向
- 指标: Supertrend
- 止损: 可选
- 复杂度: 基础
- 时间框架: 日内
- 季节性: 无
- 神经网络: 无
- 背离: 无
- 风险级别: 中等
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 Reversal strategy.
/// Uses the built-in SuperTrend indicator.
/// Enters long when SuperTrend flips to uptrend (below price).
/// Enters short when SuperTrend flips to downtrend (above price).
/// Uses cooldown to control trade frequency.
/// </summary>
public class SupertrendReversalStrategy : Strategy
{
private readonly StrategyParam<int> _period;
private readonly StrategyParam<decimal> _multiplier;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _cooldownBars;
private bool? _prevIsUpTrend;
private int _cooldown;
/// <summary>
/// ATR period for SuperTrend.
/// </summary>
public int Period
{
get => _period.Value;
set => _period.Value = value;
}
/// <summary>
/// ATR multiplier for SuperTrend.
/// </summary>
public decimal Multiplier
{
get => _multiplier.Value;
set => _multiplier.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Cooldown bars.
/// </summary>
public int CooldownBars
{
get => _cooldownBars.Value;
set => _cooldownBars.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public SupertrendReversalStrategy()
{
_period = Param(nameof(Period), 10)
.SetRange(7, 20)
.SetDisplay("Period", "ATR period for SuperTrend", "SuperTrend");
_multiplier = Param(nameof(Multiplier), 3.0m)
.SetRange(2.0m, 4.0m)
.SetDisplay("Multiplier", "ATR multiplier for SuperTrend", "SuperTrend");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
_cooldownBars = Param(nameof(CooldownBars), 500)
.SetRange(1, 1000)
.SetDisplay("Cooldown Bars", "Bars to wait between trades", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevIsUpTrend = null;
_cooldown = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevIsUpTrend = null;
_cooldown = 0;
var superTrend = new SuperTrend
{
Length = Period,
Multiplier = Multiplier
};
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(superTrend, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, superTrend);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue stValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!stValue.IsFormed)
return;
var stTyped = (SuperTrendIndicatorValue)stValue;
var isUpTrend = stTyped.IsUpTrend;
if (_prevIsUpTrend == null)
{
_prevIsUpTrend = isUpTrend;
return;
}
if (_cooldown > 0)
{
_cooldown--;
_prevIsUpTrend = isUpTrend;
return;
}
// SuperTrend flipped to uptrend = bullish
var flippedUp = _prevIsUpTrend == false && isUpTrend;
// SuperTrend flipped to downtrend = bearish
var flippedDown = _prevIsUpTrend == true && !isUpTrend;
if (Position == 0 && flippedUp)
{
BuyMarket();
_cooldown = CooldownBars;
}
else if (Position == 0 && flippedDown)
{
SellMarket();
_cooldown = CooldownBars;
}
else if (Position > 0 && flippedDown)
{
SellMarket();
_cooldown = CooldownBars;
}
else if (Position < 0 && flippedUp)
{
BuyMarket();
_cooldown = CooldownBars;
}
_prevIsUpTrend = isUpTrend;
}
}
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 SuperTrend
from StockSharp.Algo.Strategies import Strategy
class supertrend_reversal_strategy(Strategy):
"""
Supertrend Reversal strategy.
Enters long when SuperTrend flips to uptrend (below price).
Enters short when SuperTrend flips to downtrend (above price).
Uses cooldown to control trade frequency.
"""
def __init__(self):
super(supertrend_reversal_strategy, self).__init__()
self._period = self.Param("Period", 10).SetDisplay("Period", "ATR period for SuperTrend", "SuperTrend")
self._multiplier = self.Param("Multiplier", 3.0).SetDisplay("Multiplier", "ATR multiplier for SuperTrend", "SuperTrend")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(1))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._cooldown_bars = self.Param("CooldownBars", 500).SetDisplay("Cooldown Bars", "Bars to wait between trades", "General")
self._prev_is_up_trend = None
self._cooldown = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(supertrend_reversal_strategy, self).OnReseted()
self._prev_is_up_trend = None
self._cooldown = 0
def OnStarted2(self, time):
super(supertrend_reversal_strategy, self).OnStarted2(time)
self._prev_is_up_trend = None
self._cooldown = 0
st = SuperTrend()
st.Length = self._period.Value
st.Multiplier = self._multiplier.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(st, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, st)
self.DrawOwnTrades(area)
def _process_candle(self, candle, st_iv):
if candle.State != CandleStates.Finished:
return
if not st_iv.IsFormed:
return
is_up_trend = st_iv.IsUpTrend
if self._prev_is_up_trend is None:
self._prev_is_up_trend = is_up_trend
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_is_up_trend = is_up_trend
return
cd = self._cooldown_bars.Value
# SuperTrend flipped to uptrend = bullish
flipped_up = self._prev_is_up_trend == False and is_up_trend
# SuperTrend flipped to downtrend = bearish
flipped_down = self._prev_is_up_trend == True and not is_up_trend
if self.Position == 0 and flipped_up:
self.BuyMarket()
self._cooldown = cd
elif self.Position == 0 and flipped_down:
self.SellMarket()
self._cooldown = cd
elif self.Position > 0 and flipped_down:
self.SellMarket()
self._cooldown = cd
elif self.Position < 0 and flipped_up:
self.BuyMarket()
self._cooldown = cd
self._prev_is_up_trend = is_up_trend
def CreateClone(self):
return supertrend_reversal_strategy()