OrderGuardian

Download script
Author: Greatshore
OrderGuardian

This script, titled OrderGuardian, is designed as an automated management tool for your trading platform. Its primary purpose is to monitor open trades and automatically execute "Take Profit" (TP) or "Stop Loss" (SL) actions based on specific mathematical calculations or visual indicators you place on your chart.

Core Functionality

The script acts as a watchful supervisor. It scans your active trading positions and identifies which ones need protection or profit-taking. Instead of relying solely on fixed price levels, it can dynamically calculate these targets using technical indicators or by "reading" the geometry of objects you have drawn manually on the chart.

How It Works

1. Target Identification (Where to Exit) The tool provides different methods for determining your exit prices:

  • Moving Average & Envelopes: You can set the script to calculate a profit or loss level based on moving averages. It looks at specific timeframes and periods to create a dynamic "buffer" around the price.
  • Visual Objects (Trendlines & Channels): This is a sophisticated feature where the script scans your chart for manually drawn Trendlines or Channels.
    • For a Buy position, it automatically looks for the nearest line above the current price to use as a profit target and the nearest line below to use as a stop loss.
    • For a Sell position, it flips this logic, looking for the nearest line below for profit and above for risk management.
  • Parabolic SAR: For stop losses specifically, it can also use the Parabolic SAR indicator to determine the safest exit point based on volatility.

2. Order Monitoring & Execution Once the script knows where your targets are, it performs the following actions:

  • Real-Time Tracking: It constantly compares the current market price against the calculated Take Profit and Stop Loss levels.
  • Automatic Closure: If the market hits one of these target prices, the script immediately sends a command to close the corresponding trade.
  • Visual Feedback: To keep you informed, the script can draw physical dashed lines on your chart at the current calculated Take Profit and Stop Loss levels. It also displays a text summary on your screen showing exactly what those prices are (e.g., "S/L @ [Price] T/P @ [Price]").

3. Smart Filtering The script is designed to be precise. It can be configured to manage all trades, or you can specify specific trade tickets. It also ensures it only acts on the correct asset (currency pair/instrument) to prevent accidental interference with other charts you might have open.

Summary for the User

Think of OrderGuardian as an automated "Safety Net." You don't have to manually watch the charts to see if your trade hit a trendline or a moving average. You simply draw your lines or set your technical preferences, and the script handles the heavy lifting of monitoring those levels and closing your trades at the exact moment the conditions are met.

Orders Execution
Checks for the total of open ordersIt Closes Orders by itself
Indicators Used
Moving average indicatorParabolic Stop and Reverse system
12 Views
0 Downloads
0 Favorites
OrderGuardian
//+------------------------------------------------------------------+
//|                                                OrderGuardian.mq4 |
//|                                                       Greatshore |
//|                                               greatshore@live.cn |
//+------------------------------------------------------------------+
#property copyright "Greatshore"
#property link      "greatshore@live.cn"

#define TP_PRICE_LINE "OG TP Price Line"
#define SL_PRICE_LINE "OG SL Price Line"

//---- input parameters
extern string  Orders          = "*";           // ¹ÜÀíÄÄЩ¶©µ¥
extern int     TP_Method       = 2;             // »ñÀû·½Ê½£º1-Envelopes°üÂçÏߺ;ùÏߣ¬2-Ç÷ÊÆÏß
extern int     SL_Method       = 2;             // »ñÀû·½Ê½£º1-Envelopes°üÂçÏߺ;ùÏߣ¬2-Ç÷ÊÆÏß, 3-SAR
extern bool    ShowLines       = true;          // ÊÇ·ñÏÔʾ»ñÀûÖ¹ËðÏß
extern string  SPLIT1          = "=== Parameters for TP ===";
extern color   TP_LineColor    = LimeGreen;     // »ñÀû¼Û¸ñÏßÑÕÉ«
extern int     TP_TimeFrame    = 0;             // »ñÀû¼Û¼ÆËãµÄʱ¼äͼÖÜÆÚ
extern int     TP_MA_Period    = 31;            // »ñÀû¾ùÏßÖÜÆÚ
extern int     TP_MA_Method    = MODE_EMA;      // »ñÀû¾ùÏß¼ÆËã·½·¨
extern int     TP_MA_Price     = PRICE_CLOSE;   // »ñÀû¾ùÏß¼ÆËã¼Û¸ñ
extern double  TP_Env_Dev      = 0.2;           // »ñÀûEnvelopesÆ«sÒÆ°Ù·Ö±È
extern int     TP_Shift        = 0;             // »ñÀû¼Û¼ÆËãµÄshiftÖµ
extern string  SPLIT2          = "=== Parameters of SL ===";
extern color   SL_LineColor    = Red;           // Ö¹Ëð¼Û¸ñÏßÑÕÉ«
extern int     SL_TimeFrame    = 0;             // Ö¹Ëð¼Û¼ÆËãµÄʱ¼äͼÖÜÆÚ
extern int     SL_MA_Period    = 31;            // Ö¹Ëð¾ùÏß¼ÆËã·½·¨
extern int     SL_MA_Method    = MODE_EMA;      // Ö¹Ëð¾ùÏß¼ÆËã·½·¨
extern int     SL_MA_Price     = PRICE_CLOSE;   // Ö¹Ëð¾ùÏß¼ÆËã¼Û¸ñ
extern double  SL_Env_Dev      = 0;             // Ö¹ËðEnvelopesÆ«ÒÆ°Ù·Ö±È
extern double  SL_SARStep      = 0.02;          // SARÖ¹ËðµÄ²½³¤
extern double  SL_SARMax       = 0.5;           // SARÖ¹Ëð×î´óÖµ
extern int     SL_Shift        = 0;             // Ö¹Ëð¼Û¼ÆËãµÄshiftÖµ

