Welcome to THETAWIKI. If you like to create or edit a page please make sure to login or register an account. All registered users please make sure to provide a valid email address.

Tips and Tricks

From ThetaWiki
Jump to: navigation, search

ThetaML Tips and Tricks

When working with ThetaML, there are various techniques which can be used to improve the speed and accuracy of Monte-Carlo simulations with ThetaML models. This section explains the most important ones.

Nested ifs improve speed

  • Avoid evaluating conditional functions that returns zero

The most costly operation in pricing options is the evaluation of conditional stochastic functions such as E and Beta. The time complexity of such an operation is at least of order O(n2) with n as the number of Monte-Carlo paths. In many cases, we can selectively reduce the simulated paths to the most relevant ones before doing any computations with the conditional functions E and Beta.

As an example, consider the following if … end block:

 
if E(V_CUR!) <  (K – S)*CUR
  V_CUR = (K – S)*CUR
end

Since we know in advance that E(V_CUR!) must be greater than zero, we restrict the whole computations to those simulation paths where (K – S)*CUR is greater than zero.

 
if 0 < (K – S)*CUR
  if E(V_CUR!)< (K – S)*CUR
    V_CUR = (K – S)*CUR
  end
end

As an example, a selected part of the American Option is shown below.

if E(V)< K*EUR-S
  V= K*EUR-S
end

Since we know in advance that E(V) must be greater than zero, we restrict the whole computation to those simulation paths where K*EUR-S is also greater than zero.

if 0 < K*EUR-S
  if E(V)< K*EUR-S
    V= K*EUR-S
  end
end

Reducing variance by hedging improves convergence

  • The Beta function reduces the variance of simulated option prices thus increases the accuracy of price estimates.

The following two models "American" and "American_hedged" have similar runtimes but the model "American_hedged" returns option values of higher precision as a result of using the Beta function.

model American
% Model American simulates prices for an American put option
  import S     "Stock prices"
  import CUR   "Discount factors"
  import sigma "Volatility"
  import r     "Interest rate"
  import K     "Strike price"
  export P     "Option value"
 
  % current option value
  P = E(V_CUR!)
  % time to maturity of the option
  T = 1
  % n loops, assuming daily exercise interval and
  % 252  trading days in a year
  n = 252*T
  loop n
    % evaluate optimal exercise conditions, compare estimated
    % discounted hold values E(V_CUR!) with discounted
    % intrinsic values, for all Monte-Carlo paths
    if E(V_CUR!) < (K - S)*CUR
      V_CUR = (K - S)*CUR
    end
    % time passing of T/n
    theta T/n
  end
  % at maturity, option payoffs are discounted to time 0
  V_CUR = max(K - S,0)*CUR
end


model American_hedged
% Model American_hedged simulates the optimal hedge of an
% American put option; note that this hedge is variance
% optimal for any underlying process S
  import S     "Stock prices"
  import CUR   "Discount factors"
  import sigma "Volatility"
  import r     "Interest rate"
  import K     "Strike price"
  export P     "Option value"
 
  % current option value
  P = E(Pi_CUR!)
  % time to maturity
  T = 1
  %n loops
  n = 250*T
  loop n
    % hedge the discounted portfolio Pi_CUR using Beta function
    Pi_CUR = Pi_CUR! – Beta(S!*CUR!,Pi_CUR)*(S!*CUR! - S*CUR)
    % evaluate optimal exercise conditions, compare estimated
    % discounted hold values E(Pi_CUR!) with discounted
    % intrinsic values, for all Monte-Carlo paths
    if E(Pi_CUR!) < (K – S)*CUR
      Pi_CUR = (K – S)*CUR
    end
    % time passing of T/n
    theta T/n
  end
  % at option maturity, the hedged portfolio has the same value
  % distribution as the discounted option payoffs
  Pi_CUR = V_CUR!
  % at maturity, the option payoff is discounted to time 0
  V_CUR = max(K - S,0)*CUR
end

Adding control variables can improve accuracy

  • using additional information available, we can significantly improve the numerical accuracies of conditional expected values such as E and Beta

In the model "European_S_control", the underlying S is simulated with no drift, as such we can use its price at time 0 as an estimate of its expected value at time 1. We can then use this knowledge to compute a better estimate P for the expected value of V_CUR as follows:

