e-MoveSLTPbyMouse

Author: ��� ����� �. aka KimIV
e-MoveSLTPbyMouse

This script is designed to provide a visual and automated way for traders to manage their Stop Loss (SL) and Take Profit (TP) levels directly on the trading chart. It essentially bridges the gap between manual mouse interaction and the automated execution of trade adjustments.

Core Functionality

The primary logic of the script revolves around creating and maintaining horizontal lines on your chart that represent your active trade's exit points. Here is how it works step-by-step:

1. Visual Representation When you have an open trade (Buy or Sell) that already has a Stop Loss or Take Profit set, the script automatically draws a horizontal line on the chart.

  • Stop Loss lines are typically shown in one color (defaulting to Red).
  • Take Profit lines are shown in another (also defaulting to Red, but configurable). The script identifies these lines by tagging them with specific identifiers tied to your unique trade numbers.

2. Interactive Movement Logic The "logic" allows you to move these lines on the chart using your mouse. Because the script is constantly monitoring the position of these visual lines:

  • It detects whenever you click and drag a line to a new price level.
  • It captures that new price coordinate in real-time.
  • It then automatically sends a command to the broker's server to update your actual trade's Stop Loss or Take Profit to match the position of the line you just moved.

3. Precision and Safety Checks To ensure the trades remain valid according to the broker's rules, the script includes several "sanity checks":

  • Price Normalization: It rounds the price to the nearest valid "tick" (the smallest movements the market allows) so that the broker doesn't reject the order for having too many decimal places.
  • Distance Limits: It checks the "Stop Level" (the minimum distance a stop must be from the current price). If you try to drag a line too close to the current market price, the script will automatically snap the line back to the nearest allowed legal distance to prevent the trade modification from failing.

4. Automatic Cleanup The script is designed to keep your chart clean. It performs a constant "housekeeping" routine:

  • If a trade is closed, the corresponding lines are deleted.
  • If you manually delete a line or if a trade no longer exists, the script removes any "ghost" lines that are no longer connected to an active position.
  • If you open new trades without existing stops, the script will detect them and draw the necessary lines automatically.

Summary for the User

Think of this script as a "Visual Remote Control" for your trade exits. Instead of opening a complicated menu to type in new numbers for your Stop Loss or Take Profit, you can simply grab the line on your screen with your mouse and move it where you want it. The script does the heavy lifting in the background, ensuring that the actual trade follows your mouse perfectly while staying within the broker's safety rules.

Orders Execution
Checks for the total of open ordersIt can change open orders parameters, due to possible stepping strategy
13 Views
1 Downloads
0 Favorites
e-MoveSLTPbyMouse
//+----------------------------------------------------------------------------+
//|                                                     e-MoveSLTPbyMouse.mq4  |
//|                                                                            |
//|                                                    Êèì Èãîðü Â. aka KimIV  |
//|                                                       http://www.kimiv.ru  |
//|                                                                            |
//|  31.03.2008  Ñîâåòíèê äëÿ ïåðåìåùåíèÿ óðîâíåé SL è TP ñ ïîìîùüþ ìûøè.      |
//|  08.04.2008  Íîðìèðîâàíèå óðîâíåé SL è TP ïîä ðàçìåð òèêà.                 |
//+----------------------------------------------------------------------------+
#property copyright "Êèì Èãîðü Â. aka KimIV"
#property link      "http://www.kimiv.ru"

//------- Âíåøíèå ïàðàìåòðû ñîâåòíèêà -----------------------------------------+
extern string _P_Expert = "---------- Parameters of e-MoveSL&TPbyMouse";
extern int    Language    = 0;         // ßçûê: 0-English, 1-Ðóññêèé
extern double IntUpdate   = 0.371;     // Èíòåðâàë îáíîâëåíèÿ â ñåêóíäàõ
extern bool   PrintEnable = True;      // Ðàçðåøèòü ïå÷àòü â æóðíàë

