Your loop is improper because i) you are looping over the Dynare syntax of the command, which is extremely error prone;(you should use the functional command syntax that I outline above) and ii) your should be using the set_param_value command to update parameters (what you did above by assigning a value to the parameter name directly in the loop does not assure correct updating)
opt_algo=4 is a Newton-based optimizer and therefore local by construction. opt_algo=9 in contrast is a global optimizer that should work better regardless of the starting values for the parameters
The line oo_.osr = osr(var_list_,M_.osr.param_names,M_.osr.variable_indices,M_.osr.variable_weights); is the functional syntax of calling the osr-command. It is Matlab-code that can be put in an arbitrary Matlab-loop. The var_list_-variable stores that names of the variables usually put after the osr-command. If it does not yet exist, then use M_.endo_names to display results for all endogenous variables.
The oo_.osr.error_indicator contains the error code from the OSR optimization. It will be equal to 1 whenever a problem was encountered (like never finding a vector that satisfies the BK conditions)
Dynare will stop computations if for the initial parameter values the OSR parameters the model cannot be solved - unless the noprint-option is set. In that case, osr will continue, but given that no explicit error message will be shown, you will need to check the error-code whether there was a problem at a given parameter value on the grid.
The osr-optimizer always takes the last calibrated parameter value stored in M_.params as its starting value. That explains why you experience different results. You can use the set_param_value-command in your loop to try different starting values.
I tend to prefer global optimizers like 8 or 9. They usually take longer, but are more robust to the starting values. When you say that with 9 your results are poor, do you mean the OSR parameter values are large? That is common and indicates you need to set bounds.