StopFirst-Core/README.md
RUSLAN SLOBODIANIUK ccaa4ad52b 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

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() reports reliable = false; call SetGmtOffset(hours) in OnInit, or sessions and IsWithinTradingHours assume GMT+0.
  • There is no economic calendar. IsCalendarAvailable() returns false and IsNewsNear() 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 in AccountRisk.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_MAGIC matches any magic number. Magic is ulong, so there is no negative value to borrow as a sentinel.
  • Functions returning a price or a count return 0 on failure. Where 0 is 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.