A variety of applications in quantitative finance are computationally extremely demanding. For instance VaR or CVA calculations, even hundreds of millions of single instrument valuations need to be performed. newUnRisk will meet these demands by utilizing a two-fold strategy, coarse and fine parallelization. At the coarse parallelization level, each valuation in newUnRisk is represented by an object (ValuationObject) that holds all necessary information for the calculation task. These objects can be collected in a so called valuation pool, which is responsible for distributing the different valuations throughout the parallel hardware environment. The standard and portable Message Passing Interface (MPI) is used to set up the communication, ensuring support for a large variety of parallel system architectures.

Schematic display of the Valuation pool distributing the Valuation Objects to cluster nodes.

coarse parallelization

The fine grain parallelization aims at the efficient valuation of single instruments. newUnRisk will provide inherently parallel algorithms based on OpenCL technology, which is chosen for two reasons: First, it allows the parallelization of code on both multicore architectures and as on GPUs. Second use of this technology is not restricted to a specific hardware vendor.

Schematic display of the parallelization of a single instrument valuation on a node. Either multicore CPUs or GPUs can be used to speed up the calculations.

fine parallelization

The following code snippet shows OpenCL code used for path generation for a 1F Hull White Model.

#ifndef Real_t

#define Real_t float

#endif

 

#ifndef mint

#define mint int

#endif

 

#ifndef THREADS_PER_BLOCK

#define THREADS_PER_BLOCK 32

#endif

 

 

__kernel void simulateHullWhiteRatesGPU_kernel(mint nop, mint tgmcs, Real_t shortRate,  const __global Real_t* cd_drift,

const __global Real_t* cd_speed, const __global Real_t* cd_volatility,

const __global Real_t* cd_tgmcdb, __global Real_t* d_rn)  {

// one thread per path

unsigned mint pid = get_global_id(0);

mint size = tgmcs-1;

if (pid < nop) {

d_rn[pid] = shortRate + (cd_drift[0] - cd_speed[0]*shortRate)*cd_tgmcdb[0] + cd_volatility[0]*d_rn[pid];

for (mint j=1; j

d_rn[pid+j*nop] = d_rn[pid+(j-1)*nop] + (cd_drift[j] - cd_speed[j]*d_rn[pid+(j-1)*nop])*cd_tgmcdb[j] + cd_volatility[j]*d_rn[pid+j*nop];

}

}

}

 

Our OpenCL codes are tested in Mathematica - the programs support of OpenCL makes Mathematica an efficient testing platforms for algorithms and their execution on either GPU or CPU.

MathematicaOpenCL

Employing this two-fold strategy - spreading different instrument valuations on cluster nodes and speeding up the single instrument valuation locally by applying OpenCL based highly efficient algorithms - newUnrisk is not only capable to meet current demands in quantitative finance but is also fit for future trends.


UnRisk Multi Language

A key point in the interface is the object centered approach to give users full flexibility in a simple to use domain specific language. For the object creation we make heavy use of the builder pattern, an object creation software design pattern. The intention is to abstract steps of construction of objects so that different implementations of these steps can construct different representations of objects.

As an example for the use of the builder pattern and the creation of the object we show the construction of two different equity options, a Double Barrier Out Call and an Up And Out Call. (note that myEquity and expiryDate are instances of UnRisk specific objects)

//Create a Double Barrier Out Call Option

EquityOptionBuilder myEquityOptionBuilder;

//

myEquityOptionBuilder.instrumentID("MyEquity_DBOut_Call"); //user defined

myEquityOptionBuilder.currency("EUR");

myEquityOptionBuilder.underlying(myEquity);

myEquityOptionBuilder.payOffType("Call");

myEquityOptionBuilder.exerciseType("European");

myEquityOptionBuilder.optionType("DoubleBarrierOut");

myEquityOptionBuilder.strikePrice(100);

myEquityOptionBuilder.barrierUp(110);

myEquityOptionBuilder.barrierDown(90);

myEquityOptionBuilder.holidayCalendar("GER");

myEquityOptionBuilder.businessDayConvention("ModifiedFollowing");

