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>
6.1 KiB
StopFirst
A header-only MQL5 library of the calculations an Expert Advisor keeps re-implementing: position sizing from a risk percentage, pip and price conversion, broker constraint checks, bar queries and candle patterns, trading sessions in GMT, total risk across open positions, broker symbol suffixes, an economic-calendar filter, and account metrics.
No DLLs, no WebRequest, no external dependencies beyond the standard
Include\Trade\ classes that ship with MetaTrader 5.
Install
From the CodeBase archive: unpack it into the terminal's data folder
(File > Open Data Folder). It adds MQL5\Include\StopFirst\*.mqh and the
example MQL5\Scripts\StopFirst\LotByRisk.mq5, and touches nothing else.
From Algo Forge: clone the repository, then copy its Include\StopFirst\
folder into MQL5\Include\, so the headers sit at
MQL5\Include\StopFirst\*.mqh. The example is in Examples\.
Then:
#include <StopFirst\StopFirst.mqh>
Nothing to compile or link — it is header-only.
Example
#include <StopFirst\StopFirst.mqh>
void OnStart()
{
// Lot size whose 30-pip stop costs 1% of the balance
double lots = CalcLotSizeByRisk(1.0, 30);
if(lots <= 0)
{
Print("Risk budget does not cover one minimum lot.");
return;
}
PrintFormat("%.2f lots risks %.2f %s over 30 pips",
lots, CalcValueAtRisk(lots, 30), AccountInfoString(ACCOUNT_CURRENCY));
}
LotByRisk.mq5 is the same idea with the output filled in. It places no
orders.
Two things to know before using it
Sizing fails to zero, never upward. CalcLotSizeByRisk returns 0 when the
risk budget will not cover one minimum lot, rather than rounding up to the
minimum. Rounding up would silently risk more than you asked for. Check the
return value.
Pip size is a forex convention. The default rule — point * 10 on a 3- or
5-digit symbol, point otherwise — is right for currency pairs and wrong
anywhere a "pip" means something else. It is out by 10× on gold quoted to two
decimals and 100× on most crypto. No symbol property distinguishes these cases,
so declare it once at startup:
SetPipSize("XAUUSD", 0.1);
or take the conventional value for metals, indices, oil and crypto from the
built-in table with ApplyBuiltInPipSize("XAUUSD"). Everything downstream —
lot sizing, value at risk, stop distances — reads from that one definition.
In the Strategy Tester
Everything works in the tester except two things the tester does not have:
- The broker's GMT offset cannot be measured (
TimeGMT()there is not model time).DetectGmtOffset()reportsreliable = false; callSetGmtOffset(hours)inOnInit, or sessions andIsWithinTradingHoursassume GMT+0. - There is no economic calendar.
IsCalendarAvailable()returns false andIsNewsNear()returns false, so a news filter neither blocks nor allows on invented data.
Files
| Header | Contents |
|---|---|
StopFirst.mqh |
Umbrella. Include this. |
Defs.mqh |
Constants, sentinels, ENUM_SF_PATTERN, ENUM_SF_SIGNAL |
Symbol.mqh |
Pip size and overrides, price/pip conversion, lot normalisation, broker constraint checks, whether the market is open |
PipTable.mqh |
BuiltInPipSize, ApplyBuiltInPipSize — opt-in conventional pips for metals, indices, oil, crypto |
Risk.mqh |
CalcLotSizeByRisk, CalcMaxLotSize, CalcValueAtRisk, CalcRiskRewardRatio, pip value and margin per lot |
Bars.mqh |
CNewBarDetector, bar extremes, candle patterns |
Atr.mqh |
CAtr with a cached indicator handle, plus GetATRPips |
Sessions.mqh |
Broker GMT offset, Sydney/Tokyo/London/New York sessions, server/GMT conversion |
Time.mqh |
Timeframe and weekday names, trading-hour windows in GMT |
Positions.mqh |
Read-only position queries |
Account.mqh |
Floating loss, peak drawdown, compounding, summary string |
AccountRisk.mqh |
Money at risk across open positions and pending orders, positions without a stop, risk budget check |
Symbols.mqh |
Resolve EURUSD to the broker's EURUSD.m, EURUSDpro and similar |
News.mqh |
Economic-calendar filter: news near, upcoming events, minutes to the next one |
Conventions
symbol = ""means the current chart symbol — except on the position filter functions (GetPositionCount,GetTotalProfit,GetTotalVolume, and the totals inAccountRisk.mqh), where it means every symbol. Widening a filter and defaulting a subject are different operations; they happen to share a spelling.magic = STOPFIRST_ANY_MAGICmatches any magic number. Magic isulong, so there is no negative value to borrow as a sentinel.- Functions returning a price or a count return
0on failure. Where0is also a plausible real answer, the doc comment on the function says so. - Every public function documents what it returns and what it returns on failure.
Tests
The library is exercised by read-only harnesses that can be attached to any chart, and by demo-only ones that place and close real positions, on a live demo account and in the Strategy Tester, on forex, gold, indices and stocks. The test programs are not part of this archive.
Compiling proves the types line up. It proves nothing about a broker: tick values, minimum stop distances and close-time races all behave differently on different servers, and every defect found on 2026-09-24 compiled cleanly.
Requirements
MetaTrader 5, any recent build. Uses Include\Trade\ (CSymbolInfo,
CAccountInfo, CPositionInfo), which ships with the terminal.
No DLL imports. No WebRequest. Nothing in this package sends a trade request —
it reads and calculates. Order execution lives in a separate, unpublished part
of the project.
The one change it makes to the terminal is adding symbols to Market Watch, so
that they have quotes: ResolveSymbol adds the symbol it finds (pass false
to stop it), EnsureSymbolSelected exists to do exactly that, and the
currency conversion behind pip value and margin adds the conversion pair it
needs, such as USDJPY for a JPY-quoted symbol on a USD account.
License
MIT. See LICENSE.