81 lines
3.4 KiB
MQL5
81 lines
3.4 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| 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);
|
|
}
|
|
//+------------------------------------------------------------------+
|