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 | | | //+------------------------------------------------------------------+
|
| | | //| PipTable.mqh |
|
| | | //| Copyright 2026, bandersoft |
|
| | | //| https://www.mql5.com/en/users/fats |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //| Conventional pip sizes for common non-FX symbols. Read-only. |
|
| | | //| |
|
| | | //| A pip on a CFD is a CONVENTION, not a property the broker |
|
| | | //| reports. GetPipSize()'s automatic rule (point * 10 on 3- and |
|
| | | //| 5-digit symbols, point otherwise) is the forex convention, and |
|
| | | //| makes a gold pip 0.01 - while most traders mean 0.10. Someone |
|
| | | //| typing "30 pips" on gold then gets a stop ten times tighter than |
|
| | | //| they meant. The table encodes the usual retail convention. |
|
| | | //| |
|
| | | //| OPT-IN. GetPipSize() does not consult the table; a program |
|
| | | //| calls ApplyBuiltInPipSize() for a symbol to adopt it, after any |
|
| | | //| explicit override, and should show users the pip in force. |
|
| | | //| Both products do; keeping one table keeps them in agreement. |
|
| | | //| |
|
| | | //| Matching is by PREFIX of the symbol name with leading non-letter |
|
| | | //| characters stripped, case-insensitive: "XAUUSD.m", "#XAUUSD" and |
|
| | | //| "GOLDmicro" match; "MYGOLD" does not. Prefix rather than |
|
| | | //| substring, because a substring match on "DOW" or "CAC" would |
|
| | | //| catch unrelated names. |
|
| | | //| |
|
| | | //| A prefix alone is not enough. MetaQuotes-Demo lists exchange |
|
| | | //| stocks and ETFs named BTCO, BTCW, ETHE, ETHU, DJIA (observed |
|
| | | //| 2026-10-14); a prefix rule gave each of them a 1.0 pip. So the |
|
| | | //| table applies only to forex and CFD calculation modes, and |
|
| | | //| crypto needs the quote currency in the name (BTCUSD, ETHEUR). |
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | #ifndef STOPFIRST_PIPTABLE_MQH
|
| | | #define STOPFIRST_PIPTABLE_MQH
|
| | |
|
| | | #include "Symbol.mqh" // SetPipSize - the table only feeds the override
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Upper-case a symbol and drop leading characters that are not |
|
| | | //| letters or digits ("#US30" -> "US30") |
|
| | | //| Returns: the cleaned name. |
|
| | | //+------------------------------------------------------------------+
|
| | | string PipTableKey(const string symbol)
|
| | | {
|
| | | string name = symbol;
|
| | | StringToUpper(name);
|
| | |
|
| | | int start = 0;
|
| | | int length = StringLen(name);
|
| | | while(start < length)
|
| | | {
|
| | | ushort c = StringGetCharacter(name, start);
|
| | | bool alnum = (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9');
|
| | | if(alnum) break;
|
| | | start++;
|
| | | }
|
| | |
|
| | | return StringSubstr(name, start);
|
| | | }
|
| | |
|
| | | bool PipTableStartsWith(const string text, const string head)
|
| | | {
|
| | | return StringFind(text, head) == 0;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Conventional pip size for a symbol the table knows |
|
| | | //| |
|
| | | //| Returns: the pip size in price units, or 0 when the symbol is not |
|
| | | //| in the table, or when the table value is finer than the |
|
| | | //| symbol's own point (a quote too coarse for the |
|
| | | //| convention - the automatic rule is then the honest one). |
|
| | | //+------------------------------------------------------------------+
|
| | | double BuiltInPipSize(const string symbol)
|
| | | {
|
| | | //--- exchange-traded instruments (stocks, ETFs, futures, bonds) are
|
| | | //--- quoted in plain currency units; the CFD conventions below would
|
| | | //--- be wrong for every one of them
|
| | | ENUM_SYMBOL_CALC_MODE mode =
|
| | | (ENUM_SYMBOL_CALC_MODE)SymbolInfoInteger(symbol, SYMBOL_TRADE_CALC_MODE);
|
| | | if(mode != SYMBOL_CALC_MODE_FOREX && mode != SYMBOL_CALC_MODE_FOREX_NO_LEVERAGE &&
|
| | | mode != SYMBOL_CALC_MODE_CFD && mode != SYMBOL_CALC_MODE_CFDINDEX &&
|
| | | mode != SYMBOL_CALC_MODE_CFDLEVERAGE)
|
| | | return 0;
|
| | |
|
| | | string key = PipTableKey(symbol);
|
| | | double pip = 0;
|
| | |
|
| | | //--- precious metals
|
| | | if(PipTableStartsWith(key, "XAU") || PipTableStartsWith(key, "GOLD"))
|
| | | pip = 0.1;
|
| | | else if(PipTableStartsWith(key, "XAG") || PipTableStartsWith(key, "SILVER"))
|
| | | pip = 0.01;
|
| | | else if(PipTableStartsWith(key, "XPT") || PipTableStartsWith(key, "XPD"))
|
| | | pip = 0.1;
|
| | |
|
| | | //--- energy
|
| | | else if(PipTableStartsWith(key, "USOIL") || PipTableStartsWith(key, "UKOIL") ||
|
| | | PipTableStartsWith(key, "WTI") || PipTableStartsWith(key, "BRENT") ||
|
| | | PipTableStartsWith(key, "XTI") || PipTableStartsWith(key, "XBR"))
|
| | | pip = 0.01;
|
| | | else if(PipTableStartsWith(key, "XNG") || PipTableStartsWith(key, "NGAS") ||
|
| | | PipTableStartsWith(key, "NATGAS"))
|
| | | pip = 0.001;
|
| | |
|
| | | //--- equity indices: one index point
|
| | | else if(PipTableStartsWith(key, "US30") || PipTableStartsWith(key, "DJ30") ||
|
| | | PipTableStartsWith(key, "WS30") || PipTableStartsWith(key, "DJI") ||
|
| | | PipTableStartsWith(key, "US100") || PipTableStartsWith(key, "NAS100") ||
|
| | | PipTableStartsWith(key, "USTEC") || PipTableStartsWith(key, "NDX") ||
|
| | | PipTableStartsWith(key, "US500") || PipTableStartsWith(key, "SPX500") ||
|
| | | PipTableStartsWith(key, "SP500") || PipTableStartsWith(key, "US2000") ||
|
| | | PipTableStartsWith(key, "GER40") || PipTableStartsWith(key, "GER30") ||
|
| | | PipTableStartsWith(key, "DE40") || PipTableStartsWith(key, "DE30") ||
|
| | | PipTableStartsWith(key, "UK100") || PipTableStartsWith(key, "FTSE") ||
|
| | | PipTableStartsWith(key, "JP225") || PipTableStartsWith(key, "JPN225") ||
|
| | | PipTableStartsWith(key, "NIKKEI") || PipTableStartsWith(key, "FRA40") ||
|
| | | PipTableStartsWith(key, "F40") || PipTableStartsWith(key, "EU50") ||
|
| | | PipTableStartsWith(key, "STOXX50")|| PipTableStartsWith(key, "AUS200") ||
|
| | | PipTableStartsWith(key, "HK50") || PipTableStartsWith(key, "ESP35") ||
|
| | | PipTableStartsWith(key, "SPA35"))
|
| | | pip = 1.0;
|
| | |
|
| | | //--- crypto: one unit of the quote currency. The quote currency must
|
| | | //--- be in the name - a bare "BTC..." prefix also matches ETF tickers
|
| | | else if(PipTableStartsWith(key, "BTCUSD") || PipTableStartsWith(key, "BTCEUR") ||
|
| | | PipTableStartsWith(key, "BTCUSDT") || PipTableStartsWith(key, "ETHUSD") ||
|
| | | PipTableStartsWith(key, "ETHEUR"))
|
| | | pip = 1.0;
|
| | |
|
| | | if(pip <= 0) return 0;
|
| | |
|
| | | double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
|
| | | if(point <= 0 || pip < point - 1e-12) return 0;
|
| | |
|
| | | return pip;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Adopt the conventional pip size for a symbol, if the table has one|
|
| | | //| |
|
| | | //| Parameters: |
|
2026-10-16 21:48:01 +03:00 | | | //| symbol - "" for the chart symbol |
|
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: true if the table set the pip size through SetPipSize(). |
|
| | | //| false, leaving GetPipSize() unchanged, when the symbol is |
|
| | | //| not in the table. |
|
| | | //+------------------------------------------------------------------+
|
| | | bool ApplyBuiltInPipSize(string symbol = "")
|
| | | {
|
| | | if(symbol == "") symbol = _Symbol;
|
| | |
|
| | | double pip = BuiltInPipSize(symbol);
|
| | | if(pip <= 0) return false;
|
| | |
|
| | | SetPipSize(symbol, pip);
|
| | | return true;
|
| | | }
|
| | |
|
| | | #endif // STOPFIRST_PIPTABLE_MQH
|
| | | //+------------------------------------------------------------------+
|