fast_json/Tests/TestBinanceBenchmark.mq5
2026-02-19 22:19:54 -03:00

174 lines
6.8 KiB
MQL5

//+------------------------------------------------------------------+
//| TestBinanceBenchmark.mq5 |
//| AI-Toolkit |
//| |
//| Benchmark: fast_json vs JAson on REAL Binance API Responses |
//| Downloads live JSON via WebRequest, then benchmarks parse/serial |
//| |
//| IMPORTANT: Add https://api.binance.com to |
//| Tools > Options > Expert Advisors > Allow WebRequest for URLs |
//+------------------------------------------------------------------+
#property script_show_inputs
#include "../fast_json.mqh"
#include <JAson.mqh>
input int InpLoops = 10000; // Benchmark Loops per payload
input string InpSymbol = "BTCUSDT"; // Symbol
//+------------------------------------------------------------------+
//| Download JSON from URL via WebRequest |
//+------------------------------------------------------------------+
string HttpGet(string url) {
char post[];
char result[];
string headers;
string cookie = "";
string referer = "";
int timeout = 5000;
ResetLastError();
int res = WebRequest("GET", url, cookie, referer, timeout, post, 0, result,
headers);
if (res == -1) {
int err = GetLastError();
PrintFormat("WebRequest FAILED: %s (Error %d)", url, err);
if (err == 4014)
Print(">>> Add https://api.binance.com to Tools > Options > Expert "
"Advisors > Allow WebRequest");
return "";
}
if (res != 200) {
PrintFormat("HTTP %d: %s", res, url);
return "";
}
return CharArrayToString(result, 0, WHOLE_ARRAY, CP_UTF8);
}
//+------------------------------------------------------------------+
//| Benchmark a single payload: fast_json vs JAson |
//+------------------------------------------------------------------+
void BenchPayload(string label, string json, int loops) {
if (json == "") {
PrintFormat(" [%s] SKIPPED — empty payload", label);
return;
}
int bytes = StringLen(json);
PrintFormat(" [%s] %d bytes", label, bytes);
// --- fast_json ---
CJson fj;
ulong t0, fj_parse, fj_ser;
string dummy = "";
// Warmup
fj.Parse(json);
// Parse
t0 = GetMicrosecondCount();
for (int i = 0; i < loops; i++)
fj.Parse(json);
fj_parse = GetMicrosecondCount() - t0;
// Serialize
t0 = GetMicrosecondCount();
for (int i = 0; i < loops; i++)
dummy = fj.Serialize();
fj_ser = GetMicrosecondCount() - t0;
// --- JAson ---
CJAVal ja;
ulong ja_parse, ja_ser;
// Warmup
ja.Deserialize(json);
// Parse
t0 = GetMicrosecondCount();
for (int i = 0; i < loops; i++)
ja.Deserialize(json);
ja_parse = GetMicrosecondCount() - t0;
// Serialize
t0 = GetMicrosecondCount();
for (int i = 0; i < loops; i++)
dummy = ja.Serialize();
ja_ser = GetMicrosecondCount() - t0;
// --- Results ---
double parse_speedup = (ja_parse > 0) ? (double)ja_parse / fj_parse : 0;
double ser_speedup = (ja_ser > 0) ? (double)ja_ser / fj_ser : 0;
double total_speedup = (double)(ja_parse + ja_ser) / (fj_parse + fj_ser);
PrintFormat(" fast_json | Parse: %6d us (%5.1f us/op) | Serialize: %6d "
"us (%5.1f us/op)",
fj_parse, (double)fj_parse / loops, fj_ser,
(double)fj_ser / loops);
PrintFormat(" JAson | Parse: %6d us (%5.1f us/op) | Serialize: %6d "
"us (%5.1f us/op)",
ja_parse, (double)ja_parse / loops, ja_ser,
(double)ja_ser / loops);
PrintFormat(" Speedup | Parse: %.1fx | Serialize: %.1fx | Total: %.1fx",
parse_speedup, ser_speedup, total_speedup);
Print(" ────────────────────────────────────────────────");
}
//+------------------------------------------------------------------+
//| Script entry point |
//+------------------------------------------------------------------+
void OnStart() {
Print("══════════════════════════════════════════════════");
Print(" BINANCE LIVE BENCHMARK — fast_json v3.4.1 vs JAson");
Print(" Symbol: ", InpSymbol, " | Loops: ", InpLoops);
Print("══════════════════════════════════════════════════");
Print("");
string base = "https://api.binance.com/api/v3/";
//--- 1. Download all payloads first
Print("Downloading live data from Binance API...");
string klines =
HttpGet(base + "klines?symbol=" + InpSymbol + "&interval=1h&limit=100");
string depth = HttpGet(base + "depth?symbol=" + InpSymbol + "&limit=100");
string trades = HttpGet(base + "trades?symbol=" + InpSymbol + "&limit=100");
string ticker = HttpGet(base + "ticker/24hr?symbol=" + InpSymbol);
if (klines == "" && depth == "" && trades == "" && ticker == "") {
Print("ALL downloads failed. Check WebRequest permissions.");
Print(">>> Tools > Options > Expert Advisors > Allow WebRequest");
Print(">>> Add: https://api.binance.com");
return;
}
Print("Download complete. Starting benchmark...");
Print("");
//--- 2. Benchmark each payload type
// Klines: Array of arrays, heavy numeric (timestamps + OHLCV as strings)
// ~100 candles × 12 fields = 1200 values
Print("━━━ 1. KLINES (Array of Arrays — OHLCV) ━━━");
BenchPayload("Klines 100x1H", klines, InpLoops);
// Depth: Object with 2 arrays of arrays (bids/asks), pure numeric strings
// 100 bid levels + 100 ask levels × 2 fields = 400 values
Print("━━━ 2. ORDER BOOK DEPTH (Bids/Asks) ━━━");
BenchPayload("Depth L100", depth, InpLoops);
// Trades: Array of objects with mixed types (id, price, qty, bool, timestamp)
// 100 trades × 7 fields = 700 values
Print("━━━ 3. RECENT TRADES (Array of Objects) ━━━");
BenchPayload("Trades 100", trades, InpLoops);
// Ticker24hr: Single flat object with many numeric string fields
// ~20 fields, small but diverse
Print("━━━ 4. TICKER 24HR (Flat Object) ━━━");
BenchPayload("Ticker24hr", ticker, InpLoops);
//--- 3. Summary
Print("");
Print("══════════════════════════════════════════════════");
Print(" Benchmark complete. All data sourced LIVE from");
Print(" Binance REST API. No synthetic/hardcoded payloads.");
Print("══════════════════════════════════════════════════");
}