extern string _P_Graphics = "---------- Parameters of Graphic Objects";
extern color StopColor = Red;          // Öâåò ëèíèè óðîâíÿ StopLoss
extern int   StopStyle = 3;            // Ñòèëü ëèíèè óðîâíÿ StopLoss
extern int   StopWidth = 0;            // Òîëùèíà ëèíèè óðîâíÿ StopLoss
extern color TakeColor = Red;          // Öâåò ëèíèè óðîâíÿ TakeProfit
extern int   TakeStyle = 3;            // Ñòèëü ëèíèè óðîâíÿ TakeProfit
extern int   TakeWidth = 0;            // Òîëùèíà ëèíèè óðîâíÿ TakeProfit

//------- Ãëîáàëüíûå ïåðåìåííûå ñîâåòíèêà -------------------------------------+
color  clModifyBuy  = Aqua;            // Öâåò çíà÷êà ìîäèôèêàöèè ïîêóïêè
color  clModifySell = Tomato;          // Öâåò çíà÷êà ìîäèôèêàöèè ïðîäàæè
string msg[4][2];

//------- Ïîäêëþ÷åíèå âíåøíèõ ìîäóëåé -----------------------------------------+
#include <stdlib.mqh>                  // Ñòàíäàðòíàÿ áèáëèîòåêà


//+----------------------------------------------------------------------------+
//|                                                                            |
//|  ÏÐÅÄÎÏÐÅÄÅ˨ÍÍÛÅ ÔÓÍÊÖÈÈ                                                  |
//|                                                                            |
//+----------------------------------------------------------------------------+
//|  expert initialization function                                            |
//+----------------------------------------------------------------------------+
void init() {
  msg[0][0]="Adviser will is started by next tick";
  msg[0][1]="Ñîâåòíèê áóäåò çàïóùåí ñëåäóþùèì òèêîì";
  msg[1][0]="Button is not pressed \"Enable experts for running\"";
  msg[1][1]="Îòæàòà êíîïêà \"Ðàçðåøèòü çàïóñê ñîâåòíèêîâ\"";
  msg[2][0]="IS ABSENT relationship with trade server\n"+
            "Adviser is STOPPED";
  msg[2][1]="ÎÒÑÓÒÑÒÂÓÅÒ ñâÿçü ñ òîðãîâûì ñåðâåðîì\n"+
            "Ñîâåòíèê ÎÑÒÀÍÎÂËÅÍ";
  msg[3][0]="Button is not pressed \"Enable experts for running\"\n"+
            "Expert Adviser is STOPPED";
  msg[3][1]="Îòæàòà êíîïêà \"Ðàçðåøèòü çàïóñê ñîâåòíèêîâ\"\n"+
            "Ñîâåòíèê ÎÑÒÀÍÎÂËÅÍ";

  if (Language<0 || Language>1) Message("Language is invalid");
  if (IsExpertEnabled()) {
    if (IntUpdate>0) start();
    else Message(msg[0][Language]);
  } else Message(msg[1][Language]);
Print("init");
}

//+----------------------------------------------------------------------------+
//|  expert deinitialization function                                          |
//+----------------------------------------------------------------------------+
void deinit() {
  int    i, k=ObjectsTotal();
  string on;

  // óäàëåíèå ëèíèé
  for (i=0; i<k; i++) {
    on=ObjectName(i);
    if (StringSubstr(on, 0, 2)=="sl") ObjectDelete(on);
    if (StringSubstr(on, 0, 2)=="tp") ObjectDelete(on);
  }
  Comment("");
}

//+----------------------------------------------------------------------------+
//|  expert start function                                                     |
//+----------------------------------------------------------------------------+
void start() {
  if (IntUpdate<=0) ManageLines();
  else {
    while (IsExpertEnabled() && !IsStopped()) {
      if (IsConnected()) ManageLines();
      else { Comment(msg[2][Language]); return; }
      Sleep(1000*IntUpdate);
    }
    Message(msg[3][Language]);
  }
}