string TPObjName, SLObjName;
int    OrdersID[], OrdersCount, OpType;

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
{
  if ((SL_Method == 3) && (SL_Shift < 1))
    SL_Shift = 1;

  return(0);
}

//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
{
  ObjectDelete(TP_PRICE_LINE);
  ObjectDelete(SL_PRICE_LINE);
  Comment("");

  return(0);
}

//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
{
  int i;
  double TPPrice, SLPrice;
  bool   SetTPObj = false, SetSLObj = false;
  string MesgText;

  GetOrdersID();     // »ñÈ¡ÐèÒª¹ÜÀíµÄ¶©µ¥ID
  if (OpType >= 0)   // ·½ÏòÒ»ÖÂ
  {
    if (TP_Method == 2)
      SetTPObj = FindObject(TPObjName) < 0;
    if (SL_Method == 2)
      SetSLObj = FindObject(SLObjName) < 0;
    if (SetTPObj || SetSLObj)
      SearchObjName(OpType, SetTPObj, SetSLObj);         // ËÑѰ»ñÀûÖ¹ËðÏߵĶÔÏóÃû

    CalcPrice(TPPrice, SLPrice);
    MesgText = "S/L @ ";
    if (SLPrice < 0)
      MesgText = MesgText + " __ ";
    else
      MesgText = MesgText + DoubleToStr(SLPrice, Digits);
    MesgText = MesgText + "   T/P @ ";
    if (TPPrice < 0)
      MesgText = MesgText + " __ ";
    else
      MesgText = MesgText + DoubleToStr(TPPrice, Digits);
    Comment(MesgText);

    if (ShowLines)
      ShowTPSLLines(TPPrice, SLPrice);
    for (i = 0; i < OrdersCount; i++)
    {
      if ((SLPrice > 0) &&
          (((OpType == OP_BUY)  && (Bid <= SLPrice)) ||
           ((OpType == OP_SELL) && (Bid >= SLPrice))))
        CloseOrder(OrdersID[i], 1);
      if ((TPPrice > 0) &&
          (((OpType == OP_BUY)  && (Bid >= TPPrice)) ||
           ((OpType == OP_SELL) && (Bid <= TPPrice))))
        CloseOrder(OrdersID[i], 2);
    }
  }

  return(0);
}
//+------------------------------------------------------------------+

// === »ñÈ¡¶©µ¥ID ===
void GetOrdersID()
{
  int i, n, t, o;
  bool all;
  
  n = OrdersTotal();
  ArrayResize(OrdersID, n);
  all = StringFind(Orders, "*") >= 0;
  OpType = -1;
  for (i = 0, OrdersCount = 0; i < n; i++)
  {
    OrderSelect(i, SELECT_BY_POS);
    if (Symbol() == OrderSymbol())
    {
      t = OrderTicket();
      if (all || (StringFind(Orders, DoubleToStr(t, 0)) >= 0))
      {
        o = OrderType();
        if (o < 2)
        {
          if ((OpType >= 0) && (o != OpType))
          {
            OpType = -1;
            break;
          }
          else
          {
            OpType = o;
            OrdersID[OrdersCount] = t;
            OrdersCount++;
          }
        }
      }
    }
  }
  if (OrdersCount == 0)
  {
    if (ObjectFind(TP_PRICE_LINE) >= 0)
      ObjectDelete(TP_PRICE_LINE);
    if (ObjectFind(SL_PRICE_LINE) >= 0)
      ObjectDelete(SL_PRICE_LINE);
  }
}

