Simm-Lib is an implementation of version 2.5 and all previous versions of the value at risk Standard Initial Margin Model (SIMM™ 2.5) developed by ISDA, see here for methodology specifications. For all future versions of SIMM, visit Open-Source Risk Engine.
ORE is the same analytics library that powers Acadia’s hosted daily UMR Risk Suite supporting the latest version ISDA SIMM v2.5A as well as all previous versions, and contains much broader pricing and integrated market/credit risk functionality for derivatives, structured products, and other traded instruments.
Users of Simm-Lib who wish to deploy it for commercial purposes will need to obtain a license from ISDA to use ISDA SIMM™ to calculate initial margin for their or their clients’ non-cleared derivatives transactions. Please contact isdalegal@isda.org for more information on licensing the ISDA SIMM™.
- SIMM v2.5 - full recalibration and industry backtesting of the methodology
- Passing one-day benchmarks for version 2.5 including optional tests under Simmple module, checking acorss multiple applicable regulations, as well as Segregated and Unsegregated modes
- Passing ten-day benchmarks for version 2.5 including optional tests under Simmple module, checking acorss multiple applicable regulations, as well as Segregated and Unsegregated modes
Simm-Lib is built with Apache Maven, so one must get Maven installed on their machine.
Ubuntu users need only run in a terminal:
$ sudo apt-get install maven
Similarly, Mac users who have Homebrew installed can run:
$ brew install maven
All others can go to the Maven homepage for specific instructions on how to download and install Maven with any operating system.
To confirm that Maven has been successfully downloaded, check the Maven version on your machine by running:
$ mvn -version
If Maven has been successfully installed, this command should return something like:
Apache Maven 3.5.0 (ff4wa5hff; 2017-04-03T15:39:06-04:00)
Maven home: --MavenHomeDirectory--
Java version: 1.8.0_91, vendor: Oracle Corporation
Java home: --JavaHomeDirectory--
Default locale: en_US, platform encoding: UTF-8
OS name: "mac os x", version: "10.11.6", arch: "x86_64", family: "mac"
Simm-Lib's sources have to be moved onto a local machine. This can be accomplished by either downloading them as a zip file from GitHub, or by running in a terminal:
$ git clone <repo> simm-lib
Next, the code's artifacts need to be built. As Simm-Lib is a Maven project, this process is simplified to running:
$ mvn compile
After this, Simm-Lib should be fully ready to run in a local environment.
To run all of Simm-Lib's tests, simply run:
$ mvn test
If one wants to run individual tests, or an individual test module, the easiest way is to open Simm-Lib in some IDE and run the tests from that.
While there are simple tests to check the functionality of the individual methods of Simm-Lib, the main focus of the test suite is to confirm that the outputs of SIMM and Simm-Lib match. To accomplish this, the tests take in sensitivities and then run Simm-Lib's calculation, checking the result against SIMM's result:
@Test
public void test() {
Sensitivity IR1 = new DefaultSensitivity("RatesFX", "Risk_IRCurve", "GBP", "1", "6m", "OIS", new BigDecimal("200000000"));
Assert.assertEquals(new BigDecimal("13400000000"), Simm.calculateStandard(Arrays.asList(IR1)).setScale(0, RoundingMode.HALF_UP));
}
With the addition of the Schedule
and Simmple
classes the CRIF formatted objects have expanded beyond the Sensitivity
object
however the format of the testing is still generally the same as this is the main use case of the model.
This section focuses on the tests for the top level functionality
of the Simm
class, as the methods of this class directly consume CRIF
formatted data in the form of the Sensitivity
object and return the calculated IM of those inputs. There are six
methods in the Simm
class: calculateStanard()
, calculateAdditional()
,
calculateTotal()
, calculateTreeStandard()
, calculateTreeAdditional()
, and calculateTreeTotal()
.
The first method returns the IM of the input sensitivities, the second returns the Additional
IM generated by regulatory restrictions (this includes additional value created from product class multipliers),
while the third is the sum of the previous two methods. The "Tree" methods of similar names do the exact same
calculation, except the intermediate exposures at key points are saved in a tree structure to give a more thorough
view of how the exposure was calculated. All methods return the calculated value in US Dollars, so users of
Simm-Lib working in other currencies should be sure to include the "amountCurrency", and "amountUSD" columns in their
CRIF files.
The inputs to these methods are CRIF formatted data-types where all amounts are
stored as BigDecimal
and all other values as String
:
AddOnNotionalFactor(product, factor)
ProductMultiplier(productClass, multiplier)
AddOnFixedAmount(amount, amountCurrency, amountUSD)
AddOnNotional(product, notional, notionalCurrency, notionalUSD)
Sensitivity(productClass, riskType, qualifier, bucket, label1, label2, amount, amountCurrency, amountUsd)
For Sensitivity
, AddOnFixedAmount
, and AddOnNotional
the "currency", and
"amountUSD" can be omitted; however, the currency in this case will be assumed
to be US Dollars.
This section focuses on the Schedule
class. As the Schdule model is focued on trade level data, unlike the SIMM model which uses
sensitivities, new trade-level CRIF formatted objects have been added to the module to store this data. The ScheduleNotional
object
stores the notional amount of the trade (Note: the notional can be set to be positive or negative, and if multiple notionals exist
for the same trade they will be netted, the absolute value of the netted notional is then used in the calculation itself).
The SchedulePv
is the Net Present Value of the trade (similarly, the PVs will be netted by trade, and the netted value will be used).
ScheduleNotional(tradeId, schduleProductClass, valuationDate, endDate, amount, amountCurrency, amountUsd)
SchedulePv(tradeId, schduleProductClass, valuationDate, endDate, amount, amountCurrency, amountUsd)
The schdule module provides overloaded calculate()
and calculateTree()
methods
to handle both calculating the net gross rate from the input net present values, and using an input NGR instead.
All exposure amounts are returned in US Dollars.
This section focuses on the Simmple
class. The inputs to Simmple
have been stream-lined at least from a CRIF object perspective.
Simmple
takes in Crif
objects which are a super-set of all of the other CRIF formatted objects used by either the simm or schedule modules.
The intent of the Crif
object is to be able to directly translate a standard CRIF file into a List<Crif>
.
Crif(tradeId, valuationDate, endDate, notional, notionalCurrency, imModel, productClass, riskType, qualifier, bucket, label1, label2, amount, amountCurrency, amountUsd, postRegulation, collectRegulation)
You'll notice that some fields added to the Crif
object are not in any of the other CRIF formatted objects. The imModel
field is simply a String
which
indicates which model (SIMM or Schedule) that line of data should be input into. The current allowed model strings are "SIMM", "SIMM-P", "Schedule".
The notional
and notionalCurrency
fields are for convenience when running a schedule calcualtion. If a trade only has SchedulePv
inputs
but the notional
field is set for at least one of those PVs, a ScheduleNotional
will be constructed using the notional
value. The productClass
is overloaded to be
either the SIMM or Schedule product classes depending on the specified model. The postRegulation
and collectRegulation
fields are used for Pledgor and Secured regulation
respecitively. There are three different modes of specifying regulation:
- If all regulators are left blank for both post and collect, all
Crif
objects in the input list will be included in the calculation. A blank regulator string is considered to be the empty string "", any number of spaces with no other characters, or an empty set of brackets "[]" which may also conatin any number of spaces. - If some regulators are set "include" and all others are left blank, then all
Crif
objects which have "include" as one of its regulators will be included in the calcualtion. - Otherwise, the regualtors may be set to a single name ("CFTC" or "[SEC]) or a comma seperated list of names ("CFTC,SEC" or "[CFTC,SEC]"). When calculating the exposure
of a particular regulator, only
Crif
whose regulators are associated with the role you are running the calculation for will be included. An example of this would be if aCrif
had itspostRegulation
set to "CFTC" and itscollectRegulation
set to "SEC". If you are running a calculation for the regulator "SEC" and the role is set to Pledgor, the exampleCrif
would not be included in the calculation, but if the role was set to Secured the exampleCrif
would be included. For simplicities sake, we call the regulator with the highest calculated exposure to be the 'winning' regulator of a 'Worst-Of' calcualtion. The output of every fucntion in theSimmple
class is aImTreeResult
which contains the winning regulator, anImTree
breakdown of the exposure associated with the winning regulator, and finally the currency of all of the margins in theImTree
. The method names of theSimmple
class should be fairly self-explanatory:calculateSimmWorstOf()
returns the winning regulator calculating using only SIMM modelCrif
,calculateScheduleWorstOf()
returns the winning regulator calculating using only Schedule modelCrif
, andcalculateWorstOf()
returns the winning regulator calculating over theCrif
in both models.