The following code should at least get you started:
proc optmodel printlevel=0;
set INSTANCES;
num ticker {INSTANCES};
num date {INSTANCES};
num alpha_init {INSTANCES};
num delta_init {INSTANCES};
num mu_init {INSTANCES};
num eta_B_init {INSTANCES};
num eta_S_init {INSTANCES};
read data initials into INSTANCES=[_N_]
ticker date alpha_init=alpha delta_init=delta mu_init=mu eta_B_init=eta_B eta_S_init=eta_S;
set <num,num,num> TICKER_DATE_OBS;
num B {TICKER_DATE_OBS};
num S {TICKER_DATE_OBS};
read data trades into TICKER_DATE_OBS=[ticker date _N_] B S;
num t_this, d_this;
set OBS_THIS;
var alpha >= 0 <= 1, delta >= 0 <= 1;
var mu >= 0, eta_B >= 0, eta_S >= 0;
impvar one_minus_d = 1.0 - delta;
impvar one_minus_alpha = 1.0 - alpha;
impvar e1 {obs in OBS_THIS} = -1.0*mu - B[t_this,d_this,obs]*log(1+mu/eta_B);
impvar e2 {obs in OBS_THIS} = -1.0*mu - S[t_this,d_this,obs]*log(1+mu/eta_S);
impvar e3 {obs in OBS_THIS} = -B[t_this,d_this,obs]*log(1+mu/eta_B) - S[t_this,d_this,obs]*log(1+mu/eta_S);
impvar emax {obs in OBS_THIS} = max(e1[obs], e2[obs], e3[obs]);
max loglik = sum {obs in OBS_THIS} (
-1.0*eta_B + B[t_this,d_this,obs]*log(mu+eta_B)
-1.0*eta_S + S[t_this,d_this,obs]*log(mu+eta_S)
+ emax[obs]
+ log(
alpha * one_minus_d * exp(e2[obs] - emax[obs])
+ alpha * delta * exp(e1[obs] - emax[obs])
+ one_minus_alpha * exp(e3[obs] - emax[obs])
));
str solstatus {INSTANCES};
num alpha_sol {INSTANCES};
num delta_sol {INSTANCES};
num mu_sol {INSTANCES};
num eta_B_sol {INSTANCES};
num eta_S_sol {INSTANCES};
num loglik_sol {INSTANCES};
for {i in INSTANCES} do;
t_this = ticker[i];
d_this = date[i];
OBS_THIS = {<(t_this),(d_this),obs> in TICKER_DATE_OBS};
put i= t_this= d_this= monyy7. ' ';
alpha = alpha_init[i];
delta = delta_init[i];
mu = mu_init[i];
eta_B = eta_B_init[i];
eta_S = eta_S_init[i];
solve;
solstatus[i] = _solution_status_;
alpha_sol[i] = alpha;
delta_sol[i] = delta;
mu_sol[i] = mu;
eta_B_sol[i] = eta_B;
eta_S_sol[i] = eta_S;
loglik_sol[i] = loglik;
end;
create data solutions from [instance]=INSTANCES
ticker date/format=monyy7. solstatus loglik=loglik_sol alpha=alpha_sol delta=delta_sol mu=mu_sol eta_B=eta_B_sol eta_S=eta_S_sol;
quit;
Anyone has some ideas?
PROC NLP is a legacy procedure that is no longer even documented, and PROC OPTMODEL is recommended instead. With PROC OPTMODEL, you can call the solver in a loop, setting the initial values for the variables before each solver call. In fact, you can use a COFOR loop to solve these independent problems concurrently.
Thanks @RobPratt
but is there any other way to use PROC NLP?. PROC OPTMODEL is very complicated, I have to change the whole code, and this procedure is very difficult to understand to me. It is much appreciated if you could give me instructions on how to do it
The following code should at least get you started:
proc optmodel printlevel=0;
set INSTANCES;
num ticker {INSTANCES};
num date {INSTANCES};
num alpha_init {INSTANCES};
num delta_init {INSTANCES};
num mu_init {INSTANCES};
num eta_B_init {INSTANCES};
num eta_S_init {INSTANCES};
read data initials into INSTANCES=[_N_]
ticker date alpha_init=alpha delta_init=delta mu_init=mu eta_B_init=eta_B eta_S_init=eta_S;
set <num,num,num> TICKER_DATE_OBS;
num B {TICKER_DATE_OBS};
num S {TICKER_DATE_OBS};
read data trades into TICKER_DATE_OBS=[ticker date _N_] B S;
num t_this, d_this;
set OBS_THIS;
var alpha >= 0 <= 1, delta >= 0 <= 1;
var mu >= 0, eta_B >= 0, eta_S >= 0;
impvar one_minus_d = 1.0 - delta;
impvar one_minus_alpha = 1.0 - alpha;
impvar e1 {obs in OBS_THIS} = -1.0*mu - B[t_this,d_this,obs]*log(1+mu/eta_B);
impvar e2 {obs in OBS_THIS} = -1.0*mu - S[t_this,d_this,obs]*log(1+mu/eta_S);
impvar e3 {obs in OBS_THIS} = -B[t_this,d_this,obs]*log(1+mu/eta_B) - S[t_this,d_this,obs]*log(1+mu/eta_S);
impvar emax {obs in OBS_THIS} = max(e1[obs], e2[obs], e3[obs]);
max loglik = sum {obs in OBS_THIS} (
-1.0*eta_B + B[t_this,d_this,obs]*log(mu+eta_B)
-1.0*eta_S + S[t_this,d_this,obs]*log(mu+eta_S)
+ emax[obs]
+ log(
alpha * one_minus_d * exp(e2[obs] - emax[obs])
+ alpha * delta * exp(e1[obs] - emax[obs])
+ one_minus_alpha * exp(e3[obs] - emax[obs])
));
str solstatus {INSTANCES};
num alpha_sol {INSTANCES};
num delta_sol {INSTANCES};
num mu_sol {INSTANCES};
num eta_B_sol {INSTANCES};
num eta_S_sol {INSTANCES};
num loglik_sol {INSTANCES};
for {i in INSTANCES} do;
t_this = ticker[i];
d_this = date[i];
OBS_THIS = {<(t_this),(d_this),obs> in TICKER_DATE_OBS};
put i= t_this= d_this= monyy7. ' ';
alpha = alpha_init[i];
delta = delta_init[i];
mu = mu_init[i];
eta_B = eta_B_init[i];
eta_S = eta_S_init[i];
solve;
solstatus[i] = _solution_status_;
alpha_sol[i] = alpha;
delta_sol[i] = delta;
mu_sol[i] = mu;
eta_B_sol[i] = eta_B;
eta_S_sol[i] = eta_S;
loglik_sol[i] = loglik;
end;
create data solutions from [instance]=INSTANCES
ticker date/format=monyy7. solstatus loglik=loglik_sol alpha=alpha_sol delta=delta_sol mu=mu_sol eta_B=eta_B_sol eta_S=eta_S_sol;
quit;
Thanks @RobPratt Now it goes through all the initials
However, I am not able to get the right solution among these. For example, ticker 99999 must have solution: alpha=0.4, delta=0.5, mu=50, eta_B=eta_S=40. I can not find this in the output dataset
When I run my old PROC NLP code, using only 1 set of initials for ticker 99999 (alpha=0.9, delta=0.7, mu=18.5, eta_B=45, eta_S=38.3), it gives me the right solution. So it confirms that the "true" solution lies in one of my initials
After examining your PROC OPTMODEL, I think the issue might be:
- The PROC NLP uses Newton-Ralphson technique; PROC OPTMODEL uses interior point technique. I searched but I can not find Newton-Ralphson technique or any equivalent in PROC OPTMODEL
- eta_B, eta_S, mu are strictly > 0 (rather than >=0). However, when I change this constraint by using
var alpha >= 0 <= 1, delta >= 0 <= 1;
var mu, eta_B, eta_S;
con mu>0, eta_B>0, eta_S>0;
It gives me error:
ERROR: The problem contains strict inequality or predicate constraints that reference non-integer
variables.
Could you please advise me on this? Thank you very much
You cannot have strict inequalities.
The issue is that I had initially misinterpreted the trades data set. Please see the corrected code above.
Also note that the MULTISTART option for the NLP solver in PROC OPTMODEL can automate the selection of starting points for you, and that would also simplify the code.
Thanks @RobPratt. You are my hero. It works now
Glad to help. For completeness, here is the multistart approach I mentioned:
proc optmodel printlevel=0;
set <num,num,num> TICKER_DATE_OBS;
num B {TICKER_DATE_OBS};
num S {TICKER_DATE_OBS};
read data trades into TICKER_DATE_OBS=[ticker date _N_] B S;
num t_this, d_this;
set OBS_THIS;
var alpha >= 0 <= 1, delta >= 0 <= 1;
var mu >= 0, eta_B >= 0, eta_S >= 0;
impvar one_minus_d = 1.0 - delta;
impvar one_minus_alpha = 1.0 - alpha;
impvar e1 {obs in OBS_THIS} = -1.0*mu - B[t_this,d_this,obs]*log(1+mu/eta_B);
impvar e2 {obs in OBS_THIS} = -1.0*mu - S[t_this,d_this,obs]*log(1+mu/eta_S);
impvar e3 {obs in OBS_THIS} = -B[t_this,d_this,obs]*log(1+mu/eta_B) - S[t_this,d_this,obs]*log(1+mu/eta_S);
impvar emax {obs in OBS_THIS} = max(e1[obs], e2[obs], e3[obs]);
max loglik = sum {obs in OBS_THIS} (
-1.0*eta_B + B[t_this,d_this,obs]*log(mu+eta_B)
-1.0*eta_S + S[t_this,d_this,obs]*log(mu+eta_S)
+ emax[obs]
+ log(
alpha * one_minus_d * exp(e2[obs] - emax[obs])
+ alpha * delta * exp(e1[obs] - emax[obs])
+ one_minus_alpha * exp(e3[obs] - emax[obs])
));
set TICKER_DATE = setof {<t,d,o> in TICKER_DATE_OBS} <t,d>;
str solstatus {TICKER_DATE};
num alpha_sol {TICKER_DATE};
num delta_sol {TICKER_DATE};
num mu_sol {TICKER_DATE};
num eta_B_sol {TICKER_DATE};
num eta_S_sol {TICKER_DATE};
num loglik_sol {TICKER_DATE};
for {<t,d> in TICKER_DATE} do;
put t= d= monyy7.;
t_this = t;
d_this = d;
OBS_THIS = {<(t_this),(d_this),obs> in TICKER_DATE_OBS};
solve with nlp / ms;
solstatus[t,d] = _solution_status_;
alpha_sol[t,d] = alpha;
delta_sol[t,d] = delta;
mu_sol[t,d] = mu;
eta_B_sol[t,d] = eta_B;
eta_S_sol[t,d] = eta_S;
loglik_sol[t,d] = loglik;
end;
create data solutions_ms from [ticker date/format=monyy7.]=TICKER_DATE
solstatus loglik=loglik_sol alpha=alpha_sol delta=delta_sol mu=mu_sol eta_B=eta_B_sol eta_S=eta_S_sol;
quit;
SOLVE chooses a default solver based on the problem structure. In this case, it chooses the NLP solver. SOLVE WITH NLP explicitly specifies the NLP solver. To include solver options (like MS, in this case), you need the WITH clause.
Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9. Sign up by March 14 for just $795.
Learn how to run multiple linear regression models with and without interactions, presented by SAS user Alex Chaplin.
Find more tutorials on the SAS Users YouTube channel.