BookmarkSubscribeRSS Feed
maroulator
Obsidian | Level 7

I have been working with the code below and it runs well. The basic idea is for macro COLLATERAL to keep being called by the OUTER macro (via a %do-%while loop); the loop in the OUTER macro terminates once the variable DIFFERENCE reaches zero (the variable DIFFERENCE can be found in the last lines of code of the macro COLLATERAL). What I need this code for is to determine the value of the %ADD_COLL variable in the OUTER macro that will make the variable DIFFERENCE in the macro COLLATERAL equal to (or very close to) zero. Notice that the variable DIFFERENCE flows from the OUTER macro into the COLLATERAL macro. My problem is this; from my experience, I know that variable     %ADD_COLL can assume values in the thousands and more often than not in the millions (i.e, 160,000,000 etc). This being the case, my loop runs for a very very long time, because I am currently incrementing the %ADD_COLL variable by 1 after each iteration. If I increment %ADD_COLL faster, however (say by 1,000,0000 at a time), I run into the risk of overshooting the correct value of %ADD_COLL oftentimes by too much and prematurely halting my loop in the macro OUTER. Is there a way to increment %ADD_COLL more quickly without, overshooting; I was thinking of somehow starting with a large increment for %ADD_COLL, adjusting the increment in the event of an overshoot and then incrementing %ADD_COLL by a new amount that will not lead to another overshot. I am open to all suggestions, however, along with the appropriate coding solution. Many thanks in advance; below is the code in question.

%global finish add_coll;

%macro collateral();

   

      data all_daily_fees2;

           set all_daily_fees;

           collateral2=collateral+&add_coll;

           add_coll=&add_coll;

           if newbal<0 then do;

                 if abs(newbal)>collateral2 then do;

                 newcollod2=collateral2;

                 newuncollod2=abs((collateral2+newbal));

                 end;

                 else do;

                 newcollod2=abs(newbal);

                 newuncollod2;

                 end;

             end;

             else do;

             newcollod2=0;

             newuncollod2=0;

             end;

      run;

      data all_daily_fees3;

             set all_daily_fees2;

                      if fee_cd='F' then do;

                             if bal<0 then daily_cr_net=0.0000124*(uncollod/1291);

                             else daily_cr_net=0;

                              if newbal<0 then newdaily_cr_net=0.0000124*(newuncollod2/1291);

                              else newdaily_cr_net=0;

                       end;

        run;

      proc sql;

          create table all_daily_fees4 as

          select aba, sum(daily_cr_net) as rmp_cr_net, sum(newdaily_cr_net) as newrmp_cr_net

          from all_daily_fees3;

          group by aba;

       quit;

     data rmp_fees;

         set all_daily_fees4;

              assessed_fees=max(0, rmp_cr_net-150);

             newassessed_fees=max(0,newrmp_cr_net-150);

             difference=newassessed_fees-assessed_fees;

             if difference<0 then call symputx('finish',0);

       run;

%mend collateral();

%macro outer();

      %let add_coll=0;

      %let finish=1;

      %do %while (&finish);

          %collateral();

         %let add_coll = %eval(&add_coll+1);

      %end;

%mend outer();

%outer();

           


3 REPLIES 3
Patrick
Opal | Level 21

First thing would be to strip down your code an reduce passes through data. You basically could do the whole thing in a single data _null_ step. For me to be motivated to put in the effort and strip your code you first must post code where you've got the business logic right and where the syntax is correct.

The code you've posted contains 2 syntax errors. So this can't be what you're succesfully running and it's now only about tweaking for performance.

maroulator
Obsidian | Level 7

What are the syntax errors?

Patrick
Opal | Level 21

Run the code you've posted and the log will tell you. Or even better: Look first at your code in a more recent SAS editor and ask yourself why there is stuff highlighted in red. Fix it, then run your code and if there are no more errors or warnings in the log check if the result is as expected. Once you're there post your code again and ask for performance tweaking. Please provide also a log so that we can see with what volumes we're dealing here.

Syntax error 1: What's the line "newuncollod2;" supossed to achieve?

                 newcollod2=abs(newbal);

                 newuncollod2;

                 end;

SAS Innovate 2025: Call for Content

Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!

Submit your idea!

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
  • 691 views
  • 0 likes
  • 2 in conversation