FATL MACDトレンド戦略
この戦略はFATL MACDインジケーターに基づくトレンドフォローシステムを実装します。FATL(Fast Adaptive Trend Line)を価格から引くことでMACDに似たオシレーターを生成し、適応型移動平均でスムージングします。正の値は強気のモメンタムを示し、負の値は弱気のモメンタムを示します。
アルゴリズムは完成した各ローソク足でこのオシレーターの傾きを分析します。
- 前の値がその前の値より低い場合、オシレーターは上向きに転換しています。現在の値がさらに上昇すると、戦略はロングポジションを開き、ショートポジションを閉じます。
- 前の値がその前の値より高い場合、オシレーターは下向きに転換しています。現在の値がさらに下落すると、戦略はショートポジションを開き、ロングポジションを閉じます。
すべての主要パラメーターは設定可能です。
- Fast EMA – MACDの速い移動平均の期間(デフォルト12)。
- Slow EMA – MACDの遅い移動平均の期間(デフォルト26)。
- Signal EMA – MACDシグナルラインの期間(デフォルト9)。
- Candle Type – インジケーター計算に使用するローソク足シリーズ。
ポジションは成行注文で建てられ、反対シグナルが現れると決済されます。
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>
/// FATL MACD trend-following strategy.
/// Opens long positions when the indicator turns upward
/// and short positions when it turns downward.
/// </summary>
public class FatlMacdStrategy : Strategy
{
private readonly StrategyParam<int> _fastLength;
private readonly StrategyParam<int> _slowLength;
private readonly StrategyParam<DataType> _candleType;
private decimal _prev1;
private decimal _prev2;
private bool _isInitialized;
public int FastLength { get => _fastLength.Value; set => _fastLength.Value = value; }
public int SlowLength { get => _slowLength.Value; set => _slowLength.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public FatlMacdStrategy()
{
_fastLength = Param(nameof(FastLength), 12)
.SetDisplay("Fast EMA", "Period of the fast moving average", "MACD")
.SetGreaterThanZero();
_slowLength = Param(nameof(SlowLength), 26)
.SetDisplay("Slow EMA", "Period of the slow moving average", "MACD")
.SetGreaterThanZero();
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles for processing", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prev1 = default;
_prev2 = default;
_isInitialized = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var macd = new MovingAverageConvergenceDivergence
{
ShortMa = { Length = FastLength },
LongMa = { Length = SlowLength },
};
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(macd, Process)
.Start();
}
private void Process(ICandleMessage candle, decimal macdValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (!_isInitialized)
{
_prev2 = _prev1 = macdValue;
_isInitialized = true;
return;
}
// Indicator turned upward
if (_prev1 < _prev2)
{
if (Position < 0)
BuyMarket();
if (macdValue > _prev1 && Position <= 0)
BuyMarket();
}
// Indicator turned downward
else if (_prev1 > _prev2)
{
if (Position > 0)
SellMarket();
if (macdValue < _prev1 && Position >= 0)
SellMarket();
}
_prev2 = _prev1;
_prev1 = macdValue;
}
}
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 MovingAverageConvergenceDivergence
from StockSharp.Algo.Strategies import Strategy
class fatl_macd_strategy(Strategy):
def __init__(self):
super(fatl_macd_strategy, self).__init__()
self._fast_length = self.Param("FastLength", 12) \
.SetDisplay("Fast EMA", "Period of the fast moving average", "MACD")
self._slow_length = self.Param("SlowLength", 26) \
.SetDisplay("Slow EMA", "Period of the slow moving average", "MACD")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles for processing", "General")
self._prev1 = 0.0
self._prev2 = 0.0
self._is_initialized = False
@property
def FastLength(self):
return self._fast_length.Value
@FastLength.setter
def FastLength(self, value):
self._fast_length.Value = value
@property
def SlowLength(self):
return self._slow_length.Value
@SlowLength.setter
def SlowLength(self, value):
self._slow_length.Value = value
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
def OnStarted2(self, time):
super(fatl_macd_strategy, self).OnStarted2(time)
macd = MovingAverageConvergenceDivergence()
macd.ShortMa.Length = self.FastLength
macd.LongMa.Length = self.SlowLength
self.SubscribeCandles(self.CandleType) \
.Bind(macd, self.ProcessCandle) \
.Start()
def ProcessCandle(self, candle, macd_value):
if candle.State != CandleStates.Finished:
return
val = float(macd_value)
if not self._is_initialized:
self._prev2 = val
self._prev1 = val
self._is_initialized = True
return
if self._prev1 < self._prev2:
if self.Position < 0:
self.BuyMarket()
if val > self._prev1 and self.Position <= 0:
self.BuyMarket()
elif self._prev1 > self._prev2:
if self.Position > 0:
self.SellMarket()
if val < self._prev1 and self.Position >= 0:
self.SellMarket()
self._prev2 = self._prev1
self._prev1 = val
def OnReseted(self):
super(fatl_macd_strategy, self).OnReseted()
self._prev1 = 0.0
self._prev2 = 0.0
self._is_initialized = False
def CreateClone(self):
return fatl_macd_strategy()