BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
alexfx
Fluorite | Level 6

Hi there,

I work in models risk development and i my team is having some problems in making a macro code to work properly.

For example:

In table 1 i have some contracts and their historical interest rates along their lifetime period:table1.PNG

 

 

 

 

the field:

    • firstvalue    Identifies the first month of life of the contract;
    • lastvalue     Identifies the last month of life of the contract;
    • contador     identified the number of months in which the contract was alive;
    • k                  enumerates each contract;

from this table i construct table 2 (tab1 in the code below), which identifies the months in which there were changes in the interest rate of the contracts:

table2.PNG

From here, our goal is to calculate the median of the duration in months until a new repricing occurs, meaning that we want to obtain table3, in which the fields "contador_1, _2, _3" count the number of months that each contract mantained the same interest rate. The final step will then be the calculation of the median of these fields "contador_1, _2, _3" for each contract.

Table3.PNG

The code we are using to obtain table 3 (tab2 in the code below) from table 2 (tab1 in the code below), is where we are having problems and it is the following:

rsubmit;
%macro teste1;
%global first dif;

      data median.tab2;
      set median.tab1 ;

%do  i=1 %to 10;

call symput('first',firstvalue);
call symput('dif',dif_&i.);
      %put &i.;
      %put &first.;
      %put &dif.;


            %if (&i. >= %sysfunc(inputn(&first. ,best31.))   and   %sysfunc(inputn(&dif.,best31.)) = 0 ) %then %do;
                  contador_&j. =  contador_&j. + 1;      
            %end; 

            %else %if (&i. >=  %sysfunc(inputn(&first. ,best31.))  and  %sysfunc(inputn(&dif.,best31.)) = 1 ) %then %do;
                  %let  j= %eval(&j.+1); %put condicao else if &j. ;
                  contador_&j. = 1 ; 
     	    %end; 

            %else %do;
                  %put condicao do &j. ;
                  %put condicao do &i.;
            %end;

%end;
run;
%mend teste1;
%teste1; 
endrsubmit;

this code seems right but it is not producing the results we want (there aren't any errors but the results are not correct). We think that the problems has something to do with "call symput" because we are having problems in defining the variables correctly.

 

Can you please help us understand what we are doing wrong in this code? 

Thank you.

 

1 ACCEPTED SOLUTION

Accepted Solutions
ballardw
Super User

" We think that the problems has something to do with "call symput" because we are having problems in defining the variables correctly."

 

Why do you think that? What is the evidence?

 

One thing, the MACRO pre-processor does all its work before the data step executes. So macros do not see the value of data step variables. Second, macro variables created with Symput or Symputx don't exist at the time the macro pre-processor does its thing either. So the created "variables" don't exist either.

 

Placing yellow text on a white background makes trying to follow your example tedious. This has been known since the Middle ages, i.e. a thousand years or so. If you highlight in a contrasting color like red, blue or green your post is more legible.

 

I am not sure that I actually follow the connection between: "changes in the interest rate" and " months until a new repricing occurs".

 

There is NO need for any of the syput, %sysfunc(input ). The proper tool to do the same calculations using multiple variables like this would be an array, or likely two arrays.

Here is a brief example of examining the values of a loop counter, Firstvalue and DIF variables.

data example;
   set median.tab1 ;
   array d (*) dif1-dif10;
   array c (10) contador_1 - contador_10;
   do i=1 to dim(d);
      if i ge firstvalue and d[i] =0 then put "first compare " i= firstvalue=- d[i]= ;
      else if i ge firstvalue and d[i] = 1 then put "second compare " i= firstvalue=- d[i]= ;
      else put "third block " i= firstvalue=- d[i]= ;
  end;
run;

 

Your code does not show where "&j" is set so I can't attempt to translate your code.

 

 

 

View solution in original post

3 REPLIES 3
PaigeMiller
Diamond | Level 26

This doesn't answer your question directly, but macros are not needed here. An ARRAY in a data step can work, and would be much simpler than macros.

 

One of the problems in your code is that CALL SYMPUT creates a macro variable from within a data step, but that macro variable is not usable in that data step, it is not available until that specific data step where it is created ends. Which is another argument for using ARRAYs, which do not have this limitation.

--
Paige Miller
ballardw
Super User

" We think that the problems has something to do with "call symput" because we are having problems in defining the variables correctly."

 

Why do you think that? What is the evidence?

 

One thing, the MACRO pre-processor does all its work before the data step executes. So macros do not see the value of data step variables. Second, macro variables created with Symput or Symputx don't exist at the time the macro pre-processor does its thing either. So the created "variables" don't exist either.

 

Placing yellow text on a white background makes trying to follow your example tedious. This has been known since the Middle ages, i.e. a thousand years or so. If you highlight in a contrasting color like red, blue or green your post is more legible.

 

I am not sure that I actually follow the connection between: "changes in the interest rate" and " months until a new repricing occurs".

 

There is NO need for any of the syput, %sysfunc(input ). The proper tool to do the same calculations using multiple variables like this would be an array, or likely two arrays.

Here is a brief example of examining the values of a loop counter, Firstvalue and DIF variables.

data example;
   set median.tab1 ;
   array d (*) dif1-dif10;
   array c (10) contador_1 - contador_10;
   do i=1 to dim(d);
      if i ge firstvalue and d[i] =0 then put "first compare " i= firstvalue=- d[i]= ;
      else if i ge firstvalue and d[i] = 1 then put "second compare " i= firstvalue=- d[i]= ;
      else put "third block " i= firstvalue=- d[i]= ;
  end;
run;

 

Your code does not show where "&j" is set so I can't attempt to translate your code.

 

 

 

alexfx
Fluorite | Level 6
We tried the code you provided with some minor adjustments and it worked!
Thank you for your help!

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 3 replies
  • 669 views
  • 2 likes
  • 3 in conversation