// === ѰÕÒ»ñÀûÖ¹ËðÏß ===
void SearchObjName(int Type, bool GetTPObj = true, bool GetSLObj = true)
{
  int    i, ObjType, iAbove, iBelow, iTP, iSL;
  double MinAbove, MaxBelow, y1, y2;
  string ObjName;
  
  MinAbove = 999999;
  MaxBelow = 0;
  iAbove   = -1;
  iBelow   = -1;
  for (i = 0; i < ObjectsTotal(); i++)
  {
    ObjName = ObjectName(i);
    ObjType = ObjectType(ObjName);
    switch (ObjType)
    {
      case OBJ_TREND :
      case OBJ_TRENDBYANGLE :
        y1 = CalcLineValue(ObjName, 0, 1, ObjType);
        y2 = y1;
        break;
      case OBJ_CHANNEL :
        y1 = CalcLineValue(ObjName, 0, MODE_UPPER, ObjType);
        y2 = CalcLineValue(ObjName, 0, MODE_LOWER, ObjType);
        break;
      default :
        y1 = -1;
        y2 = -1;
    }
    if ((y1 > 0) && (y1 < Bid) && (y1 > MaxBelow))         // Á½ÌõÏß¶¼ÔÚµ±Ç°¼ÛÏ·½
    {
      MaxBelow = y1;
      iBelow   = i;
    }
    else if ((y2 > Bid) && (y2 < MinAbove))    // Á½ÌõÏß¶¼ÔÚµ±Ç°¼ÛÉÏ·½
    {
      MinAbove = y2;
      iAbove   = i;
    }
    else                // Á½ÌõÏßÒ»ÉÏÒ»ÏÂ
    {
      if ((y1 > 0) && (y1 < MinAbove))
      {
        MinAbove = y1;
        iAbove   = i;
      }
      if (y2 > MaxBelow)
      {
        MaxBelow = y2;
        iBelow   = i;
      }
    }
  }

  switch (Type)
  {
    case OP_BUY :
      iTP = iAbove;
      iSL = iBelow;
      break;
    case OP_SELL :
      iTP = iBelow;
      iSL = iAbove;
      break;
    default :
      iTP = -1;
      iSL = -1;
  }
  if (GetTPObj)
  {
    if (iTP >= 0)
      TPObjName = ObjectName(iTP);
  }
  if (GetSLObj)
  {
    if (iSL >= 0)
      SLObjName = ObjectName(iSL);
  }
}

// === ¼ÆËã»ñÀû¼ÛºÍÖ¹Ëð¼Û ===
void CalcPrice(double &TPPrice, double &SLPrice)
{
  // »ñÀû¼Û
  switch (TP_Method)
  {
    case 1 :
      TPPrice = (1 + TP_Env_Dev * 0.01) * iMA(NULL, TP_TimeFrame, TP_MA_Period, 0, TP_MA_Method, TP_MA_Price, TP_Shift);
      break;
    case 2 :
      TPPrice = CalcLineValue(TPObjName, TP_Shift, 1 + OpType);
      break;
    default :
      TPPrice = -1;
  }
  // Ö¹Ëð¼Û
  switch (SL_Method)
  {
    case 1 :
      SLPrice = (1 + SL_Env_Dev * 0.01) * iMA(NULL, SL_TimeFrame, SL_MA_Period, 0, SL_MA_Method, TP_MA_Price, SL_Shift);
      break;
    case 2 :
      SLPrice = CalcLineValue(SLObjName, SL_Shift, 2 - OpType);
      break;
    case 3 :
      SLPrice = iSAR(NULL, SL_TimeFrame, SL_SARStep, SL_SARMax, SL_Shift);
      break;
    default :
      SLPrice = -1;
  }
}

// === ¼ÆËãÖ±ÏßÔÚij¸ökÏßµÄÖµ ===
double CalcLineValue(string ObjName, int Shift, int ValueIndex = 1, int ObjType = -1)
{
  double y1, y2, delta, ret;
  int    i;
  
  if ((ObjType < 0) && (StringLen(ObjName) > 0))
    ObjType = ObjectType(ObjName);
  switch (ObjType)
  {
    case OBJ_TREND :
    case OBJ_TRENDBYANGLE :
      ret = LineGetValueByShift(ObjName, Shift);
      break;
    case OBJ_CHANNEL :
      i     = GetBarShift(Symbol(), 0, ObjectGet(ObjName, OBJPROP_TIME3));
      delta = ObjectGet(ObjName, OBJPROP_PRICE3) - LineGetValueByShift(ObjName, i);
      y1 = LineGetValueByShift(ObjName, Shift);
      y2 = y1 + delta;
      if (ValueIndex == MODE_UPPER)
        ret = MathMax(y1, y2);
      else if (ValueIndex == MODE_LOWER)
        ret = MathMin(y1, y2);
      else
        ret = -1;      
      break;
    default :
      ret = -1;
  }
  return(ret);
}

