Custom volume and direction indicator for MT4
Posted: Thu Jul 23, 2026 9:06 am
Hi scalpers,
i would like to share my custom indicator for MetaTrader 4, because once you are scalping, you can have opened up to several hundreds of positions at that real time, so to be able to see direction and volume, plus Actual profit/loss per pair is very usefull.
i would like to share my custom indicator for MetaTrader 4, because once you are scalping, you can have opened up to several hundreds of positions at that real time, so to be able to see direction and volume, plus Actual profit/loss per pair is very usefull.
Code: Select all
#property copyright "Net Exposure Manager EA"
#property version "2.00"
#property strict
//+------------------------------------------------------------------+
//| Inicializace |
//+------------------------------------------------------------------+
int OnInit()
{
EventSetTimer(1); // Aktualizace GUI každou vteřinu
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Úklid grafiky při odstranění EA z grafu |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
EventKillTimer();
ObjectsDeleteAll(0, "NET_EXP_");
}
//+------------------------------------------------------------------+
//| Hlavní smyčky pro aktualizaci |
//+------------------------------------------------------------------+
void OnTick() { UpdateGUI(); }
void OnTimer() { UpdateGUI(); }
//+------------------------------------------------------------------+
//| Zpracování kliknutí na tlačítko |
//+------------------------------------------------------------------+
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
if(id == CHARTEVENT_OBJECT_CLICK)
{
// Pokud bylo kliknuto na naše tlačítko
if(StringFind(sparam, "NET_EXP_BTN_") == 0)
{
// Z názvu tlačítka vyřízneme název instrumentu (od 12. znaku)
string sym = StringSubstr(sparam, 12);
CloseAllBySymbol(sym);
// Vizuální "odmáčknutí" tlačítka zpět
ObjectSetInteger(0, sparam, OBJPROP_STATE, false);
UpdateGUI();
}
}
}
//+------------------------------------------------------------------+
//| Logika výpočtu a vykreslení GUI |
//+------------------------------------------------------------------+
void UpdateGUI()
{
double totalBuy = 0.0, totalSell = 0.0, totalNet = 0.0;
double totalBuyPnL = 0.0, totalSellPnL = 0.0, totalNetPnL = 0.0;
string symbols[];
double netLots[];
double netPnL[];
int symbolCount = 0;
string accCurrency = AccountCurrency();
// 1. Agregace dat o pozicích
for(int i = 0; i < OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderType() == OP_BUY || OrderType() == OP_SELL)
{
string sym = OrderSymbol();
double lots = OrderLots();
double pnl = OrderProfit() + OrderSwap() + OrderCommission();
double calcLots = (OrderType() == OP_SELL) ? -lots : lots;
totalNet += calcLots;
totalNetPnL += pnl;
if(OrderType() == OP_BUY) { totalBuy += lots; totalBuyPnL += pnl; }
if(OrderType() == OP_SELL) { totalSell += lots; totalSellPnL += pnl; }
int foundIdx = -1;
for(int j = 0; j < symbolCount; j++)
{
if(symbols[j] == sym) { foundIdx = j; break; }
}
if(foundIdx == -1)
{
ArrayResize(symbols, symbolCount + 1);
ArrayResize(netLots, symbolCount + 1);
ArrayResize(netPnL, symbolCount + 1);
symbols[symbolCount] = sym;
netLots[symbolCount] = calcLots;
netPnL[symbolCount] = pnl;
symbolCount++;
}
else
{
netLots[foundIdx] += calcLots;
netPnL[foundIdx] += pnl;
}
}
}
}
// 2. Vykreslení hlavičky
int yPos = 30;
DrawLabel("NET_EXP_HDR1", "--- AKTUÁLNÍ EXPOZICE ---", 20, yPos); yPos += 20;
DrawLabel("NET_EXP_BUY", StringFormat("Celkový nákup: %.2f lotů (%.2f %s)", totalBuy, totalBuyPnL, accCurrency), 20, yPos); yPos += 20;
DrawLabel("NET_EXP_SELL", StringFormat("Celkový prodej: %.2f lotů (%.2f %s)", totalSell, totalSellPnL, accCurrency), 20, yPos); yPos += 20;
string netDir = (totalNet >= 0) ? "LONG" : "SHORT";
DrawLabel("NET_EXP_NET", StringFormat("ČISTÁ EXPOZICE: %s %.2f lotů (%.2f %s)", netDir, MathAbs(totalNet), totalNetPnL, accCurrency), 20, yPos); yPos += 30;
DrawLabel("NET_EXP_HDR2", "--- Dle instrumentů ---", 20, yPos); yPos += 20;
// 3. Vykreslení řádků s tlačítky pro jednotlivé páry
for(int i = 0; i < symbolCount; i++)
{
string dir = (netLots[i] >= 0) ? "Long" : "Short";
string text = StringFormat("%s: %s %.2f (%.2f %s)", symbols[i], dir, MathAbs(netLots[i]), netPnL[i], accCurrency);
DrawLabel("NET_EXP_TXT_" + symbols[i], text, 20, yPos);
DrawButton("NET_EXP_BTN_" + symbols[i], "Zavřít " + symbols[i], 300, yPos - 3);
yPos += 25;
}
// 4. Úklid grafiky - smazání tlačítek párů, které už nemají otevřené pozice
for(int obj = ObjectsTotal() - 1; obj >= 0; obj--)
{
string objName = ObjectName(0, obj);
if(StringFind(objName, "NET_EXP_TXT_") == 0 || StringFind(objName, "NET_EXP_BTN_") == 0)
{
string sym = StringSubstr(objName, 12);
bool isActive = false;
for(int i = 0; i < symbolCount; i++)
{
if(symbols[i] == sym) { isActive = true; break; }
}
if(!isActive) ObjectDelete(0, objName);
}
}
}
//+------------------------------------------------------------------+
//| Funkce pro hromadné zavření pozic dle symbolu |
//+------------------------------------------------------------------+
void CloseAllBySymbol(string sym)
{
// Smyčka musí jít vždy odzadu dopředu (OrderTotal-1 do 0)
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == sym)
{
int type = OrderType();
if(type == OP_BUY || type == OP_SELL)
{
RefreshRates(); // Důležité pro získání nejčerstvější ceny
double price = (type == OP_BUY) ? MarketInfo(sym, MODE_BID) : MarketInfo(sym, MODE_ASK);
OrderClose(OrderTicket(), OrderLots(), price, 10, clrRed);
}
}
}
}
}
//+------------------------------------------------------------------+
//| Pomocné funkce pro rychlé vykreslení GUI |
//+------------------------------------------------------------------+
void DrawLabel(string name, string text, int x, int y)
{
if(ObjectFind(0, name) < 0)
{
ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
ObjectSetString(0, name, OBJPROP_FONT, "Arial");
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, 10);
// Adaptace barvy textu podle toho, zda je graf černý nebo bílý
color textColor = (ChartGetInteger(0, CHART_COLOR_BACKGROUND) == clrBlack) ? clrWhite : clrBlack;
ObjectSetInteger(0, name, OBJPROP_COLOR, textColor);
}
ObjectSetString(0, name, OBJPROP_TEXT, text);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
}
void DrawButton(string name, string text, int x, int y)
{
if(ObjectFind(0, name) < 0)
{
ObjectCreate(0, name, OBJ_BUTTON, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, name, OBJPROP_XSIZE, 100);
ObjectSetInteger(0, name, OBJPROP_YSIZE, 20);
ObjectSetString(0, name, OBJPROP_FONT, "Arial");
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, 9);
ObjectSetInteger(0, name, OBJPROP_COLOR, clrBlack);
ObjectSetInteger(0, name, OBJPROP_BGCOLOR, clrLightGray);
}
ObjectSetString(0, name, OBJPROP_TEXT, text);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
}