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.

ThetaML Language Reference

From ThetaWiki
Jump to: navigation, search

Contents

ThetaML

The design principle of ThetaML (Theta Modeling Language) as a programming language is to make the task of pricing financial instruments simple, manageable yet powerful. ThetaML offers function operators for easy time stepping in simulation models, forward access to simulated values at a subsequent model time and simultaneously handling multiple asset processes. ThetaML also provides built-in functions for risk-neutral option valuations and computing optimal hedge ratios.

Thetawiki provides a library of ThetaML code examples, a selection of them are listed below:

  • GARCH volatility prediction model: captures the fat-tailed and volatility clustering features of financial time series.
  • Heston Volatility model: allows the stock price variance to follow a CIR type diffusion process.
  • Vasicek model: assumes that spot interest rates are mean-reverting and have one source of additive risks.
  • CIR model: assumes that spot interest rates are mean-reverting and have volatilities scaled with the square-root of spot rates.
  • Hull-White model: enables perfect fittings to the initial interest rates and interest rate volatility term structure.
  • Jump Diffusion model: assumes that the underlying asset exhibits jumps in addition to having continuous diffusion paths.
  • Geometric Brownian Motion: assumes that the relative changes of stock prices have constant mean and constant volatility.
  • Convertible Bond: is a type of bond that can be converted into a specified number of shares of stock in the issuing company or cash of equal value.
  • Asian Option: pays the difference between the strike and the average of the underlying prices observed during some specific dates.
  • Basket Option: is an option on a portfolio of underlyings whose payoffs depend on the average performance of the underlyings or on the performance of the best asset.
  • Look Back Option: gives the owner the right to buy the underlying security at the lowest (or highest) price of the underlying observed during the option's lifetime.
  • CDO: is a type of asset-backed security or structured finance product. In a CDO, a portfolio of bonds, loans or other fixed income securities is gathered and used to create a new set of fixed-income securities.
  • CPPI: a CPPI strategy chooses the number of stocks such that the portfolio value never drops below the bond floor.
  • Moving Window Asian Option: pays the difference between the current stock price and a moving average of the stock prices.


ThetaML Language Foundation and Overview

Payoff Description Language and Operator-based Modeling – ThetaML and Theta Calculus


ThetaML is a Payoff Description Language introduced by Thetaris GmbH. ThetaML [1] is built on the concept of Theta calculus. Theta calculus is a mathematical notation for stochastic and sequential processes, first introduced by Dr. Dirnstorfer [2], [3], [4]. It provides a solid mathematical basis for modeling and describing financial contracts in the form of an operator sequence that can be transformed into the contract (term sheet) description language ThetaML.

Theta calculus provides the following objects to mathematically represent the typical patterns of financial instruments:

1) The economic state $ X(t) = (t, \ B(t), \ S(t), \ r(t)) $ describes the current state at time $ t $. It contains all time dependent information, including such market parameters as the bank account $ B(t) $, the stock prices $ S(t) $, the interest rates $ r(t) $, and other relevant parameters.

2) The valuation function $ V: \mathbb{R}^n \rightarrow \mathbb{R}^m $ evaluates the function $ V( X(t) ) $ for the current economic state $ X(t) $.

3) Operators are applied to an evaluated state $ V( X(t) ) $. There are operators for waiting, transacting and deciding. The most important operator is the waiting operator $ \Theta $ that allows time to pass.

ThetaML programming language makes operational semantics available in the form of a set of operators that can be combined and that are compositional. The compositional operator concept means that every action corresponds to an operator and a sequence of operators models a financial product. Because of this, ThetaML permits a short and precise representation of financial products. It is simple, powerful, and flexible. It offers the benefit to specify the complete structure of a financial product independently of the underlying stochastic processes.

ThetaML programming language has operators for three elementary effects: waiting, transacting, and deciding.

  • Waiting is modeled with the Theta (or equivalently theta) command which implements the $ \Theta $ operator of Theta calculus. The Theta command lets time pass and describes the time-determined behavior of financial instruments.
  • Transacting operations are assignments of state variables and are represented with an equal sign.
  • Deciding: the decision operator is modeled with an if statement in ThetaML.

ThetaML programming language has five unique function operators:

  • theta: the theta command allows the time from the initiation to the termination of a financial contract to pass, it is the essential operator supporting the virtual timing model in ThetaML.
  • future access operator !: The future access operator ! allows forward access to the simulated values of a variable at a future contract time, this operation is based on forward algorithms. The future operator "!" is especially useful in Least Squares Monte Carlo simulations of early exercise decisions where the risk-neutral expectations of future option values (the ThetaML E function) have to be computed in advance.
  • fork: The fork command makes it possible to model simultaneous stochastic processes and enables cross-dependencies among the variables.
  • E( ): the function E() computes the risk-neutral expectation of a process variable, conditional on all parameter values that are known at the corresponding time in a stochastic model. The algorithm behind the E() function is based on the numerical technique - Sparse Grid.
  • Beta( ): the Beta() function computes an optimal hedge ratio from its two arguments, conditional on the parameter values known at current time in a stochastic model.

