StopFirst 1.00, the read-only core
Fourteen headers, a header-only MQL5 library: lot size from risk, pips on
forex, gold and indices, broker checks, bars and candle patterns, cached ATR,
sessions in GMT, account risk, symbol suffixes, a calendar filter. Sends no
trade requests. Plus the LotByRisk example script.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 21:40:34 +03:00 | | | //+------------------------------------------------------------------+
|
| | | //| Account.mqh|
|
| | | //| Copyright 2026, bandersoft |
|
| | | //| https://www.mql5.com/en/users/fats |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //| Account metrics, compounding, summary string. |
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | #ifndef STOPFIRST_ACCOUNT_MQH
|
| | | #define STOPFIRST_ACCOUNT_MQH
|
| | |
|
| | | #include <Trade\AccountInfo.mqh>
|
| | | //--- GetTradeStats reports position counts and profit
|
| | | #include "Positions.mqh"
|
| | | #include "Defs.mqh"
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Calculate compound growth |
|
| | | //| |
|
| | | //| Returns: initial compounded at ratePercent over periods. |
|
| | | //+------------------------------------------------------------------+
|
| | | double CalcCompoundGrowth(double initial, double ratePercent, int periods)
|
| | | {
|
| | | return initial * MathPow(1 + ratePercent / 100.0, periods);
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Does this account keep one position per ticket? |
|
| | | //| |
|
| | | //| Hedging accounts hold a position per ticket and can be long and |
|
| | | //| short the same symbol at once. Netting accounts hold one position |
|
| | | //| per symbol, so an opposing order reduces or reverses it. Several |
|
| | | //| operations, partial close among them, work differently on each. |
|
| | | //| |
|
| | | //| Returns: true for a retail hedging account, false otherwise. |
|
| | | //+------------------------------------------------------------------+
|
| | | bool IsHedgingAccount()
|
| | | {
|
| | | return (ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE) ==
|
| | | ACCOUNT_MARGIN_MODE_RETAIL_HEDGING;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Open loss as a percentage of balance |
|
| | | //| |
|
2026-10-16 21:48:01 +03:00 | | | //| Not drawdown: balance minus equity is the CURRENT floating loss, |
|
| | | //| and drawdown is measured from peak equity - for that, see |
|
| | | //| GetPeakDrawdownPercent(). |
|
StopFirst 1.00, the read-only core
Fourteen headers, a header-only MQL5 library: lot size from risk, pips on
forex, gold and indices, broker checks, bars and candle patterns, cached ATR,
sessions in GMT, account risk, symbol suffixes, a calendar filter. Sends no
trade requests. Plus the LotByRisk example script.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 21:40:34 +03:00 | | | //| |
|
| | | //| Returns: (balance - equity) / balance * 100, 2 decimals. |
|
| | | //| NEGATIVE when open trades are in profit - that is not an |
|
| | | //| error, it is what the quantity means. |
|
| | | //| 0 if balance is zero. |
|
| | | //+------------------------------------------------------------------+
|
| | | double GetFloatingLossPercent()
|
| | | {
|
| | | CAccountInfo accountInfo;
|
| | | double balance = accountInfo.Balance();
|
| | | double equity = accountInfo.Equity();
|
| | |
|
| | | if(balance == 0) return 0;
|
| | |
|
| | | return NormalizeDouble(((balance - equity) / balance) * 100.0, 2);
|
| | | }
|
| | |
|
| | | //--- highest equity seen since tracking began, for GetPeakDrawdownPercent
|
| | | double g_peakEquity = 0;
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Restart peak-equity tracking from the current equity |
|
| | | //| Returns: nothing. |
|
| | | //+------------------------------------------------------------------+
|
| | | void ResetPeakEquity()
|
| | | {
|
| | | CAccountInfo accountInfo;
|
| | | g_peakEquity = accountInfo.Equity();
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Drawdown from the highest equity seen so far |
|
| | | //| |
|
2026-10-16 21:48:01 +03:00 | | | //| The peak is built up from the first call onwards, so it measures |
|
| | | //| the run since the program started, not the account lifetime high |
|
| | | //| - call it on a schedule (each tick or each bar) or the peak means |
|
| | | //| little. |
|
StopFirst 1.00, the read-only core
Fourteen headers, a header-only MQL5 library: lot size from risk, pips on
forex, gold and indices, broker checks, bars and candle patterns, cached ATR,
sessions in GMT, account risk, symbol suffixes, a calendar filter. Sends no
trade requests. Plus the LotByRisk example script.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 21:40:34 +03:00 | | | //| ResetPeakEquity() starts the measurement over. A withdrawal |
|
| | | //| lowers equity like a loss and reads as drawdown: call |
|
| | | //| ResetPeakEquity() after moving money out. |
|
| | | //| |
|
| | | //| Returns: (peak - equity) / peak * 100, 2 decimals. 0 at a new |
|
| | | //| high, and 0 if peak equity is not positive. |
|
| | | //+------------------------------------------------------------------+
|
| | | double GetPeakDrawdownPercent()
|
| | | {
|
| | | CAccountInfo accountInfo;
|
| | | double equity = accountInfo.Equity();
|
| | |
|
| | | if(equity > g_peakEquity) g_peakEquity = equity;
|
| | | if(g_peakEquity <= 0) return 0;
|
| | |
|
| | | return NormalizeDouble(((g_peakEquity - equity) / g_peakEquity) * 100.0, 2);
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Print trade statistics summary |
|
| | | //| |
|
| | | //| Returns: a multi-line summary of balance, equity, margin, |
|
| | | //| drawdown and open exposure. Never empty. |
|
| | | //+------------------------------------------------------------------+
|
| | | string GetTradeStats(ulong magic = STOPFIRST_ANY_MAGIC)
|
| | | {
|
| | | CAccountInfo accountInfo;
|
| | |
|
| | | string stats = "=== Trade Statistics ===\n";
|
| | | stats += "Balance: " + DoubleToString(accountInfo.Balance(), 2) + "\n";
|
| | | stats += "Equity: " + DoubleToString(accountInfo.Equity(), 2) + "\n";
|
| | | stats += "Free Margin: " + DoubleToString(accountInfo.FreeMargin(), 2) + "\n";
|
| | | stats += "Margin Level: " + DoubleToString(accountInfo.MarginLevel(), 2) + "%\n";
|
| | | stats += "Floating Loss: " + DoubleToString(GetFloatingLossPercent(), 2) + "%\n";
|
| | | stats += "Open Positions: " + IntegerToString(GetPositionCount("", magic)) + "\n";
|
| | | stats += "Total Profit: " + DoubleToString(GetTotalProfit("", magic), 2) + "\n";
|
| | |
|
| | | return stats;
|
| | | }
|
| | |
|
| | | #endif // STOPFIRST_ACCOUNT_MQH
|
| | | //+------------------------------------------------------------------+
|