myEquityOptionBuilder.expiryDate(expiryDate);

//

EquityOption myDoubleBarrierOutCall = myEquityOptionBuilder.build();

 

//Create an Up And Out Call Option

EquityOptionBuilder myEquityOptionBuilder;

//

myEquityOptionBuilder.instrumentID("MyEquity_UpAndOut_Call"); //user defined

myEquityOptionBuilder.currency("EUR");

myEquityOptionBuilder.underlying(myEquity);

myEquityOptionBuilder.payOffType("Call");

myEquityOptionBuilder.exerciseType("European");

myEquityOptionBuilder.optionType("UpAndOut");

myEquityOptionBuilder.strikePrice(100);

myEquityOptionBuilder.barrierUp(110);

myEquityOptionBuilder.holidayCalendar("GER");

myEquityOptionBuilder.businessDayConvention("ModifiedFollowing");

myEquityOptionBuilder.expiryDate(expiryDate);

//

EquityOption myDoubleBarrierOutCall = myEquityOptionBuilder.build();

 

The C++ code example below shows the steps needed to valuate a European Double Barrier Out Call under a Heston Model. For discounting a flat yield curve is used. As you can see the builder pattern is used to create the Heston model, a yield curve, the instrument, the calculation parameters and even the valuation is built up as an object. This allows to collect such valuation object and to gain full control about time and type of execution (important for parallelization).

//set up dates

Date todayDate  = Date(2012,7,1);

Date expiryDate = Date(2013,7,1);

 

//----------------------------------------------------------------------------

// Build a Heston Model

// "multi-line" version, better suited for objects with many properties

HestonModelBuilder myHestonModelBuilder;

//

myHestonModelBuilder.modelID("MyEquityHestonModel");

myHestonModelBuilder.longRunMean(0.1);

myHestonModelBuilder.reversionSpeed(1.0);

myHestonModelBuilder.volOfVol(0.4);

myHestonModelBuilder.initialVariance(0.04);

myHestonModelBuilder.correlation(-0.9);

//

Model myHestonModel = myHestonModelBuilder.build();

 

 

//----------------------------------------------------------------------------

// Build a Yield Curve Object

// "multi-line" version, better suited for objects with many properties

YieldCurveBuilder myYieldCurveBuilder;

//

myYieldCurveBuilder.curveID("EUR");

myYieldCurveBuilder.rate(0.05);

myYieldCurveBuilder.compoundingFrequency("Continuous");

//

YieldCurve myEuroYieldCurve = myYieldCurveBuilder.build();

 

//----------------------------------------------------------------------------

// Set up market data

MarketData myMarketdata;

myMarketdata.addYieldCurve(myEuroYieldCurve);

 

//

//----------------------------------------------------------------------------

//set up model container for all models necessary for the valuation

ModelContainer myModelContainer;

myModelContainer.insert(myHestonModel);

 

//

//----------------------------------------------------------------------------

//Set up underlying Equity

EquityBuilder myEquityBuilder;

//

myEquityBuilder.instrumentID("MyEquity");

myEquityBuilder.flatEquityYield(0.02);

myEquityBuilder.currency("EUR");

myEquityBuilder.spotPrice(99.5);

//

Equity myEquity = myEquityBuilder.build();

//

//----------------------------------------------------------------------------

//Create a Double Barrier Out Call Option

EquityOptionBuilder myEquityOptionBuilder;

//

myEquityOptionBuilder.instrumentID("MyEquity_DBOut_Call"); //user defined

myEquityOptionBuilder.currency("EUR");

myEquityOptionBuilder.underlying(myEquity);

myEquityOptionBuilder.payOffType("Call");

myEquityOptionBuilder.exerciseType("European");

myEquityOptionBuilder.optionType("DoubleBarrierOut");

myEquityOptionBuilder.strikePrice(100);

myEquityOptionBuilder.barrierUp(110);

myEquityOptionBuilder.barrierDown(90);

myEquityOptionBuilder.holidayCalendar("GER");

myEquityOptionBuilder.businessDayConvention("ModifiedFollowing");

