ホーム
/
戦略のサンプル
GitHub で見る
MA RSI EA戦略
概要
MA RSI EA戦略 は、高速移動平均線と短期RSIフィルターを組み合わせた元のMetaTraderエキスパートアドバイザーのロジックを再現します。戦略は選択したローソク足シリーズで取引し、確定済みバーのみで新しい注文を評価し、口座残高または純資産に基づく動的なポジションサイジングを使用します。すべてのオープンポジションの浮動利益が正になると、利益を確定するためにすべてのポジションが即座にクローズされます。
インジケーター
Moving Average – 価格ソース選択とオプションのシフトを持つ設定可能なメソッド(シンプル、指数、スムーズド、線形加重)。
Relative Strength Index (RSI) – MQLバージョンと同じローソク足価格ファミリーから読み取る短期オシレーター。
トレードロジック
各完了ローソク足について、戦略は設定された価格ソースを使用して移動平均線とRSIの値を計算します。
最新の移動平均値は、MQL動作と一致させるためにユーザー定義のバー数だけシフトできます。
現在の純ポジションの浮動PnLを評価します:
すべてのオープンポジションの浮動結果がゼロより大きい 場合、戦略は利益を実現するために全ポジションをクローズします。
浮動結果が負 の場合、損失の小さい側(買い側対売り側)をその方向に追加トレードを開いて強化します。
平均化シグナルがない場合、RSI + MAフィルターが適用されます:
ショートエントリー – RSI ≥ RsiOverboughtかつローソク足の始値がシフトした移動平均線を下回る。
ロングエントリー – RSI ≤ RsiOversoldかつローソク足の始値がシフトした移動平均線を上回る。
エグジットロジック
正の浮動PnLがCloseAllPositionsをトリガーし、戦略を即座にフラット化します。
平均化ロジックからの手動反転シグナルは、StockSharpがネットポジションで動作するため反対側のエクスポージャーをクローズします。
ポジションサイジング
LotSizingModesはEAのOptLot選択を反映します:
Fixed – 常にLotSizeボリュームを送信します。
Balance – ローソク足クローズ価格を使用してPercentOfBalanceのポートフォリオ価値をボリュームに変換します。
Equity – 現在のポートフォリオ純資産のPercentOfEquityをボリュームに変換します。
計算されたボリュームは最寄りのSecurity.VolumeStepに丸められ(利用可能な場合)、注文がインストルメントのロットサイズに準拠するようにします。
パラメーター
パラメーター
説明
デフォルト
LotOption
ボリューム計算モード(Fixed、Balance、Equity)。
Balance
LotSize
Fixedモードの固定ロット値。
0.01
PercentOfBalance
Balanceモードで使用する残高のパーセンテージ。
2
PercentOfEquity
Equityモードで使用する純資産のパーセンテージ。
3
FastMaPeriod
移動平均線の長さ。
4
FastMaShift
移動平均結果に適用するシフト。
0
FastMaMethod
移動平均計算メソッド(Simple、Exponential、Smoothed、LinearWeighted)。
LinearWeighted
FastMaPrice
移動平均線のローソク足価格ソース。
Open
RsiPeriod
RSIの長さ。
4
RsiPrice
RSIのローソク足価格ソース。
Open
RsiOverbought
買われすぎ市場を定義するRSIレベル。
80
RsiOversold
売られすぎ市場を定義するRSIレベル。
20
CandleType
戦略が使用するローソク足シリーズ。
15分タイムフレーム
ローソク足価格ソース
CandlePriceSourcesはMQLの適用価格リストを複製します:
Open、High、Low、Close
Median = (High + Low) / 2
Typical = (High + Low + Close) / 3
Weighted = (High + Low + Close + Close) / 4
注意事項
注文は戦略がオンラインで、ローソク足が完了したときのみ生成されます。新しいバーでトリガーする元のEAと一致します。
StockSharpはネットポジションを維持するため、平均化シグナルはヘッジポジションを作成する代わりに現在のエクスポージャーを自動的に削減または反転します。
Python実装は要求に従い意図的に省略されています。
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// MA + RSI strategy. Uses EMA trend direction with RSI momentum confirmation.
/// </summary>
public class MaRsiEaStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _maPeriod;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<decimal> _rsiOverbought;
private readonly StrategyParam<decimal> _rsiOversold;
private decimal? _prevRsi;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int MaPeriod
{
get => _maPeriod.Value;
set => _maPeriod.Value = value;
}
public int RsiPeriod
{
get => _rsiPeriod.Value;
set => _rsiPeriod.Value = value;
}
public decimal RsiOverbought
{
get => _rsiOverbought.Value;
set => _rsiOverbought.Value = value;
}
public decimal RsiOversold
{
get => _rsiOversold.Value;
set => _rsiOversold.Value = value;
}
public MaRsiEaStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_maPeriod = Param(nameof(MaPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("MA Period", "EMA period for trend", "Indicators");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI calculation period", "Indicators");
_rsiOverbought = Param(nameof(RsiOverbought), 65m)
.SetDisplay("Overbought", "RSI overbought level", "Levels");
_rsiOversold = Param(nameof(RsiOversold), 35m)
.SetDisplay("Oversold", "RSI oversold level", "Levels");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevRsi = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevRsi = null;
var ema = new ExponentialMovingAverage { Length = MaPeriod };
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ema, rsi, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ema);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal emaValue, decimal rsiValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevRsi = rsiValue;
return;
}
var close = candle.ClosePrice;
if (_prevRsi == null)
{
_prevRsi = rsiValue;
return;
}
// Buy: price above EMA and RSI crosses above oversold
if (close > emaValue && _prevRsi.Value <= RsiOversold && rsiValue > RsiOversold && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
// Sell: price below EMA and RSI crosses below overbought
else if (close < emaValue && _prevRsi.Value >= RsiOverbought && rsiValue < RsiOverbought && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
_prevRsi = rsiValue;
}
}
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, RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class ma_rsi_ea_strategy(Strategy):
def __init__(self):
super(ma_rsi_ea_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._ma_period = self.Param("MaPeriod", 20) \
.SetDisplay("MA Period", "EMA period for trend", "Indicators")
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "RSI calculation period", "Indicators")
self._rsi_overbought = self.Param("RsiOverbought", 65.0) \
.SetDisplay("Overbought", "RSI overbought level", "Levels")
self._rsi_oversold = self.Param("RsiOversold", 35.0) \
.SetDisplay("Oversold", "RSI oversold level", "Levels")
self._prev_rsi = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def MaPeriod(self):
return self._ma_period.Value
@property
def RsiPeriod(self):
return self._rsi_period.Value
@property
def RsiOverbought(self):
return self._rsi_overbought.Value
@property
def RsiOversold(self):
return self._rsi_oversold.Value
def OnReseted(self):
super(ma_rsi_ea_strategy, self).OnReseted()
self._prev_rsi = None
def OnStarted2(self, time):
super(ma_rsi_ea_strategy, self).OnStarted2(time)
self._prev_rsi = None
ema = ExponentialMovingAverage()
ema.Length = self.MaPeriod
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(ema, rsi, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema)
self.DrawOwnTrades(area)
def _on_process(self, candle, ema_value, rsi_value):
if candle.State != CandleStates.Finished:
return
rv = float(rsi_value)
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_rsi = rv
return
close = float(candle.ClosePrice)
ev = float(ema_value)
if self._prev_rsi is None:
self._prev_rsi = rv
return
ob = float(self.RsiOverbought)
os_level = float(self.RsiOversold)
# Buy: price above EMA and RSI crosses above oversold
if close > ev and self._prev_rsi <= os_level and rv > os_level and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
# Sell: price below EMA and RSI crosses below overbought
elif close < ev and self._prev_rsi >= ob and rv < ob and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_rsi = rv
def CreateClone(self):
return ma_rsi_ea_strategy()