function rResult = fGARCH(vY,mX)
%Diese Funktion schätzt ein GARCH-X(1,1) Modell
%
%Input:
%   vY: Tx1 Vektor der empirischen Werte der abhängigen Variable
%   mX: T*K Matrix der empirischen Werte der unabhängigen Variablen

%Schätzen des Modells, um den Startwert für Beta zu erhalten
b = regress(vY,mX);
vBetaStart = b;

%Varianz der Residuen als Startwert
dVarStart = var(vY - mX * vBetaStart);

%Berechnete Parameter als Startpunkt und Gamma,Phi und Zeta auf Null setzen
vStart = [vBetaStart;dVarStart;0;0];

% Nebenbedingungen setzen
% Anzahl Beobachtungen und Variablen ermitteln
[iNumObs,iNumVars] = size(mX); 
A = [];                % Keine linearen Ungleichheitsrestriktionen
b = [];                % Keine linearen Ungleichheitsrestriktionen
Aeq = [];              % Keine linearen Gleichheitsrestriktionen
beq = [];              % Keine linearen Gleichheitsrestriktionen

% Unter- und Obergrenzen wie beschrieben setzen
vLB = [-Inf(iNumVars,1);0;0;0;0];
vUB = [+Inf(iNumVars,1);var(vY,1);0.999998;0.999998;0.999998];

%Übergabe der Daten an den Optimierer
%Setzen der Optionen
options = optimset('Display','iter','algorithm','sqp','MaxIter', 1000 *...
    length(vStart), 'TolFun',1e-10,'TolX',1e-10);
%Durchführung der Optimierung
[x,fval,exitflag,output,lambda,grad,hessianM] = fmincon(@(vPara)...
    fLLGARCH(vPara,vY,mX),vStart,A,b,Aeq,beq,vLB,vUB,@(vPara)...
    fGARCHNB(vPara, vY, mX),options);

%Zielfunktionswert, Vorzeichen umdrehen        
rResult.dLLR = -fval;
rResult.exitflag = exitflag;

% Schätzen der Standardfehler durch Funktion Poddig
mHessianB = fHessApprox( @(vPara)fLLGARCH(vPara,vY,mX), x );
mInvHes = mHessianB \ eye((iNumVars+3));
vTemp = diag(mInvHes);
vTemp(vTemp < 0) = NaN; % Negative Werte als NaN markieren
vParaSE = sqrt(vTemp);
% 
% %Schätzen der Standardfehler durch Matlabfunktion
% mHessian = hessian('fLLGARCHX',x,vY,mX);
% mInvHes = mHessian \ eye((iNumVars+3));
% vTemp = diag(mInvHes);
% vTemp(vTemp < 0) = NaN; % Negative Werte als NaN markieren
% vParaSE = sqrt(vTemp);

%Ergebnisse in Struct hinzufügen und t-Werte berechnen
rResult.vBeta = x(1:end-3);
rResult.vSEcoef = vParaSE(1:end-3);
rResult.dOmega = x(end-2);
rResult.dOmegaSE = vParaSE(end-2);
rResult.dOmegaT = rResult.dOmega/rResult.dOmegaSE;
rResult.dGamma = x(end-1);
rResult.dGammaSE = vParaSE(end-1);
rResult.dGammaT = rResult.dGamma/rResult.dGammaSE;
rResult.dPhi = x(end);
rResult.dPhiSE =vParaSE(end);
rResult.dPhiT = rResult.dPhi/rResult.dPhiSE;

end