myEquityOptionBuilder.expiryDate(expiryDate);

//

EquityOption myDoubleBarrierOutCall = myEquityOptionBuilder.build();

//

//----------------------------------------------------------------------------

//Set Calculation Control Parameters

//

CalculationParametersBuilder myCalculationParametersBuilder;

//

myCalculationParametersBuilder.valuationDate(todayDate);

myCalculationParametersBuilder.settlementDate(todayDate);

myCalculationParametersBuilder.method("HMC");

myCalculationParametersBuilder.nrPaths(pow(2,10));

myCalculationParametersBuilder.maxDeltaT(1);

myCalculationParametersBuilder.calculateDelta(true);

myCalculationParametersBuilder.calculateGamma(true);

//

CalculationParameters myCalculationParameters = myCalculationParametersBuilder.build();

//

//----------------------------------------------------------------------------

// Valuation via Valuation Object

ValuationObjectBuilder myValuationObjectBuilder;

//

myValuationObjectBuilder.instrument(myDoubleBarrierOutCall);

myValuationObjectBuilder.modelContainer(myModelContainer);

myValuationObjectBuilder.calculationParameters(myCalculationParameters);

myValuationObjectBuilder.marketData(marketdata);

//

ValuationObject myValuationObject = myValuationObjectBuilder.build();

//

//the values are calculated

ResultContainer myResults;

myResults.add(myValuationObject.calculate());

 

//----------------------------------------------------------------------------

//results can be extracted from the ResultContainer using an URL scheme

double ov = myResults.getValue<double>("MyEquity_DBOut_Call.MyEquityHestonModel.value");

double delta = myResults.getValue<double>("MyEquity_DBOut_Call.MyEquityHestonModel.delta");

double gamma = myResults.getValue<double>("MyEquity_DBOut_Call.MyEquityHestonModel.gamma");

 

A Model Container is used to pass models to the valuation - a future example will show how the model container can be used to value one instrument under different models - an important feature for model calibration.

Calibration Parameters allow to set details of the valuation - when, what, how ...

Some notes should be given to the numerical methods used in UnRisk. Basically for each instrument the default set of numerical parameters is set in a way to ensure fast and accurate  calculations. But of course the user may want to change them, for example to assess the performance of a certain numerical method in combination with a specific instrument under a specific model. The standard method used for valuation in UnRisk is a Hybrid Monte Carlo technique, very well suited for parallelization on CPU and GPU. But also Finite Element and Finite Difference techniques are used where appropriate.

In UnRisk a Key-value store (KVS) is used for data management, allowing the application to store its data in a schema-less way. The keys are built up of an URL scheme. In the example above the results are extracted from a ResultContainer (KVS) using the (user defined) Instrument ID in combination with the (user defined) Model ID for the URL. The handling of market data in our KVS store will be shown in a future example.

 

The Python code shown below performs the same task  - obviously it is very similar to the C++ code allowing the user for easy transition between different languages. The small differences between the codes are owed to the fact, that C++ is a statically typed language whereas Python is not.

#set up dates

todayDate = Date(2012,7,1)

expiryDate = Date(2013,7,1)

 

#----------------------------------------------------------------------------

# Build a Heston Model

# "multi-line" version, better suited for objects with many properties

myHestonModelBuilder = HestonModelBuilder()

#

myHestonModelBuilder.modelID("MyEquityHestonModel")

myHestonModelBuilder.longRunMean(0.1)

myHestonModelBuilder.reversionSpeed(1.0)

myHestonModelBuilder.volOfVol(0.4)

myHestonModelBuilder.initialVariance(0.04)

myHestonModelBuilder.correlation(-0.9)

#

myHestonModel = myHestonModelBuilder.build()

#----------------------------------------------------------------------------

# Build a Yield Curve

 

myYieldCurveBuilder = YieldCurveBuilder()

#

myYieldCurveBuilder.curveID("EURYC")

myYieldCurveBuilder.rate(0.05)

myYieldCurveBuilder.compoundingFrequency("Continuous")

#

myEuroYieldCurve = myYieldCurveBuilder.build()

 

