Join our fan page
- Views:
- 223
- Published:
-
Need a robot or indicator based on this code? Order it on Freelance Go to Freelance
Triple-barrier labeling pipelines frequently use an arbitrary constant (0.5–1.0%) or a legacy spread assumption as the min_ret threshold. A threshold set below the actual round-trip transaction cost causes the pipeline to label cost-driven noise as tradeable signal. The labeled dataset then systematically overstates edge, and any model trained on those labels overfits to an artifact of the labeling scheme rather than to genuine market structure.
TransactionCostCollector.mq5 is a standalone script that resolves the data-collection step of this problem. It samples the historical spread distribution, reads the broker's swap rates and commission diagnostics for the attached chart symbol, and exports everything to a structured CSV file. The CSV is consumed by the companion Python class TransactionCostModel, which converts all costs to fractional returns and computes the instrument-specific min_ret threshold for your labeling call.

Three-panel illustration of TransactionCostCollector output: intraday cost breakdown by session (a), full cost distribution (b), and percentile curve for min_ret selection (c)
What the Script Collects
The script collects three cost components for a single symbol in one run:
- Spread — historical distribution from CopySpread() across the requested bar count. Reported as mean, standard deviation, and percentiles (p25, p50, p75, p90, p95, p99), all in pips. Also computed per UTC hour of day to expose session effects.
- Swap — long and short overnight swap rates read directly from SYMBOL_SWAP_LONG / SYMBOL_SWAP_SHORT, including the swap mode (points, currency, interest) and the weekday on which triple swap is charged.
- Commission — diagnostic only. MQL5 does not expose per-lot commission as a direct API call on all brokers. The script records ACCOUNT_COMMISSION_BLOCKED and a note explaining how to derive the per-lot rate from a single reference trade.
Input Parameters
| Parameter | Default | Description |
|---|---|---|
| InpBars | 50000 | Number of bars of spread history to sample. A larger value produces a more representative distribution and captures more session variation. 50 000 bars on H1 covers roughly 5.7 years; on M15 it covers roughly 1.4 years. Reduce if the terminal has limited history for the symbol. |
| InpOutputFile | (blank) | Override the output filename. When blank (default), the file is named <SYMBOL>_costs.csv — for example, EURUSD_costs.csv for EURUSD. The file is written to MQL5\Files\ in the terminal data folder (FILE_WRITE | FILE_CSV mode). |
CSV Output Format
The CSV uses a four-column structure: section, key, value, unit. Sections are:
- symbol_properties — point size, pip factor, tick value, contract size, currency identifiers.
- swap — long/short rates, swap mode, triple-swap weekday.
- commission — diagnostic value and derivation note.
- spread_summary — mean, std, and percentiles across all sampled bars.
- spread_by_hour — mean spread (pips) for each hour of day, one row per hour (UTC, broker time).
How to Run
- Place TransactionCostCollector.mq5 in your MQL5\Scripts\Downloads\ folder and compile in MetaEditor.
- Open a chart of the target symbol on any timeframe. The timeframe controls which bar type the spread distribution is sampled from — H1 is recommended as a reasonable compromise between granularity and history length.
- Drag the script onto the chart. The input dialog will appear (controlled by #property script_show_inputs). Set InpBars to the desired sample count and click OK.
- Retrieve the output CSV from MQL5\Files\ in the terminal data folder (File → Open Data Folder in MetaTrader 5).
Integrating with Python
The companion Python class TransactionCostModel loads the CSV and computes min_ret for triple-barrier labeling:
from afml.transaction_costs import load_cost_model import pandas as pd model = load_cost_model( csv_path = "EURUSD_costs.csv", spread_percentile = "p95_pips", # conservative slippage_pips = 0.4, commission_per_lot = 7.0, # from reference trade lot_size = 0.01, ) close = pd.read_parquet("EURUSD_H1.parquet")["close"] min_ret = model.min_ret_for_symbol( price_series = close, holding_days = 1.0, cost_multiplier = 1.5, # 1.5x break-even ) print(f"min_ret = {min_ret:.6f}")
Notes on Commission
The per-lot commission rate cannot be read programmatically on all brokers. The recommended procedure is: open a reference trade of exactly 1.0 standard lot on a demo account, read ACCOUNT_COMMISSION_BLOCKED from the terminal immediately after the trade opens, then close the trade. The blocked value divided by 1.0 gives the per-lot rate. Confirm against the account statement. This needs to be done once per broker relationship.
Why p95, Not the Mean
The mean spread is dominated by quiet periods: Asian session, overnight consolidation, and orderly trending conditions. Strategy entries, however, often coincide with the moments of highest uncertainty (which is when models generate signals). Using the 95th-percentile spread as min_ret input accounts for the cost environment at typical entry conditions rather than at average market conditions.
References and Companion Article
- López de Prado, M. (2018). Advances in Financial Machine Learning, Chapter 3 (Labels), p. 44–47. Wiley.
- Full implementation and derivation: MetaTrader 5 Machine Learning Blueprint — Part 14: Transaction Cost Model by Patrick M. Njoroge.
- Companion Python class TransactionCostModel and usage examples are included in the article download package.
Spread Monitor
Allows to monitor spread and swaps!
Institutional Harmonic Volumetric Gravity Center
A quantitative volume density engine utilizing weighted Harmonic Mean mathematics to eliminate arithmetic outliers and map the true institutional liquidity center of gravity.
Heiken ashi as series
Heiken ashi with all buffers set as series
MACD Signals
Indicator edition for new platform.