ThetaML has two handy system parameters:

  • @dt: the @dt parameter is a time interval parameter. It evaluates to the time interval of the next time step. Combined with the theta command, theta @dt means a time step of length @dt has just passed.
  • @time: the @time parameter gives the current time in a stochastic model. It is the sum of all previous theta @dt time steps.

ThetaML provides transparent access to the functions in Matlab. It can call Matlab functions by directly calling the function names, such as randn(), max(), sqrt(). On top of this, ThetaML supports standard control structures such as loops and if statements, array dimensioning, calling submodels and so on.


ThetaML Language Features

ThetaML is a domain-specific Payoff Description Language, with a procedural extension for time stepping. ThetaML explicitly incorporates the passage of time in a stochastic process. Path dependencies, settlements, reinvestments and early exercise features present in a financial contract are all appropriately addressed.

Its main features are:

  • Domain specific language for financial contract design:

As a programming language, ThetaML describes and models the structural features of stochastic models in financial engineering. It has built-in functions and operators for pricing financial derivatives, selecting optimal hedging strategies and evaluating portfolio risks.

  • Programming in chronological order and computational order:

ThetaML follows the time order in which the events of a pricing model are (expected) to occur. It progresses forward. This avoids significant code reorderings required for pricing derivative products using programming languages like C/C++.

  • Built-in functions for risk-neutral valuations:

ThetaML adroitly handles the risk-neutral valuation principle of financial derivatives. It evaluates the risk-neutral expectations of stochastic processes using the E() function. The E() function is based on the high-dimensional adaptive interpolation technique - Sparse Grid.

  • Implicit handling of scenario- and time- indices:

Variables defined in ThetaML represent a stochastic process. They do not require explicit scenario- or time- indices. This feature avoids any index confusions or errors in languages that require explicit array indexing.

  • Virtual multi-threading:

ThetaML allows multiple simulation tasks to be executed in parallel at any time in a stochastic model. This feature is convenient for simulation pricings or repricings of large investment portfolios across different asset classes.

  • Pre- and post-conditions on models to ensure model correctness:

ThetaML Interfaces ensures that certain parameter or process values are within the range of user-defined constraints.


The Virtual Timing Model

ThetaML operates on the virtual timing model. This is an essential feature of ThetaML.

In a virtual timing model, the simulation tasks are virtually paralleled and synchronized. The model time combines all the event times occurred in the simulation tasks and it is shared by all the simulation tasks just like sharing the same time axis. Time passes along the model time axis from contract initiation to contract termination.

ThetaML allows the programmer to insert time delays between code statements at two different time in a stochastic model using the theta command. The values of all variables present at a given line of code are evaluated at the same model time associated with that line of code.

Different blocks of codes executed simultaneously have a common model time axis. The model time grid is a collection of all the event times occurred in multiple simulation tasks; different simulation tasks may have different events occurring at different time. Within multiple simulation tasks, variables can be cross-accessed and all variable values at that line of code are evaluated at the model time executed at that line of code.

The virtual timing model of ThetaML makes the task of pricing financial derivatives easier. Since financial derivative contracts typically have sequential time-triggered events, such as scheduled payments, early-exercise times, etc., ThetaML can simulate this type of multiple-event sequential-time processes. The ability to execute multiple code elements in parallel allows the users to model cross-dependent financial products or variables. An option on a bond can be simulated in a way such that both processes - the option and its underlying bond - evolve as what they would evolve in real-time financial markets.

ThetaML Syntax

Defining a Model

A model is the equivalent of a function or a subroutine.

A model is defined by the model keyword followed by the model name, the model body is terminated with the keyword end.

An empty model would be formulated as follows

model test
 
end


Importing and exporting variables

Models communicate variables by importing and exporting values, similar to passing and returning a value by a function in other programming languages. Imported values are either specified by the user at the beginning of a model, or specified by other models that call this model as a subroutine. Exported parameters must be assigned a value within the body of the model.

An import or export statement can be followed by an optional description string (similar to a comment) of the variable. The description for imported variables shows up in the Theta Suite configuration page used to run the model and the description for exported variables shows up in the Theta Suite Result Explorer.

Examples of import and export statements are

import x
import a,b,c
import x     "A description for x"
export y
export a,b,c
export y     "A description for y"

This is a complete model that imports a variable x and exports the squared value as variable y:

model example
  import x
  export y
 
  y = x^2
end


Comments

Comments in ThetaML are initiated with the character %, everything after a % is ignored until the end of the line.

Example of a comment:

model commented
% this
% is
% a comment
 
end


Assignments

Assignments are done using the = operator, e.g.

x = 42
x = 7 * 9
y = 2 + x


theta

The theta command is a crucial statement in ThetaML.

This command defines the virtual timing model. Every theta command is followed by a statement defining a time interval. The virtual model time synchronizes multiple threads that occur parallel in virtual time. The virtual timing model also allows synchronizations with external numerical routines when called to compute certain model parameters.

The example below illustrates how the virtual timing model works.

model A and model B are run simultaneously.

In model B the variable S is modified: S is assigned a value of 1 at time 0, and a value of 2 after a time step of length 1. The model time for S runs as follows:

  • from time 0 up to time 1 (0 included, 1 excluded): S = 1
  • from time 1 onward (1 included): S = 2

