証拠金維持率が一定水準を下回ったらLINEで通知するEAは、

既存記事(maginecole-alert-line.md)ですでに解説しました。

ただ、実際に運用していると「維持率30%と言われてもピンとこない、

それより含み損が何万円になったかで判断したい」という声が出てきます。

維持率(%)は口座残高やレバレッジによって同じ危険度でも数字が変わるため、

感覚と結びつきにくいという弱点があります。

この記事では、含み損の金額(円)そのものを基準にし、しかも「警告」

と「危険」の2段階でLINEに通知するEAのアイデアを解説します。

危険ラインを超え続けている間は一定間隔で通知を繰り返す設計にすることで、

通知を1回見逃しただけで含み損が際限なく拡大するリスクにも備えます。

設計思想: なぜ”%”ではなく”円”にしたのか

証拠金維持率は、含み損の大きさをレバレッジや口座残高との相対値として表す指標です。

同じ「含み損5万円」でも、

口座残高10万円の人と100万円の人では維持率への影響が全く違うため、

%表示は口座設計によって危険度の体感が変わってしまいます。

一方で「含み損が5万円を超えたら困る」という感覚は、

多くのトレーダーにとって口座残高に関係なく直感的です。

この記事のEAは、

`AccountBalance() – AccountEquity()`という計算式で、

口座全体の含み損を円建てで算出し、

それを基準に通知するように設計しています。

double GetFloatingLossYen()
  {
   double loss = AccountBalance() - AccountEquity();
   return (loss > 0) ? loss : 0.0;
  }

含み益のときは、

`AccountEquity()`が`AccountBalance()`を上回るため、

`loss`が負の値になりますが、

その場合は0を返すようにして、含み益を「マイナスの含み損」

として誤って扱わないようにしています。

設計思想: 警告と危険、2段階に分けた理由

maginecole-alert-line.mdの既存EAは、

しきい値を1つだけ持ち、それを超えたら通知して、

下回ったら通知状態をリセットする「1段階・一発通知」

の設計でした。

この設計には、含み損が危険水域に入ったあと放置している間にさらに悪化しても、

最初の1回しか通知が来ないという弱点があります。

そこでこの記事のEAでは、

しきい値を`WarningLossYen`(警告)と

`CriticalLossYen`(危険)の2段階に分け、

危険ラインを超えている間は、

`ResendIntervalMinutes`で指定した間隔で、

通知を繰り返す設計にしました。

①警告ライン到達: LINE通知を1回だけ送る(以降は回復するまで再送しない)
②危険ライン到達: Alertのポップアップ+LINE通知を送り、

その後は指定した間隔で「まだ危険ラインを超えたままです」という通知を繰り返す

危険ラインだけ繰り返し通知にしているのは、警告ラインの時点では緊急性が低く、

通知の連打で読者の集中を削ぐ方が問題だと判断したためです。

パラメーターの説明

input string Line_Token            = "";//LINEのアクセストークン
input double WarningLossYen        = 10000;//警告ラインの含み損(円)
input double CriticalLossYen       = 30000;//危険ラインの含み損(円)
input int    ResendIntervalMinutes = 30;//危険ラインを超え続けている間の再通知間隔(分)

`Line_Token`の取得方法は、

line-ea.mdで解説したLINE Notifyの設定手順と同じです。

`WarningLossYen`と`CriticalLossYen`は、

必ず`CriticalLossYen`の方が大きい値になるように設定してください。

`OnInit()`内でこの大小関係が逆になっていないか簡易チェックを入れていますが、

値そのものを自動で補正はしないため、設定ミスは読者自身で気づく必要があります。

実際に動くコード全体

口座全体の含み損を監視し、警告・危険の2段階でLINE通知する、

実際にMetaEditorでコンパイルできるコードです。

//+------------------------------------------------------------------+
//|                                FloatingLossLineAlert-EA.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 string Line_Token            = "";//LINEのアクセストークン
input double WarningLossYen        = 10000;//警告ラインの含み損(円)
input double CriticalLossYen       = 30000;//危険ラインの含み損(円)
input int    ResendIntervalMinutes = 30;//危険ラインを超え続けている間の再通知間隔(分)

bool     warningActive  = false;
bool     criticalActive = false;
datetime lastCriticalTime = 0;

//+------------------------------------------------------------------+
//| 口座全体の含み損(円)を取得する。含み益の場合は0を返す               |
//+------------------------------------------------------------------+
double GetFloatingLossYen()
  {
   double loss = AccountBalance() - AccountEquity();
   return (loss > 0) ? loss : 0.0;
  }

