Parabolic SAR 早期買い・MA ベース決済戦略
この戦略はParabolic SARインジケーターを使用し、インジケーターが価格に対して側面を切り替えたときに取引に入ります。単純移動平均が追加のエグジットルールを提供します。SARが価格の上にある状態で価格が移動平均を下回ったとき、ロングポジションを決済します。
詳細
- エントリー条件: SARが価格に対して側面を切り替える。
- ロング/ショート: 両方。
- エグジット条件: ロングポジションの場合、SAR > 価格かつ価格 < MAのとき決済。
- ストップ: 未定義。
- デフォルト値:
Acceleration= 0.02AccelerationStep= 0.02MaxAcceleration= 0.2MaPeriod= 11CandleType= 5分
- フィルター:
- カテゴリ: トレンドフォロー
- 方向: 両方
- インジケーター: Parabolic SAR, SMA
- ストップ: なし
- 複雑さ: 基本
- 時間軸: イントラデイ
- 季節性: なし
- ニューラルネットワーク: なし
- ダイバージェンス: なし
- リスクレベル: 中
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 early buy with moving average exit.
/// A close crossing above the Parabolic SAR goes long and a close crossing below it goes short, reversing an opposite position.
/// A long is also closed early when the SAR is above the close and the close is below the MaPeriod simple moving average.
/// </summary>
public class ParabolicSarEarlyBuyMaBasedExitStrategy : Strategy
{
private readonly StrategyParam<decimal> _acceleration;
private readonly StrategyParam<decimal> _accelerationStep;
private readonly StrategyParam<decimal> _maxAcceleration;
private readonly StrategyParam<int> _maPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal? _prevClose;
private decimal? _prevSar;
/// <summary>
/// Initial SAR acceleration factor.
/// </summary>
public decimal Acceleration
{
get => _acceleration.Value;
set => _acceleration.Value = value;
}
/// <summary>
/// SAR acceleration factor increment.
/// </summary>
public decimal AccelerationStep
{
get => _accelerationStep.Value;
set => _accelerationStep.Value = value;
}
/// <summary>
/// Maximum SAR acceleration factor.
/// </summary>
public decimal MaxAcceleration
{
get => _maxAcceleration.Value;
set => _maxAcceleration.Value = value;
}
/// <summary>
/// Period of the exit moving average.
/// </summary>
public int MaPeriod
{
get => _maPeriod.Value;
set => _maPeriod.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public ParabolicSarEarlyBuyMaBasedExitStrategy()
{
_acceleration = Param(nameof(Acceleration), 0.02m)
.SetGreaterThanZero()
.SetDisplay("Acceleration", "Initial SAR acceleration factor", "Indicators");
_accelerationStep = Param(nameof(AccelerationStep), 0.02m)
.SetGreaterThanZero()
.SetDisplay("Acceleration Step", "SAR acceleration factor increment", "Indicators");
_maxAcceleration = Param(nameof(MaxAcceleration), 0.2m)
.SetGreaterThanZero()
.SetDisplay("Max Acceleration", "Maximum SAR acceleration factor", "Indicators");
_maPeriod = Param(nameof(MaPeriod), 11)
.SetGreaterThanZero()
.SetDisplay("MA Period", "Period of the exit moving average", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).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();
_prevClose = null;
_prevSar = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevClose = null;
_prevSar = null;
var sar = new ParabolicSar
{
Acceleration = this.Acceleration,
AccelerationStep = this.AccelerationStep,
AccelerationMax = MaxAcceleration
};
var ma = new SimpleMovingAverage { Length = MaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(sar, ma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, sar);
DrawIndicator(area, ma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal sar, decimal ma)
{
if (candle.State != CandleStates.Finished)
return;
var close = candle.ClosePrice;
var prevClose = _prevClose;
var prevSar = _prevSar;
_prevClose = close;
_prevSar = sar;
if (prevClose is not decimal pc || prevSar is not decimal ps)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var crossUp = pc <= ps && close > sar;
var crossDown = pc >= ps && close < sar;
if (crossUp && Position <= 0)
BuyMarket(Volume + Math.Abs(Position));
else if (crossDown && Position >= 0)
SellMarket(Volume + Math.Abs(Position));
else if (Position > 0 && sar > close && close < ma)
SellMarket(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, Decimal
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ParabolicSar, SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class parabolic_sar_early_buy_ma_based_exit_strategy(Strategy):
"""
Parabolic SAR early buy with moving average exit.
A close crossing above the Parabolic SAR goes long and a close crossing below it goes short, reversing an opposite position.
A long is also closed early when the SAR is above the close and the close is below the MaPeriod simple moving average.
"""
def __init__(self):
super(parabolic_sar_early_buy_ma_based_exit_strategy, self).__init__()
self._acceleration = self.Param("Acceleration", 0.02).SetGreaterThanZero().SetDisplay("Acceleration", "Initial SAR acceleration factor", "Indicators")
self._acceleration_step = self.Param("AccelerationStep", 0.02).SetGreaterThanZero().SetDisplay("Acceleration Step", "SAR acceleration factor increment", "Indicators")
self._max_acceleration = self.Param("MaxAcceleration", 0.2).SetGreaterThanZero().SetDisplay("Max Acceleration", "Maximum SAR acceleration factor", "Indicators")
self._ma_period = self.Param("MaPeriod", 11).SetGreaterThanZero().SetDisplay("MA Period", "Period of the exit moving average", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._prev_close = None
self._prev_sar = None
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(parabolic_sar_early_buy_ma_based_exit_strategy, self).OnReseted()
self._prev_close = None
self._prev_sar = None
def OnStarted2(self, time):
super(parabolic_sar_early_buy_ma_based_exit_strategy, self).OnStarted2(time)
self._prev_close = None
self._prev_sar = None
sar = ParabolicSar()
sar.Acceleration = Decimal(self._acceleration.Value)
sar.AccelerationStep = Decimal(self._acceleration_step.Value)
sar.AccelerationMax = Decimal(self._max_acceleration.Value)
ma = SimpleMovingAverage()
ma.Length = self._ma_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(sar, ma, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, sar)
self.DrawIndicator(area, ma)
self.DrawOwnTrades(area)
def _process_candle(self, candle, sar, ma):
if candle.State != CandleStates.Finished:
return
close = candle.ClosePrice
prev_close = self._prev_close
prev_sar = self._prev_sar
self._prev_close = close
self._prev_sar = sar
if prev_close is None or prev_sar is None:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
cross_up = prev_close <= prev_sar and close > sar
cross_down = prev_close >= prev_sar and close < sar
if cross_up and self.Position <= 0:
self.BuyMarket(self.Volume + abs(self.Position))
elif cross_down and self.Position >= 0:
self.SellMarket(self.Volume + abs(self.Position))
elif self.Position > 0 and sar > close and close < ma:
self.SellMarket(self.Position)
def CreateClone(self):
return parabolic_sar_early_buy_ma_based_exit_strategy()