既刊のiForce(フォースインデックス)ゼロクロス矢印インジケーターの記事は、
0ラインをまたいだ瞬間に矢印を出す、表示専用の設計でした。
では、矢印に気づいて自分で発注する手間を、
そのままEAの発注条件に置き換えてしまえばどうなるでしょうか。
この記事では、ゼロクロスの判定ロジックを発注条件に転用し、
損切り必須・ポジション重複防止を備えたトレンドフォローEAに仕立てる方法を解説します。
・既刊インジケーターの判定ロジックをEA化する考え方
・ゼロラインをまたいだ”瞬間”をエントリー条件にする設計
・損切り必須
・ポジション重複防止の書き方
・実際に動くEAのコード全体
既刊インジケーターとの関係(矢印表示から発注条件へ)
まず、インジケーターとEAで判定ロジックをどう使い分けるかを整理します。
既刊iForceゼロクロス矢印インジケーターの振り返り
既刊の記事では、価格変化と出来高を組み合わせて勢いを測るiForceの値が、
プラスからマイナス、またはマイナスからプラスへ切り替わった瞬間だけを矢印で知らせました。
「気づいて発注する」から「自動で発注する」への転換
本記事のEAは、この判定関数をそのまま`OnTick()`内に移し、
矢印の代わりに発注を実行させます。
・このEAはゼロクロスの瞬間にエントリーする順張り設計
・『いつ勢いが失速してトレンドが終わるか』は判定していない
・利確
・トレーリングストップの設定で手仕舞いのタイミングを補う必要がある
順張りEAとしての位置づけ
既刊のCCI逆張りEA・Williams%R逆張りEA等とは逆方向の発想で、
勢いが切り替わった方向へ乗っていく、順張り型のEAです。
Force Index(iForce)とゼロクロス判定ロジック
発注条件の土台になる判定ロジックを確認します。
iForce関数のシグネチャ(既刊記事で確認済み)
double iForce( string symbol, //通貨ペア(NULLで現在のチャート) int timeframe, //時間足 int period, //平均化期間 int ma_method, //平均化メソッド(MODE_SMA等) int applied_price,//適用価格(PRICE_CLOSE等) int shift //シフト(0=現在のバー) );
iForce()の引数構成は、
既刊iforce-mt4.mdが2026-10-09に
MQL4公式リファレンスで直接確認済みです。
本記事でもそのまま同じ引数を使用します。
確定済みの1本前・2本前の符号を比較する判定関数
int GetForceCrossState(int shift)
{
double forceNow = iForce(_Symbol, 0, InpPeriod, InpMaMethod, InpAppliedPrice, shift);
double forcePrev = iForce(_Symbol, 0, InpPeriod, InpMaMethod, InpAppliedPrice, shift + 1);
if(forceNow > 0 && forcePrev <= 0)
return(1);
if(forceNow < 0 && forcePrev >= 0)
return(-1);
return(0);
}
値そのものではなく、符号が切り替わった瞬間だけを検知する、
既刊インジケーターと同じ考え方の関数です。
出来高が絡む指標はFXのティックボリュームに注意
・ForceIndexは本来「実際に成立した取引量(出来高)」を前提にした指標
・FXのMT4で得られるのはティックボリューム(値動きの回数)であり、実出来高ではない
・既刊iobv-mt4.mdでも指摘した『前提が崩れる』問題がこのEAにも当てはまる
発注条件・損切り・ポジション重複の防止
判定だけでは発注にならないため、安全策を組み込みます。
ゼロクロスの”瞬間”を検知する
bool BuySignal()
{
return(GetForceCrossState(1) == 1 && GetForceCrossState(2) != 1);
}
bool SellSignal()
{
return(GetForceCrossState(1) == -1 && GetForceCrossState(2) != -1);
}
確定済みの1本前(shift=1)が切り替わっていて、
2本前(shift=2)はまだ切り替わっていなかった場合だけを、
エントリーのシグナルにします。
形成中の0番目の足を基準にしないのは、既刊のアリゲーター並び順EAと同じく、
リペイント(後からサインが変わる現象)を避けるための設計です。
損切り・利確を必ず指定する
double sl = Ask - InpStopLossPips * point; double tp = Ask + InpTakeProfitPips * point; OrderSend(_Symbol, OP_BUY, InpLots, Ask, 3, sl, tp, "ForceIndexCross", InpMagic, 0, clrBlue);
損切り(`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);
}
同じマジックナンバー・同じ通貨ペアでポジションが既にあるかを確認し、
あれば新規エントリーをスキップします。
実際に動くForce IndexクロスエントリーEAのコード全体
ここまでの要素をまとめた、EAの全体です。
//+------------------------------------------------------------------+
//| ForceIndexCrossEA.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 InpPeriod = 13; //Force Indexの平均化期間
input int InpMaMethod = MODE_SMA; //平均化メソッド
input int InpAppliedPrice = PRICE_CLOSE;//適用価格
input double InpLots = 0.1; //発注ロット数
input int InpStopLossPips = 300; //損切り(pips)
input int InpTakeProfitPips = 600; //利確(pips)
input int InpMagic = 20261020; //マジックナンバー
int GetForceCrossState(int shift)
{
double forceNow = iForce(_Symbol, 0, InpPeriod, InpMaMethod, InpAppliedPrice, shift);
double forcePrev = iForce(_Symbol, 0, InpPeriod, InpMaMethod, InpAppliedPrice, shift + 1);
if(forceNow > 0 && forcePrev <= 0)
return(1);
if(forceNow < 0 && forcePrev >= 0)
return(-1);
return(0);
}
bool BuySignal()
{
return(GetForceCrossState(1) == 1 && GetForceCrossState(2) != 1);
}
bool SellSignal()
{
return(GetForceCrossState(1) == -1 && GetForceCrossState(2) != -1);
}
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(HasOpenPosition())
return;
double point = _Point;
if(_Digits == 3 || _Digits == 5)
point *= 10;
if(BuySignal())
{
double sl = Ask - InpStopLossPips * point;
double tp = Ask + InpTakeProfitPips * point;
int ticket = OrderSend(_Symbol, OP_BUY, InpLots, Ask, 3, sl, tp,
"ForceIndexCross", InpMagic, 0, clrBlue);
if(ticket < 0)
Print("買い発注に失敗しました。エラーコード: ", GetLastError());
}
else if(SellSignal())
{
double sl = Bid + InpStopLossPips * point;
double tp = Bid - InpTakeProfitPips * point;
int ticket = OrderSend(_Symbol, OP_SELL, InpLots, Bid, 3, sl, tp,
"ForceIndexCross", InpMagic, 0, clrRed);
if(ticket < 0)
Print("売り発注に失敗しました。エラーコード: ", GetLastError());
}
}
`InpPeriod`期間で平均化したForce Indexの符号が切り替わった瞬間だけ、
新規エントリーが発生します。
MetaEditorでのコンパイル・実行手順
- MetaEditorで新規Expert Advisor「ForceIndexCrossEA」を作成し、上のコードを貼り付ける
- F7キー(またはコンパイルボタン)でコンパイルし、「0 error(s), 0 warning(s)」になることを確認する
- ストラテジーテスターでこのEAを選択し、任意の通貨ペア・期間でバックテストを実行する
- 「結果」タブで、ゼロクロス直後にエントリーが発生していることを確認する
よくあるエラーと注意点
実際に運用する前に、確認しておきたい点です。
出来高が極端に少ないシンボルでは機能しにくい
・取引量が極端に少ない通貨ペア
・時間帯はティックボリュームが不安定
・ForceIndexの符号が細かく入れ替わり、エントリーが増えすぎることがある
・主要通貨ペアの主要時間帯での使用を推奨する
コンパイルエラーになる
`iForce()`の引数を6個すべて指定しているか確認してください。
`period`だけ変えたい場合でも、
`ma_method`・`applied_price`・`shift`は省略できません。
トレンドが続かずすぐに損切りになる
固定pipsの損切り(`InpStopLossPips`)は、
通貨ペアやボラティリティによって最適値が変わります。
既刊atr-volatility-indicator-mt4.mdの
ATR値を参考に調整することを推奨します。
MQL4とMQL5の違い
Force Indexの扱い方に関する2言語の違いを確認します。
MQL4は値を直接返す方式
MQL4の`iForce()`は、呼び出すたびに1つの値を直接返します。
MQL5はハンドル方式に変わる
MQL5には`iForce()`という同名関数は無く、
`iCustom()`またはテクニカル指標ハンドルとして、
独自に実装する必要があります。
既刊copybuffer.mdのハンドル方式を応用すれば移植できます。
ゼロクロス判定ロジックはMQL5でも応用可能
「直前の符号と今の符号を比較する」という考え方自体は、MQL5に移植する場合でも、
そのまま応用できます。
このEAの使いどころと限界
得意な場面と、単独では対応しきれない場面を整理します。
出来高を伴う明確な勢いの変化に強い
価格変化だけでなく出来高(ティックボリューム)も条件に含むため、
値動きだけのオシレーターより、勢いの変化を捉えやすい場面があります。
手仕舞いのロジックは別途必要
このEAは「乗る」ことに特化しており、「いつ降りるか」は固定の利確・損切りに任せています。
より精緻な手仕舞いをしたい場合は、符号が反転した時点で決済する関数を追加してください。
よくある質問
Force IndexクロスエントリーEAについて、よく検索される疑問に回答します。
・既刊インジケーターと同時に使えば、判定の根拠を目視でも確認できる
・InpStopLossPips/InpTakeProfitPipsは通貨ペア
・時間足でバックテストして調整する
・出来高が少ない時間帯は信号頻度が増えやすい点を理解しておく
既刊インジケーターと同時に使う必要がありますか?
必須ではありません。
このEAは判定ロジックを内部に持っているため単独で動作しますが、
目視で経過を確認したい場合は既刊インジケーターを併用してください。
OsMAクロスEA等と何が違いますか?
計算式が根本的に異なります。
既刊osma-cross-arrow-indicator.mdの
OsMAはMACDのメインライン-シグナルラインの差分であり、
本記事のForce Indexは価格変化と出来高を掛け合わせた別の計算式です。
数学的に同一の指標ではないため、
組み合わせ企画マトリクスの教訓(既刊記事で見送ったOsMA×EAの件)には抵触しません。
他のEAと同じ口座で同時運用できますか?
マジックナンバーを別の値にしておけば、
既刊のCCI逆張りEA等と同じ口座で同時に動かすこと自体は可能です。
ただし、同じ通貨ペアで逆方向のEAを動かすと、
意図がぶつかる場面があるため注意してください。
【MQL4】フォースインデックス(iForce)のゼロクロスを発注条件にしたトレンドフォローEAの作り方(損切り必須・ポジション重複防止つき):まとめ
この記事では、既刊のiForceゼロクロス矢印インジケーターの判定ロジックを、
そのままEAの発注条件に転用する方法を解説しました。
損切り必須・ポジション重複防止という最低限の安全策を備えつつ、
手仕舞いのロジックは今後の改善点として残しています。
コメント