//+------------------------------------------------------------------+
//| LINE Notifyにメッセージを送信する                                  |
//+------------------------------------------------------------------+
void SendLineNotify(string message)
  {
   string url     = "https://notify-api.line.me/api/notify";
   string headers = "Content-Type: application/x-www-form-urlencoded\r\nAuthorization: Bearer " + Line_Token + "\r\n";
   string postData = "message=" + message;

   char   data[];
   char   result[];
   string resultHeaders;

   int len = StringToCharArray(postData, data) - 1;
   ArrayResize(data, len);

   ResetLastError();
   int res = WebRequest("POST", url, headers, 5000, data, result, resultHeaders);

   if(res == -1)
      Print("LINE通知の送信に失敗しました。エラーコード=", GetLastError(),
            "(『ツール』→『オプション』→『EA』タブでnotify-api.line.meが許可URLに登録されているか確認してください)");
   else
      Print("LINE通知を送信しました。message=", message);
  }

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   if(CriticalLossYen <= WarningLossYen)
      Print("警告: CriticalLossYenはWarningLossYenより大きい値にしてください(現在の設定では危険通知が正しい順番で出ません)");
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   double lossYen = GetFloatingLossYen();

   if(lossYen < WarningLossYen)
     {
      warningActive  = false;
      criticalActive = false;
      return;
     }

   if(!warningActive)
     {
      SendLineNotify("含み損が警告ライン(" + DoubleToString(WarningLossYen,0) + "円)を超えました。現在の含み損: " + DoubleToString(lossYen,0) + "円");
      warningActive = true;
     }

   if(lossYen >= CriticalLossYen)
     {
      if(!criticalActive)
        {
         Alert("含み損が危険ライン(", DoubleToString(CriticalLossYen,0), "円)を超えました!");
         SendLineNotify("【危険】含み損が" + DoubleToString(CriticalLossYen,0) + "円を超えました。現在の含み損: " + DoubleToString(lossYen,0) + "円");
         criticalActive   = true;
         lastCriticalTime = TimeCurrent();
        }
      else if(TimeCurrent() - lastCriticalTime >= ResendIntervalMinutes*60)
        {
         SendLineNotify("【危険・継続中】含み損が" + DoubleToString(CriticalLossYen,0) + "円を超えたままです。現在の含み損: " + DoubleToString(lossYen,0) + "円");
         lastCriticalTime = TimeCurrent();
        }
     }
  }
//+------------------------------------------------------------------+

MetaEditorで実際に動かす手順

  1. MT4のMetaEditorで「ファイル」→「新規作成」→「Expert Advisor(テンプレートを使用)」を選び、名前を「FloatingLossLineAlert-EA」にして作成する
  2. テンプレートの中身を全て削除し、上のコードを丸ごと貼り付ける
  3. F7キー(またはコンパイルボタン)でコンパイルし、「0 error(s), 0 warning(s)」になることを確認する
  4. 「ツール」→「オプション」→「エキスパートアドバイザ」タブで、WebRequestを許可するURLリストに「https://notify-api.line.me」を追加する(line-ea.mdの設定手順を参照)
  5. デモ口座のチャートへドラッグ&ドロップし、`Line_Token`に発行済みのトークンを入力して動作を確認する

この設計の限界

この記事のEAは口座全体の含み損を監視しており、

(算出式は`AccountBalance() – AccountEquity()`)

どの通貨ペア・どのポジションが原因かまでは通知メッセージに含めていません。

複数の通貨ペアを同時に運用している場合、

通知を受け取っても「どのポジションを決済すればよいか」

は読者自身がMT4の画面を開いて確認する必要があります。

原因ポジションまで特定したい場合は、

`OrdersTotal()`でループしながら、

`OrderProfit()`+`OrderSwap()`+

`OrderCommission()`の合計が最も大きい、

(マイナス方向に大きい)チケットを探し、

通知メッセージにシンボル名やチケット番号を含める改良が考えられます。

コピペしてコンパイルが通らない・通知が来ないときに確認すること

  • WebRequestを許可するURLリストに「https://notify-api.line.me」を追加し忘れていないか(追加していないとエラーコード4060が返り、通知が一切送信されない)
  • `Line_Token`が空文字のままになっていないか(空文字でもコンパイルは通るが、LINE Notify側が認証エラーを返す)
  • `CriticalLossYen`を`WarningLossYen`より小さい値に設定していないか(この場合、`OnInit()`で警告メッセージがログに出るがEA自体は動き続けるため、意図しない挙動に気づきにくい)
  • デモ口座で含み損を意図的に作れない場合、`WarningLossYen`・`CriticalLossYen`を極端に小さい値(例: 100円)に一時的に下げて動作確認するとよい

まとめ

証拠金維持率(%)は口座残高によって体感が変わるため、

この記事では含み損の金額(円)そのものを基準にしたEAを解説しました。

警告ラインは一度だけ、

危険ラインは回復するまで一定間隔で繰り返し通知する2段階設計にすることで、

通知を1回見逃しただけで含み損が際限なく拡大するリスクを減らせます。

どのポジションが原因かまで通知したい場合は、

`OrderProfit()`等でポジション単位のループを追加してみてください。

関連記事