最終更新: 2026年6月
RSIを使ったEAのパラメータ最適化は、「バックテストで完璧な数値を見つける作業」ではない。むしろ「過去データに特化しすぎず、将来の相場でも機能する堅牢なパラメーター帯域を特定する作業」だ。この認識の違いがEA開発の成否を分ける。
筆者がRSIベースのEAを複数設計してきた経験から言うと、期間設定の最適化よりも「どの相場環境でRSIが機能しやすいか」を先に設計することの方が重要だ。RSIは本質的にオシレーター系の指標であり、トレンドが強い局面では逆張りシグナルが連続して失敗するという構造的弱点を持っている。
Claudeと会話しながらインジケータが作れるhedgrow-fxはこちら
RSIの内部構造——なぜ14期間がデフォルトか
RSI(Relative Strength Index)の計算式:
RS = 過去N期間の平均上昇幅 ÷ 過去N期間の平均下落幅
RSI = 100 − (100 ÷ (1 + RS))
デフォルトN=14はワイルダーが設定した「半月分の取引日数(28日÷2)」に由来する。月次サイクルの半分を参照することで、中期的な買われ過ぎ・売られ過ぎを検出することが意図されていた。
RSIが14のとき、最新のローソク足に与えるウェイトは約7%(1/14)だ。期間を短くすると直近の動きに敏感になり、長くすると鈍感になる。この感度の調整がパラメーター最適化の核心になる。
RSI EAの典型的なロジックパターン
最適化する前に、どのシグナルパターンを使うかを確定する必要がある。主要なパターンは4つある。
パターン1: 売られ過ぎ・買われ過ぎ逆張り
// RSI < 30 で買い、RSI > 70 で売り
if(rsiValue < 30.0) { /* 買いエントリー */ }
if(rsiValue > 70.0) { /* 売りエントリー */ }
最もシンプルだが、強いトレンド相場では30以下が続いてもさらに下落するケースが多い。
パターン2: RSI 50ライン順張り
// RSIが50を上抜けで買い、下抜けで売り
bool rsiCrossAbove50 = (prevRSI < 50.0) && (currRSI >= 50.0);
bool rsiCrossBelow50 = (prevRSI > 50.0) && (currRSI <= 50.0);
トレンドフォロー系の戦略に組み込む場合に使いやすい。ADXフィルターと組み合わせることで機能しやすい。
パターン3: ダイバージェンス検出
価格が新高値を更新してもRSIが前回高値を更新しない場合(弱気ダイバージェンス)を検出してエントリーする。実装の複雑さは高いが、シグナルの信頼性は高い。
パターン4: RSIオーバーボートからの折り返し
// RSIが70以上に達した後、70を下抜けたタイミングで売り
bool wasOverbought = (prevRSI >= 70.0);
bool nowBelowLevel = (currRSI < 70.0);
if(wasOverbought && nowBelowLevel) { /* 売りエントリー */ }
水準到達ではなく「水準からの離脱」でエントリーすることで、トレンド継続中の早期エントリーを回避できる。
MQL5でのRSI値取得コード
input int RSIPeriod = 14;
input double RSIUpperLevel = 70.0; // 買われ過ぎ水準
input double RSILowerLevel = 30.0; // 売られ過ぎ水準
input ENUM_APPLIED_PRICE RSIPrice = PRICE_CLOSE;
int RSIHandle;
double RSIBuffer[];
int OnInit()
{
RSIHandle = iRSI(_Symbol, _Period, RSIPeriod, RSIPrice);
if(RSIHandle == INVALID_HANDLE)
{
Print("RSIハンドル取得失敗");
return INIT_FAILED;
}
ArraySetAsSeries(RSIBuffer, true);
return INIT_SUCCEEDED;
}
double GetRSI(int shift = 0)
{
if(CopyBuffer(RSIHandle, 0, 0, 3 + shift, RSIBuffer) < (3 + shift))
return -1.0; // エラー値
return NormalizeDouble(RSIBuffer[shift], 2);
}
// エントリーシグナルの判定
int CheckSignal()
{
double rsi0 = GetRSI(0); // 現在足
double rsi1 = GetRSI(1); // 1本前
if(rsi0 < 0 || rsi1 < 0) return 0; // データ取得失敗
// 逆張りパターン: 売られ過ぎからの反転
if(rsi1 <= RSILowerLevel && rsi0 > RSILowerLevel) return 1; // 買いシグナル
if(rsi1 >= RSIUpperLevel && rsi0 < RSIUpperLevel) return -1; // 売りシグナル
return 0;
}
void OnDeinit(const int reason)
{
IndicatorRelease(RSIHandle);
}
ENUM_APPLIED_PRICEをinputにしている点がポイントだ。PRICE_CLOSEだけでなく、PRICE_TYPICAL(高値+安値+終値÷3)やPRICE_WEIGHTEDも試す価値がある。これもバックテストで効果を確認すべきパラメーターの一つだ。
MT5ストラテジーテスターでの最適化手順
Step 1: 最適化パラメーターの範囲設定
バックテストの「最適化」タブで各パラメーターの範囲を指定する。RSI EAの最適化で検討すべきパラメーター:
| パラメーター | 探索範囲 | ステップ | 理由 | |------------|--------|--------|------| | RSIPeriod | 7〜28 | 1 | 週次から月次のサイクル | | RSIUpperLevel | 65〜80 | 5 | 標準70を中心に上下 | | RSILowerLevel | 20〜35 | 5 | 標準30を中心に上下 | | SLMultiplier | 0.5〜2.5 | 0.25 | ATRベースの場合 |
パラメーターが4つのとき、全組み合わせ数は(22 × 4 × 4 × 9) = 3,168通り。多くなりすぎる場合は重要度の低いパラメーターを固定して絞り込む。
Step 2: 評価基準の設定
「最適化の基準」では「カスタム最大化」を選択し、プロフィットファクター・ドローダウン・トレード数のバランスを取った評価関数を使うことを推奨する:
// OnTester()で評価関数を定義
double OnTester()
{
double pf = TesterStatistics(STAT_PROFIT_FACTOR);
double dd = TesterStatistics(STAT_EQUITY_DD_RELATIVE);
int trades = (int)TesterStatistics(STAT_TRADES);
// トレード数が少なすぎる結果を除外
if(trades < 100) return 0.0;
// PFとドローダウンのバランス評価
return pf / (1.0 + dd / 10.0);
}
プロフィットファクターだけを最大化すると、トレード数が極端に少ない(N=5など)高PFの組み合わせが選ばれてしまう問題が起きる。
Step 3: アウトオブサンプル検証
バックテスト期間を以下のように分割する:
|---- 最適化期間(3年) ----|-- 検証期間1(1年) --|-- 検証期間2(1年) --|
インサンプル 1st OOS 2nd OOS
最適化で得たパラメーターを、最適化に使っていない期間(OOS: Out-of-Sample)で再テストする。インサンプルのPF=1.8 → OOS PF=1.2程度の低下は許容範囲だが、1.8 → 0.8のような大幅劣化は過剰最適化のサインだ。
期間設定の傾向——筆者の検証範囲での観察
バックテストを通じた一般的な傾向として:
短期(7〜10): シグナル頻度が高い。レンジ相場での逆張りに適しやすいが、強いトレンド相場での連続損失リスクも高い。
標準(14): 多くのトレーダーが参照するため、自己実現的なシグナル強度がある程度期待できる。バランス型。
長期(20〜28): シグナル頻度は低いが、シグナルの信頼性が上がる傾向がある。スイングトレード向け。
ただしこれはあくまで「傾向」であり、使用する戦略・通貨ペア・時間足によって最適値は変わる。筆者の経験では「デフォルト14をベースに±5の範囲でロバスト性を確認する」という手順が実用的だ。
RSIフィルターの設計ミスを避ける
RSIをエントリートリガーとして使うよりも、フィルターとして使う方が堅牢なケースがある。
フィルター設計例:
// RSIが中立ゾーン(40〜60)から逸脱している場合のみ、他のシグナルを有効化
bool isRSIExtreme = (rsiValue < 40.0 || rsiValue > 60.0);
// メインシグナル(例: MAクロス)があり、かつRSIが極端な水準の場合にエントリー
if(maSignal && isRSIExtreme)
{
// エントリー処理
}
この設計では、RSIが中立域にある(相場の方向性が不明確な)局面でのエントリーを避けられる。
Claudeと会話しながらインジケータが作れるhedgrow-fxはこちら
よくある質問(FAQ)
Q: RSI期間を短くすると勝率は上がりますか? A: 一般的に短い期間はシグナル数が増え、1シグナルあたりの期待値が低下する傾向があります。勝率が上がるかどうかは戦略の設計次第で、必ずしも短い期間が有利とは言えません。バックテストで実際に比較検証することが重要です。
Q: RSI 70/30のデフォルト閾値を変える意味はありますか? A: 通貨ペアや時間足によって、70/30が機能しやすいケースとしにくいケースがあります。例えば、上昇トレンドが強い相場では80以上が「買われ過ぎ」の目安になることがあります。最適化で65〜80の範囲を検証することを推奨します。
Q: RSI14で最適化したパラメーターはMT4とMT5で同じになりますか? A: 基本的には同じです。ただし、MQL5のiRSI実装がMQL4と内部で使用するスムージングに若干の差異がある場合があります。実際にバックテストで比較して確認することを推奨します。
Q: バックテストのトレード数はどのくらい必要ですか? A: 統計的に信頼できる結果を得るためには最低100〜200トレード以上が目安です。30トレード程度では標準偏差が大きすぎて、結果が偶然に左右される可能性が高くなります。
著者情報
本記事は金融工学・アルゴリズム取引の実務経験を持つライターが執筆しています。
免責事項: 本記事はFXの教育・情報提供を目的としており、投資勧誘を行うものではありません。FX取引には元本割れリスクがあります。バックテスト結果は将来の運用成果を保証しません。実際の取引は自己責任で行ってください。
