既存記事のパーフェクトオーダーEAは、複数の移動平均線が全て同じ順番に並んだときだけエントリーする、全条件一致(AND)方式でした。

条件を厳しくするほど「だまし」は減りますが、その代わりに条件が完全一致する場面自体が少なくなり、エントリー機会そのものを取りこぼしやすくなります。

この記事では、全会一致ではなく「3つの指標のうち何個が同じ方向を向いているか」を集計し、過半数(または任意の一致数)でエントリーする、多数決方式のEAを解説します。

一致数の基準を1つの入力パラメーターで調整できるようにすることで、厳しさと機会の多さのバランスを、あとから読者自身が変えられる設計にしています。

設計思想: 全会一致(AND)と多数決(集計)の違い

パーフェクトオーダーEAの条件式は、`条件A && 条件B && 条件C`のように、全てが真でなければエントリーしない書き方でした。

多数決方式では、各指標の判定結果を「+1(買い方向)」「-1(売り方向)」の数値として扱い、その合計(投票の集計結果)がしきい値を超えたかどうかで判定します。

//全会一致(AND)方式のイメージ
if(条件A && 条件B && 条件C) エントリー;

//多数決(集計)方式のイメージ
int votes = 指標Aの投票 + 指標Bの投票 + 指標Cの投票;
if(votes >= しきい値) エントリー;

この違いにより、多数決方式では「3つ中2つが同じ方向」のような、全会一致より緩い条件でもエントリーできるようになります。

しきい値を指標の数と同じ値(この記事の例なら3)に設定すれば、全会一致方式と全く同じ厳しさに戻すこともできます。

3つの指標にそれぞれ1票を持たせる

この記事のサンプルでは、次の3つの指標をそれぞれ「買い方向(+1)」「売り方向(-1)」のどちらかに投票させます。

  • 移動平均線: 短期MAが長期MAより上なら+1、下なら-1
  • RSI: 50より上なら+1、以下なら-1
  • CCI: 0より上なら+1、以下なら-1

いずれも「中立(0票)」を作らず、必ずどちらかに投票させている点がポイントです。

中立を許すと集計結果が曖昧になり、しきい値との比較が複雑になるため、あえて二択の投票にしています。

int GetMAVote()
  {
   double fastMA = iMA(NULL,0,FastMAPeriod,0,MODE_SMA,PRICE_CLOSE,0);
   double slowMA = iMA(NULL,0,SlowMAPeriod,0,MODE_SMA,PRICE_CLOSE,0);
   return (fastMA > slowMA) ? 1 : -1;
  }

int GetRSIVote()
  {
   double rsi = iRSI(NULL,0,RSIPeriod,PRICE_CLOSE,0);
   return (rsi > 50) ? 1 : -1;
  }

int GetCCIVote()
  {
   double cci = iCCI(NULL,0,CCIPeriod,PRICE_TYPICAL,0);
   return (cci > 0) ? 1 : -1;
  }

VoteThresholdで厳しさを調整する

3つの投票を合計すると、結果は`-3・-1・1・3`のいずれかになります(必ず二択の投票なので、合計が0や偶数になることはありません)。

`VoteThreshold`を2に設定すると、合計が`+1`(2対1で買い方向が優勢)のケースはまだエントリーせず、`+3`(全会一致)のときだけエントリーします。

`VoteThreshold`を1に設定すると、`+1`の時点でエントリーするようになり、より積極的な設計に変わります。

読者自身の相場観に合わせて、この数値を後から調整できる点が、この設計の実務的な価値です。

実際に動くコード全体

gc-dc.md(ゴールデンクロス・デッドクロスEA)のポジション重複防止・損切り設定の骨格に、多数決ロジックを組み込んだ、実際にMetaEditorでコンパイルできるコードです。

//+------------------------------------------------------------------+
//|                                MajorityVote-EA.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    MagicNumber   = 23456;//マジックナンバー
input double Lots          = 0.01;//ロット数
input int    TakeProfit    = 30;//利確(pips)
input int    StopLoss      = 30;//損切り(pips)
input int    Slippage      = 3;//スリッページ
input int    VoteThreshold = 2;//エントリーに必要な一致数(3個中いくつ賛成が必要か)
input int    FastMAPeriod  = 50;//短期移動平均線の期間
input int    SlowMAPeriod  = 100;//長期移動平均線の期間
input int    RSIPeriod     = 14;//RSIの期間
input int    CCIPeriod     = 14;//CCIの期間

//+------------------------------------------------------------------+
//| このEA(マジックナンバー)のポジションを保有しているか判定する      |
//+------------------------------------------------------------------+
bool HasPosition()
  {
   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) continue;
      if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber)
         return(true);
     }
   return(false);
  }

