「なんとなく、この通貨ペアは夜の時間帯に動きやすい気がする」。
そんな感覚を、実際の値動きから数値として確認できたら安心です。
アジア・欧州・アメリカ時間帯別でトレードするEAの記事では、
時間帯によって手法を切り替えるEAを解説しましたが、
そもそも「どの時間帯が自分の通貨ペアにとって有利なのか」を
判断する材料がなければ、時間帯を切り替える設計自体が勘に頼ったものになります。
この記事では、過去の確定足を集計し、
0時〜23時の各時間帯で陽線が出た比率を、
テキストの記号だけでヒートマップ風に表示するインジケーターのアイデアを解説します。
なぜ時間帯ごとの傾向を可視化したいのか
週末の窓リスクを避けて特定の曜日・時間だけ発注を止めるEAの記事のように、
「この時間帯はエントリーを避ける」
「この時間帯は積極的に狙う」という判断は、
多くの裁量トレーダーが経験則として行っています。
ただし、その経験則が本当にその通貨ペアの値動きに合っているかは、
チャートを目で追っているだけでは検証しづらいものです。
この記事のインジケーターは、
過去数十日分の確定足を機械的に集計することで、
その感覚を裏付けたり、逆に思い込みを修正したりする材料を提供します。
「勝率」ではなく「陽線出現率」を集計する理由
注意: このインジケーターが表示するのは、
実際のトレードの勝率ではありません。
各時間帯の確定足のうち、陽線(終値が始値より高い足)が
何%出現したかという「陽線出現率」です。
トレードの勝率を計算するには、
エントリー価格・決済価格・損切り幅といった
具体的な売買ルールが必要です。
このインジケーターはルールを前提とせず、
「その時間帯は上がりやすいのか下がりやすいのか」という
値動きの傾向だけを見るものだと理解してください。
陽線出現率が60%の時間帯があったとしても、
スプレッドや値幅を考慮すれば実際のトレードで
必ず利益が出るとは限りません。
集計とテキストヒートマップの設計
このインジケーターは、確定足が増えるたびに全期間を集計し直し、
結果を画面左上にテキストで表示します。
OnCalculateで新しい確定足のときだけ集計する
公式リファレンス(OnCalculate)によると、シグネチャは次の通りです。
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[]);
`OnCalculate()`は新しいティックが来るたびに呼ばれますが、
このインジケーターの集計は確定足単位で十分なので、
毎ティック集計し直すと無駄に重くなります。
そこで、直近の確定足の時刻(`time[rates_total-2]`)を
`static`変数に保存しておき、前回と同じ時刻であれば
集計処理をスキップする工夫をします。
時間帯別に陽線・出現本数を数える
公式リファレンス(TimeHour)で、各確定足の時刻から時間(0〜23)を取り出せます。
int hour = TimeHour(time[i]); barCount[hour]++; if(close[i] > open[i]) bullCount[hour]++;
`LookbackDays`(集計対象の過去日数)より古い足は対象から除外し、
直近の相場環境に近い傾向だけを反映するようにします。
■□の記号で棒グラフ風に表示する
オブジェクト描画関数を使わず、
`■`(全角ブロック)と`□`(全角の白抜き)を
割合に応じて並べるだけで、`Comment()`一つで
簡易的なヒートマップ表示が作れます。
int blocks = (int)MathRound(ratio / (100.0 / BlockSteps)); string bar = ""; for(int b = 0; b < BlockSteps; b++) bar += (b < blocks) ? "■" : "□";
実際に動くコード全体
過去60日分(初期値)の確定足を集計し、
0時〜23時ごとの陽線出現率をテキストヒートマップとして表示する、
実際にMetaEditorでコンパイルできるインジケーターです。
//+------------------------------------------------------------------+
//| HourlyBullRatioHeatmap.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
#property indicator_chart_window
#property indicator_plots 0
input int LookbackDays = 60;//集計対象の過去日数
input int BlockSteps = 10;//ヒートマップの棒の段階数(10=10%刻み)
datetime lastBarTime = 0;//直近に集計した確定足の時刻
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Comment("");
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
if(rates_total < 2)
return(rates_total);
//新しい確定足ができたときだけ再集計する(毎ティック集計すると重くなるため)
if(time[rates_total - 2] == lastBarTime)
return(rates_total);
lastBarTime = time[rates_total - 2];
int barCount[24];
int bullCount[24];
ArrayInitialize(barCount, 0);
ArrayInitialize(bullCount, 0);
datetime cutoff = TimeCurrent() - LookbackDays * 86400;
for(int i = 0; i < rates_total; i++)
{
if(time[i] < cutoff)
continue;
int hour = TimeHour(time[i]);
barCount[hour]++;
if(close[i] > open[i])
bullCount[hour]++;
}
string text = "時間帯別 陽線出現率(直近" + IntegerToString(LookbackDays) + "日)\n";
for(int h = 0; h < 24; h++)
{
double ratio = (barCount[h] > 0) ? (double)bullCount[h] / barCount[h] * 100.0 : 0.0;
int blocks = (int)MathRound(ratio / (100.0 / BlockSteps));
string bar = "";
for(int b = 0; b < BlockSteps; b++)
bar += (b < blocks) ? "■" : "□";
text += StringFormat("%02d時 %s %.1f%%(%d本)\n", h, bar, ratio, barCount[h]);
}
Comment(text);
return(rates_total);
}
//+------------------------------------------------------------------+
MetaEditorで実際に動かす手順
- MT4の「ツール」→「MetaQuotes Language Editor」でMetaEditorを開く
- 「ファイル」→「新規作成」→「インジケーター」を選び、名前を「HourlyBullRatioHeatmap」にして作成する(中身は空のテンプレートで構いません)
- テンプレートの中身を全て削除し、上のコードを丸ごと貼り付ける
- F7キー(またはコンパイルボタン)でコンパイルし、「0 error(s), 0 warning(s)」になることを確認する
- 1時間足(H1)のチャートへドラッグ&ドロップし、チャート左上に24行のテキストヒートマップが表示されれば成功です
解釈するときの注意点
このインジケーターが示す陽線出現率は、あくまで過去の統計です。
補足: 相場のクセ(時間帯ごとの傾向)は、
中央銀行の政策方針や市場参加者の顔ぶれが変わることで、
数か月〜数年単位で変化することがあります。
`LookbackDays`を極端に長くすると、
今の相場環境とは異なる過去のクセまで混ざってしまう点に注意してください。
特定の時間帯の陽線出現率が偏っていたとしても、
その1点だけを根拠にエントリーするのではなく、
時間帯別でトレードするEAの記事のような
他の判断材料と組み合わせて使うことをおすすめします。
コピペしてコンパイルが通らない・表示がおかしいときに確認すること
- コンパイルエラーになる: `OnCalculate()`の引数の`&`(参照渡し)を書き忘れていないか確認する
- 表示が0時〜23時全て0%になる: `LookbackDays`が短すぎて対象期間に確定足が1本もない可能性がある。値を大きくして再確認する
- 文字が四角(豆腐文字)で表示される: チャートのフォント設定が日本語や記号(■□)に対応していない可能性がある。MT4の「表示」→「言語」設定を確認する
- 表示が更新されない: `lastBarTime`の比較条件で常にスキップされていないか確認する。新しい足ができるまで表示は更新されない仕様です
- 他のインジケーターのComment表示と競合する: `Comment()`は1チャートにつき1つしか表示できないため、他のインジケーターも`Comment()`を使っていると内容が上書きされる
よくある質問
時間帯別の値動き分析でよく検索されている疑問を、3つにまとめて回答します。
日本時間ではなくサーバー時間で集計されますか?
time[]配列はMT4のチャート上の時刻、
つまりブローカーのサーバー時間で記録されています。
日本時間に変換したい場合は、
サーバーとの時差を別途`input`パラメーターとして加算する改造が必要です。
通貨ペアごとに結果は変わりますか?
変わります。同じ時間帯でも、
USDJPYとGBPJPYでは値動きの傾向が異なることが多いため、
必ず自分が実際にトレードする通貨ペアのチャートで確認してください。
このまま自動売買のフィルターに組み込めますか?
この記事のコードは表示専用です。
`TimeHour(TimeCurrent())`による判定と組み合わせれば、
「陽線出現率が高い時間帯だけエントリーを許可する」
フィルターへ応用できます。
【MQL4】時間帯ごとの陽線出現率をテキストヒートマップで表示するインジケーターのアイデア:まとめ
この記事では、過去の確定足を時間帯別に集計し、
陽線が出現した比率を■□の記号だけでテキストヒートマップ表示する
インジケーターのアイデアを解説しました。
ポイントは、「勝率」という言葉を安易に使わず、
あくまで値動きの傾向を示す「陽線出現率」として扱うことと、
`OnCalculate()`で新しい確定足のときだけ再集計することで
処理負荷を抑える設計です。
このインジケーターで見つけた時間帯の傾向は、
組み合わせることで、経験則ではなく統計に基づいた時間帯選びに活用できます。
コメント