The variable S is then exported by model B and used in model A.

The virtual timing model synchronizes the three processes X, Y and S.

In model A, the variables X and Y share the same model time axis as the variable S. The variables X is assigned the value of S at time 0.5 which is 1, this gives X = 1. The variable Y is assigned the value of S at time 2 which is 2, this gives Y = 2.

The model time grid combines all the event time occurred in the three process, it now has the following event time:

  • time 0: S is assigned a value of 1
  • time 0.5: X is assigned the value of S, which evaluates to X = 1
  • time 1: S is assigned a value of 2
  • time 2: Y is assigned the value of S, which evaluates to Y = 2
  • time 2 onward: S = 2, X = 1, Y = 2 until further value assignments take place
model A
  import S
  export X
  export Y
 
  theta 0.5
  x = S      % at time 0.5
  theta 1.5
  Y = S      % at time 2
end
model B
  export S
 
  S = 1      % at time 0
  theta 1
  S = 2      % at time 1
end


fork

The theta statement requires multiple threads to be executed in parallel.

With the fork statement, portions of code are executed in parallel in the timing model. Note that this does not necessarily imply parallel computation on your computing system. A fork block begins with fork and is terminated by an end statement. Statements between these two tokens occur in parallel.

The following example shows two fork blocks. The first block sets a = 0 at time 0 and a = 5 at time 2. The values of a and the model time of a is as follows:

  • time 0: a = 0
  • from time 0 to time 2 (0 excluded, 2 excluded): a = 0
  • time 2 and time 2 onward: a = 5

The second block proceeds to time 1 and copies the current value of a to x, which gives x = 0. After another time step of 2 (at time 3) the value of a is copied to x again and x = 5.

The model time now has the following event time:

  • time 0: a = 0
  • time 1: x = a which evaluates to x = 0
  • time 2: a = 5
  • time 3: x = a which evaluates to x = 5
fork
  a = 0    % time 0
  theta 2
  a = 5    % time 2
end
 
fork
  theta 1
  x = a     % time 1, result: x = 0
  theta 2
  x = a     % time 3, result: x = 5
end

In case multiple write operations occur in the same timing model, the original order of the statements is used. The value assigned later overwrites the previous value(s). The following example assigns two different values to variable a. A third thread would only see the value assigned by the second thread.

% the first thread
fork
  theta 1
  a = 1      % time 1
end
% the second thread
fork
  theta 1
  a = a + 1  % time 1, a = 2, it overwrites 'a = 1' in the first thread
end
% the third thread
theta 1
x = a        % time 1, result: x = 2


if...else...end

As with most programming languages, ThetaML allows for conditional execution. This is done using if...else...end blocks. The following examples assign a value to the variable x under the if conditions:

if a > 1 | b < 10
  x = 1
end
if a > 1 | b < 10
  x = 1
else
  x = 2
end


loop

Repeated execution can be achieved using the loop command. The loop statement requires a length parameter which must be set at compile time. The length parameter defines different types of loops:

  • An integer: loop a finite number of times
  • The keyword inf: the loop runs as long as the model is run
  • An array: the loop will iterate over the elements in an array.

A loop block is terminated by an end statement.

Fixed length loop

Fixed length loops are defined by a loop command followed by the number of iterations. The formula is evaluated at the start of the loop.

The following example does a loop five times. After the loop, the final value of x is 10.

x = 5
loop x
  x = x + 1
end


Infinite length loop

Using the keyword inf as the loop length causes the loop to run until all threads with fixed length have stopped looping. This is useful when writing subroutines that compute a time series of arbitrary length or in the case of a financial contract with a finite lifetime the inf loop automatically extends to the length required.

x = 0
loop inf
  x = x + 1
  theta 1   % time passes by 1 time step/unit
end


Array looping

Loops can be used to iterate over arrays, much like the for ... each statement in many other programming languages. Loops over arrays repeat the loop body once for every component of an array. For loops over arrays, the loop statement is followed by a variable that serves as an iterator for each array component, a colon ":" and the array to be processed. The iterator points directly to the array element, meaning that operations on the iterator are in fact operations on the corresponding element of the array.

The following example cycles over the components of the variable A and squares each of its component.

A = [1, 2, 3, 4]
loop a : A   % a is an array iterator
  a = a^2
end
% result: A = [1, 4, 9, 16]


Multiple array looping

Loops can cycle over multiple arrays simultaneously, given the arrays are of the same length. An iterator is defined for each array so that at the n-th cycle of the loop each iterator points to the n-th element of its corresponding array. It is further possible to additionally iterate over a previously undefined array, in which case the array size is determined by the sizes of the arrays it is being cycled with. This allows one to build an array on the fly.

The following example illustrates this. The loop cycles though arrays A and B which are both of size 4. The variable X is previously undefined and is automatically determined to be an array of the same length as A and B 4. Its values are set in the loop body.

A = [1, 2, 3, 4]   % array A has 4 elements
B = [1, 2, 2, 2]   % array B has 4 elements
loop a, b, x : A, B, X   % array X is built on the fly
  x = a + b
end
% result: X = [2, 4, 5, 6]

