Adjointable Scripting

Work in progress

Example

SL Script

from numpy import *
from intrinsic import *
from external import *

def payoff (d,p) {
  #pragma noprimal
  p[0]=gt0(d[1]-d[0])
  return p
}

def black_scholes_call (x,y,M) {
  s=[0.0]*M
  #pragma notbr
  s=mc(x,s,M)
  d=[0.0]*2
  p=[0.0]*1
  for I in range(M) {
    #pragma notbr
    d[0]=x[3]
    d[1]=s[I]
    #pragma notbr
    p=payoff(d,p)
    #pragma notbr
    y[0]=y[0]+exp(-x[1])*p[0]
  }
  #pragma noprimal
  y[0]=y[0]/M
  return y
}

Adjoint SL Script

from numpy import *
from intrinsic import *
from external import *
from tbr import *

def payoff(d,p) :
        p[0]=gt0(d[1]-d[0])
        return p

def black_scholes_call(x,y,M) :
        s=[0.0]*M
        s=mc(x,s,M)
        d=[0.0]*2
        p=[0.0]*1
        for I in range(M) :
                d[0]=x[3]
                d[1]=s[I]
                p=payoff(d,p)
                y[0]=y[0]+exp(-x[1])*p[0]
        y[0]=y[0]/M
        return y

def a_payoff(d,a_d,p,a_p) :
        v=[0.0]*4
        a_v=[0.0]*4
        v[0]=d[1]
        v[1]=d[0]
        v[2]=v[0]-v[1]
        v[3]=gt0(v[2])
        a_v[3]=a_v[3]+a_p[0]
        a_p[0]=0.0
        a_v[2]=a_v[2]+d_gt0(v[2])*a_v[3]
        a_v[3]=0.0
        a_v[0]=a_v[0]+a_v[2]
        a_v[1]=a_v[1]-a_v[2]
        a_v[2]=0.0
        a_d[0]=a_d[0]+a_v[1]
        a_v[1]=0.0
        a_d[1]=a_d[1]+a_v[0]
        a_v[0]=0.0
        return a_d

def a_black_scholes_call(x,a_x,y,a_y,M) :
        v=[0.0]*7
        a_v=[0.0]*7
        s=[0.0]*M
        a_s=[0.0]*M
        s=mc(x,s,M)
        d=[0.0]*2
        a_d=[0.0]*2
        p=[0.0]*1
        a_p=[0.0]*1
        for I in range(M) :
                d[0]=x[3]
                push_s(d[1])
                d[1]=s[I]
                p=payoff(d,p)
                y[0]=y[0]+exp(-x[1])*p[0]
        v[0]=y[0]
        v[1]=M
        v[2]=v[0]/v[1]
        a_v[2]=a_v[2]+a_y[0]
        a_y[0]=0.0
        a_v[0]=a_v[0]+a_v[2]/v[1]
        a_v[2]=0.0
        a_v[1]=0.0
        a_y[0]=a_y[0]+a_v[0]
        a_v[0]=0.0
        for I in reversed(range(M) ) :
                v[0]=y[0]
                v[1]=x[1]
                v[2]=-v[1]
                v[3]=exp(v[2])
                v[4]=p[0]
                v[5]=v[3]*v[4]
                v[6]=v[0]+v[5]
                a_v[6]=a_v[6]+a_y[0]
                a_y[0]=0.0
                a_v[0]=a_v[0]+a_v[6]
                a_v[5]=a_v[5]+a_v[6]
                a_v[6]=0.0
                a_v[3]=a_v[3]+v[4]*a_v[5]
                a_v[4]=a_v[4]+v[3]*a_v[5]
                a_v[5]=0.0
                a_p[0]=a_p[0]+a_v[4]
                a_v[4]=0.0
                a_v[2]=a_v[2]+v[3]*a_v[3]
                a_v[3]=0.0
                a_v[1]=a_v[1]-a_v[2]
                a_v[2]=0.0
                a_x[1]=a_x[1]+a_v[1]
                a_v[1]=0.0
                a_y[0]=a_y[0]+a_v[0]
                a_v[0]=0.0
                a_d=a_payoff(d,a_d,p,a_p)
                d[1]=pop_s()
                v[0]=s[I]
                a_v[0]=a_v[0]+a_d[1]
                a_d[1]=0.0
                a_s[I]=a_s[I]+a_v[0]
                a_v[0]=0.0
                v[0]=x[3]
                a_v[0]=a_v[0]+a_d[0]
                a_d[0]=0.0
                a_x[3]=a_x[3]+a_v[0]
                a_v[0]=0.0
        a_x=a_mc(x,a_x,s,a_s,M)
        return a_x