ピボットポイントは、前日の高値・安値・終値から計算式で求める、
サポート・レジスタンスの古典的な手法です。
既刊のサポート/レジスタンス自動検出インジケーターは、
直近のスイング高値・安値から「後付けで」水平線を引く設計でした。
ピボットポイントはそれとは違い、
前日の確定値から「先出しの計算式で」求めるため、
その日が始まった瞬間から使えるラインになります。
この記事では、PP・R1・S1・R2・S2という5本のラインを自動描画する、
実際に動くインジケーターの作り方を解説します。
・ピボットポイントの計算式とPP/R1/S1/R2/S2の意味
・既刊のスイング高値・安値検出との設計思想の違い
・ブローカーのサーバー時間による日付境界の注意点
・実際に動くコード全体
設計思想: なぜ「先出し」のラインが役に立つか
まず、ピボットポイントがどんな場面で役に立つのかを整理します。
既刊のスイング高値・安値検出との違い
既刊のサポート/レジスタンス自動検出インジケーターは、
直近の値動きを見てから、
後付けでスイング高値・安値を水平線として描画していました。
| 記事 | ラインの決め方 | 特徴 |
|---|---|---|
| 既刊(スイング高値・安値) | 直近の値動きから後付けで検出 | 反応は確実だが、検出まで時間がかかる |
| 本記事(ピボットポイント) | 前日の確定値から計算式で先出し | 日が始まった瞬間から使える |
どちらが優れているというものではなく、
デイトレーダーの多くは両方を併用します。
デイトレーダーに人気の理由
・前日の確定値だけで計算できるため、再計算のブレがない
・多くのトレーダーが同じ計算式を見ているため、意識されやすい
・5本のラインが損切り・利確の目安としても使いやすい
多くの参加者が同じラインを見ているという事実そのものが、
実際にそのラインで値動きが反応しやすくなる一因になっています。
ピボットポイントの計算式
使う計算式は次のとおりです。
PP(基準線)の計算
PP = (前日高値 + 前日安値 + 前日終値) / 3
PPはこの5本のラインの中心になる基準値です。
R1/S1/R2/S2(上下のライン)の計算
R1 = 2 × PP − 前日安値 S1 = 2 × PP − 前日高値 R2 = PP + (前日高値 − 前日安値) S2 = PP − (前日高値 − 前日安値)
R1・R2は上のレジスタンス(上値の目安)、
S1・S2は下のサポート(下値の目安)です。
・初心者はまずPPとR1/S1の3本だけを見る
・R2/S2は値動きが大きく伸びたときの参考値として後回しにしてよい
前日の確定値を取得する
MQL4のiHigh/iLow/iCloseで、
日足(PERIOD_D1)の1本前(前日)の値を取得します。
iHigh/iLow/iCloseで前日の値を取得する
double prevHigh = iHigh(NULL, PERIOD_D1, 1); double prevLow = iLow(NULL, PERIOD_D1, 1); double prevClose = iClose(NULL, PERIOD_D1, 1);
shiftに1を指定することで、
「確定した前日の1本」を取得しています。
日付境界(ブローカーのサーバー時間)の注意点
・PERIOD_D1の1本は「ブローカーのサーバー時間」で区切られる
・日本時間の0時とは一致しない(多くはGMT+2〜3時間が日足の区切り)
・自分で計算した「日本時間の前日」とズレることがある
このインジケーターは、
ブローカーのサーバー時間での前日を基準にしています。
日本時間での前日と比較したい場合は、
サーバー時間との時差を事前に確認してください。
新しい日が始まったらラインを再描画する
毎日1回だけ、ラインを更新する設計にします。
iTimeで新しい日足バーの開始を検知する
datetime currentDay = iTime(NULL, PERIOD_D1, 0);
if(currentDay != g_lastDay)
{
g_lastDay = currentDay;
DrawPivotLines();
}
日足の0本目(今日)の開始時刻が前回と変わった瞬間が、
「新しい日が始まった」タイミングです。
実際に動くコード全体
実際にMetaEditorでコンパイルできる、
PP・R1・S1・R2・S2の5本を自動描画するインジケーターです。
//+------------------------------------------------------------------+
//| PivotPointIndicator.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_buffers 0
input bool InpShowR2S2 = true; //R2/S2も表示するか
datetime g_lastDay = 0;
#define LN_PP "PivotPP"
#define LN_R1 "PivotR1"
#define LN_S1 "PivotS1"
#define LN_R2 "PivotR2"
#define LN_S2 "PivotS2"
void SetLine(string name, double price, color clr, int style)
{
if(ObjectFind(0, name) < 0)
ObjectCreate(0, name, OBJ_HLINE, 0, 0, price);
else
ObjectSetDouble(0, name, OBJPROP_PRICE, price);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, name, OBJPROP_STYLE, style);
}
void DrawPivotLines()
{
double prevHigh = iHigh(NULL, PERIOD_D1, 1);
double prevLow = iLow(NULL, PERIOD_D1, 1);
double prevClose = iClose(NULL, PERIOD_D1, 1);
double pp = (prevHigh + prevLow + prevClose) / 3.0;
double r1 = 2 * pp - prevLow;
double s1 = 2 * pp - prevHigh;
double r2 = pp + (prevHigh - prevLow);
double s2 = pp - (prevHigh - prevLow);
SetLine(LN_PP, pp, clrWhite, STYLE_SOLID);
SetLine(LN_R1, r1, clrTomato, STYLE_DASH);
SetLine(LN_S1, s1, clrDodgerBlue,STYLE_DASH);
if(InpShowR2S2)
{
SetLine(LN_R2, r2, clrTomato, STYLE_DOT);
SetLine(LN_S2, s2, clrDodgerBlue, STYLE_DOT);
}
else
{
ObjectDelete(0, LN_R2);
ObjectDelete(0, LN_S2);
}
}
int OnInit()
{
DrawPivotLines();
g_lastDay = iTime(NULL, PERIOD_D1, 0);
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
ObjectDelete(0, LN_PP);
ObjectDelete(0, LN_R1);
ObjectDelete(0, LN_S1);
ObjectDelete(0, LN_R2);
ObjectDelete(0, LN_S2);
}
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[])
{
datetime currentDay = iTime(NULL, PERIOD_D1, 0);
if(currentDay != g_lastDay)
{
g_lastDay = currentDay;
DrawPivotLines();
}
return(rates_total);
}
MetaEditorでのコンパイル・実行手順
実際にMT4で動かすまでの手順です。
- MetaEditorで新規インジケーター「PivotPointIndicator」を作成し、上のコードを貼り付けてコンパイルする
- エラー・警告が0件であることを確認する
- チャートに適用し、PP(白)・R1(赤破線)・S1(青破線)の3本が表示されることを確認する
- InpShowR2S2をtrueにして、R2・S2が点線で追加表示されることを確認する
- 日付が変わるタイミングで、ラインが新しい前日の値に更新されることを確認する
よくあるエラーと注意点
実装・運用でつまずきやすいポイントをまとめます。
週明け(月曜)はPERIOD_D1の1本前が金曜になる
土日は取引がないため、
月曜のPERIOD_D1の1本前は自動的に金曜になります。
特別な分岐は不要で、iHigh/iLow/iCloseが正しく金曜の値を返します。
チャートの時間足を変えてもラインは変わらない
このコードは常にPERIOD_D1を指定しているため、
チャートをM5にしてもH1にしても、
同じ「前日のピボットポイント」が表示されます。
ObjectFindの第1引数を省略するとMQL5で動かない
MQL4でもObjectFind(0, name)のようにチャートIDを明示しておくと、
将来MQL5へ移行する際にそのまま使える形になります。
よくある質問
ピボットポイントについて、よくある疑問に回答します。
既刊のスイング高値・安値検出とどちらを使うべきですか?
目的によって使い分けます。
直近の値動きから実際に反応があった価格帯を見たいなら既刊のスイング検出、
その日が始まった時点から使える目安が欲しいなら本記事のピボットポイントが向いています。
R2/S2まで見る必要がありますか?
必須ではありません。
まずはPP・R1・S1の3本だけで十分に使え、
R2/S2は値動きが大きく伸びたときの参考値として後回しにして構いません。
このラインをEAの発注条件に使えますか?
使えます。
DrawPivotLines()内のpp・r1・s1の計算部分だけを、
関数として切り出せば、
ブレイクアウトEAなどの発注条件にそのまま転用できます。
【MQL4】前日の高値・安値・終値からピボットポイントを自動描画するインジケーターの作り方:まとめ
ピボットポイントは、前日の確定値から計算式で求める、
デイトレーダーに人気の古典的なサポート・レジスタンス手法です。
既刊のスイング高値・安値検出が「後付けの検出」だったのに対し、
ピボットポイントは「先出しの計算」という別の設計思想を持っています。
まずはPP・R1・S1の3本だけを見ることから始め、
必要に応じてR2・S2を参考値として追加するとよいでしょう。
コメント