#----------------------------------------------------------------------------

# Set up market data

myMarketdata = MarketData()

myMarketdata.addYieldCurve(myEuroYieldCurve);

 

#----------------------------------------------------------------------------

#set up model container for all models necessary for the valuation

myModelContainer = ModelContainer()

#

myModelContainer.insert(myHestonModel)

#

#----------------------------------------------------------------------------

#Set up underlying Equity

myEquityBuilder = EquityBuilder()

#

myEquityBuilder.instrumentID("MyEquity")

myEquityBuilder.flatEquityYield(0.02)

myEquityBuilder.currency("EUR")

myEquityBuilder.spotPrice(99.5)

#

myEquity = myEquityBuilder.build()

#

#----------------------------------------------------------------------------

#Create an Instrument

myEquityOptionBuilder = EquityOptionBuilder()

#

myEquityOptionBuilder.instrumentID("MyEquity_DBOut_Call") #user defined

myEquityOptionBuilder.currency("EUR")

myEquityOptionBuilder.underlying(myEquity)

myEquityOptionBuilder.payOffType("Call")

myEquityOptionBuilder.exerciseType("European")

myEquityOptionBuilder.optionType("DoubleBarrierOut")

myEquityOptionBuilder.strikePrice(100)

myEquityOptionBuilder.barrierUp(110)

myEquityOptionBuilder.barrierDown(90)

myEquityOptionBuilder.holidayCalendar("GER")

myEquityOptionBuilder.businessDayConvention("ModifiedFollowing")

myEquityOptionBuilder.expiryDate(expiryDate);

#

myDoubleBarrierOutCall = myEquityOptionBuilder.build()

#

#----------------------------------------------------------------------------

#Set Calculation Control Parameters

#

myCalculationParametersBuilder = CalculationParametersBuilder()

#

myCalculationParametersBuilder.valuationDate(todayDate)

myCalculationParametersBuilder.settlementDate(todayDate)

myCalculationParametersBuilder.method("HMC")

myCalculationParametersBuilder.nrPaths(pow(2,10))

myCalculationParametersBuilder.maxDeltaT(1)

myCalculationParametersBuilder.calculateDelta(True)

myCalculationParametersBuilder.calculateGamma(True)

#

myCalculationParameters = calculationParametersBuilder.build()

#

#----------------------------------------------------------------------------

# Valuation via Valuation Object

myValuationObjectBuilder = ValuationObjectBuilder()

#

myValuationObjectBuilder.instrument(myDoubleBarrierOutCall)

myValuationObjectBuilder.modelContainer(myModelContainer)

myValuationObjectBuilder.CalculationParameters(myCalculationParameters)

myValuationObjectBuilder.marketData(marketdata)

#

myValuationObject = myValuationObjectBuilder.build()

#

#the values are calculated

myResults = ResultContainer()

myResults.add(myValuationObject.calculate())

 

#----------------------------------------------------------------------------

#results can be extracted from the ResultContainer using an URL scheme

ov = myResults.getValue("MyEquity_DBOut_Call.MyEquityHestonModel.value")

delta = myResults.getValue("MyEquity_DBOut_Call.MyEquityHestonModel.delta")

gamma = myResults.getValue("MyEquity_DBOut_Call.MyEquityHestonModel.gamma")

 

Also the Mathematica interface closely follows the design principles of newUnRisk. 

The new front end copies ideas from J/Link which allows for writing Java code in Mathematica in a syntax that resembles Java methods invocation.

UnRisk related data objects live in a MathLink or LibraryLink linked NewUnRisk execution context and are manipulated through Mathematica symbol references in the current Mathematica session.

hestonBuilder = MakeHestonModelBuilder[];

yieldCurveBuilder = MakeYieldCurveBuilder[];

equityBuilder = MakeEquityBuilder[];

equityOptionBuilder = EquityOptionBuilder[];

marketdata = MakeMarketData[];

calculationParametersBuilder = MakeCalculationParametersBuilder[];

valuationObjectBuilder = ValuationObjectBuilder[];

 

hestonBuilder

@ModelID["MyEquityHestonModel"]

