ホーム
/
戦略のサンプル
GitHub で見る
Test MACD戦略
概要
Test MACD戦略 は、MetaTraderのTestMACDエキスパートアドバイザーをStockSharp高レベルAPIへ忠実に変換したものです。Moving Average Convergence Divergence(MACD)指標を使ってモメンタム変化を検出し、確定ローソク足でMACDラインがシグナルラインをクロスするたびに取引を実行します。戦略は、CandleTypeパラメーターで指定された単一銘柄と時間軸で動作します。
取引ロジック
CandleTypeで定義されたローソク足データを購読し、設定可能な高速、低速、シグナル期間でMACD指標を計算します。
各確定ローソク足でMACD値の差(MACD - Signal)を監視します。
差が非正から正へ符号変化したとき、MACDラインがシグナルラインを上抜けたことを意味し、強気エントリー を発動します。ロングを開く前にショートエクスポージャーを閉じます。
差が非負から負へ符号変化したとき、MACDラインがシグナルラインを下抜けたことを意味し、弱気エントリー を発動します。ショートを開く前にロングエクスポージャーを閉じます。
すべての注文はTradeVolumeで設定した固定数量の成行で発行されます。
元のエキスパートのポイントベースのリスク管理を再現するため、各エントリーは価格ステップで表したストップロスとテイクプロフィット水準で自動保護されます。
リスク管理
ストップロスとテイクプロフィット距離はMetaTrader入力を反映し、価格ステップで指定されます。銘柄にPriceStep情報がない場合、戦略はMinPriceStepまたは1を乗数として絶対価格距離へフォールバックします。
保護注文は戦略開始時にStartProtectionで一度作成され、再設定なしですべての後続取引に適用されます。
パラメーター
パラメーター
説明
既定値
FastPeriod
MACD計算に使う高速EMA長。
12
SlowPeriod
MACD計算に使う低速EMA長。
24
SignalPeriod
MACD平滑化用シグナルラインEMA長。
9
StopLossPoints
価格ステップで表すストップロス距離。
90
TakeProfitPoints
価格ステップで表すテイクプロフィット距離。
110
TradeVolume
すべての成行注文の固定数量。
1
CandleType
戦略が購読するローソク足データタイプと時間軸。
30分時間軸
使用上の注意
PriceStepとMinPriceStepを利用できるよう、開始前に戦略を銘柄へ接続してください。
選択したCandleTypeに市場データが提供されることを確認してください。そうでなければMACD指標が形成されず、取引は発生しません。
戦略は各クロスイベントをログに記録するため、バックテスト中の取引判断を追跡しやすくなります。
変換詳細
元のMetaTraderクラスCSignalMACD、CTrailingNone、CMoneyFixedLotは、StockSharpの指標バインディングとStartProtection機構に置き換えられています。
MACDクロスをチェックしていたExtStateMACDのロジックは、連続する確定ローソク足間のMACD差分に対する符号変化検出器で表現されています。
資金管理は固定数量パラメーターへ簡略化され、パーセントベースサイズが無効な場合のCMoneyFixedLotの固定ロット動作に近いものです。
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Test MACD strategy: MACD histogram zero-cross.
/// Buys when MACD histogram crosses above zero.
/// Sells when MACD histogram crosses below zero.
/// </summary>
public class TestMacdStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public TestMacdStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var macd = new MovingAverageConvergenceDivergenceSignal
{
Macd = { ShortMa = { Length = 12 }, LongMa = { Length = 26 } },
SignalMa = { Length = 9 }
};
decimal? prevHistogram = null;
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(macd, (candle, macdVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (macdVal.IsEmpty)
return;
var v = (MovingAverageConvergenceDivergenceSignalValue)macdVal;
if (v.Macd is not decimal macdDec || v.Signal is not decimal signalDec)
return;
var histogram = macdDec - signalDec;
if (prevHistogram.HasValue)
{
if (prevHistogram.Value <= 0m && histogram > 0m && Position <= 0)
BuyMarket();
else if (prevHistogram.Value >= 0m && histogram < 0m && Position >= 0)
SellMarket();
}
prevHistogram = histogram;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, macd);
DrawOwnTrades(area);
}
}
}
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 MovingAverageConvergenceDivergenceSignal
from StockSharp.Algo.Strategies import Strategy
class test_macd_strategy(Strategy):
def __init__(self):
super(test_macd_strategy, self).__init__()
self._prev_histogram = None
self._macd = None
def OnReseted(self):
super(test_macd_strategy, self).OnReseted()
self._prev_histogram = None
self._macd = None
def OnStarted2(self, time):
super(test_macd_strategy, self).OnStarted2(time)
self._macd = MovingAverageConvergenceDivergenceSignal()
self._macd.Macd.ShortMa.Length = 12
self._macd.Macd.LongMa.Length = 26
self._macd.SignalMa.Length = 9
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(30)))
subscription.BindEx(self._macd, self._process_candle)
subscription.Start()
def _process_candle(self, candle, macd_val):
if candle.State != CandleStates.Finished:
return
if not self._macd.IsFormed:
return
macd_v = float(macd_val.Macd)
signal_v = float(macd_val.Signal)
histogram = macd_v - signal_v
if self._prev_histogram is not None:
if self._prev_histogram <= 0.0 and histogram > 0.0 and self.Position <= 0:
self.BuyMarket()
elif self._prev_histogram >= 0.0 and histogram < 0.0 and self.Position >= 0:
self.SellMarket()
self._prev_histogram = histogram
def CreateClone(self):
return test_macd_strategy()