This loop could equivalently be replaced by the statement X = A + B.

Calling a submodel

Models can be called from the Theta Suite user interface where the user is prompted for required import parameters, or with a call statement in a ThetaML model. In the second case, the submodel must be supplied with all the parameters specified by the import statements in the submodel. Variables exported by the submodel can optionally be imported by the calling model. All parameters are passed by reference. Hence not only static values but also processes whose values change in time can be passed to submodels.

Input and returned variables in submodels are passed after the export and import statement, respectively. If the variables passed have different names from the submodel arguments, they can be renamed (aliased) by specifying a new name after a to or from statement.

The following examples shows how to call submodels in ThetaML. The submodels are named sub_model. In the first call, the submodel reads the variables a, b and c exported from the local variables a, b and returns the variables x and y imported from its exported variables, and creates a variable c to hold the values of x + y.

% the sub_model is called by another model
call sub_model
  export a, b   % export the local variables a, b to the import variables a, b specified in sub_model
  export a + b to c   % export a + b to the import variable c specified in sub_model
  import x, y   % import x, y from the export variables x, y specified in sub_model
  import z from x + y  % import in the variable z the values of x + y


Example for calling a submodel

Assume we now wish to call a sub_model from some outside context.

The following submodel imports the variable x as a step size, uses it to increase a process with initial value of 0 and returns the result in variable y after every unit and for an arbitrary length of time defined by loop inf.

model sub_model
  import x  "step size"
  export y  "result"
 
  y = 0
  loop inf    % loop an arbitrary length of time
    y = y + x
    theta 1   % step forward 1 time unit
  end
end

We can now call this submodel. In the call, we export the variable x with a value of 1 to the variable x in the sub_model and read the result back in variable y by importing from the variable y in the sub_model.

% calling the submodel
x = 1
call sub_model
  export x
  import y
 
% result: y ~ 0 - 1 - 2 - 3 -....

We can equivalently call the submodel by specifying the initial value of x and reading the result back in a variable A as follows:

call sub_model
  export 1 to x
  import A from y
 
% result: A ~ 0 - 1 - 2 - 3 - ....

A third and final example shows the power of passing processes instead of values. We can call our submodel once to first create a time-series equal to y in either of the previous two examples and thereafter chain this process as an input variable for the step size of a second process.

% in the first call, we create a time series y
call sub_model
  export 1 to x
  import y
% in the second call, we pass the process y and create another process named A
call sub_model
  export y to x
  import A from y
 
% result: A ~ 0 - 1 - 3 - 6 - 10 - 15 - ....


Calling a Matlab function

Any Matlab function can be directly called by typing its function name. Note that only one variable can be returned and all values have to be elements of vectors or matrices.

% calls MATLAB function "randn()"
y = randn(100)
% calls MATLAB function "exp()"
t = 10
y = 100*exp(-0.05*t)

You can also call user defined m-files as long as they are located within the Matlab path.


Operators

Future access operator !

A unique feature of ThetaML is the ability to access the values of a variable at a subsequent model time. Most programming languages can only access a value that was previously assigned to a variable. Since ThetaML compiler does not have to evaluate the code sequentially, future values of a variable can also be accessed. Future access to a variable is made meaningful due to the virtual timing model in ThetaML.

Future access is achieved using the future access operator -- the exclamation mark (!). Circular definitions are not allowed.

The following example assigns the next value of y to x. Any command that changes the value of y also changes the value of x.

x = y!     % y is future-referenced with the future access operator !, result: x = 3
...
y = 3      % the next value of y is 3

In some cases, no single instance can be found to determine a future-referenced variable. The value of the reference is then determined as if the program had been run in reverse command order.

x = y!      % y is future-referenced with !, result: x = 0 if a > 1, x = 2 otherwise
if a > 1
  y = 0     % the next value of y is 0, if a > 1
end
y = 2       % the next value of y is 2, if a > 1 is false

A special case occurs when a future-referenced variable is conditionally evaluated (inside the if-statements). Future references only consider assignments after the conditional execution is completed, i.e., after the end-statement. This avoids cyclic definitions of variables in some cases.

x = y!       % result: x = 0
if y! > 1    % y! = 2, the next value of y after the if ... end statement is given to y!
  y = 0
end
y = 2        % the next value of y is 2
 
% the evaluation sequence is as follows:
% 1) y = 2 in the last line
% 2) y! = 2 in the if statement, and if y! > 1 evaluates to be true
% 3) y = 0 inside the if ... end block is executed
% 4) in the first line, y! = 0, and the result is x = 0

Further properties of the future access operator ! are listed below:

a!!      ==  a!
(a + b)! ==  a! + b!
f(a)!    ==  f(a!)
a[i]!    ==  a![i]  (not a![i!])
 
E(a)       == E(a!)
Beta(a, b) == Beta(a!, b!)


Array access []

Array elements in ThetaML can be accessed with the C-style square brackets after the variable name. Unlike C however, array indexing starts at 1.

A = [1, 2, 3, 4]
x = A[1] + A[3]   % x = 1 + 3 = 4


Functions

Stochastic functions

