//+------------------------------------------------------------------+ //| spread.mq5 | //| Copyright 2026, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2000-2026, MetaQuotes Ltd." #property link "https://www.mql5.com" //--- #property script_show_inputs //--- input string symbol_stock1 = "GOOGL"; // First market symbol for spread input string symbol_stock2 = "AAPL"; // Second market symbol for spread input datetime from_t = D'2024.04.01'; // Start of quotes analysis time interval input datetime to_t = D'2026.04.01'; // End of quotes analysis time interval input ENUM_TIMEFRAMES tf = PERIOD_D1; // Time frame input ulong p_ar = 1; // Order of the AR component input ulong q_ma = 1; // Order of the MA component //--- #include "EconometricsM.mqh" // Header file with regression_CLS() function //--- void OnStart() { ulong k=p_ar+q_ma+1; //--- quotes downloading MqlRates rates_stock1[], rates_stock2[]; int n_rates_stock1 = CopyRates(symbol_stock1, tf, from_t, to_t, rates_stock1); int n_rates_stock2 = CopyRates(symbol_stock2, tf, from_t, to_t, rates_stock2); PrintFormat("Number of downloaded quotes for first stock %s: %d", symbol_stock1, n_rates_stock1); PrintFormat("Number of downloaded quotes for second stock %s: %d", symbol_stock2, n_rates_stock2); if(n_rates_stock1 <= int(k) || n_rates_stock2 <= int(k)) {Print("Not enough data"); return;} //--- Formation of time-synchronized stock1/stock2 quote pairs vector y((ulong)n_rates_stock1); int i_stock1 = 0, i_stock2 = 0; ulong n = 0; for(; i_stock1 < n_rates_stock1; ++i_stock1) { //--- We are looking for a bar of the second instrument with time >= time of the first while(i_stock2 < n_rates_stock2 && rates_stock2[i_stock2].time < rates_stock1[i_stock1].time) i_stock2++; if(i_stock2 >= n_rates_stock2) break; // The story of the second instrument has ended if(rates_stock2[i_stock2].time > rates_stock1[i_stock1].time) continue; // Skip if there is no exact time match //--- The timestamps matched, we calculate the logarithmic spread n++; y[n-1] = MathLog(rates_stock1[i_stock1].close / rates_stock2[i_stock2].close); i_stock2++; } y.Resize(n); if(n <= k) {Print("Not enough data after synchronization"); return;} Print("y length: ", n); //--- CLS data preparation vector y_=vector::Zeros(p_ar),e_=vector::Zeros(q_ma),e(n); //--- Coefficient statistics CoefficientStats stat[]; // Forecast for the next step SPrognose prog; //--- CLS calculation regression_CLS(y,p_ar,q_ma,y_,e_,e,stat,prog); //--- Result output Print("==================================="); //--- Coefficients statistics ArrayPrint(stat,4); Print("==================================="); //--- Forecast metrics prog.print(); Print("==================================="); //--- Residuals vs t t_residuals_plot(e); //--- ACF graph correlogram(e); } //+------------------------------------------------------------------+