Orders Execution
Miscellaneous
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 Formatting Guide
# H1
## H2
### H3
**bold text**
*italicized text*
[title](https://www.example.com)

`code`
```
code block
```
> blockquote
- Item 1
- Item 2
1. First item
2. Second item
---