@LongRunMean[0.1]

@ReversionSpeed[1.0]

@volOfVol[0.4]

@initialVariance[0.04]

@correlation[-0.9];

 

myHestonModel = Build[hestonBuilder];

 

yieldCurveBuilder

@CurveID[

@Rate[0.05]

@CompoundingFrequency["Continuous"]

 

MyEuroYieldCurve = Build[yieldCurveBuilder];

 

marketdata@AddYieldCurve[myEuroYieldCurve];

 

myEqutiy = Build[equityBuilder

@InstrumentID[

@FlatEquityYield[0.02]

@Currency["EUR"]

@SpotPrice[99.5]];

 

 

equityOptionBuilder

@InstrumentID["MyEquity_DBOut_Call"]

@Currency[

@Underlying[myEqutiy]

@PayOffType[

@ExerciseType[

@OptionType["DoubleBarrierOut"]

@StrikePrice[100]

@BarrierUp[110]

@BarrierDown[90]

@HolidayCalendar["GER"]

@BusinessDayConvention["ModifiedFollowing"]

@ExpiryDate[{2013, 7, 1}];

 

 

myDoubleBarrierOutCall = Build[equityOptionBuilder];

 

calculationParametersBuilder

@ValuationsDate[Date[]]

@SettelementDate[Date[]]

@Method[

@NrPaths[2^10]

@MaxDeltaT[1]

@CalculateDelta[True]

@CalculateGamma[True];

 

myCalculationParameters = Build[calculationParametersBuilder];

 

valuationObjectBuilder

@Instrument[myDoubleBarrierOutCall]

@ModelContainer[myModelContainer]

@CalculationParameters[myCalculationParameters]

@MarketData[marektdata];

 

myValuationObject = Build[valuationObjectBuilder];

 

myResults = Calculate[myValuationObject];

 

ov = myResults@Get["MyEquity_DBOut_Call.MyEquityHestonModel.value"];

delta = myResults@Get["MyEquity_DBOut_Call.MyEquityHestonModel.delta"];

gamma = myResults@Get["MyEquity_DBOut_Call.MyEquityHestonModel.gamma"];

 

Again the Matlab interface relies on the same design concepts:

% set up dates

todayDate = [2012,7,1];

expiryDate = [2013,7,1];

% Build a Heston Model

hestonModelBuilder = HestonModelBuilder();

%

hestonModelBuilder.modelID('MyEquityHestonModel');

hestonModelBuilder.longRunMean(0.1);

hestonModelBuilder.reversionSpeed(1.0);

hestonModelBuilder.volOfVol(0.4);

hestonModelBuilder.initialVariance(0.04);

hestonModelBuilder.correlation(-0.9);

%

myHestonModel = hestonModelBuilder.build();

% Build a Yield Curve

 

yieldCurveBuilder YieldCurveBuilder();

%

yieldCurveBuilder.curveID('EURYC')

yieldCurveBuilder.rate(0.05)

yieldCurveBuilder.compoundingFrequency('Continuous')

%

myEuroYieldCurve = yieldCurveBuilder.build();

% Set up market data

marketdata = MarketData();

marketdata.addYieldCurve(myEuroYieldCurve);

%

% set up model container for all models necessary for the valuation

myModelContainer ModelContainer();

%

myModelContainer.insert(myHestonModel)

%

% Set up underlying Equity

equityBuilder EquityBuilder();

%

equityBuilder.instrumentID('MyEquity')

equityBuilder.flatEquityYield(0.02)

equityBuilder.currency('EUR')

equityBuilder.spotPrice(99.5)

%

myEquity = equityBuilder.build();

%

% Create an Instrument

equityOptionBuilder = EquityOptionBuilder();

%

equityOptionBuilder.instrumentID('MyEquity_DBOut _Call'); % user defined

equityOptionBuilder.currency('EUR');

equityOptionBuilder.underlying(myEquity);

equityOptionBuilder.payOffType('Call');

equityOptionBuilder.exerciseType('European');

equityOptionBuilder.optionType('DoubleBarrierOut');

equityOptionBuilder.strikePrice(100);

equityOptionBuilder.barrierUp(110);

equityOptionBuilder.barrierDown(90);

equityOptionBuilder.holidayCalendar('GER');

equityOptionBuilder.businessDayConvention('ModifiedFollowing');

equityOptionBuilder.expiryDate(expiryDate);

%

myDoubleBarrierOutCall = equityOptionBuilder.build();

%

% Set Calculation Control Parameters

%

calculationParametersBuilder = CalculationParametersBuilder();

%

calculationParametersBuilder.valuationDate(todayDate);

calculationParametersBuilder.settlementDate(todayDate);

calculationParametersBuilder.method('HMC');

calculationParametersBuilder.nrPaths(pow(2,10));

calculationParametersBuilder.maxDeltaT(1);

calculationParametersBuilder.calculateDelta(true);

calculationParametersBuilder.calculateGamma(true);

%

myCalculationParameters = calculationParametersBuilder.build();

%

% Valuation via Valuation Object

valuationObjectBuilder = ValuationObjectBuilder();

%

valuationObjectBuilder.instrument(myDoubleBarrierOutCall);

valuationObjectBuilder.modelContainer(myModelContainer);

valuationObjectBuilder.CalculationParameters(myCalculationParameters);

valuationObjectBuilder.marketData(marketdata);

%

myValuationObject = valuationObjectBuilder.build();

%

% the values are calculated

myResults = ResultContainer();

myResults.add(myValuationObject.calculate());

%

% results can be extracted from the ResultContainer using an URL scheme

ov = myResults.getValue('MyEquity_DBOut _Call.MyEquityHestonModel.value');

delta = myResults.getValue('MyEquity_DBOut _Call.MyEquityHestonModel.delta');

gamma = myResults.getValue('MyEquity_DBOut _Call.MyEquityHestonModel.gamma');

 

The examples will be extended (model calibration, market data management, structured interest rate products, inflation linked products,...) soon - we will keep you informed!

 

 

 

 






				

 

News

UnRisk @ Spezialtag MiFID II

UnRisk @ Spezialtag MiFID II

UnRisk will speak at Spezialtag MiFID II am 06.12.2016: Anlageberatung 4.0...

Read more

UnRisk consortium and Multilateral AG teamed up to found UnRiskOmega AG

UnRisk consortium and Multilateral AG teamed up to found UnRiskOmega AG

UnRiskOmega is a cooperation of the three companies multilateral AG, uni softwar...

Read more

Mathematica & UnRisk Workshop in Paris

Mathematica & UnRisk Workshop in Paris

Wolfram Research and UnRisk have teamed up again to invite you to a free worksho...

Read more

UnRisk in Paris

UnRisk in Paris

We are deligthed that UnRisk has spoken at the Wolfram Finance Event "A Workout...

Read more

UnRisk Pricing Engine 8.1 Released

UnRisk Pricing Engine 8.1 Released

UnRisk today announced it has released UnRisk 8.1, an enhanced version of UnRisk...

Read more

UnRisk Factory 6 is here

UnRisk Factory 6 is here

UnRisk Factory 6 is realeased with new features in valuation, instruments, marke...

Read more

UnRisk 8 Released

UnRisk 8 Released

UnRisk today announced it has released UnRisk 8, an enhanced version of UnRisk-Q...

Read more

Success Stories

UnRisk and Solventis - Or How To Build Up a SaaS Solution with UnRisk Technologies

UnRisk and Solventis - Or How To Build Up a SaaS Solution with UnRisk Technologies

Solventis is an independent financial group established in 2002 by a team of pro...

Read more

UnRisk seals cooperation with multilateral AG

UnRisk seals cooperation with multilateral AG

multilateral AG is an innovative Swiss IT-Consulting and software engineering co...

Read more

Dupire - Robust Calibration of Local Volatility Models

Dupire - Robust Calibration of Local Volatility Models

For the so-called local volatility model, Bruno Dupire derived a closed form sol...

Read more

Workout in Computational Finance

Workout in Computational Finance

The intention of the book is to give a sound overview on numerical methods which...

Read more