ThetaML can evaluate conditional statistical properties of variables using numerical techniques such as Sparse Grid. The results are conditional on all parameters that are known at the corresponding model time. The arguments of stochastic functions can have access to future values, i.e., have access to values assigned at a subsequent model time.

E

The function E computes the conditional expected value of a variable or an expression. The E function is a built-in ThetaML function and is computed based on the Sparse Grid technique.

The E function is most useful in computing the conditional risk-neutral expected American option values in Least Squares Monte Carlo simulations. It is also commonly used in computing the statistical mean of a give price distribution.

This example shows how to compute conditional expectations using the E function. It returns the variable x as the expected value of y = S * EUR at time 10, conditioned on all information that is known at time 5.

theta 5
x = E(y!)     % at time 5, the mean price of y! is computed and assigned to x
theta 5
y = S * EUR   % at time 10, y is assigned the values of S * EUR, the result could be a single value
              % or a price distribution, depending on how the variables S and EUR are defined

The future operator ! in the code above can be omitted per definition of the E function:

E(y!) == E(y)


Beta

The Beta function takes two arguments and computes the beta factor(s) between these two arguments, conditional on the current information. The first argument as the explanatory variable(s) can have multiple dimensions in which case the Beta() function computes a beta factor for each component of that array. The second argument is the dependent variable for the conditional regression.

The Beta function is most useful in computing static or dynamic hedging ratios and in computing beta factors in factor model regressions.

The tutorial Hedging in ThetaML provides examples for using the Beta function in static and dynamic hedging of derivatives contracts.

Other functions

length

The length of an array can be determined using the length function.

A = [1, 1, 1, 1]
l = length(A)   % result: l = 4


System parameters

System parameters are compile-time parameters that can be extracted with an at sign (@) followed by one of the following keywords.

@dt

The time interval parameter @dt has different values depending on its context.

If @dt is found as the argument of the theta command, it evaluates to the time interval of the next time step. In case @dt is located elsewhere, it evaluates to the time elapsed since the thread's previous invocation of the theta command.

This example computes a Brownian process for all time steps and the time horizon lasts as long as needed for a simulation task, i.e. it runs until all other fixed-length loops sharing the same model time axis stop running. Here @dt is an argument to theta.

model BrownianMotion
  export W  "Browian process"
 
  W = 0
  loop inf
    theta @dt
    W = W + sqrt(@dt) * randn()
  end
end

@time

This variable provides the current model time. It is the sum of all previous theta time steps.

The following is an example that uses the @time parameter to compute a discount factor process:

model DiscountFactor
  % This model computes a discount factor in two ways
  import r   "Risk-free interest rate"
  export Discount_1   "Discount factor process 1"
  export Discount_2   "Discount factor process 2"
 
  Discount_1 = 1   % at time 0, initialize Discount_1 at 1
  Discount_2 = 1   % at time 0, initialize Discount_2 at 1
  loop inf         % infinite loop
    theta @dt      % theta time passing at @dt time interval
    % update Discount_1 for the time interval @dt
    Discount_1 = Discount_1 * exp( -r * @dt )
    % update Discount_2 for the time that has passed since
    % time 0, this is summed by @time
    Discount_2 = exp( -r * @time )
  end
end


Matlab Backend

Models defined in ThetaML can call Matlab processes via the Theta command.

It returns a state variable that contains fields readable by the ThetaML model. Note that Matlab cannot read variables defined in ThetaML.

The communication with the Theta command has two distinct phases. First, there is an initialization phase where the Theta command is called without arguments and returns the state variables initialized. Afterwards, the Theta process uses Matlab functions to propagate the state for a time step dt. It is thus only possible to define Markov processes, albeit with an arbitrary state space.

The descriptor returned by the Theta command must be a structure with entries for each variable. Each entry is itself another structure that must contain the following fields:

  • comment: A short decription
  • value: An initial value
  • dim: The array dimension for the initial value, if not provided, a default of 1 is assumed


function state = Theta(dt, state)
 
if nargin == 0
  state.S.comment = 'Stock price';
  state.S.value = 100;
  state.EUR.comment = 'Numeraire';
  state.EUR.value = 1;
else
  r = 0.05;
  mu = r;
  sigma = 0.4;
  state.S   = state.S .* exp( (mu-0.5*sigma^2) * dt + sqrt(dt) * sigma * randn(size(state.S)));
  state.EUR = state.EUR * exp(-r * dt);
end
 
end


The ThetaML type system

On the surface ThetaML looks like an untyped language. All variables can have different types without the need to explicitly declare their type. Internally however, ThetaML is strictly typed. Once the code is analysed and its execution sequence is optimized all variable types are fixed. Although the ThetaML compiler implements sophisticated type extraction algorithms, it sometimes fails to derive the desired variables types.

Generally speaking, there are two different reasons to help the ThetaML type extraction. One applies to import variables. Its main purpose is the definition of input types, that allows custom widgets to show up in the configuration page. The second application of manual type definitions occurs in the context of external models and functions. Because, these models are defined outside the ThetaML language, their types can not be derived automatically. By default, one scalar or one scalar per Monte-Carlo path is assumed as the return type for all external functions.

The Boolean type

Boolean types automatically render a check box in the configuration page. A variable can be declared boolean with the type statement after the variable definition.