//+----------------------------------------------------------------------------+
//|                                                                            |
//|  ÏÎËÜÇÎÂÀÒÅËÜÑÊÈÅ ÔÓÍÊÖÈÈ                                                  |
//|                                                                            |
//+----------------------------------------------------------------------------+
//|  Àâòîð    : Êèì Èãîðü Â. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Âåðñèÿ   : 01.09.2005                                                     |
//|  Îïèñàíèå : Âûïîëíÿåò ïîèñê ýëåìåíòà ìàññèâà ïî çíà÷åíèþ                   |
//|             è âîçâðàùàåò èíäåêñ íàéäåííîãî ýëåìåíòà èëè -1.                |
//+----------------------------------------------------------------------------+
//|  Ïàðàìåòðû:                                                                |
//|    m - ìàññèâ ýëåìåíòîâ                                                    |
//|    e - çíà÷åíèå ýëåìåíòà                                                   |
//+----------------------------------------------------------------------------+
int ArraySearchInt(int& m[], int e) {
  for (int i=0; i<ArraySize(m); i++) {
    if (m[i]==e) return(i);
  }
  return(-1);
}

//+----------------------------------------------------------------------------+
//|  Àâòîð    : Êèì Èãîðü Â. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Âåðñèÿ   : 30.03.2008                                                     |
//|  Îïèñàíèå : Ïðîðèñîâêà ãîðèçîíòàëüíîé ëèíèè                                |
//+----------------------------------------------------------------------------+
//|  Ïàðàìåòðû:                                                                |
//|    cl - öâåò ëèíèè                                                         |
//|    nm - íàèìåíîâàíèå               ("" - âðåìÿ îòêðûòèÿ òåêóùåãî áàðà)     |
//|    p1 - öåíîâîé óðîâåíü            (0  - Bid)                              |
//|    st - ñòèëü ëèíèè                (0  - ïðîñòàÿ ëèíèÿ)                    |
//|    wd - øèðèíà ëèíèè               (0  - ïî óìîë÷àíèþ)                     |
//+----------------------------------------------------------------------------+
void DrawHLine(color cl, string nm="", double p1=0, int st=0, int wd=0) {
  if (p1==0) p1=Bid;
  if (ObjectFind(nm)<0) {
    ObjectCreate(nm, OBJ_HLINE, 0, 0,0);
    ObjectSet(nm, OBJPROP_PRICE1, p1);
    ObjectSet(nm, OBJPROP_COLOR , cl);
    ObjectSet(nm, OBJPROP_STYLE , st);
    ObjectSet(nm, OBJPROP_WIDTH , wd);
  }
}

//+----------------------------------------------------------------------------+
//|  Àâòîð    : Êèì Èãîðü Â. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Âåðñèÿ   : 01.09.2005                                                     |
//|  Îïèñàíèå : Âîçâðàùàåò íàèìåíîâàíèå òîðãîâîé îïåðàöèè                      |
//+----------------------------------------------------------------------------+
//|  Ïàðàìåòðû:                                                                |
//|    op - èäåíòèôèêàòîð òîðãîâîé îïåðàöèè                                    |
//+----------------------------------------------------------------------------+
string GetNameOP(int op) {
  switch (op) {
    case OP_BUY      : return("Buy");
    case OP_SELL     : return("Sell");
    case OP_BUYLIMIT : return("Buy Limit");
    case OP_SELLLIMIT: return("Sell Limit");
    case OP_BUYSTOP  : return("Buy Stop");
    case OP_SELLSTOP : return("Sell Stop");
    default          : return("Unknown Operation");
  }
}

//+----------------------------------------------------------------------------+
//|  Àâòîð    : Êèì Èãîðü Â. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Âåðñèÿ   : 01.02.2008                                                     |
//|  Îïèñàíèå : Âîçâðàùàåò îäíî èç äâóõ çíà÷åíèé âçàâèñèìîñòè îò óñëîâèÿ.      |
//+----------------------------------------------------------------------------+
string IIFs(bool condition, string ifTrue, string ifFalse) {
  if (condition) return(ifTrue); else return(ifFalse);
}

