Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Time decay of American options #43

Open
omdv opened this issue Jan 26, 2021 · 1 comment
Open

Time decay of American options #43

omdv opened this issue Jan 26, 2021 · 1 comment

Comments

@omdv
Copy link

omdv commented Jan 26, 2021

Hello and thanks for the library!

I am working on an integration of TFF into one of my option trading strategies and trying to figure out several practical aspects, such as IV determination and finding greeks. After reading through all issues and discussions I have a working notebook which expands the American option example (using PDE) and includes volatility estimation and (most of) greeks using tff.math.fwd_gradient. There are still some questions about gridding to manage batches with significantly different strikes, but I think I'll manage, maybe even to an extent I can do a PR for that example...

One thing I cannot comprehend yet is the time decay and time aspects overalls. How would you recommend to approach theta estimation? Should I try fwd_gradient on expiry? Related question is how to manage options with significantly different time to expiration? The example states that volatility term has to be adjusted - not sure I understand it.

expiry: A Python float. Expiry date of the options. If the options
      have different expiries, volatility term has to adjusted to
      make expiries the same.
@saxena-ashish-g
Copy link
Contributor

Hi,

You are absolutely right that a gradient on the expiry will do the trick for computing theta. Taking as an example, the vanilla option, you can do this:

volatilities = np.array([0.25, 0.35])
forwards = np.array([100.0, 5.0])
strikes = np.array([100.0, 5.1])

def value_fn(t):
  return tff.black_scholes.option_price(
      volatilities=volatilities,
      strikes=strikes,
      expiries=t,
      forwards=forwards)

expiries = tf.constant(np.array([0.25, 1.0]))
theta = -tff.math.fwd_gradient(value_fn, expiries)
price = value_fn(expiries)
print(f"Price: {price}, Theta: {theta}")
# Prints: Price: [4.98353381 0.65265898], Theta: [-9.95409642 -0.34663542]

Same logic will work with the American options.

Regarding the question about different expiries for the American options (or for anything on the grid), there are two options:

  1. You initialize the grid at the largest expiry and evolve backwards stopping at each expiry time and apply the option payoff to the grid at that expiry. This is a little tedious to do.
  2. You perform a rescaling as follows. Suppose we have two options with expiries [T1, T2], vols [sigma1, sigma2], rates [r1, r2] and underliers [S1, S2]. You have two backward equations to solve (let's call the prices V1, V2):
dV1/dt + 1/2 sigma1^2 S1^2 (d^2 V1/ dS1^2) + r1 S1 dV1 / dS1 - r1 V1 = 0
dV2/dt + 1/2 sigma2^2 S2^2 (d^2 V2/ dS2^2) + r2 S2 dV2 / dS2 - r2 V2 = 0

Apply a vector rescaling to the time t so that [tau1, tau2] = t / [T1, T2]. With this rescaling the options expire at time 1 in both tau1 and tau2. You need to account for this rescaling in the equation above so they become:

dV1/dtau1 + 1/2 sigma1^2 * T1 S1^2 (d^2 V1/ dS1^2) + r1 * T1 S1 dV1 / dS1 - r1 * T1 V1 = 0
dV2/dtau2 + 1/2 sigma2^2 * T2 S2^2 (d^2 V2/ dS2^2) + r2 * T2 S2 dV2 / dS2 - r2 * T2 V2 = 0

These are now solvable using the batching of the backward solver (tff.math.pde.fd_solvers.solve_backward as in the example you referred to) by setting the coefficients of the PDE appropriately. You can see that this corresponds to rescaling the volatilities by (sigma_i -> sigma_i * Sqrt(T_i)) and the rates by (r_i -> r_i * T). You impose the boundary conditions at time = 1.

This logic can be generalized to more than two options.

I think it will be valuable to wrap this procedure (i.e. the rescaling) for pricing a batch of American options with varying expiries as a function in the library (perhaps, under tff.black_scholes.american_option).

Thanks for bringing this up! It would be great if you could send a PR with your example when you are ready.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants