ThetaML Language Reference
Payoff Description Language and Operator-based Modeling – ThetaML and Theta Calculus
ThetaML (Theta Modeling Language) is a payoff description language introduced by Thetaris GmbH. ThetaML is built on the concept of Theta calculus. Theta calculus is a mathematical notation for stochastic and sequential processes, first introduced by Dr. Dirnstorfer , , . 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 description language ThetaML.
Theta calculus provides the following objects to mathematically represent the typical patterns of financial instruments:
1) The economic state 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 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 Θ that allows time to pass.
ThetaML 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 very flexible and offers the benefit to specify the complete structure of a financial product independently of the underlying stochastic processes.
ThetaML has operators for three elementary effects: waiting, transacting, and deciding. Waiting is modeled with the Theta command which implements the Θ 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. The decision operator is modeled with an if statement in ThetaML. ThetaML supports standard control structures such as loops and if statements. ThetaML operates on a virtual timing model. This is realized with the Theta command. The fork command makes it possible to model simultaneous processes and enables cross-dependencies among the stochastic variables. The future operator "!" allows forward access to future values of a variable, this operation is based on forward algorithms. The future operator "!" is especially useful in Monte Carlo simulations of early exercise decisions where the expected future values (the ThetaML E function) have to be computed in advance.
ThetaML is a domain-specific payoff description language, with a procedural extension for time stepping. ThetaML explicitly incorporates the passage of time. Path dependencies, settlements, reinvestments and early exercises are all appropriately addressed.
Its main features are:
- Domain specific language for contract design
- Programming in chronological order and computational order
- Built-in conditional expectations
- Implicit handling of scenario- and time- indices
- Virtual multi-threading
- Pre- and post-conditions on models to ensure model correctness
Virtual Timing Model
The essence of ThetaML is the virtual timing model it operates in.
Unlike conventional programming languages where the computational flow is determined by the order of code statements, ThetaML operates on a chronological model time axis: ThetaML allows the programmer to insert time delays between code statements at different model times using the theta command. The values of variables at a given line of code are evaluated at the 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 is the key to its ease of use in describing financial derivatives. Since financial derivative contracts typically have sequential time-triggered events, such as scheduled payments, a maturity time, 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.
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
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 common programming languages. Imported values are either specified by the user when starting the evaluation 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 shows up in the configuration page used to run the model for imported variables and in the Theta Suite Result Explorer for the exported ones.
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 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 are done using the = operator, e.g.
x = 42 x = 7 * 9 y = 2 + x
The theta command is a crucial statement in ThetaML.
This command defines the virtual timing model. Every theta statement is followed by a statement defining a time interval. The virtual model time is used to synchronize multiple threads that occur parallel in virtual time. When external numerical routines are called to compute certain model parameters, the timing model also allows synchronization.
The example below illustrates how the virtual time model works. Model A and B are run simultaneously, the variable S is modified and exported by model B and used in model A. S is assigned a value of 1 at time zero, and a value of 2 after a time step of length 1. The variables X and Y are assigned the values of S at time 0.5 and 1.5 respectively. Since the values of S are different at those times X and Y get assigned the values of 1 and 2 respectively.
model A import S export X export Y theta 0.5 x = S theta 1.5 Y = S end
model B export S S = 1 theta 1 S = 2 end
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 variable a to zero initially and sets it to 5 at time step 2. The second block proceeds to time 1 and copies the current value of a. After another time step of 2 (at time 3) the value of a is copied again.
fork a = 0 theta 2 a = 5 end fork theta 1 x = a % result: 0 theta 2 x = a % result: 5 end
In case multiple write operations occur in the same timing model, the original order of the statements is used. The following example assigns two different values to variable a. A third thread would only see the value assigned by the second thread.
fork theta 1 a = 1 end fork theta 1 a = a + 1 end theta 1 x = a % result: 2
As most programming languages ThetaML allows for conditional execution. This is done using common if...else...end blocks. The following examples assign a value to the variable x under certain conditions:
if a > 1 | b < 10 x = 1 end
if a > 1 | b < 10 x = 1 else x = 2 end
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 the different types of loops. It can be an integer for a finite number of iterations, the keyword inf in which case the loop runs as long as the model is run or it can be an array in which case the loop will iterate over 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 cycles though a loop five times. Hence, the final value of x is 10.
x = 5 loop x x = x + 1 end
Infinite length loop
Using the keyword inf for the loop length causes the loop to run until all threads with fixed length have finished. This is useful when writing subroutines that compute a time series of arbitrary length or with a lifetime that automatically extends to the length needed.
x = 0 loop inf x = x + 1 theta 1 end
Loops can be used to iterate over arrays, much like the for ... each statement in many 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 = 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] B = [1, 2, 2, 2] loop a, b, x : A, B, X 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 the second case, the submodel must be supplied with all the parameters the submodel specifies by its import statements. 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.
The following examples shows a call to submodel sub_model. The first assumes that the submodel imports (reads) the variables a, b and c and exports (returns) variables x and y.
Input and returned variables are passed after an import or export statement, respectively. If the variables passed have different names from the submodel arguments, they can be renamed (aliased) by specifing a new name after a to or from statement.
call sub_model export a, b export a + b to c import x, y import z from 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 all units of time.
model sub_model import x "step size" export y "result" y = 0 loop inf y = y + x theta 1 end end
We can now call this submodel with a step size of 1 by exporting x to it and read the result back in variable y by importing it.
x = 1 call sub_model export x import y % result: y ~ 0 - 1 - 2 - 3 -....
We can also 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 using processes instead of values. We can call our submodel once to first create a time-series equal to the either of the previous two examples and thereafter chain this process as an input variable for the step size of a second process.
call sub_model export 1 to x import y 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 called by directly typing its function name. Note that only one variable can be returned and all values have to be elements of vectors or matrices.
x = 1 y = atan(x) % calls MATLAB function "atan"
You can also call user defined m-files as long as they are located within the Matlab path.
Future access operator
A unique feature of ThetaML is the ability to access to the values of a variable at future model time. Conventional programming languages can only access a value that was previously assigned to a variable. Since ThetaML does not evaluate sequentially, future values of variable can also be accessed. Future access to a variable is meaningful because of the virtual timing model present in ThetaML. Access to a future value of a variable does not mean access to a value at a future point of code execution but rather to the value of a variable at a future point in time.
Future access is achieved using the future access operator -- the exclamation mark (!). Note that circular definitions are not allowed.
The following example assigns the next value of y to x. Any command that changes the value of y then also determines the value of x.
x = y! % result: 3 ... y = 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! % result: 0 if a > 1, 2 otherwise if a > 1 y = 0 end y = 2
A special case occurs when a future-access is conditionally evaluated (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: 0 if y! > 1 y = 0 end y = 2
Further properties of the ! operator are the following:
a!! == a! (a + b)! == a! + b! f(a)! == f(a!) a[i]! == a![i] (not a![i!])
Array access 
Array elements in ThetaML can be accessed with C-style square braces after the variable name. Unlike C however indexing starts at 1.
A = [1, 2, 3, 4] x = A + A % x = 4
ThetaML can evaluate conditional statistical properties of variables. The results are conditional on all parameters that are known at the corresponding model time. The arguments of stochastic functions are assumed to have access to future values, i.e., to have access to future assignments.
E computes the conditional expected value of a variable or an expression.
This example computes the variable x as the expected value of S*EUR at time 10 conditioned on all information that is known at time 5.
theta 5 x = E(y!) theta 5 y = S * EUR
The future operator
! in the code above can be omitted because per definition of the E function
E(y!) == E(y)
Beta function takes two arguments and computes the beta factor between these two values.
The first argument can have multiple dimensions in which case the
Beta function computes a beta factor
for each component of that array. See Hedging in ThetaScript for applications.
The length of array can be determined using the
A = [1, 1, 1, 1] l = length(A) % result: 4
System parameters are compile-time parameters that can be extracted with an at sign (@) followed by one of the following keywords.
This variable provides the current model time. It is the sum of all previous
theta time steps.
The time interval parameter
@dt has different values depending on its context.
@dt is found within the argument of the command
theta, 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
This example computes Brownian motion for all time steps needed for a simulation since
@dt is an argument to
model BrownianMotion export W "Browian process" W = 0 loop inf theta @dt W = W + sqrt(@dt) * randn() end end
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 intialized. Afterwards, the Theta process uses Matlab functions to propagate the state for a timestep 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
- ↑ S. Dirnstorfer, An introduction to Theta-calculus, SSRN eLibrary, 2005.
- ↑ S. Dirnstorfer, Multiscale calculus with applications in finance, Dissertation, Fakultät für Informatik, Technische Universität München, 2006.
- ↑ S. Dirnstorfer, On the representation of trading strategies and financial portfolios, In proceedings of the First International Workshop on Intelligent Finance, Melbourne, 2004.