VirtualLimitAndTP

Author: TheXpert
Orders Execution
It automatically opens orders when conditions are reachedIt Closes Orders by itself Checks for the total of closed orders
Miscellaneous
It plays sound alertsIt opens Message Boxes to the userUses files from the file systemIt writes information to fileIt reads information from a file
0 Views
0 Downloads
0 Favorites
VirtualLimitAndTP
//+------------------------------------------------------------------+
//|                                            VirtualLimitAndTP.mq4 |
//|                         https://login.mql5.com/ru/users/TheXpert |
//+------------------------------------------------------------------+
#property copyright "TheXpert"
#property link      "https://login.mql5.com/ru/users/TheXpert"

#define OID "_VIRTUAL_C_open_"
int OID_Len;

#define CID "_VIRTUAL_C_close_"
int CID_Len;

extern int           MaxSpread         = 3;
extern int           Magic             = 2875621956;
extern bool          ConfirmActions    = true;
extern bool          AlertComplete     = true;
extern string        AlertSound        = "alert.wav";
extern color         SelectionColor    = Red;
extern color         TextColor         = White;

double OTasks.lot[];
double OTasks.price[];
double OTasks.dir[];

double CTasks.ticket[];
double CTasks.price[];

void Alert_(string s)
{
   Print(s);
   
   PlaySound("AlertSound");
}

///=========================================================================
/// GUI
///=========================================================================
 
void SetLabel(string name, int x, int y, string text, int size = 10, color clr = White, int corner = 0, string font = "")
{
   ObjectCreate(name, OBJ_LABEL, 0, 0, 0);
   
   ObjectSet(name, OBJPROP_CORNER, corner);

   ObjectSet(name, OBJPROP_XDISTANCE, x);
   ObjectSet(name, OBJPROP_YDISTANCE, y);
   
   ObjectSetText(name, text, size, font, clr);
}

#define IDOK 1
#define IDCANCEL 2
 
bool Confirmed(string action)
{
   if (!ConfirmActions) return (true);
   
   int result = MessageBox("Do you really want to\n" + action + "?", "Please confirm", IDOK);
   return (result == IDOK);
}
 
///=========================================================================
/// Misc
///=========================================================================
 
string ID()
{
   static string result;
   if (StringLen(result) == 0) result = "ZZCEA_task";
   result = StringSetChar(result, 0, 255);
   
   return (result);
}
 
int IDLen()
{
   return (StringLen(ID()));
}
 
int x = 50;
int y = 50;
int d = 20;

string items[];

///=========================================================================
/// DND Implementation
///=========================================================================
 
bool CheckDrag(string name)
{
   double x = ObjectGet(name, OBJPROP_PRICE1);
   if (GetLastError() != 0) return (false);
   
   if (ObjectSet(name, OBJPROP_PRICE1, x*1.1))
   {
      ObjectSet(name, OBJPROP_PRICE1, x);
      return (false);
   }
   
   return (true);
}
 
bool CheckDrop(string name)
{
   double x = ObjectGet(name, OBJPROP_PRICE1);
   if (GetLastError() != 0) return (true);
   
   if (ObjectSet(name, OBJPROP_PRICE1, x*1.1))
   {
      ObjectSet(name, OBJPROP_PRICE1, x);
      return (true);
   }
   
   return (false);
}
 
 
bool IsDragging = false;
string DragName = "";
 
double DropPrice;
 
void OnDropped(string name)
{
   IsDragging = false;

   if (name != ID() + " remove") return;
   
   int y = ObjectGet(name, OBJPROP_YDISTANCE);
   int item = GetItem(y);

   if (item >= 0 && item < ArraySize(items))
   {
      if (Confirmed(" remove " + items[item]))
      {
         RemoveListItem(item);
      }
   } 
}
 
void WhileDragging(string name)
{
   if (name != ID() + " remove") return;
   
   int y = ObjectGet(name, OBJPROP_YDISTANCE);
   int item = GetItem(y);
   
   DrawList();
   if (item >= 0 && item < ArraySize(items))
   {
      ObjectSet(ID() + item, OBJPROP_COLOR, SelectionColor);
   }
}
 
///=========================================================================
/// Implementation
///=========================================================================

void DrawList()
{
   string label = StringSetChar(" ", 0, 235);
   
   SetLabel(ID() + " remove", x - 10, y - 10, label, 20, SelectionColor, 0, "Wingdings");
   
   int size = ArraySize(items);
   
   for (int i = 0; i < size; i++)
   {
      SetLabel(ID() + i, x + d, y + d*(i + 1), items[i], 10, TextColor);
   }
   
   int total = ObjectsTotal();
   for (i = total - 1; i >= 0; i--)
   {
      string s = ObjectName(i);
      if (s == ID() + " remove") continue;
      if (StringFind(s, ID()) >= 0)
      {
         int idx = StrToInteger(StringSubstr(s, IDLen()));
         if (idx >= size)
         {
            ObjectDelete(s);
         }
      }
   }
}