model European_S_control
% Pricing a European put option with S as control variable 
  import S   "Stock prices"
  import CUR "Discount factors"
  import K   "Option strike price"
  export P   "Option price"
 
  % use S as control variable for better price estimates P
  P = V_CUR! -Beta(S_control!,V_CUR!) * (S_control! - S)
 
  % 1 time unit passes
  theta 1
 
  % S_control has expected value S  
  S_control = S
  % at maturity, the option payoff is discounted to time 0
  % S is already discounted since it is simulated with no drift
  V_CUR = max(K*CUR - S,0)
end


We can even go a little further and include other knowledge like the closed-form solution of a European option price ('myBlsprice') and use it to estimate an American option price:

% Pricing an American put option with a European put option as 
% control variable
model American_Vcontrol
  import S    "Stock prices"
  import CUR   "Discount factors"
  import K     "Option strike price"
  import sigma "Volatility"
  import r     "Risk-free rate"
  export P     "Option price"
 
  % use European option V_control as control variable 
  % V_control has expected value V_ref  
  P = V_CUR! -Beta(V_control,V_CUR) * (V_control! - V_ref!)
  % V_ref is computed using the closed form formula for the 
  % European put option; the function arguments for myBlsprice 
  % are respectively: stock price, strike price, volatility,  
  % interest rate, option maturity, and option type ‘call’;
  % the option price V_ref is discounted to time 0 by CUR, this
  % is to be consistent with its simulated counterpart V_control 
  V_ref = myBlsprice(S, K, sigma, r, 1, 0)*CUR
  %loop 52 times
  loop 52
    % time passing of one week
    theta 1/52
    % early exercise evaluation: compare the expected discounted
    % hold values E(V_CUR!) with discounted option intrinsic 
    % values, for all the Monte-Carlo simulation paths
    if E(V_CUR!) < (K - S)*CUR
      V_CUR = (K - S)*CUR
    end
  end
  % at maturity 1, the control variable V_control has the same 
  % discounted payoffs as the American put option V_CUR
  V_control = V_CUR!  
  % at maturity 1, the payoff is discounted to time 0
  V_CUR = max(K - S,0)*CUR
end

Hint: myBlsprice() can be found at Black-Scholes Option Pricing


Avoiding direct assignment of expected values improves accuracy

  • We can improve the accuracy of option price estimates by avoiding direct assignments of the expected values from functions E and Beta

The expected value function E generates approximation errors and should only be used when a (statistical) expected value is required. For example, in a compound option, it advisable not to use the E function for both decisional and computational steps:

model compound
  ...
  theta 1
  %time 1 outer option payoffs, E(V_inner) is the expected value
  %of the inner option conditional on time 1 information
  V = max( E(V_inner!)- K, 0 )
 
  theta 1
  %time 2 inner option payoffs
  V_inner = max(S - K_inner,0)
 
end


Instead, the decisional and computational parts should be separated as follows:

model compound
  ...
 
  theta 1
  % at time 1, evaluate the outer option payoffs
  % E(V_inner!) is the expected value of the inner option,
  % conditional on time 1 information
  if E(V_inner!) - K > 0
    V = V_inner! - K
  else
    V = 0
  end
 
  theta 1
  % at time 2, inner option payoffs
  V_inner = max(S - K_inner,0)
end

Keep export variables unique

  • Export variables serve to report (return) results of a model. If they are also used to store temporary results, the exported results will get clogged. This situation can be avoided by keeping assignments to export variables unique.

In the following code, the first instance of x is a temporary result that gets incorrectly reported:

model test
  export x     % results of x get clogged
  ...
  x = x/(n-1)  % x has the temporary results
  x = x + S/n
  ...
end

Storing the intermediate results in a temporary variable keeps the reporting of x unique:

x_tmp = x            % store x in a temporary variable x_tmp
x_tmp = x_tmp/(n-1)  % doing computations with x_tmp
x_tmp = x_tmp + S/n  % doing computations with x_tmp
x = x_tmp            % assign x_tmp to x and report x


Stochastic Processes

Increase accuracy by using sub-steps in an Euler discretization

The Euler discretization scheme of a stochastic process usually requires small time steps in order to achieve accurate numerical results. Using ThetaSuite Analyzer with simple time-stepping might be too coarse. However, this can be avoided by using sub-steps similar to the following ones shown in Theta.m:

function state = Theta(dt, state)
  if nargin == 0
    :
    state.r.comment = "Stochastic variable";
    :
  else
    :
    max_dt = 0.1;
    % Sample Euler steps with higher frequency if "dt" is too big
    for i = 1 : floor(dt/max_dt)
      state.r= ...
    end
    % compute remaining time for last step
    dt_rest = max(0, dt-max_dt*floor(dt/max_dt));
    state.r= ...
    :
  end
end