As noted, the Finance domain provides many good candidates for vectorization. A particularly good example is the aggregation of Credit Value Adjustment (CVA) and other measures of counterparty risk.
by Rohan Douglas, CEO & Jamie Elliott, Development Manager, Risk Architecture (Quantifi)
The most common general purpose approach to calculation of CVA is based on a Monte-Carlo simulation of the distribution of forward values for all derivative trades with a counterparty. The evolution of market prices over a series of forward dates is simulated, then the value of each derivative trade is calculated at that forward date using the simulated market prices. This gives us a ‘path’ of projected values over the lifetime of each trade. By running a large number of these randomized simulated ‘paths’, we can estimate the distribution of forward values, giving both the expected and extreme ‘exposures’. The simulation step results in a 3-dimensional array of exposures, the dimensions are [trades][paths][dates]. The task of calculating CVA from these exposures occurs in several steps: Netting, Collateralization, Integration over paths, Integration over dates.
When a counterparty defaults, all positions with the counterparty must be closed out. If the appropriate legal agreements are in place, positive and negative individual trade exposures may offset each other, and a single net amount can be agreed. Mathematically, allowing netting just means that trade exposures are additive.
Computing the net exposures is a simple sum of trade exposures for each path and date.
This is equivalent to a sequence of matrix additions.
The inner loop here is clearly a classic candidate for vectorization and provided care is taken to arrange the data in appropriate order, the compiler will take care of this automatically.
In the simplest case, all the trade exposures share a common set of dates, and we wish to compute net exposures for this same set of common dates. A more complex extension of this problem comes when either the trades each have a unique set of dates, or the dates we wish to net on are not the same as the original dates. In either case, we need to first interpolate the trade exposures on a new common time grid, in order to then net them together. We use simple linear interpolation, which amounts to a weighted sum of the pair of exposures on the dates surrounding the interpolation date.
Since the size of the netExposure array is now different to the size of the source arrays, this introduces indirect memory access. As discussed, indirect references can have a negative impact on efficiency of vectorization. We examined two options for combating this problem:
- Copy into properly aligned arrays. Then all operations become matrix addition or Hadamard product.
b. Rely on improved scatter/gather produced by compiler auto-vectorization.
In our testing, it appears the scatter/gather solution remains more efficient. The cost of iterating over the arrays and copying data into well aligned arrays turns out to be greater than the consequent performance improvement in the main body of the loop. This remains a subject of active research.
Developers should always be looking for cases where vectorization and multi-threading can complement each other. One example would be the opportunity to perform interpolation of each trade exposure concurrently on multiple threads, then perform the netting of interpolated values as a final step. An alternative is to distribute the paths across multiple threads, as at this stage the path wise values are independent.
Trading parties often agree to mitigate counterparty risk by requiring collateral be posted to cover losses in the event of default. Collateral agreements can take a variety of forms, here we present a simplified version with some of the most common features. From the example, it can be seen that vectorization can be easily applied.
This is an agreement that one or both parties must provide collateral to offset the market value of a trade or trades. The margin may cover the portfolio value in excess of a threshold K. By making K=0, the full value of the portfolio at the margin call date will be covered.
Variation Margin = Max(net exposure – K, 0)
Once the net exposures have been aggregated from the trade exposures, we can compute the variation margin for each exposure.
Returning to the list of ‘intrinsic’ mathematical functions with compiler recognizable vectorized versions, we can see that a max operator is available.
Since we are interested only in positive exposures, amounts that can be lost after the default of the counterparty, our collateralized exposure then becomes:
Margin of Risk Period
The above formulas assume that collateral is posted instantaneously. In reality, margin call frequency will be at most once a day and there will be a lag between the margin call and the delivery of collateral. During this ‘Margin Period of Risk’ (MPR), the market value of the portfolio may increase, creating additional uncollateralized exposure. To introduce MPR into our model, we compare the netExposure at date t, to the collateral that can we can be sure has already been delivered by t. That means determining the collateral based on a margin call date at some lag Δt relative to t. This becomes a use case for the interpolation of exposures discussed above. We must first interpolate the exposures onto a new time grid, where each new date tmargin = t – Δt. Then our variation margin amount is determined using these interpolated exposures.
The second step, calculating collateralized exposures, remains unchanged and still uses the net exposures at the original exposure dates.
Again, note here that the results along each path are independent, so there is an opportunity to process multiple paths in concurrent threads.
Our first risk measure. Integrate over paths. Total then average.
Again this is all straightforward elementwise operations on the matrix.
Our target risk measure. Integrate over time. Weight by default prob.
Recommended Whitepapers and Articles
Vectorization, Part 1:FRTB Frameworks
A First View on the New CVA Risk Capital Charge
IFRS13 - Accounting for CVA and DVA
The Buy vs. Build Dilemma
Vectorization, Kirill Rogozhin, Intel, March 2017
Vectorization of Performance Dies for the Latest AVX SIMD, Kevin O’Leary, Intel, Aug 2016,
A Guide to Vectorization with Intel® C++ Compilers, Intel, Nov 2010,
Vectorization Codebook, Intel, Sep 2015,
The Free Lunch Is Over - A Fundamental Turn Toward Concurrency in Software, Herb Sutter, March 2005
Recipe: Using Binomial Option Pricing Code as Representative Pricing Derivative Method, Shuo-li, Intel, June 2016