//+----------------------------------------------------------------------------+
//|  Óïðàâëåíèå ëèíèÿìè                                                        |
//+----------------------------------------------------------------------------+
void ManageLines() {
  double ms=MarketInfo(Symbol(), MODE_STOPLEVEL);
  double ts=MarketInfo(Symbol(), MODE_TICKSIZE);
  double pp;                 // öåíîâîé óðîâåíü StopLoss/TakeProfit
  double np;                 // íåíîðìèðîâàííûé öåíîâîé óðîâåíü StopLoss/TakeProfit
  int    i, k;               // ñ÷¸ò÷èê è êîëè÷åñòâî îáúåêòîâ/îðäåðîâ
  int    r;                  // òèêåò èñêîìîé ïîçèöèè
  int    t[];                // ìàññèâ òèêåòîâ ñóùåñòâóþùèõ ïîçèöèé
  string on;                 // íàèìåíîâàíèå îáúåêòà
  string st;                 // ñòðîêà êîììåíòàðèÿ

  // çàïîëíåíèå ìàññèâà òèêåòîâ ñóùåñòâóþùèõ ïîçèöèé
  ArrayResize(t, 0);
  k=OrdersTotal();
  for (i=0; i<k; i++) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      if (OrderSymbol()==Symbol()) {
        if (OrderType()==OP_BUY || OrderType()==OP_SELL) {
          if (OrderStopLoss()>0 || OrderTakeProfit()>0) {
            r=ArraySize(t);
            ArrayResize(t, r+1);
            t[r]=OrderTicket();
          }
        }
      }
    }
  }

  // óäàëåíèå ëèøíèõ (íåíóæíûõ) ëèíèé, ìîäèôèêàöèÿ óðîâíåé
  k=ObjectsTotal();
  for (i=0; i<k; i++) {
    on=ObjectName(i);
    if (StringSubstr(on, 0, 2)=="sl") {
      // òèêåò ïîçèöèè
      r=StrToInteger(StringSubstr(on, 2));
      if (ArraySearchInt(t, r)<0) ObjectDelete(on);
      else {
        if (OrderSelect(r, SELECT_BY_TICKET)) {
          if (OrderStopLoss()>0) {
            np=NormalizeDouble(ObjectGet(on, OBJPROP_PRICE1), Digits);
            if (ts>0) pp=NormalizeDouble(np/ts, 0)*ts; else pp=np;
            if (pp!=np) ModifyHLine(on, pp);
            if (OrderType()==OP_BUY && pp>Bid-(ms+1)*Point) pp=Bid-(ms+1)*Point;
            if (OrderType()==OP_SELL && pp<Ask+(ms+1)*Point) pp=Ask+(ms+1)*Point;
            ModifyOrder(-1, NormalizeDouble(pp, Digits), -1);
          } else ObjectDelete(on);
        }
      }
    }
    if (StringSubstr(on, 0, 2)=="tp") {
      // òèêåò ïîçèöèè
      r=StrToInteger(StringSubstr(on, 2));
      if (ArraySearchInt(t, r)<0) ObjectDelete(on);
      else {
        if (OrderSelect(r, SELECT_BY_TICKET)) {
          if (OrderTakeProfit()>0) {
            np=NormalizeDouble(ObjectGet(on, OBJPROP_PRICE1), Digits);
            if (ts>0) pp=NormalizeDouble(np/ts, 0)*ts; else pp=np;
            if (pp!=np) ModifyHLine(on, pp);
            if (OrderType()==OP_BUY && pp<Bid+(ms+1)*Point) pp=Bid+(ms+1)*Point;
            if (OrderType()==OP_SELL && pp>Ask-(ms+1)*Point) pp=Ask-(ms+1)*Point;
            ModifyOrder(-1, -1, NormalizeDouble(pp, Digits));
          } else ObjectDelete(on);
        }
      }
    }
  }

  // óñòàíîâêà íåäîñòàþùèõ ëèíèé
  k=OrdersTotal();
  for (i=0; i<k; i++) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      if (OrderSymbol()==Symbol()) {
        if (OrderType()==OP_BUY || OrderType()==OP_SELL) {
          if (OrderStopLoss()>0) {
            DrawHLine(StopColor, "sl"+OrderTicket(), OrderStopLoss(),
                      StopStyle, StopWidth);
          }
          if (OrderTakeProfit()>0) {
            DrawHLine(TakeColor, "tp"+OrderTicket(), OrderTakeProfit(),
                      TakeStyle, TakeWidth);
          }
        }
      }
    }
  }

  st="Language="+IIFs(Language==0, "English", "Ðóññêèé")
    +"  IntUpdate="+DoubleToStr(IntUpdate, 4)
    +"  "+IIFs(PrintEnable, "PrintEnable", "");
  Comment(st);
}