model importsABoolean
  import B  "Yes or No"
  type B Boolean
end

A variable is implicitly assumed boolean, if it is used in an if statement.

model importBooleans
  import a,b,c,d   "All booleans"
  if a && (b || c)
    % do something
  end
  if d
    % something else
  end
end

The file type

Files are internally treated like strings, but they behave differently in two ways. First the configuration page shows file chooser buttons, that allow the selection of a file's location, rather than entering it as text. Secondly, file strings can contain paths that are relative to the Theta Suite workspace. Whenever, a file location is passed to an external model or an external function, this file string is automatically converted to an absolute file path.

There are to types of files. For normal files, a file chooser is generated that only shows existing files. The second type, output files, also allows the selection of nonexistent files. The output file type can only be used within the context of external models, because ThetaML itself does not provide any language features for writing files to a file system.

model fileInAndOut
  import fileIn
  import fileOut
  type fileIn file
  type fileOut outputFile
  call @matlab : fileManipulatingModel
  export fileIn, fileOut
end

The Enum type

Some models only allow a limited number of possible input values. For these cases it often desired to generate a selection box in the configuration page. Users of the model are thereby unable to manually enter incorrect values. They can only choose from a list of present values.

Enum types can be implicitly created in the model orchestration mode in the Theta Suite. Inserting a Switch with a list of named cases, internally creates an enum type with each case name as a possible value.

Enum types can also be explicitly created with the type statement. The options are given as a list of possible values.

model someChoices
  import x  "This variable can be 1,2,3, or 3.141"
  type x Enum [1, 2, 3, 3.141]
  % something
end

Enumerations can be contradicting if an imported variable is exported to different submodels. Although it will be possible to select values in the configurator that are not valid for all submodels, these selections will be considered invalid. In the Theta Suite, an error marker is shown. On the console the compiler will refuse to run that model.

Array types

In ThetaML it is of essential importance, that array lengths are known at compile time. Therefore the array length is always part of the variable type. Hence, array lengths must be fully determined and can not change during model execution. Normally, array length are implicitly determined by the use of corresponding variable accesses or definitions. These statements all specify the variable x to be an array of at least length 4.

a = 1 + x[4]
x[4] = 4
x = [1,2,3,4]

Array types can also be explicitly defined with the type statement. Arrays of numbers must be specified with float as a base type, followed by the array dimension in brackets.

model xHasLengthFour
  export x
  type x float[4]
  x = 3   % array with 4 elements, all set to 3
end


ThetaML Interfaces

ThetaML offers a very compact notation for sophisticated financial models. However, some of the ThetaML language features can be inappropriate for certain model sections. For example the future access operator ! allows effective modelling of optimal exercise decisions, but its use in other contexts may not be appropriate.

ThetaML introduces interfaces to ensure a consistent functionality within the constraints of rational financial modelling. Interfaces can be applied to a ThetaML model. If the model does not comply to the constraints defined by the interface the model can not be executed. Thereby, a model review can rely on the presence of certain interfaces, without the need to check each submodel for inappropriate use of ThetaML language features.

Interface syntax

The interface is defined similar to a model, starting with the interface keyword. The interface contains sections for obligatory variables, constraints for inputs and language features.

interface exampleFace
  % constraints
end

A model that complies to the interface must implement it with the implements keyword.

model compliantModel implements exampleFace
  % model content
end

Interfaces can also be extended with additional constraints. Again the implements keyword is used.

interface stricterFace implements exampleFace
  % additional constraints
end

Imports and Exports

ThetaML interfaces optionally contain variable imports and exports. These variable must be imported and exported by every implementing model. The interface can thereby guarantee the presence of certain variables. Accidental renaming of central variables can thereby be avoided. Furthermore, variables in the interface can be provided with a default comment for the implementing models.

interface mustExportS
  export S   "The stock price of XXX"
end

Language constraints

Language constraints can be applied for models, including all submodels. A language constraint does apply to the model itself and all models called. If a model with a language constraint calls another model which uses that language feature but does not itself implement that constraint, an error marker is shown for the call operation. No error is shown for the called model.

The following language constraints can be applied to ThetaML. All constraints are case insensitive.

  • @notheta: This model can not pass model time. All computations must be done based on the present value of state variables. There can not be any process dependency.
  • @noBackward: No use of the ! operator. The variable access in reverse execution order is forbidden.
  • @noRegression: The use of expected values E and betas Beta. Because these operators have an implicit access to future variable values @noRegression, this constraint is automatically active if @noBackward is specified.
  • @noExternalFunction: The call to external functions, such as those defined in Matlab, is forbidden. All functionality must be defined the ThetaML. This constraints ensures portability of the ThetaML model to other backends.
  • @noExternalModels: Calls to external models are forbidden. This constraint is automatically active, if @noExternalFunction is active. Models are invoked with the call @backend:ModelName. Unlike functions, models can also import and export time dependent processes.
  • @noInfLoop: The use of loop inf is restricted. The infinite loop construct allows the creation of stochastic processes, that are automatically simulated as long as needed. The use of this construct is inappropriate in product or contract models that have finite lifetimes.
  • @noFork: Forbids the fork keyword. It is important to point out, that calls to sub models implicitly create a fork. i.e., the model bodies are executed virtually parallel in model time. Calls clearly separate variable spaces and are hence easier to handle than forks. Forks are helpful for small and experimental models, but should not be used in complex projects.

An example for an interface activating all available constraints can look like this:

interface constrainAll
  @notheta
  @noExternalFunction
  @noBackward
  @noExternalModule
  @noFork
  @noinfloop
end

Value assertions

Another type of constraints can apply to input parameters. These constraints do not concern the ThetaML model, but the input parameters defined in the configuration page. Hence, if any of these assertions are violated, the errors are shown in the configuration and never in the model.

Value assertions are specified in the interface with the assert statement. An assertions has two arguments. The first is a boolean expression, that evaluates, whether the constraint is valid. The second optional argument is a human readable error message that is shown in the configuration page if the assertion fails.

An example for an assertion in a ThetaML interface looks like this:

interface assertRanges
  import sigma, rho
 
  assert(sigma > 0, "Sigma must be positive")
  assert(rho >= -1 && rho <= 1, "Correlation must be between -1 and 1")
end

Value assertions are ensured twice, at input time and at run time. Input time validation can only perform validations directly on imported variables, or variables that are passed to sub models via an export. Run time validations assert variable values at run time for import and export variables. For path dependent variables the assertion must be true on each path. However, run time validations do not validate values that are never used during model execution.

Known limitation

The following model does not show an error marker:

model no_error_shown
  export x
 
  call sub
    export @matlab:sin(2) to dummy
    import x
end
interface iface
  import dummy
  assert(dummy>5)
end
model sub
  import dummy "not used anywhere"
  export x
  x = 3
end

An error would be shown if,

  • the exported value @matlab:sin(2) was replace with a reference to an imported variable, or a constant, or
  • the dummy variable was used for computation, such as x = 3 + 0*dummy


Functions in ThetaML

This document outlines the use of functions in ThetaML, as introduced with verision 2.4 of Theta Suite.

Defining and using Functions

Defining function

Function can be defined in ThetaML in analogy to the simulation models. In fact, functions are models with a number of restrictions:

  • Functions start with the keyword function followed by its name.
  • The order of imported variables is important. They have to be provided in the same order when calling the function.
  • Functions must not use the commands: theta, fork or !.

The following code shows an example of a definition of function g.

function g
  import x1
  import x2
  export y
  y = (x1 + 0.5 * randn()) / x2
end

Calling functions from ThetaML

There are two ways in which function can be called: inline with parenthesis and explicitly with a call statement.

The function g from the previous section can be called as g(x1, x2). The result of the function is the value of the first exported variable.

The following examples calls function g and for comparison makes a call to a matlab function. For now we assume that the function g is defined in the same file.

model funcall
  import a
  import b
  export c
  c = g(g(a,2), 1) + @matlab:sin(b)
end

A second way of calling a function is using the traditional call statement. In cases where a function exports more than one variable, this is the only way to retrieve all results. Thus, function can be called with parenthesis and be called as if they were models.

model funcall2
  import a
  import b
  export c
  call g
    export a to x1, b to x2
    import c from y
end

Function calls from the configuration

Functions can also be called from the configuration and orchestrated models too. Because there is no space for an import statement all function calls must be done with complete path to the function: @thetafunction:projectname.foldername.file.func( arg1, arg2, ... ) in cases where the defining ThetaML is in the same folder as the calling model relative paths are allowed. @thetafunction:file.func( arg1, arg2, ... )

Compatibility with previous versions of ThetaML

All function calls that are not prefixed with the namespace of a computational subsystem (e.g. @matlab) are assumed to be ThetaML functions. If the function does not exist an error is reported.

In order to keep compatibility with earlier versions all function calls to unspecified functions are still considered as calls to Matlab functions, if the code does not use any of the language features from this and the following sections. Once you start using the new function language feature in existing models, the editor will immediately mark the unspecified functions and require you to explicitly apply the @matlab prefix where appropriate.

Importing functions from other files

Functions that are not part of the same ThetaML file have to be imported before they can be found. The import path follows the usual convention for file references in projects. Additionally, unlike other references to single models, the model name can be replaced with a star "*" to import all functions from a file.

The import statements must be placed at the very beginning of the ThetaML file.

import projectname.foldername.file.funcname

or

import projectname.foldername.file.*

In case the file containing the function definitions is placed in the same folder, the import statement can skip the project and folder names:

import file.funcname
import file.*

Note: The import statement does not only work with functions. It also can be used to import any models that are called from a model or a workflow.

import file.submodel
model ...
....
call submodel
export ....
....

Function variables

Functions can also be assigned to variables. A call to a function stored in a variable then depends on what function was previously assigned. To keep the types of such variables clean a number of steps have to be taken.

Function interfaces

Any function that is to be assigned to a variable must implement an interface. As discussed in the subsequent section the variable must specify that interface and can hold only functions deriving from the same interface.

Interfaces for functions do not differ from interfaces for modules, with the only difference that variable orders are important. Here is an example:

interface iface
  import x1
  import x2
  export y
end

