SAS stored process to create property monthly loss ratio reports


    /********************* STORED PROCESS MACRO CODE ***********************/
    /* NOTE THERE MAY BE HTML RENDITION ERRORS IN THIS CODE */
    /* this line tells EG to not display some specific log information */
    options nosource nosource2 nomprint nomlogic nomacrogen nosymbolgen notes=0;
    /* MACRO */
    %macro prop_entry_month_indic;
    %local filter_variav;
    /* appends the username to the filename */
    %let default_lib=comuser;
    /*THESE MACROVARS TELL WHETHER TO RUN PREMIUM AND/OR CLAIM*/
    %let run_premium=1;
    %let run_claim=1;

    data _null_;
    lib=scan("&outfile",1,".");
    if lowcase(lib)="&default_lib"
    then call symput("assign",1);
    else call symput("assign",0);
    name=scan("&outfile",2,".");
    newname=compress(lib||"."||"&_metauser"||"_"||"&sysdate"||"_"||name);
    newname=substr(newname,1,32);
    call symput("outfile",compress(newname));
    run;

    %if &assign
    %then %do;
    libname &default_lib Base "/sasdata/comuser";
    %end;

    /* tests if the provided outfile is error free */
    data &outfile;
    run;

    /* if no error with specified output file do */
    %if &syserr=0
    %then %do;
    proc sql;
    drop table &outfile;
    quit;

    %lib_actcom;

    %let selec=%str(AS_CEDE_POLICY_NO SS_TRANSACTION_CODE1 SS_SYUS_COMPANY1);

    /* FILTER CRITERIA */
    /* this part handles specifically the creation of the multiple filters */
    /* property filter */
    %let name_filter1=business_indicator;
    %let name_filter2=product_major_line;
    %let name_filter3=SS_SYUS_COMPANY;/* exception */
    %let name_filter4=risk_province;
    %let name_filter5=product_line_desc;
    %let name_filter6=SS_SYUS_BRANCH;/* exception */
    %let name_filter7=OFFICE_CODE;
    %let name_filter8=SS_PL5_FORM;
    %let name_filter9=kpnwl_code;/* 2 exceptions */
    %let name_filter10=SS_RISK_NUMBER;/* exception */
    %let name_filter11=property_industry_code;

    %let filter_comp=1;
    %do i=1 %to 11;
    /* name of the filter criteria variable */
    %let variav=&&name_filter&i;
    %let filter_variav=&variav;

    /* exceptions for Property */
    data _null_;
    select (upcase("&variav"));
    when ("SS_RISK_NUMBER") /* SS_RISK_NUMBER */
    do; 
    call symput("filter_variav","SS_RISK_NUMBER1");
    call symput("actual_variav","SS_RISK_NUMBER1");
    end;
    when ("SS_PL5_FORM") /* SS_PL5_FORM */
    do; 
    call symput("filter_variav","compress(SS_PL5_FORM1)");
    call symput("actual_variav","SS_PL5_FORM1");
    end;
    when ("SS_SYUS_COMPANY") /* SS_SYUS_COMPANY */
    do; 
    call symput("filter_variav","SS_SYUS_COMPANY1");
    call symput("actual_variav","SS_SYUS_COMPANY1");
    end;
    when ("SS_SYUS_BRANCH") /* SS_SYUS_BRANCH */
    do; 
    call symput("filter_variav","SS_SYUS_BRANCH1");
    call symput("actual_variav","SS_SYUS_BRANCH1");
    end;
    when ("KPNWL_CODE") /* KPNWL_CODE */
    do;
    call symput("filter_variav","put(KPNWL_CODE1,z4.)");
    call symput("actual_variav","KPNWL_CODE1");
    end;
    when ("PROPERTY_INDUSTRY_CODE") /* PROPERTY_INDUSTRY_CODE */
    do; 
    call symput("filter_variav","compress(PROPERTY_INDUSTRY_CODE)");
    call symput("actual_variav","PROPERTY_INDUSTRY_CODE");
    end;
    otherwise 
    do; 
    call symput("filter_variav","&variav");
    call symput("actual_variav","&variav");
    end;
    end;
    run;

    %put ### i=&i filter_variav=&filter_variav;

    /*HANDLES THE CREATION OF THE TWO PARAMETERS*/
    data pmts_&i;
    variavel="&actual_variav";
    /*TEST IF NUMBER OF PICKS FOR VAR ACTUAL_VARIAV EXIST*/
    %if %symexist(&&variav.0)
        %then %do;
                number_picks_a="&&&variav.0";
                if input(number_picks_a,12.)>0
                    then number_picks=input(number_picks_a,12.);
                    else number_picks=0;
            %end;
        %else number_picks=0;;

    /*TEST IF FIRST PICK FOR VAR ACTUAL_VARIAV EXIST*/
    %if %symexist(&&variav)
        %then first_pick="&&&variav";
        %else first_pick="";;

    if first_pick ne "" and number_picks=0 
    then number_picks=1;
    call symput("&&variav.0",compress(number_picks));
    run;

    %put variable=&actual_variav number_picks=&&&variav.0;

    %if &&&variav.0>0
        %then %let &variav.1=&&&variav;

    %if &&&variav.0>0
        %then %do;
                %let filter="&&&variav.1";
                /*THIS IS USED TO TROUBLESHOOT DIFFERENT BEHAVIOUR ON THE STORED PROCESS ENVIROMENT*/
                %put Filter step=&i%str(:) added &actual_variav to "SELEC";
                %let selec=%str(&selec &actual_variav);
            %end;
        %else %let filter="";

    %do j=2 %to &&&variav.0;
    %let filter=%str(&filter,"&&&variav&j");
    %end;
    %if &filter ne ""
        %then %let filter_comp=%str(&filter_comp and &filter_variav in (&filter));
    /* prints the filter step by step */
    /*%put ### i=&i &filter_comp;*/
    %end;

    /*THIS PART SUMMARIZES THE NUMBER OF FILTER PICKS*/
    data /*comuser.*/picks;
    length variavel first_pick $32.;
    set %do i=1 %to 11; pmts_&i %end;;
    run;

    /* handles the policy number filter, if any */
    %if &AS_CEDE_POLICY_NO ne all
    %then %let filter_comp=%str(&filter_comp and AS_CEDE_POLICY_NO="&AS_CEDE_POLICY_NO");

    proc contents data=actcom.PREMIUM_PROPERTY out=contents(keep=name) noprint;
    run;
    proc contents data=actcom.CLAIM_POLICY_PROPERTY out=aux(keep=name) noprint;
    run;

    proc sql;
    create table contents as
    select name
    from contents
    where lowcase(name) in (select lowcase(name) from aux);
    quit;

    /**********************************************************/
    /**********************************************************/
    /**********************************************************/
    /**********************************************************/
    %put ######### BEFORE TRANSFORMATION: pick_var0=&pick_var0;
    %if %symexist(pick_var0)
        %then %do;
                %if &pick_var0=
                %then %if "&pick_var" ne ""
                            %then %let pick_var0=1;
                            %else %let pick_var0=0;
            %end;
        %else %if "&pick_var" ne ""
                %then %let pick_var0=1;
                %else %let pick_var0=0;

    %if &pick_var0=0
        %then %let pick_var1=;

    %if &pick_var0=1
        %then %let pick_var1=&pick_var;
    %put ### pick_var0=&pick_var0;
    %put ### pick_var1=&pick_var1;

    /* THIS PART INCLUDES THE VARIABLES PICKED SECONDLY */
    %if %symexist(sec_pick_var0)
        %then %do;
                %if &sec_pick_var0=
                %then %if "&sec_pick_var" ne ""
                            %then %let sec_pick_var0=1;
                            %else %let sec_pick_var0=0;
            %end;
        %else %if "&sec_pick_var" ne ""
                %then %let sec_pick_var0=1;
                %else %let sec_pick_var0=0;

    %if &sec_pick_var0=1
        %then %let sec_pick_var1=&sec_pick_var;
    %put ### sec_pick_var0=&sec_pick_var0;
    %put ### sec_pick_var1=&sec_pick_var1;

    %do j=1 %to &sec_pick_var0;
    %let index=%eval(&pick_var0+&j);
    %put ### SECOND VAR LIST j=&j index=&index;
    %let pick_var&index=&&sec_pick_var&j;
    %put ### j=&j pick_var&index=&&sec_pick_var&j;
    %end;

    %let pick_var0=%eval(&pick_var0+&sec_pick_var0);
    %put ######### AFTER TRANSFORMATION: pick_var0=&pick_var0;
    /**********************************************************/
    /**********************************************************/
    /**********************************************************/
    /**********************************************************/

    %let group_selec=&pick_var1;
    %do i=2 %to &pick_var0;
    %let group_selec=%str(&group_selec,&&pick_var&i);
    %end;

    /* THIS FIXES POSSIBLE PROBLEMS WITH COMMAS IF GROUP SELECT IS BLANK */
    %if &group_selec ne %str()
        %then %let group_selec=%str(,&group_selec);

    /* this creates the selected variables without the commas */
    %let group_selec_nocomma=%sysfunc(tranwrd(&group_selec,%str(,),%str( )));

    /* this part drops variables that were picked duplicately from the variables picklist */
    /* by setting them to 'none' if they're duplicate                                     */
    /*ADD VARIABLES ON THE PICK LIST TO THE SELECTION WHICH IS THE "SELEC" MACROVAR*/
    %do i=1 %to &pick_var0;
    data _null_;
    text=lowcase(compbl("@@@ &selec @@@"));
    search=index(text,lowcase(" "||compress("&&pick_var&i")||" "));
    if search ne 0
    then call symput("pick_var&i","none");
    run;

    proc sql noprint;
    select count(*)>0 into :exist
    from contents
    where lowcase("&&pick_var&i") in (select lowcase(name) from contents);
    quit;

    %put step=&i%str(:) Testing if "&&pick_var&i" is added to "SELEC";
    %if "&&pick_var&i" ne "none" and &exist
        %then %do;
                %let selec=%str(&selec &&pick_var&i);
                %put step=&i%str(:) Added "&&pick_var&i" to "SELEC";
            %end;
    %end;

    %let selec=%str(&selec entered_date effective_date_of_policy transaction_date policy_expiry_date written_exposure written_premium);
    proc sql;
    drop table contents;
    quit;

    data _null_;
    start=input("&start",yymmn6.0);
    call symput("start_date",start);
    /*ONLY USED FOR DISPLAY*/
    call symput("start_date_disp",put(start,date9.0));
    end=input("&end",yymmn6.0);
    end=intnx('month',end,1)-1;
    call symput("end_date",end);
    /*ONLY USED FOR DISPLAY*/
    call symput("end_date_disp",put(end,date9.0));
    claims_as_of=input("&claims_as_of",yymmn6.0);
    call symput("claims_as_of_date",claims_as_of);
    /*ONLY USED FOR DISPLAY*/
    call symput("claims_as_of_disp",put(claims_as_of,date9.0));
    format start end claims_as_of ddmmyy10.;
    run;

    /*CREATES A LABEL ON THE YEAR VARIABLE TO INFORM THE CRITERIA AND CUT-OFF DATES*/
    %let label=%sysfunc(compress(%superq(filter_comp),%str(%"))); 
    %let label=criteria=%sysfunc(substr(&label,7)) start=&start end=&end claims_as_of=&claims_as_of;
    %put Label=&label;

    %put ### ;
    %put ### Filter=&filter_comp;
    %put ### Selec=&selec;
    %put ### Group_selec=&Group_selec;
    %put ### group_selec_nocomma=&group_selec_nocomma;
    %put ### start_date=&start_date_disp end_date=&end_date_disp claims_as_of=&claims_as_of_disp;

    /*SHOULD THE PART THAT CREATES PREMIUM TABLES BE RUN? YES=1 N0=0*/
    %if &run_premium
    %then %do;
    %put ### 1. CREATING PREMIUM DATASET...;
    data premium;
    retain &selec;
    set actcom.PREMIUM_PROPERTY(keep=&selec /*obs*/);
    where &filter_comp and 
    (max(transaction_date,&start_date)<=min(policy_expiry_date,&end_date) or 
    &start_date<=entered_date<=&end_date) and
    SS_TRANSACTION_CODE1 not in ("3","7") and
    SS_SYUS_COMPANY1 not in ("05","08");
    run;

    /**********************************************************************/
    /******************************* PREMIUMS *****************************/
    /**********************************************************************/
    %put ### 2. COMPUTING EARNED PREMIUM...;
    data earned;
    set PREMIUM;
    where max(transaction_date,&start_date)<=min(policy_expiry_date,&end_date);

    if transaction_date ne . and policy_expiry_date ne . and (policy_expiry_date-transaction_date) ne 0 
    then full_term_wp=written_premium*(policy_expiry_date-effective_date_of_policy)/(policy_expiry_date-transaction_date);
    else full_term_wp=0;

    /* compute the number of months exposed on the transaction */
    begin_mth=max(transaction_date,&start_date);
    end_mth=min(policy_expiry_date,&end_date);
    n_month=(year(end_mth)-year(begin_mth))*12+month(end_mth)-month(begin_mth)+1;
    month=.;
    next_month=.;
    begin_day=.;
    end_day=.;
    sign=SIGN(written_premium);

    /* these vars are placed here just so they show up orderly on the table,*/
    /* not needed though */
    length earned_month $6.;
    earned_month="";
    earned_exposure=0;
    earned_premium=0;

    do i=0 to n_month-1;
    month=intnx('month',begin_mth,i);
    next_month=intnx('month',begin_mth,i+1)-1;
    earned_month=put(month,yymmn6.); 

    /* restrict the calculation to the months that fall onto the interval */
    if "&start"<=earned_month<="&end"
    then do;
    begin_day=max(month,transaction_date);
    end_day=min(next_month,policy_expiry_date);

    earned_exposure=round((end_day-begin_day+1)/365.25*sign,.001);
    earned_premium=round(full_term_wp*round((end_day-begin_day+1)/(policy_expiry_date-effective_date_of_policy),.001),.01);

    IF -0.001&caploss then &caploss else calculated gross_incurred end as caploss format=12.0,
    case when calculated gross_incurred>&caploss then 1 else 0 end as capcount,
    sum(p_amt) as Paid
    from actcom.CLAIM_POLICY_PROPERTY
    where &filter_comp and 
    &start_date<=CR_LOSS_DATE<=&end_date and 
    product_major_line in ("B","C","P") and
    cr_transaction_date<=intnx('month',&claims_as_of_date,1)-1 and
    rectype=1
    /* HERE THE EQUIVALENT TO SS_CLASS_TYPE1=fclas3 */
    group by LINE,CLAIMSYM,CR_CLAIM_NO,CR_LOSS_DATE,CR_OCCURANCE,
    fclas3,tou,CR_AUTO_DRIVER_REC_SECA,cr_fire_class,
    cr_coverage_cd,kol;
    quit;

    proc sort data=claims nodupkey;
    by LINE CLAIMSYM CR_CLAIM_NO CR_LOSS_DATE CR_OCCURANCE 
    fclas3 tou CR_AUTO_DRIVER_REC_SECA cr_fire_class cr_coverage_cd kol;
    run;

    proc sql;
    create table claims_sum as
    select Year_Month &group_selec, 
    sum(claim_cnt) as claim_cnt,
    sum(paid) as paid,
    sum(gross_incurred) as gross_incurred,
    sum(capcount) as capcount,
    sum(caploss) as caploss
    from claims
    group by Year_Month &group_selec
    order by Year_Month &group_selec;
    quit;

    %if &run_premium=1 and &run_claim=1
    %then %do;
    data &outfile;
    merge premium_sum claims_sum;
    by Year_Month &group_selec_nocomma;
    if claim_cnt=. then claim_cnt=0;
    if paid=. then paid=0;
    if gross_incurred=. then gross_incurred=0;
    if capcount=. then capcount=0;
    if caploss=. then caploss=0;
    format 
    written_exposure earned_exposure 12.2 
    written_premium earned_premium gross_incurred caploss paid 12.0;
    label Year_Month="&label";
    run;
    %end;
    %end;

    /*DROPS THE INDIVIDUAL PARAMETER FILES*/
    proc sql;
    drop table aux %do i=1 %to 11; ,pmts_&i %end;;
    quit;

    /*proc sql;
    drop table premium, premium2, premium3, claims, claims2, contents, aux;
    quit;*/
    %end;
    /* User specified an invalid output filename or unaccessible library */
    %else %do;
    %put ### ERROR, INVALID OUTPUT FILE: %trim(&outfile);
    %end;
    options source source2 notes=1;
    %mend;

    * %prop_entry_month_indic;

    /* VARIABLES to pick and choose */
    %let pick_var0=4;
    %let pick_var1=product_major_line; /**/
    %let pick_var2=product_line_desc; /*SS_SYUS_BRANCH1 AS_CEDE_POLICY_NO*/
    %let pick_var3=division_desc;
    %let pick_var4=OFFICE_DESC; /*SS_TRANSACTION_CODE1*/
    %let pick_var5=AS_CEDE_POLICY_NO;
    %let pick_var6=SS_RISK_NUMBER1;
    %let pick_var7=product_line_desc;
    %let pick_var8=OFFICE_CODE;
    %let pick_var9=SS_PL5_FORM1;
    %let pick_var10=kpnwl_code1;
    %let pick_var11=business_indicator;
    %let pick_var12=property_industry_code;
    %let pick_var=&pick_var1;
    /* SECOND LIST OF VARIABLES to pick and choose */
    %let sec_pick_var0=0;
    %let sec_pick_var1=; /*SS_LINE_CODE1*/
    %let sec_pick_var2=SUB_BROKER_NO;
    %let sec_pick_var=&sec_pick_var1;
    /* 1. business indicator */
    %let business_indicator0=0;
    %let business_indicator1=;/*Mid-Market*/
    %let business_indicator2=Fastrax;
    %let business_indicator=&business_indicator1;
    /* 2. product major line */
    %let product_major_line0=2;
    %let product_major_line1=P;
    %let product_major_line2=C;
    %let product_major_line=&product_major_line1;
    /* 3. company_number */
    %let SS_SYUS_COMPANY0=0;
    %let SS_SYUS_COMPANY1=;
    %let SS_SYUS_COMPANY2=10;
    %let SS_SYUS_COMPANY=&SS_SYUS_COMPANY1;
    /* 4. risk_province */
    %let risk_province0=0;
    %let risk_province1=;
    %let risk_province2=ALTA;
    %let risk_province=&risk_province1;
    /* 5. product */
    %let product_line_desc0=0;
    %let product_line_desc1=;
    %let product_line_desc2=;
    %let product_line_desc=&product_line_desc1;
    /* 6. branch */
    %let SS_SYUS_BRANCH0=0;
    %let SS_SYUS_BRANCH1=;
    %let SS_SYUS_BRANCH2=03;
    %let SS_SYUS_BRANCH=&SS_SYUS_BRANCH1;
    /* 7. office code */
    %let OFFICE_CODE0=0;
    %let OFFICE_CODE1=;
    %let OFFICE_CODE2=46P;
    %let OFFICE_CODE=&OFFICE_CODE1;
    /* 8. Form number */
    %let SS_PL5_FORM0=0;
    %let SS_PL5_FORM1=;
    %let SS_PL5_FORM2=31;
    %let SS_PL5_FORM3=210;
    %let SS_PL5_FORM4=400;
    %let SS_PL5_FORM=&SS_PL5_FORM1;
    /* 9. Liability Industry Code */
    %let kpnwl_code0=0;
    %let kpnwl_code1=;
    %let kpnwl_code2=5513;
    %let kpnwl_code3=;
    %let kpnwl_code=&kpnwl_code1;
    /* 10. Risk number */
    %let SS_RISK_NUMBER0=0;
    %let SS_RISK_NUMBER1=;
    %let SS_RISK_NUMBER2=002;
    %let SS_RISK_NUMBER3=003;
    %let SS_RISK_NUMBER4=004;
    %let SS_RISK_NUMBER=&SS_RISK_NUMBER1;
    /* 11. Property industry code */
    %let property_industry_code0=0;
    %let property_industry_code1=;/*1812*/
    %let property_industry_code2=5812;/*6670*/
    %let property_industry_code3=003;
    %let property_industry_code4=004;
    %let property_industry_code=&property_industry_code1;
    /* 12. Policy number 81207476 92200383*/
    %let AS_CEDE_POLICY_NO=92200383;
    /* cut-off dates */
    %let start=200601;
    %let end=200912;
    %let caploss=100000;
    %let claims_as_of=200912;
    /* file name */
    %let _METAUSER=jsousa;
    %let outfile=work.trouble;

    %prop_entry_month_indic;