This script functions as an automated monitoring and notification system for your trading account. Instead of executing trades itself, it acts as a "watchdog" that tracks every action taken on your active orders—whether manual or automated—and alerts you in real-time.
Core Functionality
The script continuously scans your open positions and pending orders. It compares the current state of your trading account against the previous state to identify specific events. When it detects a change, it can trigger three types of notifications based on your preferences:
- Visual Alerts: Pop-up messages on your trading screen.
- Audio Alerts: Sound files played through your speakers.
- Email Notifications: Direct messages sent to your registered email address.
Key Events Monitored
The logic is designed to recognize and report the following specific activities:
1. New Order Execution
- Market Orders: Notifies you immediately when a Buy or Sell order is opened in the live market.
- Pending Orders: Alerts you when new "limit" or "stop" orders are placed (e.g., Buy Limits, Sell Stops).
2. Order Modifications
- The script detects if you change the price, stop-loss, or take-profit levels of any existing order. It differentiates between modifications made to active market trades and those made to pending orders.
3. Trade Completions & Closures
- Profit/Loss Targets: If a trade closes specifically because it hit your Take Profit or Stop Loss levels, the script identifies this and notifies you.
- Manual/General Closures: If a trade is closed at any other price (such as a manual exit), it provides an alert showing the closing price and the final profit or loss in currency.
4. Pending Order Management
- The script monitors for the deletion of pending orders, notifying you if a limit or stop order is removed from the books before it has a chance to trigger.
How It Works Internally
To ensure accuracy, the script maintains a "memory" of your account. Every time it runs, it takes a snapshot of all current tickets, symbols, types, and prices. It then compares this new snapshot to the memory of the previous one. If it finds a discrepancy (like a ticket that was there before but is gone now, or a price that has changed), it determines which specific event occurred and sends out the corresponding notification.
//+------------------------------------------------------------------+
//| FX-EVENTS.mq4 |
//| Copyright © 2007, MetaQuotes Software Corp. |
//| http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, MetaQuotes Software Corp."
#property link "http://www.metaquotes.net"
#property indicator_chart_window
bool Show_Alert=true;//îòêðûâàòü îêíî ñîîáùåíèé
bool Play_Sound=false;//èãðàòü çâóê (ñîâìåñòíî ñ àëåðòîì ìîæåò ïëîõî èãðàòü)
string SoundFile="news.wav";//çâóêîâîé ôàéë (äîëæåí áûòü â êàòàëîãå sounds)
bool Send_Mail=false;//îòïðàâëÿòü åìàéë (íóæíî íàñòðîèòü â òåðìèíàëå)
string s0="==============================";
bool MarketOpen=false;//îòêðûòèå ðûíî÷íîãî îðäåðà (íå ñðàáàòûâàíèå îòëîæåííîãî!)
bool MarketClose=false;//çàêðûòèå ðûíî÷íîãî îðäåðà, íî íå ïî ñòîïëîññ èëè òéåêïðîôèò
bool MarketStopLoss=true;//çàêðûòèå ðûíî÷íîãî ïî ñë
bool MarketTakeProfit=true;//çàêðûòèå ðûíî÷íîãî ïî òï
bool PendingSet=false;//óñòàíîâêà îòëîæåííîãî
bool PendingDelete=false;//óäàëåíèå îòëîæåííîãî
bool PendingOpen=true;//ñðàáàòûâàíèå îòëîæåííîãî
bool MarketModify=false;//ìîäèôèêàöèÿ ñòîïëîññ èëè òåéêïðîôèò
bool PendingModify=false;//ìîäèôèêàöèÿ îòëîæåíííîãî
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- indicators
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
static bool ft;
//----
static int LastTicketList[];
static string LastSymbolList[];
static int LastOrderType[];
static double LastOrderOpenPrice[];
static double LastOrderStopLoss[];
static double LastOrderTakeProfit[];
static double LastOrderLots[];
int CurrTicketList[];
string CurrSymbolList[];
int CurrOrderType[];
double CurrOrderOpenPrice[];
double CurrOrderStopLoss[];
double CurrOrderTakeProfit[];
double CurrOrderLots[];
ArrayResize(CurrTicketList,0);
ArrayResize(CurrSymbolList,0);
ArrayResize(CurrOrderType,0);
ArrayResize(CurrOrderOpenPrice,0);
ArrayResize(CurrOrderStopLoss,0);
ArrayResize(CurrOrderTakeProfit,0);
ArrayResize(CurrOrderLots,0);
for(int i=0;i<OrdersTotal();i++){
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)){
ArrayResize(CurrTicketList,ArraySize(CurrTicketList)+1);
ArrayResize(CurrSymbolList,ArraySize(CurrSymbolList)+1);
ArrayResize(CurrOrderType,ArraySize(CurrOrderType)+1);
ArrayResize(CurrOrderOpenPrice,ArraySize(CurrOrderOpenPrice)+1);
ArrayResize(CurrOrderStopLoss,ArraySize(CurrOrderStopLoss)+1);
ArrayResize(CurrOrderTakeProfit,ArraySize(CurrOrderTakeProfit)+1);
ArrayResize(CurrOrderLots,ArraySize(CurrOrderLots)+1);
CurrTicketList[ArraySize(CurrTicketList)-1]=OrderTicket();
CurrSymbolList[ArraySize(CurrSymbolList)-1]=OrderSymbol();
CurrOrderType[ArraySize(CurrOrderType)-1]=OrderType();
CurrOrderOpenPrice[ArraySize(CurrOrderOpenPrice)-1]=OrderOpenPrice();
CurrOrderStopLoss[ArraySize(CurrOrderStopLoss)-1]=OrderStopLoss();
CurrOrderTakeProfit[ArraySize(CurrOrderTakeProfit)-1]=OrderTakeProfit();
CurrOrderLots[ArraySize(CurrOrderLots)-1]=OrderLots();
}
else{
return(0);
}
}
//=================================================================================
if(ft){
for(i=0;i<ArraySize(CurrTicketList);i++){
bool NewOrder=true;
for(int j=0;j<ArraySize(LastTicketList);j++){
if(CurrTicketList[i]==LastTicketList[j]){
NewOrder=false;
//èçìåíåíèå òèïà
if(CurrOrderType[i]!=LastOrderType[j]){
if(CurrOrderType[i]==OP_BUY){
if(LastOrderType[j]==OP_BUYLIMIT){
if(PendingOpen){
//========== Open BUYLIMIT ========== 1
if(Show_Alert)Alert(CurrSymbolList[i]+" "+"BUYLIMIT "+LastTicketList[j]+" -> BUY ");
if(Play_Sound)PlaySound(SoundFile);
if(Send_Mail)SendMail("Order Event",CurrSymbolList[i]+" "+"BUYLIMIT "+LastTicketList[j]+" -> BUY ");
}
}
if(LastOrderType[j]==OP_BUYSTOP){
if(PendingOpen){
//========== Open BUYSTOP ========== 2
if(Show_Alert)Alert(CurrSymbolList[i]+" "+"BUYSTOP "+LastTicketList[j]+" -> BUY ");
if(Play_Sound)PlaySound(SoundFile);
if(Send_Mail)SendMail("Order Event",CurrSymbolList[i]+" "+"BUYSTOP "+LastTicketList[j]+" -> BUY ");
}
}
}
if(CurrOrderType[i]==OP_SELL){
if(LastOrderType[j]==OP_SELLLIMIT){
if(PendingOpen){
//========== Open SELLLIMIT ========== 3
if(Show_Alert)Alert(CurrSymbolList[i]+" "+"SELLLIMIT "+LastTicketList[j]+" -> SELL ");
if(Play_Sound)PlaySound(SoundFile);
if(Send_Mail)SendMail("Order Event",CurrSymbolList[i]+" "+"SELLLIMIT "+LastTicketList[j]+" -> SELL ");
}
}
if(LastOrderType[j]==OP_SELLSTOP){
if(PendingOpen){
//========== Open SELLSTOP ========== 4
if(Show_Alert)Alert(CurrSymbolList[i]+" "+"SELLSTOP "+LastTicketList[j]+" -> SELL ");
if(Play_Sound)PlaySound(SoundFile);
if(Send_Mail)SendMail("Order Event",CurrSymbolList[i]+" "+"SELLSTOP "+LastTicketList[j]+" -> SELL ");
}
}
}
}
//ìîäèôèêàöèÿ
if(CurrOrderOpenPrice[i]!=LastOrderOpenPrice[i] || CurrOrderStopLoss[i]!=LastOrderStopLoss[i] || CurrOrderTakeProfit[i]!=LastOrderTakeProfit[i]){
if(CurrOrderType[i]==OP_BUY){
if(MarketModify){
//========== Modify BUY ========== 5
if(Show_Alert)Alert(CurrSymbolList[i]+" "+"BUY "+LastTicketList[j]+" modified ");
if(Play_Sound)PlaySound(SoundFile);
if(Send_Mail)SendMail("Order Event",CurrSymbolList[i]+" "+"BUY "+LastTicketList[j]+" modified ");
}
}
if(CurrOrderType[i]==OP_SELL){
if(MarketModify){
//========== Modify SELL ========== 6
if(Show_Alert)Alert(CurrSymbolList[i]+" "+"SELL "+LastTicketList[j]+" modified ");
if(Play_Sound)PlaySound(SoundFile);
if(Send_Mail)SendMail("Order Event",CurrSymbolList[i]+" "+"SELL "+LastTicketList[j]+" modified ");
}
}
if(CurrOrderType[i]==OP_BUYSTOP){
if(PendingModify){
//========== Modify BUYSTOP ========== 7
if(Show_Alert)Alert(CurrSymbolList[i]+" "+"BUYSTOP "+LastTicketList[j]+" modified ");
if(Play_Sound)PlaySound(SoundFile);
if(Send_Mail)SendMail("Order Event",CurrSymbolList[i]+" "+"BUYSTOP "+LastTicketList[j]+" modified ");
}
}
if(CurrOrderType[i]==OP_SELLSTOP){
if(PendingModify){
//========== Modify SELLSTOP ========== 8
if(Show_Alert)Alert(CurrSymbolList[i]+" "+"SELLSTOP "+LastTicketList[j]+" modified ");
if(Play_Sound)PlaySound(SoundFile);
if(Send_Mail)SendMail("Order Event",CurrSymbolList[i]+" "+"SELLSTOP "+LastTicketList[j]+" modified ");
}
}
if(CurrOrderType[i]==OP_BUYLIMIT){
if(PendingModify){
//========== Modify BUYLIMIT ========== 9
if(Show_Alert)Alert(CurrSymbolList[i]+" "+"BUYLIMIT "+LastTicketList[j]+" modified ");
if(Play_Sound)PlaySound(SoundFile);
if(Send_Mail)SendMail("Order Event",CurrSymbolList[i]+" "+"BUYLIMIT "+LastTicketList[j]+" modified ");
}
}
if(CurrOrderType[i]==OP_SELLLIMIT){
if(PendingModify){
//========== Modify SELLLIMIT ========== 10
if(Show_Alert)Alert(CurrSymbolList[i]+" "+"SELLLIMIT "+LastTicketList[j]+" modified ");
if(Play_Sound)PlaySound(SoundFile);
if(Send_Mail)SendMail("Order Event",CurrSymbolList[i]+" "+"SELLLIMIT "+LastTicketList[j]+" modified ");
}
}
}
}
}
//ïîÿâëåíèå íîâîãî îðäåðà
if(NewOrder){
if(CurrOrderType[i]==OP_BUY){
if(MarketOpen){
//========== Market BUY Open ========== 11
if(Show_Alert)Alert(CurrSymbolList[i]+" "+"BUY "+CurrTicketList[i]+" opened ");
if(Play_Sound)PlaySound(SoundFile);
if(Send_Mail)SendMail("Order Event",CurrSymbolList[i]+" "+"BUY "+CurrTicketList[i]+" opened ");
}
}
if(CurrOrderType[i]==OP_SELL){
if(MarketOpen){
//========== Market SELL Open ========== 12
if(Show_Alert)Alert(CurrSymbolList[i]+" "+"SELL "+CurrTicketList[i]+" opened ");
if(Play_Sound)PlaySound(SoundFile);
if(Send_Mail)SendMail("Order Event",CurrSymbolList[i]+" "+"SELL "+CurrTicketList[i]+" opened ");
}
}
if(CurrOrderType[i]==OP_BUYSTOP){
if(PendingSet){
//========== BUYSTOP Set ========== 13
if(Show_Alert)Alert(CurrSymbolList[i]+" "+"BUYSTOP "+CurrTicketList[i]+" placed ");
if(Play_Sound)PlaySound(SoundFile);
if(Send_Mail)SendMail("Order Event",CurrSymbolList[i]+" "+"BUYSTOP "+CurrTicketList[i]+" placed ");
}
}
if(CurrOrderType[i]==OP_SELLSTOP){
if(PendingSet){
//========== SELLSTOP Set ========== 14
if(Show_Alert)Alert(CurrSymbolList[i]+" "+"SELLSTOP "+CurrTicketList[i]+" placed ");
if(Play_Sound)PlaySound(SoundFile);
if(Send_Mail)SendMail("Order Event",CurrSymbolList[i]+" "+"SELLSTOP "+CurrTicketList[i]+" placed ");
}
}
if(CurrOrderType[i]==OP_BUYLIMIT){
if(PendingSet){
//========== BUYLIMIT Set ========== 15
if(Show_Alert)Alert(CurrSymbolList[i]+" "+"BUYLIMIT "+CurrTicketList[i]+" placed ");
if(Play_Sound)PlaySound(SoundFile);
if(Send_Mail)SendMail("Order Event",CurrSymbolList[i]+" "+"BUYLIMIT "+CurrTicketList[i]+" placed ");
}
}
if(CurrOrderType[i]==OP_SELLLIMIT){
if(PendingSet){
//========== SELLLIMIT Set ========== 16
if(Show_Alert)Alert(CurrSymbolList[i]+" "+"SELLLIMIT "+CurrTicketList[i]+" placed ");
if(Play_Sound)PlaySound(SoundFile);
if(Send_Mail)SendMail("Order Event",CurrSymbolList[i]+" "+"SELLLIMIT "+CurrTicketList[i]+" placed ");
}
}
}
}
//---- èñ÷åçåíîâåíèå îðäåðà: çàêðûòèå, óäàëåíèå, ñë, òï
for(i=0;i<ArraySize(LastTicketList);i++){
bool OrderExist=false;
for(j=0;j<ArraySize(CurrTicketList);j++){
if(LastTicketList[i]==CurrTicketList[j]){
OrderExist=true;
}
}
if(!OrderExist){
if(LastOrderType[i]==OP_BUY){
if(OrderSelect(LastTicketList[i],SELECT_BY_TICKET)){
if(ND(OrderClosePrice())>=ND(OrderTakeProfit()) && ND(OrderTakeProfit())!=0){
if(MarketTakeProfit){
//========== BUY TP ========== 17
if(Show_Alert)Alert(LastSymbolList[i]+" "+"BUY "+LastTicketList[i]+" closed by TakeProfit ");
if(Play_Sound)PlaySound(SoundFile);
if(Send_Mail)SendMail("Order Event",LastSymbolList[i]+" "+"BUY "+LastTicketList[i]+" closed by TakeProfit ");
}
}
else{
if(ND(OrderClosePrice())<=ND(OrderStopLoss()) && ND(OrderStopLoss())!=0){
if(MarketStopLoss){
//========== BUY SL ========== 18
if(Show_Alert)Alert(LastSymbolList[i]+" "+"BUY "+LastTicketList[i]+" closed by StopLoss ");
if(Play_Sound)PlaySound(SoundFile);
if(Send_Mail)SendMail("Order Event",LastSymbolList[i]+" "+"BUY "+LastTicketList[i]+" closed by StopLoss ");
}
}
else{
if(MarketClose){
//========== BUY Close ========== 19
if(Show_Alert)Alert(LastSymbolList[i]+" "+"BUY "+LastTicketList[i]+" closed at "+DS(OrderClosePrice())+" ");
if(Play_Sound)PlaySound(SoundFile);
if(Send_Mail)SendMail("Order Event",LastSymbolList[i]+" "+"BUY "+LastTicketList[i]+" closed at "+DS(OrderClosePrice())+" ($"+DS2(OrderProfit())+")");
}
}
}
}
else{
if(MarketTakeProfit || MarketStopLoss || MarketClose){
//========== BUY Undefined Close ========== 20
if(Show_Alert)Alert(LastSymbolList[i]+" "+"BUY "+LastTicketList[i]+" closed (undefined method)");
if(Play_Sound)PlaySound(SoundFile);
if(Send_Mail)SendMail("Order Event",LastSymbolList[i]+" "+"BUY "+LastTicketList[i]+" closed (undefined method)");
}
}
}
if(LastOrderType[i]==OP_SELL){
if(OrderSelect(LastTicketList[i],SELECT_BY_TICKET)){
if(ND(OrderClosePrice())<=ND(OrderTakeProfit()) && ND(OrderTakeProfit())!=0.0){
if(MarketTakeProfit){
//========== SELL TP ========== 21
if(Show_Alert)Alert(LastSymbolList[i]+" "+"SELL "+LastTicketList[i]+" closed by TakeProfit ");
if(Play_Sound)PlaySound(SoundFile);
if(Send_Mail)SendMail("Order Event",LastSymbolList[i]+" "+"SELL "+LastTicketList[i]+" closed by TakeProfit ");
}
}
else{
if(ND(OrderClosePrice())>=ND(OrderStopLoss()) && ND(OrderStopLoss())!=0.0){
if(MarketStopLoss){
//========== SELL SL ========== 22
if(Show_Alert)Alert(LastSymbolList[i]+" "+"SELL "+LastTicketList[i]+" closed by StopLoss ");
if(Play_Sound)PlaySound(SoundFile);
if(Send_Mail)SendMail("Order Event",LastSymbolList[i]+" "+"SELL "+LastTicketList[i]+" closed by StopLoss ");
}
}
else{
if(MarketClose){
//========== SELL Close ========== 23
if(Show_Alert)Alert(LastSymbolList[i]+" "+"BUY "+LastTicketList[i]+" closed at "+DS(OrderClosePrice())+" ");
if(Play_Sound)PlaySound(SoundFile);
if(Send_Mail)SendMail("Order Event",LastSymbolList[i]+" "+"BUY "+LastTicketList[i]+" closed at "+DS(OrderClosePrice())+" ");
}
}
}
}
else{
if(MarketTakeProfit || MarketStopLoss || MarketClose){
//========== SELL Undefined Close ========== 24
if(Show_Alert)Alert(LastSymbolList[i]+" "+"SELL "+LastTicketList[i]+" closed (undefined method)");
if(Play_Sound)PlaySound(SoundFile);
if(Send_Mail)SendMail("Order Event",LastSymbolList[i]+" "+"SELL "+LastTicketList[i]+" closed (undefined method)");
}
}
}
if(LastOrderType[i]==OP_BUYSTOP){
if(PendingDelete){
//========== BUYSTOP Delete ========== 25
if(Show_Alert)Alert(LastSymbolList[i]+" "+"BUYSTOP "+LastTicketList[i]+" deleted");
if(Play_Sound)PlaySound(SoundFile);
if(Send_Mail)SendMail("Order Event",LastSymbolList[i]+" "+"BUYSTOP "+LastTicketList[i]+" deleted");
}
}
if(LastOrderType[i]==OP_SELLSTOP){
if(PendingDelete){
//========== SELLSTOP Delete ========== 26
if(Show_Alert)Alert(LastSymbolList[i]+" "+"SELLSTOP "+LastTicketList[i]+" deleted");
if(Play_Sound)PlaySound(SoundFile);
if(Send_Mail)SendMail("Order Event",LastSymbolList[i]+" "+"SELLSTOP "+LastTicketList[i]+" deleted");
}
}
if(LastOrderType[i]==OP_BUYLIMIT){
if(PendingDelete){
//========== BUYLIMIT Delete ========== 27
if(Show_Alert)Alert(LastSymbolList[i]+" "+"BUYLIMIT "+LastTicketList[i]+" deleted");
if(Play_Sound)PlaySound(SoundFile);
if(Send_Mail)SendMail("Order Event",LastSymbolList[i]+" "+"BUYLIMIT "+LastTicketList[i]+" deleted");
}
}
if(LastOrderType[i]==OP_SELLLIMIT){
if(PendingDelete){
//========== SELLLIMIT Delete ========== 28
if(Show_Alert)Alert(LastSymbolList[i]+" "+"SELLLIMIT "+LastTicketList[i]+" deleted");
if(Play_Sound)PlaySound(SoundFile);
if(Send_Mail)SendMail("Order Event",LastSymbolList[i]+" "+"SELLLIMIT "+LastTicketList[i]+" deleted");
}
}
}
}
}
//=================================================================================
ArrayResize(LastTicketList,ArraySize(CurrTicketList));
ArrayResize(LastSymbolList,ArraySize(CurrSymbolList));
ArrayResize(LastOrderType,ArraySize(CurrOrderType));
ArrayResize(LastOrderOpenPrice,ArraySize(CurrOrderOpenPrice));
ArrayResize(LastOrderStopLoss,ArraySize(CurrOrderStopLoss));
ArrayResize(LastOrderTakeProfit,ArraySize(CurrOrderTakeProfit));
ArrayResize(LastOrderLots,ArraySize(CurrOrderLots));
if(ArraySize(CurrTicketList)>0){
ArrayCopy(LastTicketList,CurrTicketList,0,0,ArraySize(CurrTicketList));
ArrayCopy(LastSymbolList,CurrSymbolList,0,0,ArraySize(CurrSymbolList));
ArrayCopy(LastOrderType,CurrOrderType,0,0,ArraySize(CurrOrderType));
ArrayCopy(LastOrderOpenPrice,CurrOrderOpenPrice,0,0,ArraySize(CurrOrderOpenPrice));
ArrayCopy(LastOrderStopLoss,CurrOrderStopLoss,0,0,ArraySize(CurrOrderStopLoss));
ArrayCopy(LastOrderTakeProfit,CurrOrderTakeProfit,0,0,ArraySize(CurrOrderTakeProfit));
ArrayCopy(LastOrderLots,CurrOrderLots,0,0,ArraySize(CurrOrderLots));
}
ft=true;
//----
return(0);
}
//+------------------------------------------------------------------+
string DS2(double v){
return(DoubleToStr(v,2));
}
string DS(double v){
return(DoubleToStr(v,Digits));
}
double ND(double v){
return(NormalizeDouble(v,Digits));
}
Comments