GitHub で見る
スマートACトレーダー戦略
概要
Smart AC Trader は、元の MetaTrader の「Smart AC Trader」のアイデアを StockSharp の高レベルの API に適応させています。 MQL の専門家は、ペア内の通貨の相対的な強さを評価し、基本通貨が相場通貨を上回った場合に反応しました。 StockSharp では、同じ勢いに基づく動作に焦点を当てますが、戦略が関連付けられている単一の手段で動作します。強さは、指数移動平均 (EMA) と変化率 (ROC) 指標の組み合わせによって近似されます。
- 速い EMA は短期的なトレンドの方向性を測定します。
- 遅い EMA は主な傾向を表します。
- ROC は、エントリーが許可される前に、価格の勢いがトレンドと一致していることを確認します。
ポジションがオープンされると、この戦略は、元のエキスパートの広範な資金管理構成を反映したストップロス、テイクプロフィット、トレーリングストップ、損益分岐点ルールを使用して取引をアクティブに管理します。
取引ロジック
- 設定されたローソク足タイプ (時間枠) をサブスクライブし、ローソク足終値の速い EMA、遅い EMA、および ROC を計算します。
- ファースト EMA がスロー EMA を上回っており、ROC が購入モメンタムしきい値以上の場合にロング ポジションを入力します。既存のショートエクスポージャは、新しいロングがオープンされる前にクローズされます。
- ファースト EMA がスロー EMA を下回り、かつ ROC がマイナスの売りモメンタムしきい値以下の場合にショート ポジションを入力します。新しいショートが開かれる前に、既存の長時間露光が閉じられます。
- 完成したすべてのキャンドルのオープンポジションを管理します。
- 構成されたテイクプロフィットまたはストップロスの距離(価格ステップで表されます)で取引を終了します。
- オプションで、価格がトリガー距離だけ取引に有利に動いたら損益分岐点エグジットを準備し、価格が保存されたオフセットに戻ったら清算します。
- オプションで、入場後に観察された最高高値 (長い) または最低最低値 (短い) から設定された距離だけストップを追跡します。
パラメーター
| パラメータ |
説明 |
| 高速 EMA |
高速 EMA トレンド フィルターの長さ。 |
| 遅い EMA |
低速 EMA トレンド フィルターの長さ。 |
| ROC 期間 |
変化率モメンタムフィルターのルックバックウィンドウ。 |
| 購入の勢い |
ロング取引を開始するには、最小プラスの ROC が必要です。 |
| 販売の勢い |
ショートトレードを開始するには最小絶対マイナス ROC が必要です。 |
| ストップロス |
価格ステップで表されるストップロス距離。 |
| 利益確定 |
価格ステップで表される利食い距離。 |
| 末尾を使用 |
トレーリングストップ管理を有効にします。 |
| 末尾 |
価格ステップでのトレーリングストップ距離。 |
| 損益分岐点を使用する |
損益分岐点保護ロジックを有効にします。 |
| 損益分岐点トリガー |
損益分岐点ロジックを確立するために必要な価格ステップでの利益。 |
| 損益分岐点オフセット |
損益分岐点トリガーに達した後に維持される価格ステップの距離。 |
| キャンドルタイプ |
インジケーターを供給するために使用されるキャンドルのタイプ。 |
注意事項
- この戦略では、プロジェクト ガイドラインで推奨されているように、組み込みの位置保護システムがアクティブであることを確認するために、起動時に
Strategy.StartProtection() を 1 回使用します。
- 位置のサイズ設定は、ベースの
Strategy.Volume プロパティに依存します。反転注文には現在のエクスポージャが自動的に含まれるため、反対シグナルが既存のポジションを決済し、新しいポジションを確立します。
- 元のエキスパートアドバイザーはピップベースの距離を使用していたため、すべてのリスクパラメーターは価格ステップで表されます。機器に有効な
PriceStep が設定されていることを確認してください。
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Smart AC Trader: EMA trend + ROC momentum filter.
/// Buys when fast EMA above slow EMA and ROC positive.
/// Sells when fast EMA below slow EMA and ROC negative.
/// </summary>
public class SmartAcTraderStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _rocPeriod;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int FastPeriod
{
get => _fastPeriod.Value;
set => _fastPeriod.Value = value;
}
public int SlowPeriod
{
get => _slowPeriod.Value;
set => _slowPeriod.Value = value;
}
public int RocPeriod
{
get => _rocPeriod.Value;
set => _rocPeriod.Value = value;
}
public SmartAcTraderStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 50)
.SetGreaterThanZero()
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
_rocPeriod = Param(nameof(RocPeriod), 13)
.SetGreaterThanZero()
.SetDisplay("ROC Period", "Rate of Change period", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var roc = new RateOfChange { Length = RocPeriod };
decimal? prevFast = null;
decimal? prevSlow = null;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, slow, roc, (candle, fastVal, slowVal, rocVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (prevFast.HasValue && prevSlow.HasValue)
{
var crossUp = prevFast.Value <= prevSlow.Value && fastVal > slowVal;
var crossDown = prevFast.Value >= prevSlow.Value && fastVal < slowVal;
if (crossUp && rocVal > 0 && Position <= 0)
BuyMarket();
else if (crossDown && rocVal < 0 && Position >= 0)
SellMarket();
}
prevFast = fastVal;
prevSlow = slowVal;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fast);
DrawIndicator(area, slow);
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 ExponentialMovingAverage, RateOfChange
from StockSharp.Algo.Strategies import Strategy
class smart_ac_trader_strategy(Strategy):
def __init__(self):
super(smart_ac_trader_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._fast_period = self.Param("FastPeriod", 10) \
.SetGreaterThanZero() \
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 50) \
.SetGreaterThanZero() \
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators")
self._roc_period = self.Param("RocPeriod", 13) \
.SetGreaterThanZero() \
.SetDisplay("ROC Period", "Rate of Change period", "Indicators")
self._prev_fast = None
self._prev_slow = None
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(smart_ac_trader_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(smart_ac_trader_strategy, self).OnStarted2(time)
self._fast_ind = ExponentialMovingAverage()
self._fast_ind.Length = self._fast_period.Value
self._slow_ind = ExponentialMovingAverage()
self._slow_ind.Length = self._slow_period.Value
self._roc_ind = RateOfChange()
self._roc_ind.Length = self._roc_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._fast_ind, self._slow_ind, self._roc_ind, self._process_candle).Start()
def _process_candle(self, candle, fast_value, slow_value, roc_value):
if candle.State != CandleStates.Finished:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
fast_val = float(fast_value)
slow_val = float(slow_value)
roc_val = float(roc_value)
if self._prev_fast is not None and self._prev_slow is not None:
cross_up = self._prev_fast <= self._prev_slow and fast_val > slow_val
cross_down = self._prev_fast >= self._prev_slow and fast_val < slow_val
if cross_up and roc_val > 0 and self.Position <= 0:
self.BuyMarket()
elif cross_down and roc_val < 0 and self.Position >= 0:
self.SellMarket()
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return smart_ac_trader_strategy()