Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Solving two equations simultaneously

    Is there a way to simultaneously solve two non-linear equations for two variables?

    (basically a solution of the Black-Scholes Formula for Asset Value and for Asset Volatility)

    one being:

    ev=av*normal[(ln(av/fv)+(r+asigma/2)*t)/(asigma*sqrt(t))]-debt*e^(-r*t)*normal[((ln(av/fv)+(r+asigma/2)*t)/(asigma*sqrt(t))-asigma*sqrt(t)]

    the second being:

    esigma=av*normal[(ln(av/fv)+(r+asigma/2)*t)/(asigma*sqrt(t))]*asigma/ev

    The variables I have to solve it for are asigma and av the rest of the variables is given.

    I am really desperate

    Thank you in advance!

    Kind Regards
    Daria




  • #2
    Take a look at :

    http://www.stata.com/support/faqs/pr...ear-equations/

    or this thread:

    http://www.stata.com/statalist/archi.../msg00138.html

    Comment


    • #3
      Thank you for the links.

      Following the example, I have written this:
      -------------------------------------------------------------------------------------
      program nlfaq

      syntax varlist(min=1 max=1) [if], at(name)

      tempname av asigma
      scalar `av' = `at'[1, 1]
      scalar `asigma' = `at'[1, 2]

      tempvar yh
      gen double `yh' = `av'*normal((ln(`av'/`debt')+(`r'+`asigma'/2)*`t')/(`asigma'*sqrt(`t')))-`debt'*e^(-`r'*`t')*normal(((ln(`av'/`debt')+(`r'+`asigma'/2)*`t')/(`asigma'*sqrt(t'))-`asigma'*sqrt(`t'))-`ev'+1 in 1
      replace `yh' = `av'*normal[(ln(`av'/`debt')+(`r'+`asigma'/2)*`t')/(`asigma'*sqrt(`t'))]*`asigma'/`ev'-`esigma'in 2

      replace `varlist' = `yh'

      end

      . clear
      . set obs 3

      . generate y = 0

      . replace y = 1 in 1

      nl faq @ y, parameters(av asigma) initial(av 1 asigma 1)

      ------------------------------------------------------------------------------------

      But I get an Error Message, saying:

      nlfaq returned 132
      verify that nlfaq is a function evaluator program

      What can I do to solve the problem?

      Thanks!

      Daria

      Comment


      • #4
        Keep in mind that the strategy gives the solution for av and sigma, however, you still need to state what are the values for the rest of the variables in those equations (substitute debt, t, r, esigma, etc)
        HTH

        Comment


        • #5
          Thank you, Fernando.

          I have a dataset looking like this (https://dl.dropboxusercontent.com/u/...2015-41-20.jpg) what do i have to do with the program to fill out the cells for asigma and av?

          Sorry guys, I am really horrible at stata, and I appreciate your help a lot!
          Last edited by Daria Fomenko; 07 Nov 2014, 07:53.

          Comment


          • #6
            See the nl help where it gives an example of a function evaluator program. You need to include both the RHS and LHS variables in the varlist for your function evaluator program, parsing the first variable in the list as the LHS and the rest as RHS variables (debt, t, r) which can then be substituted in the equations. Something like this:

            Code:
            program nlfunc
                        syntax varlist [if], at(name)
                        local lhs: word 1 of `varlist'
                        local debt: word 2 of `varlist'
                        local t: word 3 of `varlist'
                        local r: word 4 of `varlist'
            
                       tempname av asigma
                       scalar `av' = `at'[1, 1]
                       scalar `asigma' = `at'[1, 2]
            
                        tempvar yh
                        gen double `yh' = `av'*normal((ln(`av'/`debt')+(`r'+`asigma'/2)*`t')/(`asigma'*sqrt(`t')))-`debt'*e^(-`r'*`t')*normal(((ln(`av'/`debt')+(`r'+`asigma'/2)*`t')/(`asigma'*sqrt(t'))-`asigma'*sqrt(`t'))-`ev'+1 in 1
                        replace `yh' = `av'*normal[(ln(`av'/`debt')+(`r'+`asigma'/2)*`t')/(`asigma'*sqrt(`t'))]*`asigma'/`ev'-`esigma' in 2
             
                        replace `lhs' = `yh'
            
                    end
            
            ...
            
            nl func @ y debt t r, parameters(av asigma) initial(av 1 asigma 1)

            Comment


            • #7
              If I write the following:



              program nlfunc
              syntax varlist [if], at(name)
              local lhs: word 1 of `varlist'
              local debt: word 2 of `varlist'
              local t: word 3 of `varlist'
              local r: word 4 of `varlist'
              local esigma: word 5 of `varlist'
              local ev: word 6 of `varlist'
              tempname av asigma
              scalar `av' = `at'[1, 1]
              scalar `asigma' = `at'[1, 2]
              tempvar yh
              gen double `yh' = `av'*normal((ln(`av'/`debt')+(`r'+`asigma'/2)*`t')/(`asigma'*sqrt(`t')))-`debt'*e^(-`r'*`t')*normal(((ln(`av'/`debt')+(`r'+`asigma'/2)*`t')/(`asigma'*sqrt(t'))-`asigma'*sqrt(`t'))-`ev'+1 in 1
              replace `yh' = `av'*normal[(ln(`av'/`debt')+(`r'+`asigma'/2)*`t')/(`asigma'*sqrt(`t'))]*`asigma'/`ev'-`esigma' in 2

              replace `lhs' = `yh'
              end
              . generate y = 0
              . replace y = 1 in 1


              nl func @ y debt t r esigma ev, parameters(av asigma) initial(av 1 asigma 1)



              It still says: "verify that nlfunc is a function evaluator program"

              Comment


              • #8
                There are several problem with your code. You are using a lone square bracket in the second equation, the parentheses do not balance, the exponential function is exp() not e^(), and your terms: debt, r, t, ev, and esigma are macro variables but have not been define.

                Try this:

                Code:
                clear*
                set obs 2
                gen ev = 100 in 1
                replace ev = 120 in 2
                gen esigma = .15 in 1
                replace esigma = .13 in 2
                gen debt = 50 in 1
                replace debt = 70 in 2
                gen r = .05 in 1
                replace r = .045 in 2
                gen t = 1
                
                
                program nlfaq
                    syntax varlist(min=1 max=1) [if], at(name)
                    tempname av asigma
                    scalar `av' = `at'[1, 1]
                    scalar `asigma' = `at'[1, 2]
                    tempvar yh
                
                    gen double `yh' = `av'*normal(  ln(`av'/debt)+(r+`asigma'/2)*t)/(`asigma'*sqrt(t)  ) -debt*exp((-r*t)*normal(ln(`av'/debt)+(r+`asigma'/2)*t)/(`asigma'*sqrt(t))-`asigma'*sqrt(t))-ev+1 in 1
                    replace `yh' = `av'*normal( ln(`av'/debt)+(r+`asigma'/2)*t)/(`asigma'*sqrt(t))*`asigma'/ev-esigma in 2
                
                    replace `varlist' = `yh'
                end
                
                generate y = 0
                replace y = 1 in 1
                
                nl faq @ y, parameters(av asigma) initial(av 1 asigma 1)

                Comment


                • #9
                  Dear Scott, thank you so much!

                  It worked!

                  It gives the solution for one set of values, the problem is that I have to calculate it for 100 000 observations.

                  Is there a way to somehow get the results into the dataset?

                  Comment


                  • #10
                    I have found the SAS code for something similar, but neither I have a clue about SAS nor I have any idea how to translate it to Stata. Does anyone have any idea?

                    http://www-personal.umich.edu/~shumw...er99_print.sas

                    Comment


                    • #11
                      If you're comfortable working in Mata, Stata 13 has a set of functions to solve systems of nonlinear equations that I suspect would work better than trying to trick -nl- into doing.

                      Type

                      Code:
                      help mata solvenl
                      Once you have it working for a single observation, writing a loop in Mata to do it for all your observations won't be hard.

                      Comment


                      • #12
                        Here is one way using statsby

                        Code:
                        clear*
                        set obs 5
                        gen id = _n
                        expand 2
                        bys id: gen order = _n
                        gen ev = rnormal(100,20)
                        gen esigma = runiform()
                        gen debt = 70+ runiform()*50
                        gen rate =  runiform()*.20
                        gen t = 1
                        egen y = fill(0 1 0 1)
                        save inputdata.dta,replace
                        
                        
                        program nlfaq, byable(recall)
                            syntax varlist(min=1 max=1) [if], at(name)
                            tempname av asigma
                            scalar `av' = `at'[1, 1]
                            scalar `asigma' = `at'[1, 2]
                            tempvar yh
                        
                            gen double `yh' = `av'*normal(  ln(`av'/debt)+(r+`asigma'/2)*t)/(`asigma'*sqrt(t)  ) -debt*exp((-r*t)*normal(ln(`av'/debt)+(r+`asigma'/2)*t)/(`asigma'*sqrt(t))-`asigma'*sqrt(t))-ev+1 if order ==1
                            replace `yh' = `av'*normal( ln(`av'/debt)+(r+`asigma'/2)*t)/(`asigma'*sqrt(t))*`asigma'/ev-esigma if order == 2
                        
                            replace `varlist' = `yh'
                        end
                        
                        
                        statsby _b, by(id) clear: nl faq @ y, parameters(av asigma) initial(av 1 asigma 1)
                        
                        merge 1:m id using inputdata
                        sort id order
                        
                        rename ( av_  asigma_ ) (av asigma)
                        drop _m y
                        order id order ev - t av asigma
                        l, sepby(id)

                        Comment


                        • #13
                          Thank you Scott,

                          I have a couple of questions about your code.

                          From what I have understood (and as you might have noticed I am really lame at stata) the first part generates the randomized input data. so in order for my actual input data to be suitable it has to have a variable y alternating between 1 and 0; duplicates of each observation for y=0 and generally look like this: https://dl.dropboxusercontent.com/u/45541413/bsdata.jpg

                          Tell me if I am wrong.

                          More crutial question though is whether it all makes sence, because from what I got the solution is based on setting the temporary variable yh ==0 initially, so that at the end:

                          gen yh = av*normal( ln(av/debt)+(r+asigma/2)*t)/(asigma*sqrt(t))*asigma/ev-esigma

                          should return 0. And it doesnt if I run the programme for the randomized input.

                          Thank you so much for your help.

                          Comment


                          • #14
                            The code is incorrect. The y variable should be (1, 0) not (0, 1).

                            Code:
                            clear*
                            set obs 1
                            gen id = _n
                            expand 2
                            bys id: gen order = _n
                            gen ev = rnormal(100,20)
                            gen esigma = runiform()
                            gen debt = 70+ runiform()*50
                            gen rate =  runiform()*.20
                            gen t = 1
                            egen y = fill(1 0 )
                            
                            program nlfaq, byable(recall)
                                syntax varlist(min=1 max=1) [if], at(name)
                                tempname av asigma
                                scalar `av' = `at'[1, 1]
                                scalar `asigma' = `at'[1, 2]
                                tempvar yh
                            
                                gen double `yh' = `av'*normal(  ln(`av'/debt)+(r+`asigma'/2)*t)/(`asigma'*sqrt(t)  ) -debt*exp((-r*t)*normal(ln(`av'/debt)+(r+`asigma'/2)*t)/(`asigma'*sqrt(t))-`asigma'*sqrt(t))-ev+1 if order ==1
                                replace `yh' = `av'*normal( ln(`av'/debt)+(r+`asigma'/2)*t)/(`asigma'*sqrt(t))*`asigma'/ev-esigma if order == 2
                                replace `varlist' = `yh'
                            end
                            
                            nl faq @ y, parameters(av asigma) initial(av 1 asigma 1)
                            gen test = [av]_cons *normal( ln([av]_cons/debt)+(r+[asigma]_cons/2)*t)/([asigma]_cons*sqrt(t))*[asigma]_cons/ev-esigma
                            l
                            l

                            Comment


                            • #15
                              Hi Scott,

                              it works for the simulated data, but it doesn't want to work with my actual data.

                              I keep getting the Error message:

                              nlfaq returned 111
                              verify that nlfaq is a function evaluator program

                              Thank you so much for your help!

                              Comment

                              Working...
                              X