string StringIf(bool c, string ifTrue, string ifFalse)
{
   if (c) return (ifTrue);
   return (ifFalse);
}

void MakeList()
{
   int oSize = ArraySize(OTasks.price);
   int cSize = ArraySize(CTasks.price);
   
   ArrayResize(items, oSize + cSize);
   
   for (int i = 0; i < oSize; i++)
   {
      string s = " Open ";
      s = s + StringIf(OTasks.dir[i] == 0, "Buy ", "Sell ");
      s = s + DoubleToStr(OTasks.lot[i], 2) + " at " + DoubleToStr(OTasks.price[i], Digits);
      
      items[i] = s;
   }

   for (i = 0; i < cSize; i++)
   {
      s = " Close #" + DoubleToStr(CTasks.ticket[i], 0);
      
      if (OrderSelect(CTasks.ticket[i], SELECT_BY_TICKET))
      {
         s = s + " ( " + DoubleToStr(OrderLots(), 2) + StringIf(OrderType() == OP_BUY, " Buy ", " Sell ") + " at " + DoubleToStr(OrderOpenPrice(), Digits) + " ) ";
      }
      
      s = s + " at " + DoubleToStr(CTasks.price[i], Digits);
      
      items[oSize + i] = s;
   }
}

int GetItem(int yPos)
{
   return ((yPos - y)/d - 1);
}

void RemoveListItem(int pos)
{
   int oSize = ArraySize(OTasks.price);
   int cSize = ArraySize(CTasks.price);
   
   int iSize = ArraySize(items);
   
   if (iSize != oSize + cSize) return;
   if (pos < 0 || pos >= iSize) return;
   
   if (pos < oSize)  RemoveOpenTask(pos);
   else              RemoveCloseTask(pos - oSize);
}

void WaitForContext()
{
   while (IsTradeContextBusy() && !IsStopped())
   {
      Sleep(10 + (MathRand() % 30));
   }
}

void CheckNewTasks()
{
   bool needSave = false;
   
   int total = GlobalVariablesTotal();
   for (int i = 0; i < total; i++)
   {
      string s = GlobalVariableName(i);
      int pos = StringFind(s, OID);
      
      if (pos != -1)
      {
         string dir = StringSubstr(s, pos + OID_Len, 1);
         string lots = StringSubstr(s, pos + OID_Len + 1);
         double price = NormalizeDouble(GlobalVariableGet(s), Digits);
         
         GlobalVariableDel(s);
         
         OnNewOpenTask(StrToInteger(dir), NormalizeDouble(StrToDouble(lots), 2), price);
         needSave = true;
      }
   }
   
   if (needSave) SaveOpenTasks();
   
   needSave = false;
   
   total = GlobalVariablesTotal();
   for (i = 0; i < total; i++)
   {
      s = GlobalVariableName(i);
      pos = StringFind(s, CID);
      
      if (pos != -1)
      {
         string ticket = StringSubstr(s, pos + CID_Len);
         price = NormalizeDouble(GlobalVariableGet(s), Digits);
         
         GlobalVariableDel(s);

         OnNewCloseTask(StrToInteger(ticket), price);
         needSave = true;
      }
   }
   
   if (needSave) SaveCloseTasks();
}

void OnNewOpenTask(int direction, double lots, double price)
{
   if (lots <= 0) return;
   if (price <= 0) return;
   
   int size = ArraySize(OTasks.price);
   
   ArrayResize(OTasks.lot, size + 1);
   ArrayResize(OTasks.price, size + 1);
   ArrayResize(OTasks.dir, size + 1);
   
   OTasks.lot[size] = lots;
   OTasks.price[size] = price;
   OTasks.dir[size] = direction;
   
   Print("Added new open task");
}

void OnNewCloseTask(int ticket, double price)
{
   if (ticket <= 0) return;
   if (price <= 0) return;
   
   int size = ArraySize(CTasks.price);

   ArrayResize(CTasks.ticket, size + 1);
   ArrayResize(CTasks.price, size + 1);

   CTasks.ticket[size] = ticket;
   CTasks.price[size] = price;

   Print("Added new close task");
}

void SaveOpenTasks()
{
   int size = ArraySize(OTasks.price);

   string path = TerminalCompany() + "\\" + AccountNumber() + "\\" + Symbol() + "\\" + "otasks.csv";

   if (size == 0)
   {
      FileDelete(path);
      return;
   }

   int hFile = FileOpen(path, FILE_WRITE | FILE_CSV);
   if (hFile == -1) return;
   
   for (int i = 0; i < size; i++)
   {
      string s;
      s = StringConcatenate(OTasks.lot[i], ";", OTasks.price[i], ";", OTasks.dir[i]);
      FileWrite(hFile, s);
   }
   
   FileClose(hFile);
}