//+----------------------------------------------------------------------------+
//|  Âûâîä ñîîáùåíèÿ â êîììåíò è â æóðíàë                                      |
//|  Ïàðàìåòðû:                                                                |
//|    m - òåêñò ñîîáùåíèÿ                                                     |
//+----------------------------------------------------------------------------+
void Message(string m) {
  Comment(m);
  if (StringLen(m)>0 && PrintEnable) Print(m);
}

//+----------------------------------------------------------------------------+
//|  Àâòîð    : Êèì Èãîðü Â. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Âåðñèÿ   : 08.04.2008                                                     |
//|  Îïèñàíèå : Ìîäèôèêàöèÿ öåíîâîãî óðîâíÿ ãîðèçîíòàëüíîé ëèíèè               |
//+----------------------------------------------------------------------------+
//|  Ïàðàìåòðû:                                                                |
//|    nm - íàèìåíîâàíèå               ("" - âðåìÿ îòêðûòèÿ òåêóùåãî áàðà)     |
//|    p1 - öåíîâîé óðîâåíü            (0  - Bid)                              |
//+----------------------------------------------------------------------------+
void ModifyHLine(string nm="", double p1=0) {
  if (p1==0) p1=Bid;
  if (ObjectFind(nm)>=0) ObjectSet(nm, OBJPROP_PRICE1, p1);
}

//+----------------------------------------------------------------------------+
//|  Àâòîð    : Êèì Èãîðü Â. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Âåðñèÿ   : 28.03.2008                                                     |
//|  Îïèñàíèå : Ìîäèôèêàöèÿ îðäåðà. Âåðñèÿ ôóíêöèè äëÿ òåñòîâ íà èñòîðèè.      |
//+----------------------------------------------------------------------------+
//|  Ïàðàìåòðû:                                                                |
//|    pp - öåíà îòêðûòèÿ ïîçèöèè, óñòàíîâêè îðäåðà                            |
//|    sl - öåíîâîé óðîâåíü ñòîïà                                              |
//|    tp - öåíîâîé óðîâåíü òåéêà                                              |
//|    ex - äàòà èñòå÷åíèÿ                                                     |
//+----------------------------------------------------------------------------+
void ModifyOrder(double pp=-1, double sl=0, double tp=0, datetime ex=0) {
  int    dg=MarketInfo(OrderSymbol(), MODE_DIGITS), er;
  double op=NormalizeDouble(OrderOpenPrice() , dg);
  double os=NormalizeDouble(OrderStopLoss()  , dg);
  double ot=NormalizeDouble(OrderTakeProfit(), dg);
  color  cl;

  if (pp<=0) pp=OrderOpenPrice();
  if (sl<0 ) sl=OrderStopLoss();
  if (tp<0 ) tp=OrderTakeProfit();
  
  pp=NormalizeDouble(pp, dg);
  sl=NormalizeDouble(sl, dg);
  tp=NormalizeDouble(tp, dg);

  if (pp!=op || sl!=os || tp!=ot) {
    if (MathMod(OrderType(), 2)==0) cl=clModifyBuy; else cl=clModifySell;
    if (!OrderModify(OrderTicket(), pp, sl, tp, ex, cl)) {
      er=GetLastError();
      Print("Error(",er,") modifying order: ",ErrorDescription(er));
      Print("Ask=",Ask," Bid=",Bid," sy=",OrderSymbol(),
            " op="+GetNameOP(OrderType())," pp=",pp," sl=",sl," tp=",tp);
    }
  }
}
//+----------------------------------------------------------------------------+

Comments