Announcement

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

  • How to evaluate a string formula within a function?

    Dear Mata friends,

    I have written this simple ready-to-execute code for computing the yield-to-maturity of a two-period coupon-paying bond:

    Code:
    clear
    input float(AMOUNTISSUED CF_1 CF_2) double YTM
     100  23  22  .
    end
    
    mata
      z=J(1,1,.)
      st_view(z,., "YTM AMOUNTISSUED CF_1 CF_2")
      function s(ytm,amountissued,cf_1,cf_2) {
          
          return((amountissued+cf_2)/ytm^2+cf_1/ytm - amountissued)
      }
     
      for (i=1;i<=rows(z);i++) {
          r=mm_root(YTM=.,&s(),epsilon(1),5-epsilon(1),1e-9,1000,z[i,2],z[i,3],z[i,4])
          YTM-1
          z[i,1]=YTM-1
          
      }
    end

    However, this code is insufficient for my final purpose: I need to define the function s(.) dynamically for a varying number of cash-flows CF_1 ... CF_N.

    Given my limited Mata knowledge, I think that the easiest solution is to write the respective formula as a string using Stata and then to evaluate this formula in the function s(ytm). The code would look like this:

    Code:
    clear
    input double YTM str20 formula
    . "(100+23)/ytm^2 + 23/ytm - 100"
    . "(100+20)/ytm^3 + 20/ytm^2 + 20/ytm- 100"
    *. "(100+20)/ytm^N + ... + 20/ytm^2 + 20/ytm- 100"
    end
    
    mata
      z=J(1,1,.)
      st_view(z,., "YTM")
      function s(ytm) {
          return(??????????)
      }
     
      for (i=1;i<=rows(z);i++) {
          r=mm_root(YTM=.,&s(),epsilon(1),5-epsilon(1),1e-9,1000)
          YTM-1
          z[i,1]=YTM-1
      }
    end

    Do you have any suggestions on how to evaluate the string formula "(100+23)/ytm^2 + 23/ytm - 100" using function s(ytm)?

    Thank you,
    David

  • #2

    Code:
    clear
    input double YTM str50 formula
    . "(100+23)/ytm^2 + 23/ytm - 100"
    . "(100+20)/ytm^3 + 20/ytm^2 + 20/ytm- 100"
    *. "(100+20)/ytm^N + ... + 20/ytm^2 + 20/ytm- 100"
    end
    First create the mata functions s1() to s3(). Set the formula in local macros. Then find the adress of theses functions with findexternal().
    Code:
    clear mata
    set trace off
    set tracedepth 1
    forval i = 1/`=_N' {
            local formula `:di formula[`i']'
            mata : function s`i'(ytm) return(`formula');
    }
    
    mata : mata describe
    scalar Nfunc = _N
    mata:
    N = st_numscalar("Nfunc")
    for (i = 1; i<=N ;i++)
    {
            pFunc = findexternal("s"+strofreal(i)+"()")  //  pFunc is successively a pointer to the function s1(), s2(), s3()
            pFunc 
            r=mm_root(YTM=.,pFunc,epsilon(1),5-epsilon(1),1e-9,1000)
            YTM
    }
    end
    Another way is to use a single function s(), which you replace with the correct formula during a loop
    Code:
    set trace off
    set tracedepth 1
    forval i = 1/`=_N' {
            local formula `:di formula[`i']'
            di "`formula'"
    
            cap mata mata drop s()
            mata : function s(ytm) return(`formula') 
            mata: r=mm_root(YTM=.,&s(),epsilon(1),5-epsilon(1),1e-9,1000);
            mata: YTM
    
    }

    Comment


    • #3
      Thank you very much, Christophe!

      Both approaches help a lot.

      Comment

      Working...
      X