void SaveCloseTasks()
{
   int size = ArraySize(CTasks.price);

   string path = TerminalCompany() + "\\" + AccountNumber() + "\\" + Symbol() + "\\" + "ctasks.csv";

   if (size == 0)
   {
      FileDelete(path);
      return;
   }

   int hFile = FileOpen(path, FILE_WRITE | FILE_CSV);
   if (hFile == -1) return;
   
   for (int i = 0; i < size; i++)
   {
      string s;
      s = StringConcatenate(DoubleToStr(CTasks.ticket[i], 0), ";", DoubleToStr(CTasks.price[i], Digits));
      FileWrite(hFile, s);
   }
   
   FileClose(hFile);
}

void LoadOpenTasks()
{
   string path = TerminalCompany() + "\\" + AccountNumber() + "\\" + Symbol() + "\\" + "otasks.csv";
   int hFile = FileOpen(path, FILE_READ | FILE_CSV);
   if (hFile == -1) return;
   
   ArrayResize(OTasks.lot, 0);
   ArrayResize(OTasks.price, 0);
   ArrayResize(OTasks.dir, 0);
   
   int lastErr = 0;
   
   while (lastErr == 0)
   {
      double lots = FileReadNumber(hFile);
      lastErr = GetLastError();
      if (lastErr != 0) break;
      
      double price = FileReadNumber(hFile);
      lastErr = GetLastError();
      if (lastErr != 0) break;
      
      double dir = FileReadNumber(hFile);
      lastErr = GetLastError();
      if (lastErr != 0) break;

      int size = ArraySize(OTasks.price);

      ArrayResize(OTasks.lot, size + 1);
      ArrayResize(OTasks.price, size + 1);
      ArrayResize(OTasks.dir, size + 1);
      
      OTasks.lot[size] = lots;
      OTasks.price[size] = price;
      OTasks.dir[size] = dir;
   }
   
   FileClose(hFile);
}

void LoadCloseTasks()
{
   string path = TerminalCompany() + "\\" + AccountNumber() + "\\" + Symbol() + "\\" + "ctasks.csv";
   int hFile = FileOpen(path, FILE_READ | FILE_CSV);
   if (hFile == -1) return;
   
   ArrayResize(CTasks.ticket, 0);
   ArrayResize(CTasks.price, 0);
   
   int lastErr = 0;
   
   while (lastErr == 0)
   {
      double ticket = FileReadNumber(hFile);
      lastErr = GetLastError();
      if (lastErr != 0) break;
      
      double price = FileReadNumber(hFile);
      lastErr = GetLastError();
      if (lastErr != 0) break;
      
      int size = ArraySize(CTasks.price);

      ArrayResize(CTasks.ticket, size + 1);
      ArrayResize(CTasks.price, size + 1);

      CTasks.ticket[size] = ticket;
      CTasks.price[size] = price;
   }
   
   FileClose(hFile);
}

void ProcessOpenTasks()
{
   int size = ArraySize(OTasks.price);
   
   for (int i = size - 1; i >= 0; i--)
   {
      if (OTasks.dir[i] == 0)
      {
         ProcessOpenBuy(i, OTasks.lot[i], OTasks.price[i]);
      }
      else if (OTasks.dir[i] == 1)
      {
         ProcessOpenSell(i, OTasks.lot[i], OTasks.price[i]);
      }
   }
}

void ProcessCloseTasks()
{
   int size = ArraySize(CTasks.price);
   
   for (int i = size - 1; i >= 0; i--)
   {
      if (!OrderSelect(CTasks.ticket[i], SELECT_BY_TICKET))
      {
         RemoveCloseTask(i);
         continue;
      }
      
      if (OrderCloseTime() > 0)
      {
         RemoveCloseTask(i);
         continue;
      }
      
      if (OrderType() == OP_BUY)
      {
         ProcessCloseBuy(i, CTasks.ticket[i], CTasks.price[i]);
      }
      else if (OrderType() == OP_SELL)
      {
         ProcessCloseSell(i, CTasks.ticket[i], CTasks.price[i]);
      }
   }
}

void ProcessOpenBuy(int pos, double lots, double price)
{
   WaitForContext();
   RefreshRates();

   if (Ask < (price + (MaxSpread + 0.5)*Point))
   { // ìîæíî îòêðûâàòüñÿ
      int res = OrderSend(Symbol(), OP_BUY, lots, Ask, 0, 0, 0, NULL, Magic, 0, Blue);
      if (res != -1)
      {
         RemoveOpenTask(pos);
         Alert_("Open buy task processed successfully");
      }
   }
}