// === ÏÔʾ»ñÀûÖ¹Ëð¼ÛˮƽÏß ===
void ShowTPSLLines(double TPPrice, double SLPrice)
{
  if (TPPrice < 0)
    ObjectDelete(TP_PRICE_LINE);
  else
  {
    if (FindObject(TP_PRICE_LINE) < 0)
    {
      ObjectCreate(TP_PRICE_LINE, OBJ_HLINE, 0, 0, 0);
      ObjectSet(TP_PRICE_LINE, OBJPROP_COLOR, TP_LineColor);
      ObjectSet(TP_PRICE_LINE, OBJPROP_STYLE, STYLE_DASHDOTDOT);
      ObjectSet(TP_PRICE_LINE, OBJPROP_WIDTH, 1);    
    }
    ObjectMove(TP_PRICE_LINE, 0, Time[0], TPPrice);
  }

  if (SLPrice < 0)
    ObjectDelete(SL_PRICE_LINE);
  else
  {
    if (FindObject(SL_PRICE_LINE) < 0)
    {
      ObjectCreate(SL_PRICE_LINE, OBJ_HLINE, 0, 0, 0);
      ObjectSet(SL_PRICE_LINE, OBJPROP_COLOR, SL_LineColor);
      ObjectSet(SL_PRICE_LINE, OBJPROP_STYLE, STYLE_DASHDOTDOT);
      ObjectSet(SL_PRICE_LINE, OBJPROP_WIDTH, 1);    
    }
    ObjectMove(SL_PRICE_LINE, 0, Time[0], SLPrice);
  }
}

// === ²éÕÒ¶ÔÏó ===
int FindObject(string Name)
{
  if (StringLen(Name) <= 0)
    return(-1);
  else
    return(ObjectFind(Name));
}

// === ƽ²Ö ===
void CloseOrder(int Ticket, int type)
{
  double ClosePrice;
  string str[2] = {"TP", "SL"};
  
  if (OrderSelect(Ticket, SELECT_BY_TICKET, MODE_TRADES))
  {
    if (OrderType() == OP_BUY)
      ClosePrice = MarketInfo(Symbol(), MODE_BID);
    else
      ClosePrice = MarketInfo(Symbol(), MODE_ASK);
    if (OrderClose(Ticket, OrderLots(), ClosePrice, 0))
      Print("Order #", Ticket, " was closed successfully at ", str[type], " ", ClosePrice);
    else
      Print("Order #", Ticket, " reached ", str[type], " ", ClosePrice, ", but failed to close for error ", GetLastError());
  }
}

// === ¼ÆËãÖ±ÏßÉϵÄÖµ ===
double LineGetValueByShift(string ObjName, int Shift)
{
  double i1, i2, i, y1, y2, y;
  
  i1 = GetBarShift(Symbol(), 0, ObjectGet(ObjName, OBJPROP_TIME1));
  i2 = GetBarShift(Symbol(), 0, ObjectGet(ObjName, OBJPROP_TIME2));
  y1 = ObjectGet(ObjName, OBJPROP_PRICE1);
  y2 = ObjectGet(ObjName, OBJPROP_PRICE2);
  if (i1 < i2)
  {
    i  = i1;
    i1 = i2;
    i2 = i;
    y  = y1;
    y1 = y2;
    y2 = y;
  }
  if (Shift > i1)
    y = (y2 - y1) / (i2 - i1) * (Shift - i1) + y1;
  else
    y = ObjectGetValueByShift(ObjName, Shift);
    
  return(y);
}

// === ȡʱ¼äÖµµÄshiftÊý ===
int GetBarShift(string symbol, int timeframe, datetime time)
{
  int now;
  
  now = iTime(symbol, timeframe, 0);
  if (time < now + timeframe * 60)
    return(iBarShift(symbol, timeframe, time));
  else
  {
    if (timeframe == 0)
      timeframe = Period();
    return((now - time) / timeframe / 60);
  }
}

Comments