Parabolic SAR リバーサルストラテジー
Parabolic SARインジケーターはトレンドの方向を示すために価格の上または下にドットを配置します。ドットが反対側に移動するとき、それは前の動きの終わりを示す可能性があります。この戦略はその転換でトレードに入り、短期的なリバーサルを期待します。
テストでは年平均リターン約148%を示しています。外国為替市場で最も優れたパフォーマンスを発揮します。
各ローソク足に対してParabolic SARの継続的な値が維持されます。インジケーターが価格の上から下に移動すると、ロングポジションが開かれます。下から上に転換すると、ショートトレードが実行されます。この方法は明示的な利益目標を使用せず、通常はサンプルコード外の裁量的な決済やトレーリングストップに依存します。
SARは素早く反応するため、レンジ相場では誤ったシグナルが発生することがあり、価格が決定的な動きをするときに使用するのが最も適しています。
詳細
- エントリー条件: Parabolic SARが価格に対して側面を変える。
- ロング/ショート: 両方。
- エグジット条件: 手動または外部ストップ。
- ストップ: 未定義。
- デフォルト値:
InitialAcceleration= 0.02MaxAcceleration= 0.2CandleType= 15 minute
- フィルター:
- カテゴリ: トレンドフォロー
- 方向: 両方
- インジケーター: Parabolic SAR
- ストップ: オプション
- 複雑さ: 基本
- 時間軸: イントラデイ
- 季節性: いいえ
- ニューラルネットワーク: いいえ
- ダイバージェンス: いいえ
- リスクレベル: 中
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>
/// Parabolic SAR Reversal strategy.
/// When the SAR moves from above the close to below it the position turns long, and when it moves from below to above it turns short.
/// There is no other exit.
/// </summary>
public class ParabolicSarReversalStrategy : Strategy
{
private readonly StrategyParam<decimal> _initialAcceleration;
private readonly StrategyParam<decimal> _maxAcceleration;
private readonly StrategyParam<DataType> _candleType;
private bool? _prevSarAbove;
/// <summary>
/// Initial acceleration factor of the SAR.
/// </summary>
public decimal InitialAcceleration
{
get => _initialAcceleration.Value;
set => _initialAcceleration.Value = value;
}
/// <summary>
/// Maximum acceleration factor of the SAR.
/// </summary>
public decimal MaxAcceleration
{
get => _maxAcceleration.Value;
set => _maxAcceleration.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public ParabolicSarReversalStrategy()
{
_initialAcceleration = Param(nameof(InitialAcceleration), 0.02m)
.SetGreaterThanZero()
.SetDisplay("Initial Acceleration", "Initial acceleration factor of the SAR", "Indicators");
_maxAcceleration = Param(nameof(MaxAcceleration), 0.2m)
.SetGreaterThanZero()
.SetDisplay("Max Acceleration", "Maximum acceleration factor of the SAR", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).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();
_prevSarAbove = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevSarAbove = null;
var sar = new ParabolicSar
{
Acceleration = InitialAcceleration,
AccelerationMax = MaxAcceleration,
};
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(sar, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, sar);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue sarValue)
{
if (candle.State != CandleStates.Finished || !sarValue.IsFormed || sarValue.IsEmpty)
return;
var sar = sarValue.GetValue<decimal>();
if (sar <= 0)
return;
var isSarAbove = sar > candle.ClosePrice;
var wasSarAbove = _prevSarAbove;
_prevSarAbove = isSarAbove;
if (wasSarAbove is not bool previous || previous == isSarAbove || !IsFormedAndOnlineAndAllowTrading())
return;
if (!isSarAbove && Position <= 0)
BuyMarket(Volume + Math.Abs(Position));
else if (isSarAbove && Position >= 0)
SellMarket(Volume + Math.Abs(Position));
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math, Decimal
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ParabolicSar
from StockSharp.Algo.Strategies import Strategy
class parabolic_sar_reversal_strategy(Strategy):
"""
Parabolic SAR Reversal strategy.
When the SAR moves from above the close to below it the position turns long, and when it moves from below to above it turns short.
There is no other exit.
"""
def __init__(self):
super(parabolic_sar_reversal_strategy, self).__init__()
self._initial_acceleration = self.Param("InitialAcceleration", 0.02).SetGreaterThanZero().SetDisplay("Initial Acceleration", "Initial acceleration factor of the SAR", "Indicators")
self._max_acceleration = self.Param("MaxAcceleration", 0.2).SetGreaterThanZero().SetDisplay("Max Acceleration", "Maximum acceleration factor of the SAR", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(15))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._prev_sar_above = None
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(parabolic_sar_reversal_strategy, self).OnReseted()
self._prev_sar_above = None
def OnStarted2(self, time):
super(parabolic_sar_reversal_strategy, self).OnStarted2(time)
self._prev_sar_above = None
sar = ParabolicSar()
sar.Acceleration = Decimal(self._initial_acceleration.Value)
sar.AccelerationMax = Decimal(self._max_acceleration.Value)
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(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 or not sar_value.IsFormed or sar_value.IsEmpty:
return
sar = sar_value.GetValue[Decimal](None)
if sar <= 0:
return
is_sar_above = sar > candle.ClosePrice
was_sar_above = self._prev_sar_above
self._prev_sar_above = is_sar_above
if was_sar_above is None or was_sar_above == is_sar_above or not self.IsFormedAndOnlineAndAllowTrading():
return
if not is_sar_above and self.Position <= 0:
self.BuyMarket(self.Volume + Math.Abs(self.Position))
elif is_sar_above and self.Position >= 0:
self.SellMarket(self.Volume + Math.Abs(self.Position))
def CreateClone(self):
return parabolic_sar_reversal_strategy()