StopFirst-Core/Include/StopFirst/Positions.mqh

142 lines
5.6 KiB
MQL5

//+------------------------------------------------------------------+
//| Positions.mqh|
//| Copyright 2026, bandersoft |
//| https://www.mql5.com/en/users/fats |
//+------------------------------------------------------------------+
//| |
//| Read-only queries on open positions. |
//| |
//+------------------------------------------------------------------+
#ifndef STOPFIRST_POSITIONS_MQH
#define STOPFIRST_POSITIONS_MQH
#include <Trade\PositionInfo.mqh>
#include "Defs.mqh"
//+------------------------------------------------------------------+
//| Commission and fees already charged on an open position |
//| |
//| MT5 charges commission on DEALS. POSITION_COMMISSION, which |
//| CPositionInfo::Commission() reads, is deprecated and reports 0, |
//| so "profit + swap + commission" silently leaves commission out. |
//| This sums DEAL_COMMISSION and DEAL_FEE over the position's deals |
//| instead. |
//| |
//| Side effect: replaces the history selection, as any |
//| HistorySelectByPosition call does. |
//| |
//| Returns: the total, normally negative. 0 when the broker charges |
//| none or the history cannot be selected. |
//+------------------------------------------------------------------+
double PositionCommission(const ulong ticket)
{
if(!HistorySelectByPosition(ticket)) return 0;
double total = 0;
for(int i = HistoryDealsTotal() - 1; i >= 0; i--)
{
ulong deal = HistoryDealGetTicket(i);
if(deal == 0) continue;
total += HistoryDealGetDouble(deal, DEAL_COMMISSION) + HistoryDealGetDouble(deal, DEAL_FEE);
}
return total;
}
//+------------------------------------------------------------------+
//| Get total profit/loss for symbol |
//| |
//| Returns: profit plus swap plus commission over matching |
//| positions, 2 decimals. 0 if nothing matches, which reads |
//| the same as a flat P/L. |
//+------------------------------------------------------------------+
double GetTotalProfit(string symbol = "", ulong magic = STOPFIRST_ANY_MAGIC)
{
//--- "" here means EVERY symbol, not the chart symbol
CPositionInfo positionInfo;
double totalProfit = 0;
for(int i = 0; i < PositionsTotal(); i++)
{
if(positionInfo.SelectByIndex(i))
{
if(symbol == "" || positionInfo.Symbol() == symbol)
{
if(magic == STOPFIRST_ANY_MAGIC || positionInfo.Magic() == magic)
{
totalProfit += positionInfo.Profit() + positionInfo.Swap() +
PositionCommission(positionInfo.Ticket());
}
}
}
}
return NormalizeDouble(totalProfit, 2);
}
//+------------------------------------------------------------------+
//| Get position count for symbol |
//| |
//| Returns: how many open positions match the filter. 0 if none. |
//+------------------------------------------------------------------+
int GetPositionCount(string symbol = "", ulong magic = STOPFIRST_ANY_MAGIC, int posType = -1)
{
//--- "" here means EVERY symbol, not the chart symbol
CPositionInfo positionInfo;
int count = 0;
for(int i = 0; i < PositionsTotal(); i++)
{
if(positionInfo.SelectByIndex(i))
{
if(symbol == "" || positionInfo.Symbol() == symbol)
{
if(magic == STOPFIRST_ANY_MAGIC || positionInfo.Magic() == magic)
{
if(posType == -1 || positionInfo.PositionType() == (ENUM_POSITION_TYPE)posType)
count++;
}
}
}
}
return count;
}
//+------------------------------------------------------------------+
//| Get total volume for symbol |
//| |
//| Returns: summed volume of matching positions, unrounded. Long |
//| and short both count positive, so this is gross exposure,|
//| not net. 0 if nothing matches. |
//+------------------------------------------------------------------+
double GetTotalVolume(string symbol = "", ulong magic = STOPFIRST_ANY_MAGIC)
{
//--- "" here means EVERY symbol, not the chart symbol
CPositionInfo positionInfo;
double totalVolume = 0;
for(int i = 0; i < PositionsTotal(); i++)
{
if(positionInfo.SelectByIndex(i))
{
if(symbol == "" || positionInfo.Symbol() == symbol)
{
if(magic == STOPFIRST_ANY_MAGIC || positionInfo.Magic() == magic)
{
totalVolume += positionInfo.Volume();
}
}
}
}
//--- not rounded to 2 decimals: on a 0.001 step, 3 x 0.005 is 0.015
//--- and rounding would give 0.02 or 0.01
return NormalizeDouble(totalVolume, 8);
}
#endif // STOPFIRST_POSITIONS_MQH
//+------------------------------------------------------------------+