既刊のiRVI(Relative Vigor Index)インジケーターの記事では、

メイン線とシグナル線のクロスを矢印で知らせる設計を解説しました。

この記事ではあえてその判定を使わず、iRVIのメイン線が0ラインを、

上下に抜けた瞬間だけをエントリー条件にする順張りEAを作ります。

この記事で分かること
・既刊のメイン線・シグナル線クロスとの判定軸の違い
・既刊MACD/StochasticクロスEAとの違い(ライン同士 vs 0ライン)
・既刊Force Index/MomentumクロスEAとの違い(計算対象の違い)
・損切り必須・ポジション重複防止の書き方
・実際に動くEAのコード全体

なぜメイン線・シグナル線クロスではなく0ラインクロスを使うのか

まず、既刊インジケーターとの違いを整理します。

既刊iRVIインジケーターのおさらい

既刊インジケーターは、メイン線がシグナル線を、

上に抜けたらゴールデンクロス、下に抜けたらデッドクロスとして、

矢印で知らせる設計でした。

既刊のクロス系EA群との違い

このサイトには、クロス判定を発注条件にするEAが、

既にいくつかの系統で存在します。

EA 判定方法 見ているもの
既刊MACDクロスEA メインラインとシグナルラインの交差 2本のラインの位置関係
既刊StochasticクロスEA %Kと%Dの交差 2本のラインの位置関係
既刊Force IndexクロスEA 0ラインクロス 価格変化×出来高の符号反転
既刊MomentumクロスEA 基準線100クロス 一定期間前との価格比の符号反転
本記事(iRVI 0ラインクロスEA) メイン線の0ラインクロス 値幅に対する終値の位置の符号反転

本記事は、ライン同士の交差ではなく、既刊Force Index/Momentumと同じ、

「値そのものの符号が反転した瞬間」を見る系統に属します。

0ラインクロスを使う設計思想

補足
・RVIは(終値-始値)を値幅で割った比率がもとになっている
・終値が始値より上なら正の値、下なら負の値になりやすい
・0ラインを上に抜ける=買い方向の勢いに転じた瞬間とみなす
・メイン線・シグナル線クロスより早いタイミングで反応しやすい

メイン線・シグナル線のクロスは、

2本のラインが追いつくまでの時間差がある分、

反応がやや遅れる傾向があります。

0ラインクロスは、メイン線そのものの符号だけを見るため、

より早いタイミングで方向転換を捉える設計です。

iRVI関数のシグネチャ(既刊記事で確認済み)

既刊irvi-mt4.mdで確認済みの引数構成を再掲します。

5つの引数の意味

double iRVI(
   string symbol,     // 通貨ペア名(NULLで現在のチャート)
   int    timeframe,  // 時間足(0で現在の時間足)
   int    period,     // 計算用の平均化期間
   int    mode,       // ラインインデックス(MODE_MAIN または MODE_SIGNAL)
   int    shift        // 何本前のバーの値を取得するか
);

本EAでは`mode`に`MODE_MAIN`だけを指定し、

シグナル線(`MODE_SIGNAL`)は使いません。

本EAで使うのはMODE_MAINのみ

シグナル線はメイン線をさらに滑らかにした補助線のため、

0ラインクロスだけを見る本EAでは不要です。

使う引数を1本に絞ることで、コードもシンプルになります。

0ラインを跨いだ瞬間の判定ロジック

double main     = iRVI(_Symbol, 0, InpRviPeriod, MODE_MAIN, 1);
double mainPrev = iRVI(_Symbol, 0, InpRviPeriod, MODE_MAIN, 2);

bool crossedUp   = (mainPrev <= 0 && main > 0);
bool crossedDown = (mainPrev >= 0 && main < 0);

確定済みの直近バー(shift=1)とその前のバー(shift=2)を比較し、

形成中の最新バー(shift=0)は判定に使いません。

発注条件・損切り・ポジション重複の防止

