1. iCCI関数の概要と実務での活用法
iCCI関数は、ドナルド・ランバートによって開発されたCCI(Commodity Channel Index:商品チャネル指数)のハンドルを取得するためのMQL5組み込み関数です。CCIは、現在の価格が統計的な平均からどれだけ離れているかを測定するオシレーター系のインディケータで、相場の買われすぎ・売られすぎ、あるいはトレンドの強さを測るために広く利用されています。
実務での活用シーン
実務開発では、主に以下の2つのパターンで活用されます。
1. 逆張り戦略: +100以上で「買われすぎ」、-100以下で「売られすぎ」と判断し、反転を狙う。
2. 順張り・ブレイクアウト: +100を上抜けた際に強い上昇トレンドの開始、-100を下抜けた際に下落トレンドの開始とみなす。
実務でつまずきやすいポイント
MQL4に慣れた開発者が最も戸惑うのは、「iCCI関数を呼び出しても、その瞬間にCCIの数値(例:120.5など)が返ってくるわけではない」という点です。MQL5では、まずiCCI関数で「計算設定(ハンドル)」を作成し、そのハンドルを使ってCopyBuffer関数で数値を取得するという2ステップの手順が必要です。この設計を理解していないと、EAが全く動かない、あるいは動作が極端に重くなるといったトラブルの原因になります。
2. 構文と戻り値
iCCI関数の構文は以下の通りです。
int iCCI(
string symbol, // 通貨ペア名(NULLで現在のチャート)
ENUM_TIMEFRAMES period, // 時間軸(0で現在の時間軸)
int ma_period, // 平均化期間(CCIの期間)
ENUM_APPLIED_PRICE applied_price // 適用価格(典型価格 TYPICAL が一般的)
);
パラメーターの解説
- symbol: 対象とする通貨ペアを指定します。
- period:
PERIOD_M15やPERIOD_H1などの時間軸を指定します。 - ma_period: 計算に用いる期間です。一般的には「14」や「20」がよく使われます。
- applied_price: どの価格を用いて計算するかを指定します。CCIの標準的な計算では
PRICE_TYPICAL( (高値+安値+終値)/3 ) が使用されます。
戻り値
- 成功した場合、CCIの計算設定を指す「ハンドル(整数値)」が返されます。
- 失敗した場合は
INVALID_HANDLEが返されます。
3. 具体的な使い方・実践サンプルコード
以下に、EA(エキスパートアドバイザー)でCCIの値を正しく取得し、ログに出力する実用的なコード例を示します。
//+------------------------------------------------------------------+
//| CCI_Sample_EA.mq5 |
//+------------------------------------------------------------------+
#property strict
// 変数宣言
int cciHandle; // CCIのハンドルを格納
double cciBuffer[]; // CCIの値を格納する配列
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// 1. CCIのハンドルを取得(期間14, 典型価格を使用)
cciHandle = iCCI(_Symbol, _Period, 14, PRICE_TYPICAL);
// ハンドル取得に失敗した場合の処理
if(cciHandle == INVALID_HANDLE)
{
Print("CCIハンドルの作成に失敗しました。");
return(INIT_FAILED);
}
// 配列を時系列順(最新のバーがインデックス0)に設定
ArraySetAsSeries(cciBuffer, true);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// 2. 最新のCCIデータを配列にコピー(最新から3本分)
if(CopyBuffer(cciHandle, 0, 0, 3, cciBuffer) < 0)
{
Print("CCIデータのコピーに失敗しました。エラーコード:", GetLastError());
return;
}
// 3. 値を取得してロジックに使用
double currentCCI = cciBuffer[0]; // 最新のCCI値
double prevCCI = cciBuffer[1]; // 1本前のCCI値
// 例:+100を上に突き抜けたらログ出力
if(prevCCI <= 100 && currentCCI > 100)
{
Print("CCIが+100を上抜けました。強い上昇トレンドの可能性があります。値:", currentCCI);
}
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// 4. ハンドルを解放してメモリを節約
IndicatorRelease(cciHandle);
}
4. 使用上の注意点とよくあるエラー
OnTick 内で iCCI を呼び出さない
初心者が最もやりがちなミスは、OnTick(価格が動くたびに実行される関数)の中で毎回 iCCI を呼び出すことです。これを行うと、ティックごとに新しい計算用ハンドルが生成され、PCのメモリを急激に消費してプラットフォームがフリーズします。必ず OnInit で一度だけハンドルを作成し、OnTick では CopyBuffer のみを行うようにしてください。
配列の時系列(ArraySetAsSeries)
MQL5のデフォルトでは、配列のインデックス0は「最も古いデータ」を指します。しかし、トレード戦略では「最新のバー」をインデックス0として扱う方が直感的です。ArraySetAsSeries(buffer, true) を忘れると、最新の値を取得したつもりが過去の値を参照してしまうというロジックミスに繋がります。
ヒストリカルデータの不足
EAの起動直後は、チャートの過去データが十分に読み込まれていない場合があります。その状態で CopyBuffer を行うとエラーになるか、不正な値(0や空の値)が返ることがあります。本番運用では、必ず CopyBuffer の戻り値(コピーされた要素数)をチェックする堅牢な実装が求められます。
5. 【重要】自動売買における約定スピードと環境の罠
アルゴリズムトレードにおいて、iCCIなどのインディケータから完璧なシグナルを算出できたとしても、それを実行する「環境」が貧弱であれば、その戦略は机上の空論に終わります。特に自宅のPCから一般的なインターネット回線を通じてEAを稼働させている場合、ネットワークの物理的な距離に起因する「遅延(レイテンシ)」が致命的な損失を招きます。例えば、CCIが100を突破した瞬間に注文を出したとしても、パケットが地球を半周して証券会社のサーバーに届く頃には、価格はすでに滑っており(スリッページ)、本来得られるはずだった利益が損なわれるのです。
このコンマ数秒のラグを極限まで排除するには、ブローカーの取引サーバーと同じデータセンター内に設置された、FX専用のVPS(仮想専用サーバー)を利用することがエンジニアとしての定石です。専用サーバーであれば、24時間365日の安定稼働はもちろんのこと、ネットワーク遅延を1ミリ秒(1000分の1秒)単位まで短縮でき、高精度なバックテスト結果に近いパフォーマンスを実運用で再現することが可能になります。プロフェッショナルな開発者を目指すのであれば、コードの最適化だけでなく、インフラ環境の構築にも妥協すべきではありません。
💡 この記事の内容を実運用で活かすには?
この記事の内容を実運用で活かすには、正しい環境が必要です。
特にVPSを使わないと、このロジックは再現できません。

コメント