//+------------------------------------------------------------------+
//| 移動平均線の投票(短期が長期より上なら+1、下なら-1)                 |
//+------------------------------------------------------------------+
int GetMAVote()
  {
   double fastMA = iMA(NULL,0,FastMAPeriod,0,MODE_SMA,PRICE_CLOSE,0);
   double slowMA = iMA(NULL,0,SlowMAPeriod,0,MODE_SMA,PRICE_CLOSE,0);
   return (fastMA > slowMA) ? 1 : -1;
  }

//+------------------------------------------------------------------+
//| RSIの投票(50より上なら+1、以下なら-1)                             |
//+------------------------------------------------------------------+
int GetRSIVote()
  {
   double rsi = iRSI(NULL,0,RSIPeriod,PRICE_CLOSE,0);
   return (rsi > 50) ? 1 : -1;
  }

//+------------------------------------------------------------------+
//| CCIの投票(0より上なら+1、以下なら-1)                              |
//+------------------------------------------------------------------+
int GetCCIVote()
  {
   double cci = iCCI(NULL,0,CCIPeriod,PRICE_TYPICAL,0);
   return (cci > 0) ? 1 : -1;
  }

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   if(HasPosition())
      return;

   int votes = GetMAVote() + GetRSIVote() + GetCCIVote();
   int ticket;

   if(votes >= VoteThreshold)
     {
      ticket = OrderSend(Symbol(),OP_BUY,Lots,Ask,Slippage,
                          Ask-StopLoss*Point*10,Ask+TakeProfit*Point*10,
                          "Vote Buy "+IntegerToString(votes),MagicNumber,0,Blue);
      if(ticket < 0)
         Print("買い注文に失敗しました。votes=",votes," エラーコード=",GetLastError());
     }
   else if(votes <= -VoteThreshold)
     {
      ticket = OrderSend(Symbol(),OP_SELL,Lots,Bid,Slippage,
                          Bid+StopLoss*Point*10,Bid-TakeProfit*Point*10,
                          "Vote Sell "+IntegerToString(votes),MagicNumber,0,Red);
      if(ticket < 0)
         Print("売り注文に失敗しました。votes=",votes," エラーコード=",GetLastError());
     }
  }
//+------------------------------------------------------------------+
Copy

MetaEditorで実際に動かす手順

  1. MT4のMetaEditorで「ファイル」→「新規作成」→「Expert Advisor(テンプレートを使用)」を選び、名前を「MajorityVote-EA」にして作成する
  2. テンプレートの中身を全て削除し、上のコードを丸ごと貼り付ける
  3. F7キー(またはコンパイルボタン)でコンパイルし、「0 error(s), 0 warning(s)」になることを確認する
  4. デモ口座のチャートへドラッグ&ドロップし、`VoteThreshold`を3(全会一致)にした場合と2(多数決)にした場合で、ストラテジーテスターのエントリー回数がどう変わるか比較する

この設計の限界

多数決方式は「機会を増やす」設計であり、精度そのものを上げるわけではありません。

3つの指標が示す方向がそもそも似た性質(この記事の3つはいずれも順張り寄りの判定)である場合、実質的に似た情報に3票を割り振っているだけになり、見かけ上「3票中2票」でも本当の意味での独立した合意とは言えない場合があります。

指標を増やす際は、値動きの方向を判定する指標だけでなく、環境認識(トレンド/レンジ判定など)のように性質の異なる指標も混ぜることを検討してください。

意図通りに動かないときに確認すること

  • `VoteThreshold`に指標の数(この記事なら3)より大きい値を設定していないか。3を超える値を設定すると、投票の合計が理論上到達できずエントリーが一切発生しない
  • `GetMAVote()`等の各投票関数が、必ず`+1`か`-1`のどちらかを返しているか(中立の0を返す分岐を追加すると、合計が偶数になり`VoteThreshold`との比較設計が崩れる)
  • ストラテジーテストでエントリー回数が想定より多い場合、3つの指標の判定期間(`FastMAPeriod`・`RSIPeriod`・`CCIPeriod`)が近すぎて、実質的に同じタイミングでしか投票結果が変わらない可能性がある

まとめ

パーフェクトオーダーEAのような全会一致(AND)方式は、条件が厳しいぶん「だまし」を減らせますが、その代わりにエントリー機会そのものを取りこぼしやすくなります。

複数の指標にそれぞれ投票させ、合計がしきい値を超えたらエントリーする多数決方式にすることで、`VoteThreshold`という1つのパラメーターだけで厳しさと機会の多さのバランスを調整できるようになります。指標を増やす際は、性質の異なる指標を組み合わせることも検討してください。

関連記事