简体   繁体   中英

Pricing American Stock Option with TensorFlow Neural Network , Simulate by Monte Carlo

so what I try to do is to simulate with Monte Carlo a American Option (Stock) and use TensorFlow to price it.

I use two helper function , get_continuation_function to create the TF operators. And the pricing_function to create the computational graph for the pricing.

The npv operator is sum of the optimal exercise decisions. At each time I check if the exercise value is greater than the predicted continuation value (in other words, whether the option is in the money).

And the actual pricing function is american_tf . I execute the function to create the paths, the exercise values for the training path. Then, I iterate backward through the training_functions and learn the value and decision on each exercise date.

def get_continuation_function():
    X = tf.placeholder(tf.float32, (None,1),name="X")
    y = tf.placeholder(tf.float32, (None,1),name="y")
    w = tf.Variable(tf.random_uniform((1,1))*0.1,,name="w")
    b = tf.Variable(initial_value = tf.ones(1)*1,name="b")
    y_hat = tf.add(tf.matmul(X, w), b)
    pre_error = tf.pow(y-y_hat,2)
    error = tf.reduce_mean(pre_error)
    train = tf.train.AdamOptimizer(0.1).minimize(error)
    return(X, y, train, w, b, y_hat)


def pricing_function(number_call_dates):
    S = tf.placeholder(tf.float32,name="S")
    # First excerise date
    dts = tf.placeholder(tf.float32,name="dts")
    # 2nd exersice date
    K = tf.placeholder(tf.float32,name="K")
    r = tf.placeholder(tf.float32,,name="r")
    sigma = tf.placeholder(tf.float32,name="sigma")
    dW = tf.placeholder(tf.float32,name="dW") 

    S_t = S * tf.cumprod(tf.exp((r-sigma**2/2) * dts + sigma * tf.sqrt(dts) * dW), axis=1)
    E_t = tf.exp(-r * tf.cumsum(dts)) * tf.maximum(K-S_t, 0)

    continuationValues = []
    training_functions = []

    previous_exersies = 0
    npv = 0
    for i in range(number_call_dates-1):
        (input_x, input_y, train, w, b, y_hat) = get_continuation_function()
        training_functions.append((input_x, input_y, train, w, b, y_hat))
        X = tf.keras.activations.relu(S_t[:, i])
        contValue = tf.add(tf.matmul(X, w),b)
        continuationValues.append(contValue)
        inMoney = tf.cast(tf.greater(E_t[:,i], 0.), tf.float32)
        exercise = tf.cast(tf.greater(E_t[:,i], contValue[:,0]), tf.float32) * inMoney * (1-previous_exersies)
        previous_exersies += exercise
        npv += exercise*E_t[:,i]

    # Last exercise date
    inMoney = tf.cast(tf.greater(E_t[:,-1], 0.), tf.float32)
    exercise =  inMoney * (1-previous_exersies)
    npv += exercise*E_t[:,-1]
    npv = tf.reduce_mean(npv)
    return([S, dts, K, r, sigma,dW, S_t, E_t, npv, training_functions])


def american_tf(S_0, strike, M, impliedvol, riskfree_r, random_train, random_pricing):
    n_exercise = len(M)
    with tf.Session() as sess:

        S,dts,K,r,sigma,dW,S_t,E_t,npv,training_functions = pricing_function(n_exercise)
        sess.run(tf.global_variables_initializer())
        paths, exercise_values = sess.run([S_t,E_t], {
            S: S_0,
            dts: M,
            K: strike,
            r: riskfree_r,
            sigma: impliedvol,
            dW: random_train
        })

        for i in range(n_exercise-1)[::-1]:
            (input_x,input_y,train,w,b,y_hat) = training_functions[i]
            y= exercise_values[:,i+1:i+2]
            X = paths[:,i]
            print(input_x.shape)
            print((exercise_values[:,i]>0).shape)
            for epochs in range(100):
                _ = sess.run(train, {input_x:X[exercise_values[:,i]>0], 
                                     input_y:y[exercise_values[:,i]>0]})
                cont_value = sess.run(y_hat, {input_x:X, input_y:y})   
                exercise_values[:,i+1:i+2] = np.maximum(exercise_values[:,i+1:i+2], cont_value)

        npv = sess.run(npv, {S: S_0, K: strike, r: riskfree_r, sigma: impliedvol, dW: N_pricing})

        return npv


N_samples_learn = 1000
N_samples_pricing = 1000
calldates = 12
N = np.random.randn(N_samples_learn,calldates)
N_pricing = np.random.randn(N_samples_pricing,calldates)

american_tf(100., 90., [1.]*calldates, 0.25, 0.05, N, N_pricing)

Calldates is the number of steps
training sample set = 1000
test sample size = 1000

