Binomial-Baum Function

Wie erweitere ich R um eigene Funktionen oder Pakete? Welches Paket ist passend für meine Fragestellung?

Moderatoren: EDi, jogo

Maxel
Beiträge: 9
Registriert: Mi Apr 03, 2019 2:12 pm

Binomial-Baum Function

Beitrag von Maxel »

Hallo zusammen,

ich schreibe momentan meine Thesis und muss mich nun zum ersten mal mit Programmieren beschäftigen. Ich habe einen Code für R, welcher dazu dient Wandelanleihen zu Bewerten.
Leider habe ich absolut keine Ahnung vom Programmieren und habe mich erst seit einigen Tagen damit beschäftig. Daher hoffe ich, dass Ihr mir helfen könnt.
Ich habe das Problem, dass wenn ich die Funktion mit Werten eingebe ständig " ERROR: object 'xyz' not found" als Fehlermeldung bekomme.

Was jemand wo das Problem liegt?

Ganz unten ist die Funktion mit Werten, wenn ich auf Run gehe zeig er sich mir in der Console einfach an ohne etwas zu rechnen. Falls jemand ein Link für ein gutes Tutorial (wenn möglich kostenlos, da armer Student) hat wäre ich auch sehr dankbar.

Gruß
Maxel

Code: Alles auswählen

CCBond <- function(S0, FV, ttm, r, sigma, L, k , CallPrice,rho, c, PD, CallYN)

  #definition der Intervalle und Längen'  
dt <- 1/12
n <-ttm/dt+1
n <- ceiling(n)

#ceiling verwendet ein einzelnes numerisches Argument n und gibt einen numerischen
#Vektor zurück, der die kleinsten ganzen Zahlen enthält, 
#die nicht unter den entsprechenden Elementen von n liegen

u <- exp((r-(sigma^2)/2)* dt + sigma *sqrt(dt))
d <- exp((r-(sigma^2)/2)* dt - sigma *sqrt(dt))
p = 1/2

gamma <- -log(1-PD)*S0

#Aktienkurs entwickeln und Ausfallwahrscheinlichkeit

S <- lambda <- rep(0, times(n*n)
                   
  dim(S) <- c(n,n)
  dim(lambda) <- c(n,n)

S[1,1] <- S0
lambda[1,1] <- gamma/S[1,1]

for (j in 2:n) {
  
  for (1 in 1:j) {
    if(i==j){
      S[i,j]= S[i-1,j-1]*d* exp(lambda[i-1,j-1]*dt)
    
    lambda[i,j] <- gamma/S[i,j]
  } else {
    if(i<j){
    
        s[i,j] = S[i-1,j-1]*u* exp(lambda[i,j-1]*dt)
    
          lambda[i,j] <- gamma/S[i,j]
    } else {
        S[i,j]= 0
        lambda[i,j] <- 0
      
      }
  }

CCValue <- NoCall<- Y <- Call <- rep(0,times=n*n)

dim(CCValue) <- c(n,n)
dim(NoCall)  <- c(n,n)
dim(Y) <- c(n,n)
dim(Call) <- c(n,n)
for (j in seq(from = n, to = 1, by =-1)) {
  for (i in 1:j) {
    if (j==n){
    
      CCValue[i,j]<- max(FV, k*S[i,j])
      } else
      {
        NoCall[i,j] <- exp(-r*dt)*(exp(-lambda[i,j]*dt)*(p*CCValue[i,j+1] + (1-p)
                                      *CCValue[i+1,j+1])+ (1-exp(-lambda[i,j]*dt))
                                   *(1-L)*FV)
        
   Coupon <- exp(-(r+lambda[i,j])*dt)*c*FV*(ttm/n)     
   if (Call == 1) {
     Call[i,j] <- max(k*S[i,j],CallPrice)
     Y[i,j]<- (NoCall[i,j]/Call[i,j])-1
     
    if (Y[i,j]<0) {Y[i,j]=0 }
       
     } else {
       Call[i,j] <- 0
       Y[i,j] <- 0
     }
  
   CCValue[i,j] <- Coupon + exp(-(rho*Y[i,j])*dt)* NoCall[i,j] + (1-exp(-(rho*
                                                        Y[i,j]*dt)))* Call[i,j]
      }
  }    
} 
 CCValue[1,1]
  } 
  
CCBond(23,100,3.6,0.015,0.1,0.677,12,0,7,0.03,0.076,0)
jogo
Beiträge: 2085
Registriert: Fr Okt 07, 2016 8:25 am

Re: Binomial-Baum Function

Beitrag von jogo »

Hallo Maxel,

willkommen im Forum!
In der ersten Zeile:

Code: Alles auswählen

CCBond <- function(S0, FV, ttm, r, sigma, L, k , CallPrice,rho, c, PD, CallYN)
fehlt die öffnende geschweifte Klammer. Es muss heißen:

Code: Alles auswählen

CCBond <- function(S0, FV, ttm, r, sigma, L, k , CallPrice,rho, c, PD, CallYN)  {
In der Zeile

Code: Alles auswählen

  S <- lambda <- rep(0, times(n*n)
fehlt die schließende runde Klammer. Bei der Verwendung von RStudio kann mann die Einrückungen für den Code nochmal neu automatisch generieren lassen und würde dann solche Fehler sofort bemerken.

... vielleicht sind noch weitere ähnliche Fehler im Code.
Nachtrag:
Eine der beiden for-Schleifen

Code: Alles auswählen

  for (j in 2:n) {
    
    for (1 in 1:j) {
hat kein Ende. Hier kann ich nicht genau feststellen, wo die schließende geschweifte Klammer hingehört.

Auch ist mir nicht klar, welchen Wert die Funktion zurückliefert.

Und dann bin ich auch noch neugierig:
der Code sieht aus, als ob er von einer anderen Programmiersprache stammt (, die keine Vektorisierung kennt); ist das so?

Gruß, Jörg
Maxel
Beiträge: 9
Registriert: Mi Apr 03, 2019 2:12 pm

Re: Binomial-Baum Function

Beitrag von Maxel »

Hallo Jörg,

besten dank für deine Hilfe!

Wenn ich die Werte in die Funktion also "CCBond(23,100,3.6,0.015,0.1,0.677,8,0,7,0.03,0.076,0)" eingebe und auf Run gehe zeigt er mir "object 's' not found" in der Funktion an. Hast du dazu eine Idee?

In dem Modell simuliere ich Aktienkurse. Am Ende soll entschieden werden was größer ist, der Nominalwert der Wandelanleihe (z.b 100,-) oder man tauscht/wandelt die Anleihe in Aktien z.b. eine Anleihe = 10 Aktien. Bei einem Kurs von 11 Euro würde man tauschen. Das macht man in jedem Knoten des Baums und diskontiert bis zum Startzeitpunkt ab. Also in diesem Beispiel liegt der Wert (wahrscheinlich) bei etwas über 100 Euro.

Leider fehlt mich da der Durchblick um zu sagen woher der Code stammt. Deklariert wurde er auf jeden Fall als R.

Gruß
Maxel
Benutzeravatar
EDi
Beiträge: 1599
Registriert: Sa Okt 08, 2016 3:39 pm

Re: Binomial-Baum Function

Beitrag von EDi »

debugger anwerfen und Zeilenweise ausführen:

Code: Alles auswählen

debug(CCBond)
CCBond(23,100,3.6,0.015,0.1,0.677,8,0,7,0.03,0.076,0)
Bitte immer ein reproduzierbares Minimalbeispiel angeben. Meinungen gehören mir und geben nicht die meines Brötchengebers wieder.

Dieser Beitrag ist lizensiert unter einer CC BY 4.0 Lizenz
Bild.
jogo
Beiträge: 2085
Registriert: Fr Okt 07, 2016 8:25 am

Re: Binomial-Baum Function

Beitrag von jogo »

Hallo Maxel,
Maxel hat geschrieben: Mi Apr 03, 2019 4:44 pm Wenn ich die Werte in die Funktion also "CCBond(23,100,3.6,0.015,0.1,0.677,8,0,7,0.03,0.076,0)" eingebe und auf Run gehe zeigt er mir "object 's' not found" in der Funktion an. Hast du dazu eine Idee?
Es könnte diese Zeile sein:

Code: Alles auswählen

        s[i,j] = S[i-1,j-1]*u* exp(lambda[i,j-1]*dt)
Sonst kann ich nirgends das kleine s als Namen für ein Objekt entdecken.
Gleich ein kleiner Test (in einer sauberen R-Session):

Code: Alles auswählen

s[3,4] <- 33
jepp

Code: Alles auswählen

Leider fehlt mir da der Durchblick um zu sagen woher der Code stammt. Deklariert wurde er auf jeden Fall als R. 
Das mag ja sein, dass er jetzt der R-Syntax genügt, aber ich vermute er hatte eine Vorlage in einer anderen Programmiersprache (eventuell C).
Meine Vermutung stützt sich u.a. auf diese Stelle:

Code: Alles auswählen

CCValue <- NoCall<- Y <- Call <- rep(0,times=n*n)

dim(CCValue) <- c(n,n)
dim(NoCall)  <- c(n,n)
dim(Y) <- c(n,n)
dim(Call) <- c(n,n)
In R würde man schreiben:

Code: Alles auswählen

CCValue <- NoCall <- Y <- Call <- matrix(0, n, n)
Ein Blick in den Hilfetext zu matrix() zeigt, dass es völlig äquivalent ist.

Gruß, Jörg
Maxel
Beiträge: 9
Registriert: Mi Apr 03, 2019 2:12 pm

Re: Binomial-Baum Function

Beitrag von Maxel »

Hi Jörg,

ich habe wie EDI empfohlen hat, mir mal den Debugger angeschaut und ein wenig damit rumgespielt und ja der Fehler liegt bei der Else if Schleife.

Code: Alles auswählen

   if(i==j){
        S[i,j]= S[i-1,j-1]*d* exp(lambda[i-1,j-1]*dt)
        
        lambda[i,j] <- gamma/S[i,j]
      } else {
        if(i<j){
          
          S[i,j] = S[i-1,j-1]*u* exp(lambda[i,j-1]*dt)
          
          lambda[i,j] <- gamma/S[i,j]
        } else {
       
Allerdings ist der Code (zu mindestens nach meinem geringen Verständnis) in Ordnung. Hier soll einfach der Vorherige Aktienkurs [i-1,j-1] mit vereinfacht gesagt einmal u und einmal d multipliziert werden. Und das soll in jedem Knoten erneut erfolgen.
Hab auch nochmal nach den S kontrolliert und nun heißt es "replacement has length zero".Das heißt es gibt keinen Vektor (also 0) oder?
Der Startwert ist der Wert von S0 welcher S[1,1] ist, in dem Fall also 23.
jogo
Beiträge: 2085
Registriert: Fr Okt 07, 2016 8:25 am

Re: Binomial-Baum Function

Beitrag von jogo »

Maxel hat geschrieben: Mi Apr 03, 2019 9:29 pm Allerdings ist der Code (zu mindestens nach meinem geringen Verständnis) in Ordnung. Hier soll einfach der Vorherige Aktienkurs [i-1,j-1] mit vereinfacht gesagt einmal u und einmal d multipliziert werden. Und das soll in jedem Knoten erneut erfolgen.
Hab auch nochmal nach den S kontrolliert und nun heißt es "replacement has length zero".Das heißt es gibt keinen Vektor (also 0) oder?
Aber das i oder das j könnten eventuell den Wert 1 haben - dann ist einer der beiden Indizes 0.
Schau mal, dann passiert etwa sowas:

Code: Alles auswählen

S <- matrix(1:16, 4)
S[0,3]
S[1,4] <- S[0,3]
Kannst Du nach der Korrektur bitte Deinen Code nochmal komplett posten? Danke!

Gruß, Jörg
Maxel
Beiträge: 9
Registriert: Mi Apr 03, 2019 2:12 pm

Re: Binomial-Baum Function

Beitrag von Maxel »

Hallo Jörg,

ich habe gedacht, dass wenn der Startwert mit S[1,1] definiert ist, das Problem eigentlich nicht auftauchen sollte. Oder liegt es an

Code: Alles auswählen

                           S[i,j]= S[i-1,j-1]*d* exp(lambda[i-1,j-1]*dt)
, dass dann der Wert auf 0 geht?

Gruß
Max
Anbei der Code:

Code: Alles auswählen

CCBond <- function(S0, FV, ttm, r, sigma, L, k , CallPrice,rho, c, PD, CallYN) {
  
  #definition der Intervalle und Längen'  
  dt <- 1/12
  n <-ttm/dt+1
  n <- ceiling(n)
  
  
  u <- exp((r-(sigma^2)/2)* dt + sigma *sqrt(dt))
  d <- exp((r-(sigma^2)/2)* dt - sigma *sqrt(dt))
  p = 1/2
  
  gamma <- -log(1-PD)*S0
  
  #Aktienkurs entwickeln und Ausfallwahrscheinlichkeit
  
  S <- lambda <- matrix(0, n, n)
  
  dim(S) <- c(n,n)
  dim(lambda) <- c(n,n)
  
  S[1,1] <- S0
  lambda[1,1] <- gamma/S[1,1]
  
  for (j in 2:n) {
    
    for (i in 1:j) {
      if(i==j){
        S[i,j]= S[i-1,j-1]*d* exp(lambda[i-1,j-1]*dt)
       
        lambda[i,j] <- gamma/S[i,j]
      } else {
        if(i<j){
          
          S[i,j] = S[i-1,j-1]*u* exp(lambda[i,j-1]*dt)
          
          lambda[i,j] <- gamma/S[i,j]
        } else {
          S[i,j]= 0
          lambda[i,j] <- 0
          
        }
      }
    }
  }
  #Rückwärtsschleife vom letzten Zeitpunkt zum Startzeitpunk
  
  CCValue <- NoCall<- Y <- Call <- matrix(0, n, n)
  
  dim(CCValue) <- c(n,n)
  dim(NoCall)  <- c(n,n)
  dim(Y) <- c(n,n)
  dim(Call) <- c(n,n)
  for (j in seq(from = n, to = 1, by =-1)) {
    for (i in 1:j) {
      if (j==n){
        
        CCValue[i,j]<- max(FV, k*S[i,j])
      } else
      {
        NoCall[i,j] <- exp(-r*dt)*(exp(-lambda[i,j]*dt)*(p*CCValue[i,j+1] + (1-p)
                                                         *CCValue[i+1,j+1])+ (1-exp(-lambda[i,j]*dt))
                                   *(1-L)*FV)
        
        Coupon <- exp(-(r+lambda[i,j])*dt)*c*FV*(ttm/n)     
        if (Call == 1) {
          Call[i,j] <- max(k*S[i,j],CallPrice)
          Y[i,j]<- (NoCall[i,j]/Call[i,j])-1
          
          if (Y[i,j]<0) {Y[i,j]=0 }
          
        } else {
          Call[i,j] <- 0
          Y[i,j] <- 0
        }
        
        CCValue[i,j] <- Coupon + exp(-(rho*Y[i,j])*dt)* NoCall[i,j] + (1-exp(-(rho*
                                                                                 Y[i,j]*dt)))* Call[i,j]
      }
    }    
  } 
  CCValue[1,1]
}  
  CCBond(23,100,3.6,0.015,0.1,0.677,12,0,7,0.03,0.076,0)
jogo
Beiträge: 2085
Registriert: Fr Okt 07, 2016 8:25 am

Re: Binomial-Baum Function

Beitrag von jogo »

Hallo Maxel,
Maxel hat geschrieben: Do Apr 04, 2019 8:26 am ich habe gedacht, dass wenn der Startwert mit S[1,1] definiert ist, das Problem eigentlich nicht auftauchen sollte. Oder liegt es an

Code: Alles auswählen

                           S[i,j]= S[i-1,j-1]*d* exp(lambda[i-1,j-1]*dt)
, dass dann der Wert auf 0 geht?
es geht z.B. um folgenden Abschnitt, bei dem auch die Konstellation ( j=2 und i=1 ) auftreten kann:

Code: Alles auswählen

  for (j in 2:n) {
    for (i in 1:j) {
      if(i==j){
        S[i,j]= S[i-1,j-1]*d* exp(lambda[i-1,j-1]*dt)
        lambda[i,j] <- gamma/S[i,j]
      } else {
        if(i<j){
          S[i,j] = S[i-1,j-1]*u* exp(lambda[i,j-1]*dt)
Das bedeutet in der letzten Zeile S[1,2] = S[0, 1]*... mit der entsprechenden Fehlermeldung.

Gruß, Jörg
jogo
Beiträge: 2085
Registriert: Fr Okt 07, 2016 8:25 am

Re: Binomial-Baum Function

Beitrag von jogo »

Hallo Maxel,

ich habe den Code etwas bearbeitet.

Code: Alles auswählen

CCBond <- function(S0, FV, ttm, r, sigma, L, k, CallPrice, rho, c, PD, CallYN) {
  
  #definition der Intervalle und Längen'  
  dt <- 1/12
  n <- ceiling(ttm/dt+1)
  
  u <- exp((r-(sigma^2)/2)* dt + sigma *sqrt(dt))
  d <- exp((r-(sigma^2)/2)* dt - sigma *sqrt(dt))
  p = 1/2
  
  gamma <- -S0*log(1-PD)
  
  #Aktienkurs entwickeln und Ausfallwahrscheinlichkeit
  
  S <- lambda <- matrix(0, n, n)
  
  S[1,1]      <- S0
  lambda[1,1] <- gamma/S[1,1]
  
  for (j in 2:n) {
    S[j,j]      <- S[j-1,j-1]*d* exp(lambda[j-1,j-1]*dt)
    lambda[j,j] <- gamma/S[j,j]
    
    if (j<3) break
    i <- 2:(j-1)
    S[i,j]      <- S[i-1,j-1]*u* exp(lambda[i,j-1]*dt)
    lambda[i,j] <- gamma/S[i,j]
    
    # for (i in 2:j) {
    #   if(i==j){
    #     S[i,j]= S[i-1,j-1]*d* exp(lambda[i-1,j-1]*dt)
    #     lambda[i,j] <- gamma/S[i,j]
    #   } else {
    #     if(i<j){
    #       S[i,j] = S[i-1,j-1]*u* exp(lambda[i,j-1]*dt)
    #       lambda[i,j] <- gamma/S[i,j]
    #     } else {  # dieser Zweig wird nie erreicht!
    #       S[i,j] = 0
    #       lambda[i,j] <- 0
    #     }
    #   }
    # }
  }
  #Rückwärtsschleife vom letzten Zeitpunkt zum Startzeitpunk
  
  CCValue <- NoCall <- Y <- Call <- matrix(0, n, n)
  
  for (j in n:1) {
    for (i in 1:j) {
      if (j==n) { CCValue[i,j] <- max(FV, k*S[i,j])
      } else {
        NoCall[i,j] <- exp(-r*dt)*(exp(-lambda[i,j]*dt)*
                                     (p*CCValue[i,j+1] + (1-p)*CCValue[i+1,j+1])+ (1-exp(-lambda[i,j]*dt)) *(1-L)*FV)
        Coupon <- exp(-(r+lambda[i,j])*dt)*c*FV*(ttm/n)     
        if (Call == 1) {  ### hier ist noch ein kapitaler Fehler (der produziert die Warnungen)
          Call[i,j] <- max(k*S[i,j], CallPrice)
          Y[i,j]    <- max((NoCall[i,j]/Call[i,j])-1, 0)
          
        } else { Call[i,j] <- Y[i,j] <- 0 }
        
        CCValue[i,j] <- Coupon + 
          exp(-(rho*Y[i,j])*dt)* NoCall[i,j] + (1-exp(-(rho*Y[i,j]*dt)))* Call[i,j]
      }
    }    
  } 
  CCValue[1,1]
}  
CCBond(S0=23, FV=100, ttm=3.6, r=0.015, sigma=0.1, L=0.677, k=12, CallPrice=0, rho=7, c=0.03, PD=0.076, CallYN=0)
Schau mal, ob das soweit ok ist. Ich habe die obere Doppelschleife ersetzt und rechne dort vektorbasiert; der kommentierte Teil ist jetzt obsolet.
Die untere Doppelschleife habe ich noch nicht umgestaltet. In der unteren Doppelschleife ist ein Fehler bei dem Test

Code: Alles auswählen

       if (Call == 1) {  ### hier ist noch ein kapitaler Fehler (der produziert die Warnungen)
Bei if (...) kann nur ein Element geprüft werden - if nimmt einfach das erste Element auch wenn Dein Vergleich Call==0 eine ganze Matrix mit logischen Werten erzeugt. So wie es jetzt im Code steht ist if (Call == 1) ... identisch mit if (Call[1,1] == 1) ...

Gruß, Jörg
Antworten