以前の記事(ゴールデンクロス・デッドクロスEA)では、損切り幅(StopLoss)を10pipsのような固定値で設定していました。
ですが、値動きが小さいレンジ相場と、値動きが大きいトレンド相場で同じ10pipsを使うと、
レンジ相場では余裕を持ちすぎ、トレンド相場ではあっさり損切りに引っかかる、
という不釣り合いが起きます。
この記事では、相場の変動幅そのものを数値化する`iATR()`関数を使って、
損切り幅を相場に合わせて自動調整する方法を解説します。
ATR(平均真の値幅)とは何か
ATR(Average True Range、平均真の値幅)は、
直近の値動きの大きさを1本の数値で表す指標です。
値が大きいほど値動きが荒く、小さいほど値動きが穏やかであることを意味します。
MT4では、この値をチャートに描画せずに直接取得できる`iATR()`関数が用意されています。
double iATR( string symbol, //通貨ペア(NULLで現在のチャート) int timeframe, //時間足(0で現在のチャートの時間足) int period, //ATRの計算期間(本数) int shift //何本前の足を見るか(0=最新、1=1つ前の確定足) );
戻り値は価格の単位そのもの(pipsではなく通貨ペアの価格差)です。
たとえばUSDJPYで`iATR()`が0.350を返した場合、
直近の値動きの平均が約35pips(5桁表示の場合)相当であることを意味します。
shift引数の落とし穴
`iATR()`の第4引数`shift`は、`iMA()`などと同じ考え方で「何本前の足を見るか」
を指定します。
`shift=0`を指定すると、まだ確定していない「形成中の足」のATRを返します。
形成中の足は値が動くたびに変化するため、EAの判定に使うと毎ティック微妙に違う値を参照してしまい、
意図しない挙動につながります。
損切り幅の計算のように「直近で確定した値動きの大きさ」を基準にしたい場合は、
`shift=1`(直近に確定した1本前の足)を指定するのが安全です。
double atr = iATR(NULL, 0, 14, 1);//1つ前の確定足のATR
ATRを損切り幅に変換する
取得したATRの値に倍率(ATRMultiplier)を掛けることで、
損切り幅を計算します。
倍率は相場やEAの方針によって調整しますが、1.5〜2.0倍が目安としてよく使われます。
double atr = iATR(NULL, 0, ATRPeriod, 1);
if(atr <= 0)
{
Print("iATRの取得に失敗しました。エラーコード=", GetLastError());
return;
}
double slDistance = atr * ATRMultiplier;
double buySL = Ask - slDistance;//買いエントリーの損切りライン
double sellSL = Bid + slDistance;//売りエントリーの損切りライン
`iATR()`は、データがまだ揃っていない(チャートを開いた直後で指定期間分の履歴が読み込まれていない)場合に0を返すことがあります。
前の記事で扱った`OrderSend()`のStopLossと同様、
0のまま損切り価格の計算に使うと不正な値になるため、必ず戻り値をチェックしてください。
実際に動くコード全体
ここまでの内容をまとめた、現在のATRと、そこから計算した推奨損切りラインをチャート左上に表示する、
実際にMetaEditorでコンパイルできるインジケーターです。
//+------------------------------------------------------------------+
//| ATRStopDemo.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 int ATRPeriod = 14;//ATR計算期間
input double ATRMultiplier = 1.5;//ATRに掛ける倍率
//このインジケーターはチャートに線を描かず、値をComment()で表示するだけなので、
//バッファ0個で問題ありません(線を描く場合は1以上が必要です)。
//+------------------------------------------------------------------+
//| 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[])
{
double atr = iATR(NULL, 0, ATRPeriod, 1);//1つ前の確定足のATR
if(atr <= 0)
{
Comment("iATRの取得に失敗しました。エラーコード=", GetLastError());
return(rates_total);
}
double slDistance = atr * ATRMultiplier;
double buySL = Bid - slDistance;
double sellSL = Ask + slDistance;
Comment(
"ATR(", ATRPeriod, ")= ", DoubleToString(atr, Digits), "\n",
"推奨損切り幅(ATR×", DoubleToString(ATRMultiplier, 1), ")= ", DoubleToString(slDistance, Digits), "\n",
"買いなら損切りライン: ", DoubleToString(buySL, Digits), "\n",
"売りなら損切りライン: ", DoubleToString(sellSL, Digits)
);
return(rates_total);
}
//+------------------------------------------------------------------+
MetaEditorで実際に動かす手順
- MT4の「ツール」→「MetaQuotes Language Editor」でMetaEditorを開く
- 「ファイル」→「新規作成」→「インジケーター」を選び、名前を「ATRStopDemo」にして作成する(中身は空のテンプレートで構いません)
- テンプレートの中身を全て削除し、上のコードを丸ごと貼り付ける
- F7キー(またはコンパイルボタン)でコンパイルし、「0 error(s), 0 warning(s)」になることを確認する
- MT4の「ナビゲーター」パネルからインジケーターを探し、チャートへドラッグ&ドロップする
- チャート左上にATRの値と推奨損切りラインが表示されれば成功です
コピペしてコンパイルが通らないときに確認すること
- 拡張子が「.mq4」になっているか
- `OnCalculate()`の引数の数・型が1文字も欠けていないか(コピペ時に1行欠けるとコンパイルエラーになります)
- ATRの値が常に0で表示される場合、チャートを開いた直後で`ATRPeriod`分の過去データがまだ読み込まれていない可能性があります。しばらく待つか、通貨ペアの履歴データをダウンロードし直してください
まとめ
`iATR()`を使うと、固定pipsではなく相場の実際の値動きの大きさに合わせて損切り幅を計算できます。
EA記事群で繰り返し指摘してきた「損切り未設定・固定値のまま」
という問題に対して、ATRベースの動的な損切りは実務でもよく使われる改善策です。
今回計算した`slDistance`は、そのまま以前の記事のOrderSend()の損切り価格の計算に組み込めます。
コメント