But my error is very weird

 ---> 23                 nput_y:y[exercise_values[:,i]>0]})

 ValueError: Cannot feed value of shape (358,) for Tensor 'Placeholder_441:0', which has shape '(?, 1)'

There are a bunch of things discussed in comment with @hallo12. I just want to upload a working version incorporating all the changes. The code is tested and runs without error. But to make sure the final training output is correct, you may want to compare against some benchmark.

General comment : It's good to separate the variable and time dimension in this type of application, especially when you only have 1 variable. For example, your input array should be 3D with

[time, training sample, input variable]

rather than 2D with [training sample, time]. This way when you iterate over the time dimension, the rest of the dimensions are kept unchanged.

import tensorflow as tf
import numpy as np

def get_continuation_function():
    X = tf.placeholder(tf.float32, (None,1),name="X")
    y = tf.placeholder(tf.float32, (None,1),name="y")
    w = tf.Variable(tf.random_uniform((1,1))*0.1,name="w")
    b = tf.Variable(initial_value = tf.ones(1)*1,name="b")
    y_hat = tf.add(tf.matmul(X, w), b)
    pre_error = tf.pow(y-y_hat,2)
    error = tf.reduce_mean(pre_error)
    train = tf.train.AdamOptimizer(0.1).minimize(error)
    return(X, y, train, w, b, y_hat)


def pricing_function(number_call_dates):
    S = tf.placeholder(tf.float32,name="S")
    # First excerise date
    dts = tf.placeholder(tf.float32,name="dts")
    # 2nd exersice date
    K = tf.placeholder(tf.float32,name="K")
    r = tf.placeholder(tf.float32,name="r")
    sigma = tf.placeholder(tf.float32,name="sigma")
    dW = tf.placeholder(tf.float32,name="dW")

    S_t = S * tf.cumprod(tf.exp((r-sigma**2/2) * dts + sigma * tf.sqrt(dts) * dW), axis=1)
    E_t = tf.exp(-r * tf.cumsum(dts)) * tf.maximum(K-S_t, 0)

    continuationValues = []
    training_functions = []

    previous_exersies = 0
    npv = 0
    for i in range(number_call_dates-1):
        (input_x, input_y, train, w, b, y_hat) = get_continuation_function()
        training_functions.append((input_x, input_y, train, w, b, y_hat))
        X = tf.keras.activations.relu(S_t[:, i:i+1])
        contValue = tf.add(tf.matmul(X, w),b)
        continuationValues.append(contValue)
        inMoney = tf.cast(tf.greater(E_t[:,i], 0.), tf.float32)
        exercise = tf.cast(tf.greater(E_t[:,i], contValue[:,0]), tf.float32) * inMoney * (1-previous_exersies)
        previous_exersies += exercise
        npv += exercise*E_t[:,i]

    # Last exercise date
    inMoney = tf.cast(tf.greater(E_t[:,-1], 0.), tf.float32)
    exercise =  inMoney * (1-previous_exersies)
    npv += exercise*E_t[:,-1]
    npv = tf.reduce_mean(npv)
    return([S, dts, K, r, sigma,dW, S_t, E_t, npv, training_functions])


def american_tf(S_0, strike, M, impliedvol, riskfree_r, random_train, random_pricing):
    n_exercise = len(M)
    with tf.Session() as sess:

        S,dts,K,r,sigma,dW,S_t,E_t,npv,training_functions = pricing_function(n_exercise)
        sess.run(tf.global_variables_initializer())
        paths, exercise_values = sess.run([S_t,E_t], {
            S: S_0,
            dts: M,
            K: strike,
            r: riskfree_r,
            sigma: impliedvol,
            dW: random_train
        })

        for i in range(n_exercise-1)[::-1]:
            (input_x,input_y,train,w,b,y_hat) = training_functions[i]
            y= exercise_values[:,i+1:i+2]
            X = paths[:,i]
            print(input_x.shape)
            print((exercise_values[:,i]>0).shape)
            for epochs in range(100):
                _ = sess.run(train, {input_x:(X[exercise_values[:,i]>0]).reshape(len(X[exercise_values[:,i]>0]),1),
                                     input_y:(y[exercise_values[:,i]>0]).reshape(len(y[exercise_values[:,i]>0]),1)})
                cont_value = sess.run(y_hat, {input_x:X.reshape(len(X),1), input_y:y.reshape(len(y),1)})
                exercise_values[:,i+1:i+2] = np.maximum(exercise_values[:,i+1:i+2], cont_value)

        npv = sess.run(npv, {S: S_0, K: strike, dts:M, r: riskfree_r, sigma: impliedvol, dW: N_pricing})

        return npv


N_samples_learn = 1000
N_samples_pricing = 1000
calldates = 12
N = np.random.randn(N_samples_learn,calldates)
N_pricing = np.random.randn(N_samples_pricing,calldates)

print(american_tf(100., 90., [1.]*calldates, 0.25, 0.05, N, N_pricing))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM