*! glmcstar Esarey c* loss aversion JEsarey NDanneman 10sep2009 program glmcstar version 10.1 args Gamma if `: word count `0'' != 1 { //displays an error if user inputs any number of arguments other than one mata _error("cstar takes exactly one integer as an argument") } if `Gamma' ==0 { //displays an error if user inputs 0 as the Gamma parameter mata _error("the loss aversion parameter cannot equal zero") } quietly glmcstargears `Gamma' local NumBetas = colsof(CSTAR) local regs : colnames e(b) display as text "c* values for the previous regression" //displays C-star generic info display as text "gamma = `Gamma'" //reports the gamma parameter input by the user display "" //adds a blank line to reduce visual clutter forvalues i = 1/`NumBetas' { display as text word("`regs'", `i') //displays the name of each regressor in green display as result CSTAR[1,`i'] //displays each c-star value in yellow di "" //adds a blank line between a c-star value and the following regressor's name } if `Gamma' == 1 { display "Note: you have entered a loss aversion factor of 1, so cstar has returned the original betas." } if `Gamma' < 1 { display "Note: you have entered a loss aversion factor less than one, signifying risk-seeking behavior." } end ********************************************** program glmcstargears version 10.1 args Gamma matrix b = e(b) //creates matrix b, a rowvector of betas matrix V = e(V) //V, a rowvector of variances mata: CstarExecute() //executes the mata function CstarExecute end ********************************************* mata: void function CstarExecute() { Betas = st_matrix("b") //pulls the beta matrix in from stata AbsBetas = abs(Betas) //absolute values of beta matrix Sign = sign(Betas) //sign of the beta matrix Variances = diagonal(st_matrix("V")) //same for variances, but it is a column Variances = Variances' //makes Variances a rowvector Sigmas = sqrt(Variances) //turns Variances into Sigmas via square root Pieces = (AbsBetas \ Sigmas \ Sign) NumberOfBetas = cols(Pieces) //to get the number of times to loop numslic = 5000 //extended this for higher accuracy Gammaparm = st_local("Gamma") //this is treated as a string scalar, but the program needs a real scalar a = strtoreal(Gammaparm) //convert string to real, and give it correct letter real rowvector Output //declare Output Output = J(1,NumberOfBetas,.) //set up empty Output rowvector for (i=1; i<=NumberOfBetas; i++) { m = Pieces[1,i] sigma = Pieces[2,i] sign = Pieces[3,i] lower = m - (8*sigma) //extended the limits to 8*sigma from 6 higher = m + (8*sigma) Output[1,i] = sign * rootfinder(lower, higher, numslic, a, m, sigma) //fill empty Output vector with results of rootfinder } cstarsign = sign(Output) //creats a vector of the signs of the output for (i=1; i<=NumberOfBetas; i++) { //this loop assigns c* values of zero to those that would otherwise have the opposite sign of their betas if (cstarsign[1,i] != Pieces[3,i]) Output[1,i] = 0 } st_matrix("CSTAR", Output) } //********************************* //THE UTILITY FUNCTION function utility( real scalar x, //variable of integration real scalar a, //gamma - the loss parameter real scalar m, //beta real scalar sigma, //sd of beta real scalar t) //variable, roots taken over t { k = ( (x>t) ? 1 : -1 ) //a logical expression distr = ( normalden(x, m, sigma) ) return( (a^(-k)) * (distr) * (x-t) ) } //********************************* //INTEGRATION //An n-slice integration routine using simpson's approximation, use 120 slices for numslic scalar NDint( // to perform integration via simpson'sapproximation real scalar t, pointer scalar f, real scalar lower, //lower bound of integration real scalar higher, //upper bound real scalar numslic, // where numslic = number of slices, must be an EVEN number real scalar a, real scalar m, real scalar sigma) { if (lower > higher) _error("limits of integration reversed") //make sure upper > lower NB: better to use _error() than return() if ( (numslic/2) != (floor(numslic/2)) ) _error("numslic must be an EVEN number") //ensures that the number of slices used is even real scalar width //declarations, for assurance's sake real colvector Y real rowvector X real scalar numslicplsone //slices plus one numslicplsone = numslic +1 width = (higher-lower) / numslic //calculates width of each "slice" Y = J(numslicplsone,1,.) //creates an empty column vector for (i=1; i<=numslicplsone; i++) { x = lower + ((i-1)*width) Y[i,1] = (*f)(x,a, m, sigma, t) //places function evaluations directly into Y } X = J(1,numslicplsone,.) //this loop creates a vector of the fudge factors for integration via simpson's rule for (i=1;i<=numslicplsone; i++) { // ie. (1, 4, 2...2, 4, 1) if (i==1) X[1,i] = 1 if (i==numslicplsone) X[1,i] = 1 if ((i/2) == (floor(i/2))) X[1,i] = 4 if ( ((i+1)/2) == (floor( ((i+1)/2)) ) & (i!=1) & (i!=numslicplsone) ) X[1,i] = 2 } return(X*Y*width/3) //matrix multiplication makes this quicker and more readable } //********************************* //THE ROOT FINDER - uses mm_root from the moremata package function rootfinder( real scalar lower, real scalar higher, real scalar numslic, real scalar a, real scalar m, real scalar sigma) { mm_root(answer=., &NDint(), -m, m, 0, 1000, &utility(), lower, higher, numslic, a, m, sigma) return(answer) } end