判定だけでは発注にならないため、安全策を組み込みます。

買い・売りの発注条件

if(crossedUp)
  {
   double sl = Bid - InpStopLossPips * point;
   double tp = Ask + InpTakeProfitPips * point;
   OrderSend(_Symbol, OP_BUY, InpLots, Ask, 3, sl, tp, "RviZeroCross", InpMagic, 0, clrBlue);
  }
else if(crossedDown)
  {
   double sl = Ask + InpStopLossPips * point;
   double tp = Bid - InpTakeProfitPips * point;
   OrderSend(_Symbol, OP_SELL, InpLots, Bid, 3, sl, tp, "RviZeroCross", InpMagic, 0, clrRed);
  }

0ラインを上に抜けたら買い、下に抜けたら売りという、

単純な順張り条件にしています。

損切り・利確を必ず指定する

`sl`(損切り)・`tp`(利確)は発注時点で必ず計算し、

未設定のまま放置しません。

ポジション重複を防ぐチェック

bool HasOpenPosition()
  {
   for(int i = 0; i < OrdersTotal(); i++)
     {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) &&
         OrderSymbol() == _Symbol && OrderMagicNumber() == InpMagic)
         return(true);
     }
   return(false);
  }

同じマジックナンバー・同じ通貨ペアでポジションが既にあるかを確認し、

あれば新規エントリーをスキップします。

実際に動くコード全体

ここまでの要素をまとめた、EAの全体です。

//+------------------------------------------------------------------+
//|                                         RVIZeroCrossEA.mq4         |
//|                     Copyright 2026, FX-EA System Project Creator |
//|                        https://creator.fx-ea-system-project.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, FX-EA System Project Creator"
#property link      "https://creator.fx-ea-system-project.com/"
#property version   "1.00"
#property strict

input int    InpRviPeriod        = 10;         //RVIの平均化期間
input double InpLots             = 0.1;        //発注ロット数
input int    InpStopLossPips     = 300;        //損切り(pips)
input int    InpTakeProfitPips   = 600;        //利確(pips)
input int    InpMagic            = 20261105;   //マジックナンバー

datetime lastBarTime = 0;

bool HasOpenPosition()
  {
   for(int i = 0; i < OrdersTotal(); i++)
     {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) &&
         OrderSymbol() == _Symbol && OrderMagicNumber() == InpMagic)
         return(true);
     }
   return(false);
  }

void OnTick()
  {
   if(Time[0] == lastBarTime)
      return;
   lastBarTime = Time[0];

   int needed = InpRviPeriod + 10;
   if(Bars < needed)
      return;

   double main     = iRVI(_Symbol, 0, InpRviPeriod, MODE_MAIN, 1);
   double mainPrev = iRVI(_Symbol, 0, InpRviPeriod, MODE_MAIN, 2);

   bool crossedUp   = (mainPrev <= 0 && main > 0);
   bool crossedDown = (mainPrev >= 0 && main < 0);

   if(HasOpenPosition())
      return;

   double point = _Point;
   if(_Digits == 3 || _Digits == 5)
      point *= 10;

   if(crossedUp)
     {
      double sl = Bid - InpStopLossPips * point;
      double tp = Ask + InpTakeProfitPips * point;
      int ticket = OrderSend(_Symbol, OP_BUY, InpLots, Ask, 3, sl, tp,
                             "RviZeroCross", InpMagic, 0, clrBlue);
      if(ticket < 0)
         Print("買い発注に失敗しました。エラーコード: ", GetLastError());
     }
   else if(crossedDown)
     {
      double sl = Ask + InpStopLossPips * point;
      double tp = Bid - InpTakeProfitPips * point;
      int ticket = OrderSend(_Symbol, OP_SELL, InpLots, Bid, 3, sl, tp,
                             "RviZeroCross", InpMagic, 0, clrRed);
      if(ticket < 0)
         Print("売り発注に失敗しました。エラーコード: ", GetLastError());
     }
  }

