MA PSAR ATRトレンド戦略
MA PSAR ATRトレンド戦略は、移動平均クロスオーバーと日足パラボリックSARフィルターを組み合わせます。価格が両方の平均の上方または下方に揃い、PSARが同意する場合にのみ取引を行います。ATRベースのストップがリスクを管理します。
このメソッドは、動的ストップを使用したトレンドフォローを求めるトレーダーに適しています。シグナルはデフォルトで5分足ローソク足で発動します。
詳細
- エントリー条件:
- ロング: 高速MA > 低速MA、終値 > 高速MA、安値 > 日足PSAR
- ショート: 高速MA < 低速MA、終値 < 高速MA、高値 < 日足PSAR
- ロング/ショート: 両方向。
- エグジット条件:
- ロング: トレンドが弱気に転じるか価格がATRストップを下回る
- ショート: トレンドが強気に転じるか価格がATRストップを上回る
- ストップ: はい、ATRベース。
- デフォルト値:
FastMaPeriod= 40SlowMaPeriod= 160SarStep= 0.02mSarMaxStep= 0.2mAtrPeriod= 14AtrMultiplierLong= 2mAtrMultiplierShort= 2mUsePsarFilter= trueCandleType= TimeSpan.FromMinutes(5)
- フィルター:
- カテゴリ: トレンド
- 方向: 両方
- インジケーター: MA, Parabolic SAR, ATR
- ストップ: はい
- 複雑さ: 中級
- 時間軸: イントラデイ
- 季節性: いいえ
- ニューラルネットワーク: いいえ
- ダイバージェンス: いいえ
- リスクレベル: 中
namespace StockSharp.Samples.Strategies;
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
/// <summary>
/// MA PSAR ATR Trend Strategy.
/// A long opens when Fast MA > Slow MA, the close is above the fast MA and the low is above the Parabolic SAR of the last
/// finished daily candle; a short mirrors this. UsePsarFilter switches the daily SAR condition off. Each entry gets a stop
/// AtrMultiplierLong or AtrMultiplierShort ATRs away; a position closes when the stop is hit or the fast MA crosses back
/// over the slow MA.
/// </summary>
public class MaPsarAtrTrendStrategy : Strategy
{
private readonly StrategyParam<int> _fastMaPeriod;
private readonly StrategyParam<int> _slowMaPeriod;
private readonly StrategyParam<decimal> _sarStep;
private readonly StrategyParam<decimal> _sarMaxStep;
private readonly StrategyParam<int> _atrPeriod;
private readonly StrategyParam<decimal> _atrMultiplierLong;
private readonly StrategyParam<decimal> _atrMultiplierShort;
private readonly StrategyParam<bool> _usePsarFilter;
private readonly StrategyParam<DataType> _candleType;
private decimal? _dailySar;
private decimal? _stopPrice;
/// <summary>
/// Fast MA period.
/// </summary>
public int FastMaPeriod
{
get => _fastMaPeriod.Value;
set => _fastMaPeriod.Value = value;
}
/// <summary>
/// Slow MA period.
/// </summary>
public int SlowMaPeriod
{
get => _slowMaPeriod.Value;
set => _slowMaPeriod.Value = value;
}
/// <summary>
/// Parabolic SAR acceleration step.
/// </summary>
public decimal SarStep
{
get => _sarStep.Value;
set => _sarStep.Value = value;
}
/// <summary>
/// Parabolic SAR maximum acceleration.
/// </summary>
public decimal SarMaxStep
{
get => _sarMaxStep.Value;
set => _sarMaxStep.Value = value;
}
/// <summary>
/// ATR period.
/// </summary>
public int AtrPeriod
{
get => _atrPeriod.Value;
set => _atrPeriod.Value = value;
}
/// <summary>
/// ATR multiplier of the long stop.
/// </summary>
public decimal AtrMultiplierLong
{
get => _atrMultiplierLong.Value;
set => _atrMultiplierLong.Value = value;
}
/// <summary>
/// ATR multiplier of the short stop.
/// </summary>
public decimal AtrMultiplierShort
{
get => _atrMultiplierShort.Value;
set => _atrMultiplierShort.Value = value;
}
/// <summary>
/// Require the daily Parabolic SAR to agree.
/// </summary>
public bool UsePsarFilter
{
get => _usePsarFilter.Value;
set => _usePsarFilter.Value = value;
}
/// <summary>
/// Candle type of the signals.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public MaPsarAtrTrendStrategy()
{
_fastMaPeriod = Param(nameof(FastMaPeriod), 40)
.SetGreaterThanZero()
.SetDisplay("Fast MA", "Fast MA period", "Indicators");
_slowMaPeriod = Param(nameof(SlowMaPeriod), 160)
.SetGreaterThanZero()
.SetDisplay("Slow MA", "Slow MA period", "Indicators");
_sarStep = Param(nameof(SarStep), 0.02m)
.SetGreaterThanZero()
.SetDisplay("SAR Step", "Parabolic SAR acceleration step", "PSAR");
_sarMaxStep = Param(nameof(SarMaxStep), 0.2m)
.SetGreaterThanZero()
.SetDisplay("SAR Max Step", "Parabolic SAR maximum acceleration", "PSAR");
_atrPeriod = Param(nameof(AtrPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("ATR Period", "ATR period", "Risk");
_atrMultiplierLong = Param(nameof(AtrMultiplierLong), 2m)
.SetGreaterThanZero()
.SetDisplay("ATR Multiplier Long", "ATR multiplier of the long stop", "Risk");
_atrMultiplierShort = Param(nameof(AtrMultiplierShort), 2m)
.SetGreaterThanZero()
.SetDisplay("ATR Multiplier Short", "ATR multiplier of the short stop", "Risk");
_usePsarFilter = Param(nameof(UsePsarFilter), true)
.SetDisplay("Use PSAR Filter", "Require the daily Parabolic SAR to agree", "PSAR");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle type of the signals", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType), (Security, TimeSpan.FromDays(1).TimeFrame())];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_dailySar = null;
_stopPrice = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_dailySar = null;
_stopPrice = null;
var fastMa = new ExponentialMovingAverage { Length = FastMaPeriod };
var slowMa = new ExponentialMovingAverage { Length = SlowMaPeriod };
var atr = new AverageTrueRange { Length = AtrPeriod };
var psar = new ParabolicSar { AccelerationStep = SarStep, AccelerationMax = SarMaxStep };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(fastMa, slowMa, atr, ProcessCandle)
.Start();
SubscribeCandles(TimeSpan.FromDays(1).TimeFrame())
.BindEx(psar, ProcessDailyCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fastMa);
DrawIndicator(area, slowMa);
DrawOwnTrades(area);
}
}
private void ProcessDailyCandle(ICandleMessage candle, IIndicatorValue psarValue)
{
if (candle.State != CandleStates.Finished || !psarValue.IsFormed)
return;
_dailySar = psarValue.GetValue<decimal>();
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue fastValue, IIndicatorValue slowValue, IIndicatorValue atrValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!fastValue.IsFormed || !slowValue.IsFormed || !atrValue.IsFormed)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var fast = fastValue.GetValue<decimal>();
var slow = slowValue.GetValue<decimal>();
var atr = atrValue.GetValue<decimal>();
var close = candle.ClosePrice;
if (Position > 0)
{
if (fast < slow || (_stopPrice is decimal stop && candle.LowPrice <= stop))
{
SellMarket(Position);
_stopPrice = null;
}
return;
}
if (Position < 0)
{
if (fast > slow || (_stopPrice is decimal stop && candle.HighPrice >= stop))
{
BuyMarket(-Position);
_stopPrice = null;
}
return;
}
if (UsePsarFilter && _dailySar is null)
return;
var longSar = !UsePsarFilter || candle.LowPrice > _dailySar;
var shortSar = !UsePsarFilter || candle.HighPrice < _dailySar;
if (fast > slow && close > fast && longSar)
{
BuyMarket(Volume);
_stopPrice = close - atr * AtrMultiplierLong;
}
else if (fast < slow && close < fast && shortSar)
{
SellMarket(Volume);
_stopPrice = close + atr * AtrMultiplierShort;
}
}
}
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 ExponentialMovingAverage, AverageTrueRange, ParabolicSar
from StockSharp.Algo.Strategies import Strategy
class ma_psar_atr_trend_strategy(Strategy):
"""
MA PSAR ATR Trend Strategy.
A long opens when Fast MA > Slow MA, the close is above the fast MA and the low is above the Parabolic SAR of the last
finished daily candle; a short mirrors this. UsePsarFilter switches the daily SAR condition off. Each entry gets a stop
AtrMultiplierLong or AtrMultiplierShort ATRs away; a position closes when the stop is hit or the fast MA crosses back
over the slow MA.
"""
def __init__(self):
super(ma_psar_atr_trend_strategy, self).__init__()
self._fast_ma_period = self.Param("FastMaPeriod", 40).SetGreaterThanZero().SetDisplay("Fast MA", "Fast MA period", "Indicators")
self._slow_ma_period = self.Param("SlowMaPeriod", 160).SetGreaterThanZero().SetDisplay("Slow MA", "Slow MA period", "Indicators")
self._sar_step = self.Param("SarStep", 0.02).SetGreaterThanZero().SetDisplay("SAR Step", "Parabolic SAR acceleration step", "PSAR")
self._sar_max_step = self.Param("SarMaxStep", 0.2).SetGreaterThanZero().SetDisplay("SAR Max Step", "Parabolic SAR maximum acceleration", "PSAR")
self._atr_period = self.Param("AtrPeriod", 14).SetGreaterThanZero().SetDisplay("ATR Period", "ATR period", "Risk")
self._atr_multiplier_long = self.Param("AtrMultiplierLong", 2.0).SetGreaterThanZero().SetDisplay("ATR Multiplier Long", "ATR multiplier of the long stop", "Risk")
self._atr_multiplier_short = self.Param("AtrMultiplierShort", 2.0).SetGreaterThanZero().SetDisplay("ATR Multiplier Short", "ATR multiplier of the short stop", "Risk")
self._use_psar_filter = self.Param("UsePsarFilter", True).SetDisplay("Use PSAR Filter", "Require the daily Parabolic SAR to agree", "PSAR")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Candle type of the signals", "General")
self._daily_sar = None
self._stop_price = None
@property
def candle_type(self):
return self._candle_type.Value
def GetWorkingSecurities(self):
return [(self.Security, self.candle_type), (self.Security, DataType.TimeFrame(TimeSpan.FromDays(1)))]
def OnReseted(self):
super(ma_psar_atr_trend_strategy, self).OnReseted()
self._daily_sar = None
self._stop_price = None
def OnStarted2(self, time):
super(ma_psar_atr_trend_strategy, self).OnStarted2(time)
self._daily_sar = None
self._stop_price = None
fast_ma = ExponentialMovingAverage()
fast_ma.Length = self._fast_ma_period.Value
slow_ma = ExponentialMovingAverage()
slow_ma.Length = self._slow_ma_period.Value
atr = AverageTrueRange()
atr.Length = self._atr_period.Value
psar = ParabolicSar()
psar.AccelerationStep = Decimal(float(self._sar_step.Value))
psar.AccelerationMax = Decimal(float(self._sar_max_step.Value))
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(fast_ma, slow_ma, atr, self._process_candle).Start()
self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromDays(1))).BindEx(psar, self._process_daily_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast_ma)
self.DrawIndicator(area, slow_ma)
self.DrawOwnTrades(area)
def _process_daily_candle(self, candle, psar_value):
if candle.State != CandleStates.Finished or not psar_value.IsFormed:
return
self._daily_sar = float(psar_value.GetValue[Decimal](None))
def _process_candle(self, candle, fast_value, slow_value, atr_value):
if candle.State != CandleStates.Finished:
return
if not fast_value.IsFormed or not slow_value.IsFormed or not atr_value.IsFormed:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
fast = float(fast_value.GetValue[Decimal](None))
slow = float(slow_value.GetValue[Decimal](None))
atr = float(atr_value.GetValue[Decimal](None))
close = float(candle.ClosePrice)
high = float(candle.HighPrice)
low = float(candle.LowPrice)
if self.Position > 0:
if fast < slow or (self._stop_price is not None and low <= self._stop_price):
self.SellMarket(self.Position)
self._stop_price = None
return
if self.Position < 0:
if fast > slow or (self._stop_price is not None and high >= self._stop_price):
self.BuyMarket(-self.Position)
self._stop_price = None
return
use_psar = self._use_psar_filter.Value
if use_psar and self._daily_sar is None:
return
long_sar = not use_psar or low > self._daily_sar
short_sar = not use_psar or high < self._daily_sar
if fast > slow and close > fast and long_sar:
self.BuyMarket(self.Volume)
self._stop_price = close - atr * float(self._atr_multiplier_long.Value)
elif fast < slow and close < fast and short_sar:
self.SellMarket(self.Volume)
self._stop_price = close + atr * float(self._atr_multiplier_short.Value)
def CreateClone(self):
return ma_psar_atr_trend_strategy()