A function implementing that interface must not change the order of these variables.

function myfunc implements iface
  import x1
  import x2
  export y
  y = x1 + x2
end

Now, the function myfunc is prepared for being applied to any variable that is defined to have matching function type.

Function types

Any variable that should hold a variable value is strictly required to be defined as variable of function. Following the definition of variable types they can be defined in a separate line or with an import statement.

Function types are specified with the keyword function followed by a reference to the interface implemented by all functions assignable to this variable.

model somemodel
  import f : function projectname.foldername.file.iface "comment"
  import g : iface "comment"
  type y function projectname.foldername.file.iface
  type z function iface
  ....

Now, function values can be assigned to this variable:

x = @thetafunction:projectname.foldname.file.f2
z = @thetafunction:f2
y = f

Naturally, functions can also be evaluated to a plain value:

value1 = x(1,2)
value2 = y(2,4)
value3 = z(value1, value2)

Partial evaluation

A common concept of functional programming is partial evaluation of functions. Under some circumstances a function with two arguments f( _ , _ ) can be converted into a function with only one argument by fixing one of them, e.g. f( _ , value) or f(value, _ ). ThetaML allows such partial evaluation if the remaining free parameters adhere to the function interface. The examples below shows this in more detail.

Example1: Payoff function

Consider the case where a model requires a function of type iPayoff with one parameter named spot.

interface iPayoff
  import spot
  export value
end

Now consider that you have a payoff function for a call option. The payoff of the call option has one additional parameter named strike. We are allowed to add that parameter, if we partially bind that parameter before assigning it to a function variable, as shown below.

function callPayoff implements iPayoff
  import spot
  import strike
  export value
  value = max(0, spot - strike)
end

Now, you would like to take the callPayoff function and convert it to a function that adheres to the interface iPayoff. In order to do this we need to fix its strike.

We can do partial evaluation with the placeholder "_". The placeholder is inserted wherever a variable remains free.

type f : function iPayoff
f = callPayoff( _ , 100)

Partial evaluation can also provide an alternative way of addressing function values. The following are expressions are equivalent: 1. @thetafunction:callPayoff 2. @thetafunction:callPayoff( _ , _ ) 3. callPayoff( _ , _ )

Example2: Bond valuator

Bond valuator interface

A term structure model typically does not export single valued variables, but functions that can be used to price any bond. We define the interface for a bond evaluation function as iBondValuator.

interface iBondValuator
  import T
  export price
end

The term structure model

A function that implements iBondValuator could for example be the bond valuator for the Ho-Lee interest rate model. The function is a bond valuator implementing iBondValuator, but requires additional parameters.

function HooLeeBondValuator implements iBondValuator
  import T             "Time to Maturity"
  import r             "Current short rate (Brownian Motion)"
  import t             "Time since start"
  import sigma         "Volatility"
  export price
  price = exp(-r*T + t*T^2*sigma^2/2)
end

Now, we define the Ho-Lee model as a model that exports a bond valuator function. The exported function must only take one parameter T as specified, whereas the bond valuator for the Ho-Lee model takes more parameters. Partial evaluation solves this conflict. See the Ho-Lee model below:

model HooLeeModel
  import context
  export BondValuator : function iBondValuator
  r0 = context.esg.r0
  sigma = context.esg.sigma
  fork
  r = r0
    loop inf
      theta @dt
      r = r + sigma * sqrt(@dt) * randn();
    end
  end
  BondValuator = HooLeeBondValuator(_, r, @time, sigma)
end

The bond option model

Now, let's continue and define a bond option model that uses the bond valuator.

model BondOptionModel
  import BondValuator : function iBondValuator
  import context
  export OptionPrice
 
  T1 = context.option.OptionMaturity
  T2 = context.option.BondMaturity
  strike = context.option.Strike
 
  OptionPrice = E(final!)
  theta T1
  final = max(0, BondValuator(T2) - strike)
end

Orchestrating the two models

The next step is a combination of the two in the Theta Orchestrator. The orchestrator checks the validity of the BondValuator type. You can try to pass invalid or non-functional variables to the BondValuator and see the error messages.

Setting parameters

Now setting the values in the Theta Configurator:

Results

And here is the result of this simple example from Theta Result Explorer:


Workflows

Workflows are extensions to ThetaML, they have the same coding capabilities as other programming languages like Matlab. Workflows allow automated pricing of recurring tasks. Typical applications of workflows are in sensitivity and scenario analyses. Workflows can iteratively run a pricing task for a given set of starting values, compute option deltas and gammas and run a large set of portfolio scenarios within a single workflow.

For details of workflows, please see the definition and use of workflows in ThetaML at this link.

References

  1. [0]S. Dirnstorfer, A. Grau, H. Li: ThetaML Handbook
  2. [1]S. Dirnstorfer, An introduction to Theta-calculus, SSRN eLibrary, 2005.
  3. [2]S. Dirnstorfer, Multiscale calculus with applications in finance, Dissertation, Fakultät für Informatik, Technische Universität München, 2006.
  4. [3]S. Dirnstorfer, On the representation of trading strategies and financial portfolios, In proceedings of the First International Workshop on Intelligent Finance, Melbourne, 2004.