diff --git a/matlab/discretionary_policy/discretionary_policy.m b/matlab/discretionary_policy/discretionary_policy.m
index 778d1789db328591ee1aaa01ac997397a7d97cb4..b2c67403d6d2bbf87dd1f47c83b4ee540751680e 100644
--- a/matlab/discretionary_policy/discretionary_policy.m
+++ b/matlab/discretionary_policy/discretionary_policy.m
@@ -1,5 +1,5 @@
-function [info, oo_, options_] = discretionary_policy(M_, options_, oo_, var_list)
-% function [info, oo_, options_] = discretionary_policy(M_, options_, oo_, var_list)
+function [info, oo_, options_, M_] = discretionary_policy(M_, options_, oo_, var_list)
+% function [info, oo_, options_, M_] = discretionary_policy(M_, options_, oo_, var_list)
 % INPUTS
 % - M_            [structure]     Matlab's structure describing the model (M_).
 % - options_      [structure]     Matlab's structure describing the current options (options_).
@@ -10,8 +10,9 @@ function [info, oo_, options_] = discretionary_policy(M_, options_, oo_, var_lis
 % - info          [integer]       scalar or vector, error code.
 % - oo_           [structure]     Matlab's structure containing the results (oo_).
 % - options_      [structure]     Matlab's structure describing the current options (options_).
+% - M_            [structure]     Matlab's structure describing the model (M_).
 
-% Copyright (C) 2007-2019 Dynare Team
+% Copyright (C) 2007-2020 Dynare Team
 %
 % This file is part of Dynare.
 %
@@ -33,7 +34,7 @@ M_=discretionary_policy_initialization(M_,options_);
 origorder = options_.order;
 options_.discretionary_policy = 1;
 options_.order = 1;
-[info, oo_] = stoch_simul(M_, options_, oo_, var_list);
+[info, oo_, options_, M_] = stoch_simul(M_, options_, oo_, var_list);
 
 if ~options_.noprint
     disp_steady_state(M_,oo_)
diff --git a/matlab/identification_analysis.m b/matlab/identification_analysis.m
index 6395a51b31a7382449bd22d517dad29439138840..75d429182bdb5319a527d0aa8b553aea6a028c24 100644
--- a/matlab/identification_analysis.m
+++ b/matlab/identification_analysis.m
@@ -283,7 +283,7 @@ if info(1) == 0 %no errors in solution
                 end
                 analytic_derivation              = options_.analytic_derivation;
                 options_.analytic_derivation     = -2; %this sets asy_Hess=1 in dsge_likelihood.m                
-                [info, oo_, options_] = stoch_simul(M_, options_, oo_, options_.varobs);
+                [info, oo_, options_, M_] = stoch_simul(M_, options_, oo_, options_.varobs);
                 dataset_ = dseries(oo_.endo_simul(options_.varobs_id,100+1:end)',dates('1Q1'), options_.varobs); %get information on moments
                 derivatives_info.no_DLIK = 1;
                 bounds = prior_bounds(bayestopt_, options_.prior_trunc); %reset bounds as lb and ub must only be operational during mode-finding 
diff --git a/matlab/osr.m b/matlab/osr.m
index 25db19bdd4e52308f30535908607376d589dc131..3a0d463f2271c3f0947c9744a28205ab3149e122 100644
--- a/matlab/osr.m
+++ b/matlab/osr.m
@@ -62,4 +62,4 @@ if ~options_.noprint
 end
 osr_res = osr1(i_params,i_var,W);
 
-[~, oo_, options_] = stoch_simul(M_, options_, oo_, var_list);
+[~, oo_, options_, M_] = stoch_simul(M_, options_, oo_, var_list);
diff --git a/matlab/ramsey_policy.m b/matlab/ramsey_policy.m
index 0ce386c8a3c7d0ae92d001187f3f0fadb5c932d9..46acdb85464df17891af79b057d17f892607fe24 100644
--- a/matlab/ramsey_policy.m
+++ b/matlab/ramsey_policy.m
@@ -39,7 +39,7 @@ else
     end
 end
 
-[info, oo_, options_] = stoch_simul(M_, options_, oo_, var_list);
+[info, oo_, options_, M_] = stoch_simul(M_, options_, oo_, var_list);
 
 oo_.steady_state = oo_.dr.ys;
 
diff --git a/matlab/stoch_simul.m b/matlab/stoch_simul.m
index c8af0c6f5e1f8b54e446cfea8441d75c9e7ec1d3..ba3765da0b9482bf4330e01af3a1dfdd20b8e4a3 100644
--- a/matlab/stoch_simul.m
+++ b/matlab/stoch_simul.m
@@ -1,4 +1,4 @@
-function [info, oo_, options_] = stoch_simul(M_, options_, oo_, var_list)
+function [info, oo_, options_, M_] = stoch_simul(M_, options_, oo_, var_list)
 
 % Copyright (C) 2001-2020 Dynare Team
 %
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 7648c381877ffb0e3ec0f2033d617c8c3269a1a7..a1fe16771727115345acbf2db84ed97de4f8704a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -124,6 +124,7 @@ MODFILES = \
 	steady_state/walsh1_ssm_block.mod \
 	steady_state/multi_leads.mod \
 	steady_state/example1_trust_region.mod \
+	steady_state/Gali_2015_chapter_6_4.mod \
 	steady_state_operator/standard.mod \
 	steady_state_operator/use_dll.mod \
 	steady_state_operator/block.mod \
diff --git a/tests/moments/fs2000_post_moments.mod b/tests/moments/fs2000_post_moments.mod
index f25a60b380d92f13349b512d322e1d8fe5c79c4a..3ea15dcef0946954f34f1a85f03927a40fa13c09 100644
--- a/tests/moments/fs2000_post_moments.mod
+++ b/tests/moments/fs2000_post_moments.mod
@@ -130,7 +130,7 @@ par=load([M_.fname filesep 'metropolis' filesep M_.fname '_posterior_draws1']);
 
 for par_iter=1:size(par.pdraws,1)
    M_=set_parameters_locally(M_,par.pdraws{par_iter,1});
-   [info, oo_, options_]=stoch_simul(M_, options_, oo_, var_list_);
+   [info, oo_, options_, M_]=stoch_simul(M_, options_, oo_, var_list_);
    correlation(:,:,par_iter)=cell2mat(oo_.autocorr);
    covariance(:,:,par_iter)=oo_.var;
    conditional_variance_decomposition(:,:,:,par_iter)=oo_.conditional_variance_decomposition;
diff --git a/tests/steady_state/Gali_2015_chapter_6_4.mod b/tests/steady_state/Gali_2015_chapter_6_4.mod
new file mode 100644
index 0000000000000000000000000000000000000000..64c5df3c05c35a371124759049cf6c9072b187dd
--- /dev/null
+++ b/tests/steady_state/Gali_2015_chapter_6_4.mod
@@ -0,0 +1,277 @@
+/*
+ * This file implements the New Keynesian model with price and wage rigidities under optimal policy 
+ * with commitment (Ramsey) of Jordi Gal� (2015): Monetary Policy, Inflation, and the Business Cycle, Princeton 
+ * University Press, Second Edition, Chapter 6.4
+ *
+ * THIS MOD-FILE REQUIRES DYNARE 4.6 OR HIGHER
+ *
+ * Notes:
+ *  - all model variables are expressed in deviations from steady state, i.e. in contrast to
+ *      to the chapter, the nominal interest rate, natural output, and the natural real wage are not in log-levels, but rather mean 0
+ *  - in the LOM for the discount rate shock z the shock enters with a minus sign in this mod-file to generate the 
+ *      IRF to a -0.5% shock
+ *
+ * This implementation was written by Johannes Pfeifer. In case you spot mistakes,
+ * email me at jpfeifer@gmx.de
+ *
+ * Please note that the following copyright notice only applies to this Dynare 
+ * implementation of the model.
+ */
+
+/*
+ * Copyright (C) 2020 Dynare Team
+ *
+ * This is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * It is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * For a copy of the GNU General Public License,
+ * see <http://www.gnu.org/licenses/>.
+ */
+
+%define whether to use interest rate or money growth rate rule 
+@#define money_growth_rule=1
+
+var pi_p        ${\pi^p}$               (long_name='price inflation')
+    y_gap       ${\tilde y}$            (long_name='output gap')
+    y_nat       ${y^{nat}}$             (long_name='natural output')      //(in contrast to the textbook defined in deviation from steady state)
+    y           ${y}$                   (long_name='output')
+    yhat        ${\hat y}$              (long_name='output deviation from steady state')
+    r_nat       ${r^{nat}}$             (long_name='natural interest rate')
+    r_real      ${r^r}$                 (long_name='real interest rate')     
+    i           ${i}$                   (long_name='nominal interrst rate')
+    n           ${n}$                   (long_name='hours worked')
+    m_real      ${(m-p)}$                 (long_name='real money stock')
+    m_growth_ann ${\Delta m}$           (long_name='money growth annualized')
+    m_nominal   ${m}$                   (long_name='nominal money stock')
+    nu          ${\nu}$                 (long_name='AR(1) monetary policy shock process')    
+    a           ${a}$                   (long_name='AR(1) technology shock process')
+    r_real_ann  ${r^{r,ann}}$           (long_name='annualized real interest rate')
+    i_ann       ${i^{ann}}$             (long_name='annualized nominal interest rate')
+    r_nat_ann   ${r^{nat,ann}}$         (long_name='annualized natural interest rate')
+    pi_p_ann    ${\pi^{p,ann}}$         (long_name='annualized inflation rate')
+    z           ${z}$                   (long_name='AR(1) preference shock process')
+    p           ${p}$                   (long_name='price level')
+    w           ${w}$                   (long_name='nominal wage')
+    c           ${c}$                   (long_name='consumption')
+    w_real      $\omega$                (long_name='real wage')
+    w_gap       ${\tilde \omega}$       (long_name='real wage gap')
+    pi_w        ${\pi^w}$               (long_name='wage inflation')
+    w_nat       ${w^{nat}}$             (long_name='natural real wage')
+    mu_p        ${\mu^p}$               (long_name='markup')
+    pi_w_ann    ${\pi^{w,ann}}$         (long_name='annualized wage inflation rate')
+;     
+
+varexo  eps_a       ${\varepsilon_a}$   (long_name='technology shock')
+        eps_nu      ${\varepsilon_\nu}$ (long_name='monetary policy shock')
+        eps_z       ${\varepsilon_z}$   (long_name='preference shock innovation')
+       ;
+
+parameters alppha       ${\alpha}$     (long_name='capital share')
+    betta               ${\beta}$       (long_name='discount factor')
+    rho_a               ${\rho_a}$      (long_name='autocorrelation technology shock')
+    rho_nu              ${\rho_{\nu}}$  (long_name='autocorrelation monetary policy shock')
+    rho_z               ${\rho_{z}}$    (long_name='autocorrelation monetary demand shock')
+    siggma              ${\sigma}$      (long_name='inverse EIS')
+    varphi              ${\varphi}$     (long_name='inverse Frisch elasticity')
+    phi_pi              ${\phi_{\pi}}$  (long_name='inflation feedback Taylor Rule')
+    phi_y               ${\phi_{y}}$    (long_name='output feedback Taylor Rule')
+    eta                 ${\eta}$        (long_name='semi-elasticity of money demand')
+    epsilon_p           ${\epsilon_p}$  (long_name='demand elasticity goods')
+    theta_p             ${\theta_p}$    (long_name='Calvo parameter prices')
+    epsilon_w           ${\epsilon_w}$  (long_name='demand elasticity labor services')
+    theta_w             ${\theta_w}$    (long_name='Calvo parameter wages')
+    lambda_p            ${\lambda_p}$   (long_name='composite parameter Phillips Curve')
+    lambda_w            ${\lambda_w}$   (long_name='composite parameter wage Phillips Curve')
+    ;
+%----------------------------------------------------------------
+% Parametrization, p. 67  and p. 113-115
+%----------------------------------------------------------------
+siggma = 1;
+varphi=5;
+phi_pi = 1.5;
+phi_y  = 0.125;
+theta_p=3/4;
+rho_nu =0.5;
+rho_z  = 0.5;
+rho_a  = 0.9;
+betta  = 0.99;
+eta  =3.77; %footnote 11, p. 115
+alppha=1/4;
+epsilon_p=9;
+
+epsilon_w=4.5;
+theta_w=3/4;
+%----------------------------------------------------------------
+% First Order Conditions
+%----------------------------------------------------------------
+
+model(linear); 
+//Composite parameters
+#Omega=(1-alppha)/(1-alppha+alppha*epsilon_p);              %defined on page 166
+#psi_n_ya=(1+varphi)/(siggma*(1-alppha)+varphi+alppha);     %defined on page 171
+#psi_n_wa=(1-alppha*psi_n_ya)/(1-alppha);                   %defined on page 171
+#aleph_p=alppha*lambda_p/(1-alppha);                         %defined on page 172
+#aleph_w=lambda_w*(siggma+varphi/(1-alppha));               %defined on page 172
+[name='New Keynesian Phillips Curve eq. (18)']
+pi_p=betta*pi_p(+1)+aleph_p*y_gap+lambda_p*w_gap;
+[name='New Keynesian Wage Phillips Curve eq. (22)']
+pi_w=betta*pi_w(+1)+aleph_w*y_gap-lambda_w*w_gap;
+[name='Dynamic IS Curve eq. (22)']
+y_gap=-1/siggma*(i-pi_p(+1)-r_nat)+y_gap(+1);
+[name='Definition natural rate of interest eq. (24)']
+r_nat=-siggma*psi_n_ya*(1-rho_a)*a+(1-rho_z)*z;
+w_gap=w_gap(-1)+pi_w-pi_p-(w_nat-w_nat(-1));
+[name='Definition natural wage, eq (16)']
+w_nat=psi_n_wa*a;
+[name='Definition markup']
+mu_p=-alppha/(1-alppha)*y_gap-w_gap;
+[name='Definition real wage gap, p. 171']
+w_gap=w_real-w_nat;
+[name='Definition real interest rate']
+r_real=i-pi_p(+1);
+[name='Definition natural output, eq. (20)']
+y_nat=psi_n_ya*a;
+[name='Definition output gap']
+y_gap=y-y_nat;
+[name='Monetary policy shock']
+nu=rho_nu*nu(-1)+eps_nu;
+[name='TFP shock']
+a=rho_a*a(-1)+eps_a;
+[name='Production function, p. 171']
+y=a+(1-alppha)*n;
+[name='Preference shock, p. 54']
+z     = rho_z*z(-1) - eps_z;
+[name='Money growth (derived from eq. (4))']
+m_growth_ann=4*(y-y(-1)-eta*(i-i(-1))+pi_p);
+[name='Real money demand (eq. 4)']
+m_real=y-eta*i;
+[name='Annualized nominal interest rate']
+i_ann=4*i;
+[name='Annualized real interest rate']
+r_real_ann=4*r_real;
+[name='Annualized natural interest rate']
+r_nat_ann=4*r_nat;
+[name='Annualized inflation']
+pi_p_ann=4*pi_p;
+[name='Annualized wage inflation']
+pi_w_ann=4*pi_w;
+[name='Output deviation from steady state']
+yhat=y-steady_state(y);
+[name='Definition price level']
+pi_p=p-p(-1);
+[name='resource constraint, eq. (12)']
+y=c;
+[name='definition real wage']
+w_real=w-p;
+[name='definition real wage']
+m_nominal=m_real+p;
+
+
+end;
+
+steady_state_model;
+lambda_p=(1-theta_p)*(1-betta*theta_p)/theta_p*((1-alppha)/(1-alppha+alppha*epsilon_p));      %defined on page 166
+lambda_w=(1-theta_w)*(1-betta*theta_w)/(theta_w*(1+epsilon_w*varphi));      %defined on page 170
+end;
+%----------------------------------------------------------------
+%  define shock variances
+%---------------------------------------------------------------
+
+
+shocks;
+    var eps_a       = 1; 
+    var eps_z       = 1; 
+end;
+
+
+%----------------------------------------------------------------
+% generate IRFs for technology shock under optimal policy, replicates Figures 6.3, p. 182
+%----------------------------------------------------------------
+//planner objective, uses lambda_w and lambda_p updated in steady_state_model-block
+planner_objective 0.5*((siggma+(varphi+alppha)/(1-alppha))*y_gap^2+ epsilon_p/lambda_p*pi_p^2+epsilon_w*(1-alppha)/lambda_w*pi_w^2);
+
+ramsey_model(instruments=(i),planner_discount=betta, planner_discount_latex_name = $\delta$);
+stoch_simul(order=1,irf=16,noprint) y_gap pi_p_ann pi_w_ann w_real;
+evaluate_planner_objective;
+
+oo_baseline=oo_;
+
+%flexible wage case
+set_param_value('theta_w',0.0000000001);
+set_param_value('theta_p',3/4);
+stoch_simul(order=1,irf=16,noprint) y_gap pi_p_ann pi_w_ann w_real;
+evaluate_planner_objective;
+oo_flexible_wages=oo_;
+
+%flexible price case
+set_param_value('theta_w',3/4)
+set_param_value('theta_p',0.000000001)
+stoch_simul(order=1,irf=16,noprint) y_gap pi_p_ann pi_w_ann w_real;
+evaluate_planner_objective;
+oo_flexible_prices=oo_;
+
+
+figure('Name','Dynamic Responses to a technology shock under optimal policy')
+subplot(2,2,1)
+plot(1:options_.irf,oo_baseline.irfs.y_gap_eps_a,'-o',1:options_.irf,oo_flexible_wages.irfs.y_gap_eps_a,'-d',1:options_.irf,oo_flexible_prices.irfs.y_gap_eps_a,'-s')
+ylim([-0.1 0.1])
+title('Output gap')
+ll=legend('baseline','flexible wages','flexible prices');
+set(ll,'Location','SouthEast');
+subplot(2,2,2)
+plot(1:options_.irf,oo_baseline.irfs.pi_p_ann_eps_a,'-o',1:options_.irf,oo_flexible_wages.irfs.pi_p_ann_eps_a,'-d',1:options_.irf,oo_flexible_prices.irfs.pi_p_ann_eps_a,'-s')
+title('Price Inflation')
+subplot(2,2,3)
+plot(1:options_.irf,oo_baseline.irfs.pi_w_ann_eps_a,'-o',1:options_.irf,oo_flexible_wages.irfs.pi_w_ann_eps_a,'-d',1:options_.irf,oo_flexible_prices.irfs.pi_w_ann_eps_a,'-s')
+title('Wage inflation')
+subplot(2,2,4)
+plot(1:options_.irf,oo_baseline.irfs.w_real_eps_a,'-o',1:options_.irf,oo_flexible_wages.irfs.w_real_eps_a,'-d',1:options_.irf,oo_flexible_prices.irfs.w_real_eps_a,'-s')
+title('Real wage')
+
+
+%----------------------------------------------------------------
+% generate first row of Table 6.1, p. 186
+%----------------------------------------------------------------
+shocks;
+    var eps_a       = 1; 
+end;
+set_param_value('theta_w',3/4);
+set_param_value('theta_p',3/4);
+
+stoch_simul(order=1,irf=16,noprint) y_gap y_gap pi_p pi_w;
+oo_baseline=oo_;
+
+y_gap_pos=strmatch('y_gap',var_list_ ,'exact');
+pi_p_pos=strmatch('pi_p',var_list_ ,'exact');
+pi_w_pos=strmatch('pi_w',var_list_ ,'exact');
+
+%read out current parameter values
+par.alppha=M_.params(strmatch('alppha',M_.param_names,'exact'));
+par.epsilon_p=M_.params(strmatch('epsilon_p',M_.param_names,'exact'));
+par.epsilon_w=M_.params(strmatch('epsilon_w',M_.param_names,'exact'));
+par.siggma=M_.params(strmatch('siggma',M_.param_names,'exact'));
+par.varphi=M_.params(strmatch('varphi',M_.param_names,'exact'));
+par.lambda_w=M_.params(strmatch('lambda_w',M_.param_names,'exact'));
+par.lambda_p=M_.params(strmatch('lambda_p',M_.param_names,'exact'));
+
+variance.y_gap=oo_.var(y_gap_pos,y_gap_pos);
+variance.pi_p=oo_.var(pi_p_pos,pi_p_pos);
+variance.pi_w=oo_.var(pi_w_pos,pi_w_pos);
+L=0.5*((par.siggma+(par.varphi+par.alppha)/(1-par.alppha))*variance.y_gap+ par.epsilon_p/par.lambda_p*variance.pi_p+par.epsilon_w*(1-par.alppha)/par.lambda_w*variance.pi_w)
+
+labels={'sigma(pi_p)';'sigma(pi_w)';'sigma(tilde y)';'L'};
+headers={' ';'Optimal'};
+values=[sqrt([variance.pi_p;variance.pi_w;variance.y_gap]);L];
+options_.noprint=0;
+dyntable(options_,'Evaluation of Simple Rules',headers,labels,values,size(labels,2)+2,4,3)
+
+if any(isnan(values))
+    error('Parameter updating in steady state went wrong')
+end
\ No newline at end of file