メイン線が0ラインを跨いだ瞬間だけ、新規エントリーが発生します。

MetaEditorでのコンパイル・バックテスト手順

実際に動かすまでの手順です。

  1. MetaEditorで新規Expert Advisor「RVIZeroCrossEA」を作成し、上のコードを貼り付ける
  2. F7キー(またはコンパイルボタン)でコンパイルし、「0 error(s), 0 warning(s)」になることを確認する
  3. ストラテジーテスターでこのEAを選択し、任意の通貨ペア・期間でバックテストを実行する
  4. 「結果」タブで、RVIのメイン線が0を跨いだ直後にエントリーが発生していることを確認する
  5. 既刊のiRVIインジケーターを同時に表示し、エントリーのタイミングがメイン線のどの位置にあたるかを目視で確認する

よくあるエラーと注意点

実際に運用する前に、確認しておきたい点です。

InpRviPeriodの遡り本数が足りない

注意
・RVIはメイン線・シグナル線それぞれが内部で重み付き平均を行う
・period本数よりやや多めの履歴が必要
・ヒストリーが少ない通貨ペアではneeded本数を満たすか必ず確認する

0ラインクロスとメイン・シグナルクロスを混同する

既刊インジケーターの矢印と、本EAのエントリーは、

同じタイミングで発生するとは限りません。

メイン線が0ラインを跨ぐ瞬間と、

メイン線がシグナル線を跨ぐ瞬間は、別々のタイミングです。

コンパイルエラーになる

`MODE_MAIN`の指定を数値の`0`に置き換えても動作は同じですが、

可読性のため定数名のまま使うことをおすすめします。

よくある質問

iRVIの0ラインクロスEAについて、よく検索される疑問に回答します。

実践アドバイス
・既刊iRVIインジケーターを併用すれば、メイン線の推移を目視でも確認できる
・既刊Force Index/MomentumEAと同時運用する場合は、
マジックナンバーを分けて区別する
・損切り幅(InpStopLossPips)は通貨ペア・時間足に応じて調整する

既刊のMACD/StochasticクロスEAと何が違いますか?

判定の対象が違います。

既刊のMACD/StochasticクロスEAは、

2本のラインの位置関係(どちらが上か)を見ますが、

本記事は1本のライン(メイン線)の符号そのものを見ています。

既刊のForce Index/MomentumEAと何が違いますか?

いずれも「0ラインまたは基準線を跨ぐ」という判定方法は同じですが、

計算対象が異なります。

Force Indexは価格変化×出来高、Momentumは一定期間前との価格比、

本記事のRVIは値幅に対する終値の位置という、別々の値の符号を見ています。

同じ日に3つのEAが同時にシグナルを出すとは限りません。

シグナル線を使わないのはなぜですか?

シグナル線はメイン線をさらに滑らかにした補助線のため、

メイン線自体の符号反転を見る本EAの設計では使う必要がありませんでした。

シグナル線を使ったメイン線・シグナル線クロスのEAは、

既刊インジケーターの矢印判定をそのまま転用すれば別途作成できます。

【MQL4】iRVIのメイン線が0ラインを交差した瞬間にエントリーする順張りEAの作り方(既刊クロス系EA群との違いも解説):まとめ

この記事では、既刊iRVIインジケーターのメイン線・シグナル線クロスではなく、

メイン線の0ラインクロスを発注条件にする順張りEAを解説しました。

既刊MACD/StochasticクロスEA(ライン同士の交差)とは、

判定の軸を変え、既刊Force Index/MomentumEA、

(0ライン・基準線クロス)と同じ系統に属しつつ、

計算対象(値幅に対する終値の位置)で差別化しています。

損切り必須・ポジション重複防止という最低限の安全策を備えた上で、

InpRviPeriodの調整で、シグナルの頻度を変えられる構成にしています。

関連記事