GitHub で見る
AML RSI 会議ライン戦略
概要
AML RSI ミーティング ライン戦略は、MetaTrader 5 エキスパート アドバイザー Expert_AML_RSI.mq5 の StockSharp 移植版です。オリジナルのシステムは、日本のローソク足パターン認識と相対力指数 (RSI) を組み合わせて、強気と弱気の「ミーティング ライン」の反転を取引します。この変換では、コア取引ロジックを維持しながら、ローソク足サブスクリプションと組み込みインジケーターを備えた StockSharp の高レベルの API に適応させます。
取引ロジック
- 構成可能なキャンドル タイプをサブスクライブし、完成したキャンドルのみを処理します。
- ローソク本体のサイズの単純移動平均を計算して、ミーティング ライン パターンを形成する「長い」ローソクを検出します。
- 確認シグナルと終了シグナルとして、最も最近完了した 2 つのローソク足の RSI 値を追跡します。
- 強気のセットアップ: RSI が強気の閾値を下回る 2 本バーのミーティング ラインの反転はロングエントリーをトリガーします。
- 弱気のセットアップ: 弱気の閾値を上回る RSI のミラーリングされたパターンは、ショートエントリーをトリガーします。
- ポジションのエグジット: 設定可能な下位レベルと上位レベルを介した RSI クロスオーバーにより、反対方向のオープン取引が終了します。
BuyMarket、SellMarket、および ClosePosition ヘルパーを使用して露出を管理し、逆の信号が現れたときに位置サイズを自動的に反転します。
パラメーター
| 名前 |
説明 |
デフォルト |
CandleType |
ローソク足パターンを評価するために使用される時間枠。 |
1時間枠 |
RsiPeriod |
RSI ルックバックの長さ。 |
11 |
BodyAveragePeriod |
平均的な身体サイズに応じたキャンドルの数。 |
3 |
BullishRsiLevel |
強気のミーティングラインを検証する最大値 RSI。 |
40 |
BearishRsiLevel |
弱気のミーティングラインを検証する最小値 RSI。 |
60 |
LowerExitLevel |
RSI レベルは上向きのクロスでショートをクローズします。 |
30 |
UpperExitLevel |
下向きクロスでロングを決済する RSI レベル。 |
70 |
すべてのパラメータは StrategyParam<T> オブジェクトとして公開されるため、StockSharp デザイナーで最適化できます。
リスク管理
StartProtection() は OnStarted で呼び出され、フレームワークの組み込み位置モニタリングを有効にします。
- この戦略では、RSI が設定された出口境界を越えるたびに、新しいシグナルを検討する前に既存のエクスポージャをクローズします。
- 成行注文は、現在のエクスポージャーの絶対値を構成されたボリュームに追加することにより、ポジションを自動的に反転します。
変換メモ
- ローソク足の平均化では、絶対的なローソク足を供給された
SimpleMovingAverage を使用し、MQL5 ソースからの AvgBody ヘルパーをミラーリングします。
- RSI の確認は、前の 2 つのローソク足の値に依存し、元の専門家からの
RSI(1) と RSI(2) のチェックを再現します。
- コード内のすべてのコメントは英語で書き直され、その構造は、タブ インデントを使用したファイル スコープの名前空間のリポジトリ要件に従っています。
使用法
- StockSharp の証券に戦略をアタッチし、目的のローソクのタイプを選択します。
- 取引会場または金融商品のボラティリティに合わせて、RSI と終了しきい値を設定します。
- ライブ取引または最適化に移行する前に、最初にペーパー取引で戦略を実行してパターン認識を検証します。
- 最適化中に提供されたパラメーターを使用して、さまざまな市場に合わせて RSI レベルと平均体長を微調整します。
免責事項
この戦略は教育目的のみに提供されています。稼働中の資本に導入する前に、過去のデータとシミュレートされた環境で徹底的にテストします。
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Meeting Lines + RSI strategy.
/// Buys on bullish meeting lines with low RSI, sells on bearish meeting lines with high RSI.
/// </summary>
public class AmlRsiMeetingLinesStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<decimal> _rsiLow;
private readonly StrategyParam<decimal> _rsiHigh;
private ICandleMessage _prevCandle;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public decimal RsiLow { get => _rsiLow.Value; set => _rsiLow.Value = value; }
public decimal RsiHigh { get => _rsiHigh.Value; set => _rsiHigh.Value = value; }
public AmlRsiMeetingLinesStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI period", "Indicators");
_rsiLow = Param(nameof(RsiLow), 40m)
.SetDisplay("RSI Low", "RSI level for bullish entry", "Signals");
_rsiHigh = Param(nameof(RsiHigh), 60m)
.SetDisplay("RSI High", "RSI level for bearish entry", "Signals");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevCandle = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevCandle = null;
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(rsi, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal rsiValue)
{
if (candle.State != CandleStates.Finished) return;
if (_prevCandle != null)
{
var avgBody = (Math.Abs(candle.ClosePrice - candle.OpenPrice) +
Math.Abs(_prevCandle.ClosePrice - _prevCandle.OpenPrice)) / 2m;
if (avgBody > 0)
{
var prevBearish = _prevCandle.OpenPrice > _prevCandle.ClosePrice;
var currBullish = candle.ClosePrice > candle.OpenPrice;
var closesNear = Math.Abs(candle.ClosePrice - _prevCandle.ClosePrice) < avgBody * 0.3m;
if (prevBearish && currBullish && closesNear && rsiValue < RsiLow && Position <= 0)
BuyMarket();
var prevBullish = _prevCandle.ClosePrice > _prevCandle.OpenPrice;
var currBearish = candle.OpenPrice > candle.ClosePrice;
var closesNear2 = Math.Abs(candle.ClosePrice - _prevCandle.ClosePrice) < avgBody * 0.3m;
if (prevBullish && currBearish && closesNear2 && rsiValue > RsiHigh && Position >= 0)
SellMarket();
}
}
_prevCandle = candle;
}
}
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 RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class aml_rsi_meeting_lines_strategy(Strategy):
def __init__(self):
super(aml_rsi_meeting_lines_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5)))
self._rsi_period = self.Param("RsiPeriod", 14)
self._rsi_low = self.Param("RsiLow", 40.0)
self._rsi_high = self.Param("RsiHigh", 60.0)
self._prev_candle = None
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def RsiPeriod(self):
return self._rsi_period.Value
@RsiPeriod.setter
def RsiPeriod(self, value):
self._rsi_period.Value = value
@property
def RsiLow(self):
return self._rsi_low.Value
@RsiLow.setter
def RsiLow(self, value):
self._rsi_low.Value = value
@property
def RsiHigh(self):
return self._rsi_high.Value
@RsiHigh.setter
def RsiHigh(self, value):
self._rsi_high.Value = value
def OnReseted(self):
super(aml_rsi_meeting_lines_strategy, self).OnReseted()
self._prev_candle = None
def OnStarted2(self, time):
super(aml_rsi_meeting_lines_strategy, self).OnStarted2(time)
self._prev_candle = None
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(rsi, self._process_candle).Start()
def _process_candle(self, candle, rsi_value):
if candle.State != CandleStates.Finished:
return
rsi_val = float(rsi_value)
if self._prev_candle is not None:
avg_body = (abs(float(candle.ClosePrice) - float(candle.OpenPrice))
+ abs(float(self._prev_candle.ClosePrice) - float(self._prev_candle.OpenPrice))) / 2.0
if avg_body > 0:
prev_bearish = float(self._prev_candle.OpenPrice) > float(self._prev_candle.ClosePrice)
curr_bullish = float(candle.ClosePrice) > float(candle.OpenPrice)
closes_near = abs(float(candle.ClosePrice) - float(self._prev_candle.ClosePrice)) < avg_body * 0.3
if prev_bearish and curr_bullish and closes_near and rsi_val < self.RsiLow and self.Position <= 0:
self.BuyMarket()
prev_bullish = float(self._prev_candle.ClosePrice) > float(self._prev_candle.OpenPrice)
curr_bearish = float(candle.OpenPrice) > float(candle.ClosePrice)
closes_near2 = abs(float(candle.ClosePrice) - float(self._prev_candle.ClosePrice)) < avg_body * 0.3
if prev_bullish and curr_bearish and closes_near2 and rsi_val > self.RsiHigh and self.Position >= 0:
self.SellMarket()
self._prev_candle = candle
def CreateClone(self):
return aml_rsi_meeting_lines_strategy()