void ProcessOpenSell(int pos, double lots, double price)
{
   WaitForContext();
   RefreshRates();

   if (Bid > price - 0.5*Point)
   { // ìîæíî îòêðûâàòüñÿ
      int res = OrderSend(Symbol(), OP_SELL, lots, Bid, 0, 0, 0, NULL, Magic, 0, Red);
      if (res != -1)
      {
         RemoveOpenTask(pos);
         Alert_("Open sell task processed successfully");
      }
   }
}

void ProcessCloseBuy(int pos, int ticket, double price)
{
   if (!OrderSelect(ticket, SELECT_BY_TICKET)) return;

   WaitForContext();
   RefreshRates();

   if (Bid > price - 0.5*Point)
   { // ìîæíî çàêðûâàòüñÿ
      if (OrderClose(ticket, OrderLots(), Bid, 0, Blue))
      {
         RemoveCloseTask(pos);
         Alert_("Close buy task processed successfully");
      }
   }
}

void ProcessCloseSell(int pos, int ticket, double price)
{
   if (!OrderSelect(ticket, SELECT_BY_TICKET)) return;

   WaitForContext();
   RefreshRates();

   if (Ask < (price + (MaxSpread + 0.5)*Point))
   { // ìîæíî çàêðûâàòüñÿ
      if (OrderClose(ticket, OrderLots(), Ask, 0, Red))
      {
         RemoveCloseTask(pos);
         Alert_("Close sell task processed successfully");
      }
   }
}

void RemoveOpenTask(int i)
{
   int size = ArraySize(OTasks.price);
   int pos = size - 1;
   
   OTasks.lot[i] = OTasks.lot[pos];
   OTasks.price[i] = OTasks.price[pos];
   OTasks.dir[i] = OTasks.dir[pos];
   
   ArrayResize(OTasks.lot, pos);
   ArrayResize(OTasks.price, pos);
   ArrayResize(OTasks.dir, pos);
   
   SaveOpenTasks();
}

void RemoveCloseTask(int i)
{
   int size = ArraySize(CTasks.price);
   int pos = size - 1;
   
   CTasks.ticket[i] = CTasks.ticket[pos];
   CTasks.price[i] = CTasks.price[pos];
   
   ArrayResize(CTasks.ticket, pos);
   ArrayResize(CTasks.price, pos);
   
   SaveCloseTasks();
}

bool FirstRun;

int init()
{
   OID_Len = StringLen(OID);
   ArrayResize(OTasks.lot, 0);
   ArrayResize(OTasks.price, 0);
   ArrayResize(OTasks.dir, 0);
   
   CID_Len = StringLen(CID);
   ArrayResize(CTasks.ticket, 0);
   ArrayResize(CTasks.price, 0);

   
   LoadOpenTasks();
   LoadCloseTasks();
   
   IsDragging = false;
   DragName = "";
   
   FirstRun = true;
   
   return(0);
}

int deinit()
{
   int count = ObjectsTotal();
   for (int i = count - 1; i >= 0; i--)
   {
      string name = ObjectName(i);
      if (StringFind(name, ID()) != -1)
      {
         ObjectDelete(name);
      }
   }
   
   return(0);
}

int start()
{
   if (IsTesting()) return (0);
   
   if (ArraySize(CTasks.ticket) > 0 && OrdersHistoryTotal() == 0 && FirstRun)
   {
      // potential fail while processing close tasks. Trying to avoid.
      Print("Waiting for terminal synchronization");
      Sleep(10000);
   }
   FirstRun = false;
   
   while (!IsStopped() && IsExpertEnabled())
   {
      if (IsDragging)
      {
         if (CheckDrop(DragName))
         {
            OnDropped(DragName);
         }
         else
         {
            WhileDragging(DragName);
         }
      }
      else
      {
         CheckNewTasks();
   
         ProcessCloseTasks();
         ProcessOpenTasks();

         MakeList();
         DrawList();
         
         if (CheckDrag(ID() + " remove")) 
         {
            DragName = ID() + " remove";
            IsDragging = true;
         }
      }
   
      WindowRedraw();
   
      Sleep(50);
   }
   
   return(0);
}

Comments

Markdown supported. Formatting help

Markdown Formatting Guide

Element Markdown Syntax
Heading # H1
## H2
### H3
Bold **bold text**
Italic *italicized text*
Link [title](https://www.example.com)
Image ![alt text](image.jpg)
Code `code`
Code Block ```
code block
```
Quote > blockquote
Unordered List - Item 1
- Item 2
Ordered List 1. First item
2. Second item
Horizontal Rule ---