function [y_train, y_test, yF, minimo, maximo] =  grid_search(signal, prc_test_forecast, n_iteraciones, date, nombre_empresa, nombre_data, random_seed)
    % random seed
    rng(random_seed);
    % scaler:
    [signal_normalized, minimo, maximo] = minmax_scaler(signal);
    % number of samples:
    N = length( signal_normalized );
    % index to cut data set (train/ test)
    index_cut = floor(prc_test_forecast*N);
    % data train
    y_train = signal_normalized(1:index_cut);
    % data dest
    y_test = signal_normalized(index_cut + 1 : N);
    N_periods_forecast = length(y_test);
    % P,D,Q ranges:
    P = 0:9;
    D = 0:3;
    Q = 0:9;
    % vector to save pdq's
    Hiper_parametros = [];
    % vector to save error (RMSE's):
    Error = [];
    Error_train = [];
    % vector to save residuals:
    Residuos = [];
    % structure to save models:
    m = struct();
    % count iteration
    iteracion = 1;
    % made a perpetual while...
    ii = 1;
    while 1
        try
            % index random
            p_i = randi(length(P));
            d_i = randi(length(D));
            q_i = randi(length(Q));
            % random selection of pdq by iteration:
            p = P( p_i );
            d = D( d_i );
            q = Q( q_i );
            % create a ARIMA model:
            model = arima(p,d,q);
            %% train model:
            model = estimate(model, y_train);
            % save tuple selected:
            Hiper_parametros = [Hiper_parametros; [p,d,q]];
            % save model:
            m.(['model_', num2str(ii)]) = model;
            ii = ii + 1;
            % residual after train:
            residuos = infer(model, y_train);
            % RMSE:
            rmse_train = RMSE(y_train + residuos, y_train);
            fprintf("RMSE train %d = %e \n", iteracion, rmse_train)
            %% forecast
            % number of periods to forecast:
            n_test_periods = length(y_test);
            % forecasting
            y_pred = forecast(model, n_test_periods, y_train);
            rmse_test = RMSE(y_pred, y_test);
            fprintf("RMSE test %d = %e \n",iteracion, rmse_test)
            % Save error
            Error = [Error; rmse_test];
            Error_train = [Error_train; rmse_train];
            Residuos = [Residuos; residuos];
            iteracion = iteracion + 1;
            fprintf("Iteracion = %d \n", iteracion)
        catch
            disp("ERROR")
            iteracion = iteracion + 1;
            fprintf("Iteracion = %d pero con error \n", iteracion)
        end
        
       % if number of iterations surpasses n_iterciones variable then break
       % while.
        if n_iteraciones <= iteracion
            break
        end
    end
    % fin min error
    [min_error, index_min] = min(Error);
    fprintf("El minimo error es = %4.2f y se encontró en la iteración %d \n",min_error, index_min)
    % hiperparametros optimos:
    params = Hiper_parametros(index_min, :);
    % edit name of company
    nombre_empresa = strrep(nombre_empresa, '_', ' ');
    %% Extraer los coeficientes del modelo
    % best model:
    best_model = m.(['model_', num2str(index_min)]);
    ARCoefs = cell2mat(best_model.AR);
    MACoefs = cell2mat(best_model.MA);
    Constant = best_model.Constant;
    vari = best_model.Variance;
    % prepared data to export:
    n_ar_coefs = length(ARCoefs);
    n_ma_coefs = length(MACoefs);
    filename = sprintf('resultados_comcel/ARIMA_Coefficients %s - %s .xlsx',nombre_empresa, nombre_data);
    if n_ar_coefs > n_ma_coefs 
        A = [ ARCoefs;...
            MACoefs zeros(1,n_ar_coefs - n_ma_coefs);...
            Constant  zeros(1,n_ar_coefs-1);...
            vari zeros(1,n_ar_coefs-1)];
        writematrix(A,filename)
    elseif n_ar_coefs < n_ma_coefs
        A = [ ARCoefs zeros(1,n_ma_coefs - n_ar_coefs);...
             MACoefs ;...
             Constant  zeros(1,n_ma_coefs-1);...
             vari zeros(1,n_ma_coefs-1)];
        writematrix(A,filename)
    elseif n_ar_coefs == n_ma_coefs
        A = [ARCoefs ;...
             MACoefs ;...
             Constant  zeros(1,n_ma_coefs -1);...
             vari zeros(1,n_ma_coefs -1)];
        writematrix(A,filename)
        clear A
    end
    
    %% Si Residuos no esta vacia...
    if ~isempty(Residuos)
        %% Grafica total
        figure()
        plot(date, signal)
        title(sprintf("Datos originales \n %s _ %s",nombre_empresa, nombre_data))
        xlabel("Años")
        grid on
        saveas(gcf, sprintf("resultados_comcel/señal_original %s _ %s .png",nombre_empresa, nombre_data));
        %% Plot diffs
        nd = params(2);
        if nd > 0
            figure()
            subplot(2, 1, 1); % Subplot 1
            plot(date(1:index_cut),y_train);
            title('Señal original');
            subplot(2, 1, 2); % Subplot 2
            grid on
            x_dif = diff(y_train,nd);
            n_diff = length(x_dif);
            dif_n = length(date) - n_diff;
            plot(date(1:n_diff),x_dif);
            title(sprintf("Señal con d = %d diferencias aplicadas",nd));
            %sgtitle(sprintf("Diferencias aplicadas a %s \n de la empresa %s",nombre_data, nombre_empresa));
            grid on
            saveas(gcf, sprintf("resultados_comcel/diferencias_aplicadas %s _ %s .png",nombre_empresa, nombre_data));
        else
            x_dif = y_train;
            sprintf("diferencias = %d \n no se necesita grafica de diferencias",nd)
        end
        %% AC and PAC plots:
        figure()
        subplot(2, 1, 1); % Subplot 1
        parcorr(x_dif, NumLags = 20) % ACP
        title("Función de autocorrelación parcial")
        subplot(2, 1, 2); % Subplot 2
        autocorr(x_dif, NumLags = 20) % AC
        title("Función de autocorrelación")
        %sgtitle(sprintf("Funciones de autocorrelación a %s \n de la empresa %s",nombre_data, nombre_empresa));
        grid on
        saveas(gcf, sprintf("resultados_comcel/auto_correlacion %s _ %s .png",nombre_empresa, nombre_data));
        %% Grafica de entrenamiento
        figure()
        plot(date(1:index_cut), y_train)
        hold on
        plot(date(1:index_cut), y_train + Residuos(index_min,:))
        hold off
        legend('Datos entrenamieno','Datos predichos en entrenamiento')
        title(sprintf("Entrenamiento de %s \n de la empresa %s \n Error entrenamiento = %2.4f", nombre_data, nombre_empresa,Error_train(index_min)))
        grid on
        saveas(gcf, sprintf("resultados_comcel/train %s _ %s .png",nombre_empresa, nombre_data));
        %% forecast
        [yF, yMSE] = forecast(best_model, n_test_periods, y_train);
        upper1 = yF + 1.96*sqrt(yMSE);
        lower1 = yF - 1.96*sqrt(yMSE);
        date_test = date(index_cut + 1 : N);
        figure()
        plot(date(1:index_cut),y_train,'Color',[.75,.75,.75])
        hold on
        h1 = plot(date_test,yF,'r','LineWidth',1);
        h2 = plot(date_test,y_test,'b','LineWidth',1);
        h3 = plot(date_test,upper1,'k--','LineWidth',1.5);
        plot(date_test,lower1,'k--','LineWidth',1.5)
        xlim([date(1) date_test(end)])
        legend([h1 h2, h3],'Forecast','True','Intervalo de confianza','Location','NorthWest')
        title(sprintf("%s - %s \n error %2.4f parametros = (p = %d  d = %d q = %d) \n Periodos forecast = %d",nombre_empresa,...
                                                                               nombre_data,...
                                                                               min_error,...
                                                                               params(1),...
                                                                               params(2),...
                                                                               params(3),N_periods_forecast ))
        saveas(gcf, sprintf("resultados_comcel/test %s _ %s .png",nombre_empresa, nombre_data));
        hold off
    end
end


