1. MASTER OF BANKING AND FINANCE 2010-2011
COHERENT STRESS TESTING
A Bayesian Approach to Scenario Analysis
and Stress Testing
GRADUATION PROJECT
ADVISORS AUTHORS
Rudi Vander Vennet KEVIN HOEFMAN
Michael Frommel MAXENS BERRE
Nikolas Vander Vennet
Wim Konings
1|P a ge
2. Introduction
For the past several decades, financial crises have highlighted the need to assess the stability of the
financial system.
The current global financial crisis has demonstrated limitations in the purely statistical approaches which
have heretofore been employed to assess the stability of financial institutions. During 2007 and 2008,
several multiple-standard-deviation loss events, predicted to only occur once every several thousand
years occurred in the space of 24 months. Clearly, the models in use were no longer functioning.1
In January 2009, during the depths of the financial crisis, the Basel Committee on Banking Supervision
published its view that the bank stress-testing which had heretofore taken place was insufficient for a
number of reasons. The views of the BIS were that the long period of historical stability preceding the
crisis reduced likelihood that stress test was detecting severe shocks and systemic weaknesses.
Furthermore, estimations of “severe” were dramatically underrated and neither correlation of shocks
nor rational feedback effects were being taken into account. The effects of recent financial innovations
were also being ignored.2
Essentially, the financial market had grown considerably more complex and less transparent since the
previous round of financial crises at the end of the 20th century. The BIS’ concern is that stress-testing
had not kept up with the times.
In 2009, the Committee of European Banking Supervisors (CEBS), an independent advisory group on EU
banking supervision implemented the first EU-wide stress tests. These stress tests were also executed in
accordance with frequentist methodology. 22 major EU cross-border banks were examined. Potential
2009-2010 trading and credit losses could amount to almost € 400 Billion in the adverse scenario.
Nevertheless, none of the banks in the test saw their Tier-1 ratios potentially fall below 6%. The
European Council subsequently requested that further stress testing be done with broader objectives
and measuring the ability to absorb further shocks.
Subsequently, in July 2010 a more inclusive battery of stress test examining 91 banks was undertaken by
CEBS, in which, five banks failed. This second-round of stress tests was undertaken amid concerns that
the September 2009 round was insufficiently strict in its examinations and that, while large systemic
banks on the European scale were examined, not enough of the banks systemic to individual member-
nations were accounted for in the CEBS 2010 stress tests. Furthermore, because illiquidity was assumed
to be the primary threat, assets in the bank’s trading book were targeted while held-to-maturity assets
held in the banking book were not. The latter represented approximately 83% of bank assets. Another
shortfall of the 2010 stress tests was the assumption that there would be no sovereign defaults in the
EU. A better approach would have been to also attempt to determine which scenario could have led to a
sovereign default in the EU.
1
Rebonato, 2010
2
BIS, 2009
2|P a ge
3. The subsequent 2011 European banking stress test is currently being performed by the newly founded
European Banking Authority. The 2011 exercise incorporates lessons learned as well as policy demands
from Economic and Financial Affairs Council (ECOFIN) and the Economic and Financial Committee (EFC).
One can take the fact that the EU has gone through three rounds of stress testing as an indication of
dissatisfaction with the thoroughness of the stress tests in unearthing bank vulnerabilities throughout
the EU. A different approach was needed.
The European stress tests tried to answer the question of what would happen in the event of both
current loss expectations as well as a worst-case scenario whereby losses exceeded current loss
expectations. However, the stress tests consider each potential source of loss as a separate aspect,
without accounting for dynamics of the situation where if one shock happens, it can have a causal effect
on the other shocks. Thus, they have left something to be desired, irrespective of the number of banks
or percentage of GDP investigated.
According to Rebonato, the key missing ingredient from stress testing procedures is a solid way of
capturing the co-relationships between the various stress events. Rebonato suggests that subjective
expert assessments for the marginal probabilities of the various stress events and the conditional
probabilities between them, and a Bayesian procedure for consistently tying these together, can lead to
a better understanding of the dynamics of the stress scenario that is being considered. This allows us to
generate statistical information about stress losses that are more realistic than losses captured by
conventional stress testing methodologies.
The rest of this paper proceeds as follows. The following section discusses what progress has thus far
been made in stress testing, as well as the way forward. Section three presents a hypothetical Bayesian
stress scenario. A bank and selected and its situation described in detail. Then sources of vulnerabilities
are analyzed and a stress scenario is presented along with its accompanying topology. Lastly, the final
section provides concluding analysis.
Where Are We With Stress Testing?
Where do We Need to Go?
While economists have made great bounds in terms of designing scenarios, more progress is needed. In
the view of the Basel Committee on Banking Supervision, there are major shortcomings which need to
be addressed, related to concerns that the financial world had fallen into a sense of security due to the
length of time since the last crisis and that systemic risks, correlation of shocks, and the effect financial
3|P a ge
4. innovations were being overlooked in stress testing. 3 The current shortcomings in stress-testing can also
be seen in the European Council’s reception of the 2009 and 2010 CEBS stress tests.
The traditional approach to stress-testing applies loss estimates that are ultimately based on frequentist
techniques. In order to come up with an adverse scenario for a stress test, one first needs to have an
understanding of what the “normal” scenario is. This idea of what is “normal” is derived from
frequentist techniques like VaR. This approach has the drawback of being backward-looking. Another
drawback comes in the area of extremely rare events. In order for the frequentist approach to generate
meaningful results, one needs a relatively large amount of relevant data. Extremely rare events are
difficult to analyze with a frequentist approach, meaning that assigning stress losses to them is equally
difficult.4 What is needed is a forward-looking and conditional approach to losses, which can be applied
in situations with little relevant data and in dynamic situations.
In the view of both Keynes and Taleb, the frequentist approach has the major drawback that it relies
that the future is like the future in that it is like the past, predictable, calculable to within a certain
bound, and therefore hedge-able. This reaches to the basic difference, in the Keynesian view, of risk and
uncertainty. Under uncertainty, “No scientific basis on which to form any calculable probability
whatever. We simply don’t know.” 5 By contrast, the prevailing neoclassical economic view is that market
participants have complete knowledge of probability distributions over future events. In other words,
we face only measureable risk.6
A further major drawback of the frequentist approach, expressed by Rebonato, is the unavailability of
sufficient quantities of relevant data concerning extremely rare situations. Fundamentally, in order for a
frequentist approach to be valid, data must be drawn from identical conditions. If however we are
gathering data on a black swan event or black swan scenario, we may find ourselves needing to draw
data from a wide breadth of sources and/or across a long time-horizon. Unfortunately, if we engage in
either drawing data from the distant past or from dissimilar situations, we cannot accurately use it for
frequentist analysis.
WHAT IS NEEDED IN STRESS TESTING?
Given the shortcomings enumerated, some improvements are necessary.
The most important aspect needed in stress testing in order to overcome black swan events is a
forward-looking element. Subjective probability is a plausible way in which this can be achieved. A
subjective probability is essentially an opinion – hopefully a well-informed expert opinion – regarding
the probability distribution of an event occurring. While there is no mathematical proof behind the
3
BIS, 2009
4
Rebonato, 2010
5
Keynes, 1937
6
Skidelsky, 2009
4|P a ge
5. answer, one can expect that in addition to historical probability distribution, a subjective probability
might be influenced by expectations, indicators as to what may occur in the future, and indicators as to
why this time might be different. The most significant upsides to this approach are the incorporation of
a wide range of indicative and qualitative data, as well as the non-reliance on vast and often difficult-to-
obtain amounts of data. The latter factor would render this approach particularly valuable during
scenarios involving one or more extremely rare (statistical tail) events.7
Unfortunately, subjective probability is still subjective and might in fact be vulnerable to a high degree
of bias. Nevertheless, bias can be overcome by via the use of the law of larger numbers. That is, several
expert subjective judgments can be employed in order to construct the subjective probability. This
would particularly be the case in situations in which a diversity of opinions and views could be
assembled. Within a financial institution this can be achieved by polling experts and risk managers of
different departments, regional offices and business segments on the same probabilistic views.
Another important issue which needs to be addressed in stress testing is correlation of shocks. In many
stress tests, this has truly come to be a key missing ingredient. The simple fact that a financial institution
survives an economic shock may might not be perfectly indicative of bank-survivability when the
economic shock in question might also set off (or might otherwise be associated with) a chain reaction
of economic shocks.
In order to approach this within the context of stress-testing, conditional probabilities can be utilized. In
contrast, stress testing methodology so far relies chiefly on marginal probabilities. The question
answered by this method is “Assuming that a specific economic shock (or set of shocks) takes place,
what is the likelihood of bank failure?” A Bayesian approach to stress testing would instead ask the
question “Assuming that a specific economic shock (or set of shocks) takes place, what is the likelihood
that this will trigger other shocks as well? What would then be their effect on a financial institution at
each given stage? And finally, is bank failure likely to occur at any of these stages?”
THE BAYESIAN NET
A Bayesian net is a way of modeling the relationships between the various stress events that are being
considered in a single stress scenario.
For instance, given a default of a Euro zone country, the risk free rate (German government bond) is
likely to spike upward and equity markets will crash given that investors are likely to have a risk-averse
reaction. One possible Bayesian net for this scenario looks like this:
7
Rebonato, 2010
5|P a ge
6. E1: Euro zone Country
Default
E2: Yield curve shift E3: Equity market
crash
The risk manager creates a Bayesian net according to his idea of how reality works. He assigns marginal
probabilities to the events in the net, and conditional probabilities to the causal relationships. Different
risk managers could come up with different Bayesian nets and/or probabilities for the same stress test.
Since all Bayesian nets are simplifications, there isn’t one “true” Bayesian net. The Bayesian net
ultimately expresses a statement of conditional independence reflecting the causal assumption that we
intend to propose. While correlations and conditional probabilities don’t necessarily give information
about causality, we can use expert subjective judgment to determine a causal structure.
Consider the diagram above. Setting aside the fact that any of these three events can take place with
probability P(Ei) and that each of these three events has its own direct and independent effect on a
financial institution, the Bayesian net also indicates that, once we know that event E1 has occurred,
there is a higher probability that the events E2 and E3 will occur.
Ultimately, we can use the Bayesian net in order to determine the probability of joint occurrence of any
combination of the three economic shocks. As we can see from the Bayesian net, these probabilities are
not independent. Given such a structure, the probabilistic relationship between the occurrence of shock
E1 and the joint occurrence of E1 and E2 is given by the relationship:
P( E1 E2 )
PE2 | E1
P( E1 )
In this scenario, there are six conditional probabilities.
PE2 | E1 PE3 | E1 PE1 | E2
PE2 | E3 PE3 | E2 PE1 | E3
6|P a ge
7. One additional useful fact about the Bayesian net is that large and complex Bayesian nets are able to
provide us a powerful deductive tool in cases when we only have some of requisite information.
7|P a ge
8. DECONSTRUCTING A BAYESIAN NET
We can use the relationship between conditional and joint probabilities to deconstruct the joint
occurrence of any combination of events into a functional form. Consider the following Bayesian net:
The probability of these events happening at the same time is:
P(A ∩ B ∩ C ∩ D)
Since for any two events E1 and E2:
P( E1 E2 )
PE2 | E1 <=> P(E1 ∩ E2) = P(E2 | E1) . P(E1)
P( E1 )
It follows that:
P(A ∩ B ∩ C ∩ D) = P(A | B ∩ C ∩ D) . P(B ∩ C ∩ D)
The joint probability on the right hand side of the equation can further be deconstructed by using the
same rule. If we follow this through to its logical conclusion, we get:
P(A ∩ B ∩ C ∩ D) =
P(A | B ∩ C ∩ D) . P(B | C ∩ D) . P(C | D) . P(D)
This principle of breaking down the full joint probability into a combination of conditional and marginal
probabilities is the first step towards solving the Bayesian net.
A more practical way of deconstructing the Bayesian net is by ordering the events from bottom to top
before deconstructing the model into a functional form. If we start from a reverse ordering, we can
show that:
8|P a ge
9. P(D ∩ C ∩ B ∩ A) =
P(D | C ∩ B ∩ A) . P(C | B ∩ A) . P(B | A) . P(A)
Of course, the end result should be the same. The rationale for this reverse ordering will become clear in
the next chapter.
CONDITIONAL INDEPENDENCE
The Bayesian net orders the events in a parent-child relationship. In our diagram:
Node A is a parent node of node D and node C. Node D and node C are children of node A. Node B is also
a parent of node C, but not of node D.
We can see that node A is the only node that affects node D. As a consequence, the probability of D
following from A, B and C is equal to the probability of D following from just A. This can written as:
P(D | C ∩ B ∩ A) = P(D | A)
Node C is affected by node A and node B, but not by node D. By the same reasoning, the probability of C
following from A, B and D is the same as the probability of C following from A and B:
P(C | D ∩ B ∩ A) = P(C | B ∩ A)
In general, a probability where a node is dependent on its parents and other nodes that are not its
parents can be reduced to the probability where that node depends only its parents. It is said that nodes
C and D are conditionally independent: the nodes aren’t independent from one another (since they are
still connected through their parent A), but once the states of their parent A is known, node C contains
no extra information that would help us determine whether event D has occurred, or vice versa.
9|P a ge
10. We can put the rules of conditional independence to use, and further reduce the functional form of the
Bayesian structure from the point where we left off in the earlier chapter:
P(D ∩ C ∩ B ∩ A) =
P(D | C ∩ B ∩ A) . P(C | B ∩ A) . P(B | A) . P(A)
with P(D | C ∩ B ∩ A) = P(D | A)
Which leads to:
P(D ∩ C ∩ B ∩ A) =
P(D | A) . P(C | B ∩ A) . P(B | A) . P(A)
INDEPENDENCE
When two nodes are fully independent, it means that they don’t contain information about each other’s
occurrence. In the diagram we are considering:
Nodes A and B are considered to be fully independent of one another. As a result, the conditional
probability of one happening if the other has happened is equal to the probability of one happening
regardless of whether the other has happened:
P(A | B) = P(A)
P(B | A) = P(B)
Note that it is not correct to state that P(D|C) = P(D). Node D and node C may be conditionally
independent, but they are not independent since they are connected through their parent A
(independence and conditional independence are different concepts with different rules).
10 | P a g e
11. Applying this principle, we can reduce the functional form of this model to its final form:
P(D ∩ C ∩ B ∩ A) =
P(D | A) . P(C | B ∩ A) . P(B | A) . P(A)
with P(B | A) = P(B)
Which leads to:
P(D ∩ C ∩ B ∩ A) = P(D | A) . P(C | B ∩ A) . P(B) . P(A)
The final functional form consists of marginal probabilities of the parent nodes and conditional
probabilities of the occurrence of the parent nodes causing the occurrence of their children. This
functional form will be used by the program (see section below) to create the table of joint probabilities
for all combinations of events.
The Program
TECHNOLOGY
The program is created in Excel and written in Visual Basic for Applications (VBA).
DRAWING A BAYESIAN NET IN EXCEL
First of all, the risk manager needs to decide what the events are that he or she wishes to consider.
These events are drawn in the structure of a Bayesian net. If we take the diagram:
11 | P a g e
12. In this scenario, a risk manager considers four possible events A, B, C and D. Event A could be an equity
crash, event B a housing market crash, and so on.
The Bayesian net is entered into Excel in a two-dimensional matrix form. A matrix representation of the
diagram above looks as follows:
A B C D
A 1 0 0 0
B 0 1 0 0
C 1 1 1 0
D 1 0 0 1
The diagonal in the matrix is filled with ones. The upper right triangle is filled with zeros. These values
aren’t used by the program. The connection structure of the Bayesian net can be read from the lower
left triangle, where the ones indicate which nodes are connected to which: the titles of the columns
indicate where the connections start, whereas the titles of the rows indicate where each node is
connected to. The relevant ones are marked in bold.
A VBA program is able to read values from cells in Excel. This allows the program to understand what the
Bayesian net looks like.
ENTERING THE PROBABILITIES
Each of the events has a probability of occurring within the time frame that the risk manager chooses to
consider. This marginal probability is the probability that the event occurs during the chosen time frame
(regardless of how it is triggered). In addition, the Bayesian net shows that if event A occurs, there is a
probability that A will trigger events D and C. Similarly, event B can trigger event C.
The risk manager needs to make an assessment for the following pieces of information:
- P(A): the marginal probability that event A occurs
- P(B): the marginal probability that event B occurs
- P(C): the marginal probability that event C occurs
- P(D): the marginal probability that event D occurs
- P(D|A): the conditional probability that event A, when it occurs, triggers event D
- P(C|A): the conditional probability that event A, when it occurs, triggers event C
- P(C|B): the conditional probability that event B, when it occurs, triggers event C
- P(C|A∩B): the conditional probability that events A and B, when they occur together, trigger
event C
12 | P a g e
13. In general, the risk manager needs to specify a marginal probability for each of the events, and a
conditional probability for each parent-child connection inside the Bayesian net. Note that while related,
the conditional probability of C being triggered by events A and B occurring together does not follow
directly from the conditional probability of A triggering C and the conditional probability of B triggering
C. For example, the occurrence of A and B happening at the same time could lead to a dramatically
higher probability of C occurring than if A or B would occur separately. The risk manager takes this into
consideration by supplying both the single-conditional probabilities and the double-conditional
probability.
Since these are probabilities, the risk manager will supply values between 0 and 1 for each.
DOUBLE-CONDITIONED PROBABILITIES
A double-conditioned probability arises from the situation where two parent nodes share one child
node. In the example we are considering there is one double-conditioned probability: where A and B are
the parent nodes and C is the child node.
Rebonato assumes that there won’t be any networks where nodes can have more than two parents.
This means that double-conditioned probabilities are the most complex conditioned probabilities we can
encounter.
Unfortunately, the book is incomplete as far as double-conditioned probabilities go (see A Word of
Caution About The Book, below). In order to allow the program to solve double-conditioned
probabilities, the risk manager needs to supply one more conditional probability: the one where one
parent leads to the other parent. In our example, this would be P(A|B). When the parent nodes are
independent this is easy: P(A|B) should then be given the same value as P(A), according to the Bayesian
rules of independence. If the nodes are not independent but instead conditionally independent, things
get more complex. See A Word Of Caution About The Book, below for a derivation.
CHECK IF ALL VALUES ARE ENTERED
Based on the matrix representation above, the program knows the names of the nodes and the
connections between them. The program uses this information to deduce what the required
probabilities are, and checks the rest of the Excel sheet for their values. The program will prompt the
risk manager if any values are missing.
13 | P a g e
14. SANITY CHECKS
It is possible that the risk manager provides values that by themselves look correct, but when combined
imply an impossible situation. For example, consider the following triplet of values:
- P(A) = 0,16
- P(B) = 0,03
- P(B|A) = 0,25
Each of these probabilities look fine by themselves (they are numbers between 0 and 1). However,
combined they imply the following impossible situation:
- Out of 100 situations, there will statistically be 16 situations where A occurs.
- 25% of these situations lead to B also being true. Meaning that out of 100 situations, there are 4
instances where B is true following from the fact that A is true.
- However, the probability of B in itself is only 3%. There should only be 3 cases out of 100 in total
where B is true! The number of instances of B occurring as a result of the occurrence of A is too
high.
These kinds of impossible situations can be checked for by applying Bayes’ theorem. In our example:
P(A|B) = P(B|A) . P(A) / P(B) with P(B|A) = 0,25; P(A) = 0,16; P(B) = 0,03
<=> P(A|B) = 1,3333 (!)
The resulting conditional probability is higher than 1. This is an impossible value. This procedure allows
the program to recognize that the values that the risk manager supplied are inconsistent. The program
checks all possible conditional probabilities that can be created from the values that the risk manager
supplied, and verifies that in no situation there is a probability that is not between 0 and 1. This is the
process of sanity checking.
The sanity checking process will warn the risk manager which values are inconsistent, if any. The risk
manager can then enter new values. In our example, the risk manager could lower the probability that A
happens, lower the conditional probability that B happens if A happens, or raise the probability that B
happens. Or a combination of all three.
THE JOINT PROBABILITY TABLE
Once all required values have been found and are consistent, the program deduces the functional form
of the Bayesian net from the matrix representation, by deconstructing the joint probability and applying
the rules of conditional independence and (full) independence. The program then calculates the full
joint probability table by applying the rules of Bayesian logic on the values that the risk manager
14 | P a g e
15. entered. While this is a calculation-heavy process, the risk manager only needs to sit back and wait for
the results.
GAINS AND LOSSES
The program allows the risk manager to associate losses (or if appropriate, gains) for each of the events.
These losses are used to calculate extra information: since a probability is calculated for every
combination of events, it is possible to calculate the loss that is associated with that combination of
events, and the probabilistic loss. This can be used to calculate various forms of capital (economic,
regulatory, etc.
THE PROGRAM CODE
A full listing of the program code can be found in Appendix 7.
A WORD OF CAUTION ABOUT THE BOOK
While Rebonato‘s insights into stress testing and his views on how to take it to the next level are
commendable, the way he puts the material in practice in this book leaves a lot to be desired. We were
surprised to discover that the procedure which Rebonato describes as a general way to generate the
joint probability table doesn’t actually work when one tries to put it in practice. This is because of two
reasons:
- In Chapter 11, the transition in 11.24 is mathematically incorrect as it does not follow from the
Bayesian rules as Rebonato claims. However, the further development of the procedure is based
on this transition.
- Also in Chapter 11, Rebonato gives a partial explanation for how to break up doubly-jointed
probabilities. Formula 11.32 contains a term P(C|D) that can’t be solved in a trivial way.
However, Rebonato concludes the explanation at this point with the sentence “The good news is
that, given the limited topological complexity (…), matters do not get any more complex”.
Unfortunately, matters really do get more complex.
We created a new procedure for handling doubly-conditioned probabilities, and used this instead of the
one that Rebonato suggests in Chapter 11. The current procedure for evaluating a Bayesian net is based
on the principles that are explained in Chapter 8, not on the procedure that can be found in Chapter 11.
In order to make it work, we had to find a mathematically consistent way to obtain the term P(C|D)
from 11.32, and for resolving doubly-conditioned probabilities in general.
15 | P a g e
16. We emailed Dr. Rebonato about the term P(C|D). He was quick to help us, confirming the situation by
replying that his thoughts on the matter have evolved a lot since he wrote the book and sending us a
draft of a new book that looks at the same problems in a somewhat different light. We decided to stay
with the old book for the scope of this thesis since that was its topic. However, we used the
confirmation of Dr. Rebonato as a basis for coming up with a way of solving the term in question that
isn’t in the book (credit Dr. Nicolas Vander Vennet and Wim Konings of Deloitte). This derivation is:
P(D ∩ C) = P(D ∩ C ∩ A) + P(D ∩ C ∩ Â)
= P(D|C ∩ A) . P(C|A) . P(A)
+ P(D|C ∩ Â) . P(C|Â) . P(Â)
= P(D|A) . P(C|A) . P(A) + P(D|Â) . P(C|Â) . P(Â)
with P(D ∩ C) = P(D|C) / P(C)
This way of solving the term P(C|D) and similar terms in general allows us to reduce Bayesian nets with
doubly-jointed probabilities.
LINEAR PROGRAMMING
Rebonato explains two ways of coherent stress testing. The methodology explained in Chapter 10 relies
on linear programming. The methodology explained in Chapter 10 relies on Bayesian nets.
Suppose that the risk manager would supply values for the conditional probabilities P(A|C) and P(C|A).
These values are not independent of one another: they are linked through the marginal probabilities of
P(A) and P(C) by Bayes’ theorem. A risk manager might accidentally enter values for the conditional
probabilities that are inconsistent with one another. Linear programming is a technique that checks
whether conditional probabilities are consistent and if not, it alters the values in such a way that they
are made to be consistent.
Since our program uses the Bayesian net approach, a risk manager needs only to provide conditional
probabilities in one direction: from top to bottom. While it is certainly true that there are checks to be
done on the values that the risk manager supplies (the sanity checks), the checks that are performed by
linear programming aren’t relevant to us: the conditional probabilities will never be inconsistent in the
way that linear programming checks for. As such, the linear programming technique, while interesting in
itself, had no added value to our program.
Also: in an email exchange we had with Dr. Rebonato, he stated that he no longer uses linear
programming.
16 | P a g e
17. The Scenario
TARGET BANK
The target bank for the stress scenario is Österreichische Volksbanken-AG. The bank’s activities are
diversified into five strategic segments. These are retail banking, real estate, corporate banking
(corporate segment), and investment banking (financial markets segment) and asset management
(investment book/other operations segment). Overall, Volksbank has 594 subsidiaries, most of which as
wholly-owned. For the most part, the Volksbank subsidiaries are headquartered in Central and Eastern
Europe.
Volksbank’s retail banking operation is active in Austria via VB Leasing Finanzierungsgesellschaft m.b.H.
and in Bosnia, Croatia, Czech Republic, Germany, Hungary, Malta, Romania, Serbia, Slovakia, Slovenia,
Russia, and Ukraine via Volksbank International (VBI) and via VB-Leasing International Holding GmbH.
Furthermore, Volksbank has a large number of daughter companies spread throughout Central and
Eastern Europe and operations in the CEE region have been ongoing since 1991.
STRATEGIC BUSIENSS SEGMENTS
Volksbank AG
Financial Investment
Corporate Retail Real Estate Book/Other
Markets Operations
Segment Segment Segment
Segment Segment
The Retail segment of Volksbank’s business provides various banking and related financial products and
services, including deposit products, lease financing, project and real estate financing, treasury products,
and advisory services to private individuals, and small and medium sized enterprises. Furthermore, the
retail segment involves retail banking in both Austria and in the Central / Eastern European region.
Retail operations are divided into two companies. VB Leasing Finanzierungsgesellschaft m.b.H. is
17 | P a g e
18. responsible for domestic operations in Austria, while Volksbank International owns ten daughter
companies responsible for retail banking in Central and Eastern Europe. 2010 domestic operations were
the most successful in Volksbank’s history8. Volksbank’s International holdings meanwhile, experienced
a small decline in total value of assets. As outlined in the segmental reporting for 2010 displayed in the
appendix, this is the largest of Volksbank’s business segments in terms of net income and the second-
largest in terms of total assets, comprising 72% and 35% respectively of overall Volksbank figures. In
addition, this operational segment is characterized by a large concentration of Volksbank’s exposure to
Central and Eastern European markets.
This is an area of high initial vulnerability. Because success in the retail banking segments depends on
generation of new loans, successful rates of loan repayment, and deposits, this may be an initial point of
shock-entry, where negative and positive economic shocks might first enter the banking system and
start to affect Volksbank. Furthermore, a shock in this commercial segment might lead to further risks
within the bank. It would therefore be reasonable to assign shocks to this segment of Volksbank a
relatively high spot on the Bayesian net topology.
The bank’s real estate segment focuses on commercial real estate financing as well as real estate leasing
and real estate project development (each via different subsidiaries) in both Austria and the CEE region.
Furthermore, real estate project development is done in collaboration with partners and co-investors
from both the international public sector and private sector entities other European countries.
Performance in this segment improved during 2010 and risks were reduced significantly vis-à-vis 2009.
This is another potential entry point through which economic shocks might enter the banking system.
During the 2008 financial crisis, the collapses of asset values within the real estate sector in the US were
the first shock which touched-off the worldwide financial crisis. For Volksbank, this is another business
segment in which expose to the CEE market is concentrated. Moreover, Volksbank’s exposure to the
region in this segment reaches beyond the EU’s borders as far as Russia, making this segment potentially
more volatile than other Volksbank business segments. Thus, a high place in the Bayesian topology
should be assigned to shocks emanating from this segment.
Volksbank’s corporate segment provides banking services to firms and entrepreneurs. This includes a
diverse range of services ranging from project finance to private equity, M&A, leveraged finance,
corporate lending, and syndicated financing. Germany is the core market for the corporate segment.
The 2010 Annual report indicates that corporate lending was muted because corporate spreads were
high and that client firms were in fact not expanding their operations nor their physical capital. Export
financing meanwhile saw an increase in demand for transaction-linked loans. As for project finance on
the other hand, 2010 was a successful year.
While it is likely that corporate banking may suffer some vulnerability, due to generalized downturns in
corporate activity and profitability, any initial shocks suffered in this area are likely to be highly localized.
In the event of a wider stress situation however, a generalized exposure of corporate counterparty
8
Volksbank, 2010
18 | P a g e
19. clients to an economic shock would threaten the sustainability of this business segment within
Volksbank. Therefore, in a real-life situation, it would be likely that a generalized shock to this segment
would emerge only as a secondary step within a crisis scenario.
The financial markets segment offers exchange rate, derivatives, money market, and interest and price
products, as well as involves in securities and foreign exchange trading, and asset management
businesses.
The investment book/other operations segment in concentrated on management of Volksbank Group’s
assets. It is the group’s largest segment in terms of total assets, but has seen negative net income in
both 2009 and 2010.9
While Volksbank group’s geographic focus is primarily on Central and Eastern Europe, the segment
reporting by regional markets reveal that 81% of income from financial investments is drawn from
“other markets” in 2010, while 90% of income from financial investments was drawn from Austria in
2009.10
The potential vulnerabilities of these two segments lie in their international transmission roles.
Essentially, this segment could turn into a transmission mechanism for contagion in the CEE region, as is
true for this segment’s counterparts in competitor banks in the CEE such as KBC and Credit Agricole. It is
therefore plausible that regulatory authorities in the CEE region may act in order to either respond to or
preempt contagion transmission. Such action might take the form of capital controls affecting foreign
exchange positions and transactions or special taxes and restrictions suddenly erected vis-à-vis positions
in specific asset classes.
Another viable possibility would be that of sudden radical loss in asset values and portfolios. These could
come as a result of bond defaults (either sovereign or corporate) or the crash of equities markets. This in
turn could affect the bank’s overall financial health and even bring problems home to Austria, as assets
would have to be reduced in order to maintain liquidity and solvency. Such an event should be assigned
an intermediate position within a Bayesian topographical structure.
CENTRAL AND EASTERN EUROPE
The Central and Eastern European market is quite an interesting market for in which to analyze bank
operations due to its position on the frontier of the EU. This market is constituted by a dynamic mix of
Eurozone countries, peripheral non-Eurozone EU countries and non EU countries. Operations in this area
play a central role in Volksbank’s activities and Volksbank’s exposures. According to the 2010 Annual
Report, 71% of Volksbank’s net income flows from CEE region operations while 18.6% was drawn from
Austrian operations. Despite the fact that
9
Volksbank, 2010
10
Ibid
19 | P a g e
20. Nevertheless, the Non-EU regions of Central and Eastern Europe suffer for much higher volatility than
do the core EU countries. Ukraine suffered a 15.1% GDP decline in 2009 and returned to positive GDP
growth figures the following year while Romania swung from a 7.3% GDP increase in 2008 to a 7.3%
contraction the following year.11 It would appear that Volksbank takes seriously the risks of doing
business in the CEE region. According to its 2010 Annual Report, risk provisions for operations in Austria
were 36% of regional net income. Risk provisions for CEE operations meanwhile were 54% of regional
net income.
2009 was a year of negative GDP growth across the entire region of operation, ranging from a 15.1%
GDP drop in the Ukraine to a 3% GDP drop in Serbia. In Croatia, direct investments and gross capital
investments have also declined year-after year. Direct investments have declined by a full 30% in 2009,
as the flow of investment from the core EU dried up. 12
In 2010, recovery was uneven across the region, with Croatia and Romania experiencing negative GDP
growth, while Slovakia experienced a 4.1% GDP growth. Overall, exports are a main driver of GDP
growth in the region, while government expenditures declines year-after year.
In comparison, the German GDP saw a 1% increase during 2008 and a 4.7% decrease as Germany
reduced its spending in 2009. In 2010, German GDP growth recovered to 3.7%, the highest GDP growth
figure since reunification. 13
The Eurozone GDP meanwhile, grew at 0.4% in 2008 and suffered a 4.1% GDP contraction in 2009. The
following year brought 1.7% GDP growth. In 2010, the also Eurozone experienced a strong recovery of
industrial production, with capital goods experiences double-digit growth rates.14
According to Volksbank’s 2010 annual report, the stated business strategy for the CEE region includes a
conservative risk strategy and a focus on microenterprise and SME’s.
SOURCES OF VULNERABILITY
Given the structure and exposures of Volksbank, there are a number of potential sources of bank stress.
There are both environmental potential sources of bank stress as well as firm-specific idiosyncratic
potential sources.
Intransparency in the financial markets
Poor understanding and management of risks and uncertainties
Poor understanding and management of liquidity and characteristics of assets in portfolio
11
Ibid
12
Ibid
13
Ibid
14
Ibid
20 | P a g e
21. Underlying the 2008 financial crisis was increased intransparency in the global financial markets in
relation to the growth of financial innovation during the period immediately preceding the financial
crisis. This intransparency was the result of financial innovation outpacing the growth in accompanying
regulation aimed at ensuring best practices. In fact, regulation actually shrank during this period, as did
financial regulatory enforcement capability.
The resulting financial environment was one in which gaps and lags in general understanding of risk and
uncertainty in the financial markets were widespread.
Another feature of the 2008 financial crisis was immediate onset of chronic illiquidity which ensued
once it became clear that the financial models upon which many of the positions and portfolios of many
of the major investment banks were built had – for all their complexity – failed to provide a complete
understanding of risks and uncertainties in the financial markets.
Since 2008, a consensus has emerged regarding generalized misunderstanding of risk and uncertainty in
the financial markets reflecting the Keynesian view that there are clear distinctions between uncertainty
and risk. The key difference is that we essentially know, understand and can quantify risk. It is a known
unknown. Uncertainty on the other hand, is best represented by the idea that we cannot predict
perfectly the events of the future. 15 Taleb argues that while the bell curve has made us confident that
we have tamed uncertainty, it in fact ignores large and actually cannot handle deviations. 16 Essentially,
the mathematical models built based on understanding of the bell-curve become useless in this context.
In short, many of the largest players in the financial markets became victim of their unknown unknowns.
Lax lending standards and regulations
Leverage during a bubble situation
Insufficient standards for capital vis-à-vis the positions, portfolios, and activities of the financial
and banking sectors
Generally, the development of asset bubbles takes place in a context of massive amounts of leverage
and lax lending standards. Furthermore, standards for capital and loss provisions are usually insufficient
for the riskiness of the operations of the parties.
During the US asset bubble linked to the 2008 financial crisis, lax capital requirements stemmed from an
imperfect understanding of the risks, uncertainties, liquidity, and correlation of recently-developed
financial derivatives being traded.
Interconnectedness/correlation of segments and segmental shocks
Correlation of asset classes is a common characteristic of nearly all financial crises. This undermines the
stability and security value of diversified portfolios during such times. In many cases, it is the growth of
financial innovation and the nature of ownership structure which actually leads to the
interconnectedness of the asset classes.
15
Skidelsky, 2009
16
Taleb, 2007
21 | P a g e
22. Prior to the 2008 financial crisis for instance, (Real Estate Investment Trust) REITs were a common way
in which real estate exposure was included in portfolios. This is especially true of exposure to overseas
real estate. While real estate investment is typically characterized by its non-correlation with other asset
classes, REITs were known to have high correlation to equity.
Currency crisis
Collapse of one of the CEE region economies
Contagion
The CEE region’s dependence on export-led growth could easily make it susceptible to economic
downturns in trading partners. Furthermore, given the CEE region’s highly volatile GDP growth and
dependence on the core EU countries as a source of investment, the collapse of an individual economy
in the CEE region could occur. Such an event would have far-reaching consequences.
Due to both dependence on export-driven growth and the economic interconnectedness of this region,
the possibilities for contagion are quite good. Furthermore, the most of the region’s financial
investments come from the same source-Western Europe-. This means that the same asset managers
might quickly dump all of their assets in the region once they detected trouble in one country, further
exacerbating contagion potential.
During the 1998 Asian financial crisis, the collapse of export-growth-dependent economies came in the
form of a localized currency crisis, which then provoked a regional contagion. The central mechanism
was one of losses in Thailand due to devaluation of the Thai Baht led to a region-wide sell-off of assets
by international investors. Furthermore, the Asian financial crisis arose in the aftermath of a region-wide
liberalization of foreign portfolio investment regulations and financial capital mobility regulations in the
early 1990’s. It is a well-documented phenomenon that increases in capital mobility have historically
been followed by crisis.17
Currency instability in one of the CEE countries would lead to losses in value of local-currency-
denominated assets, leading to their sell-off, irrespective of the actual domestically-weighted
performance of said assets.
Decline in the retail banking business in home market or in low-volatility foreign markets.
Any sound bank, business, or portfolio needs solid diversification in order to minimize idiosyncratic risk.
Given the size and importance of Volksbank’s retail segment as part of its overall business, it would be
safe to assume that potentially more lucrative, higher-risk operations on the periphery of the CEE region
are being financed with deposits and income from retail operations in less volatile countries. The
deposits and income from the retail segment also serve to maintain the banks liquidity as it invests in
peripheral risky projects and maintain solvency in the event of losses stemming from riskier peripheral
activities. Thus, the bank’s riskier activities are counterbalanced by a large and regionally-diversified
17
Reinhart and Rogoff, 2008
22 | P a g e
23. retail banking business. A decline in this business would lead to high exposure and higher sensitivity to
peripheral volatility, exacerbating the effect of any adverse shocks.
CAPITAL
Volksbank’s regulatory capital can be broken into three elements.18
Tier I: Core Capital consisting of capital reserves, retained earnings, subscribed capital, and
hybrid capital less intangible assets.
Tier II: Supplementary Capital consisting of non-current subordinated liabilities, unrealized
trading profits, and risk provisions from lending operations. Amount is limited to 100% of Tier I
capital.
Tier III: Short-term (current) Subordinated Liabilities.19 Tier III capital may only be employed to
cover market risks.20
In 2010, Austrian capital requirements were slightly in excess of Basel II requirements. Capital
requirements in Austria are compared against a risk-weighted assessment base, comprised of assets,
activities, and positions. Volksbank’s 2010 regulatory risk-weighted assessment base was reported at 25,
25.5 Billion EUR.
While the minimum credit risk capital requirement was 8%, the Austrian government imposed further
capital requirements for both market risk and operational risk. According to Volksbank’s Annual Report,
2010 Tier I capital requirement stood at 2.230 Billion EUR, constituting a core capital requirement ratio
of 8.76% of the risk-weighted assessment base. Nevertheless, Volksbank’s actual capital stood at 2.612
Billion EUR, constituting a core capital ratio of 9.37%.
Volksbank’s 2010 Total Eligible Capital figures showed a total capital buffer of 3.562 Billion EUR,
constituting 14% of the bank’s risk-weighted assessment base.21
18
Volksbank 2010
19
Ibid
20
Ibid
21
Ibid
23 | P a g e
24. THE STRESS SEQUENCE
A1: A localized currency crisis occurs in the CEE region. Foreign-currency-denominated assets radically
decrease in value.
Total assets and annual result before taxes suffer a 10% haircut vis-à-vis 2010 figures. This
represents losses caused by exposure to the localized currency crisis, which is assumed to locally
penetrate all business segments.
A2: A spike in industrial plant closures occurs in the core Eurozone counties. The macro-effect of the
closures in the Eurozone economy is a drop in output, demand, and employment. All of these factors
come to have an effect in node B2. The direct and immediate effect of the closures takes the form of:
A 5% decrease in corporate segment annual result before taxes, as the flow of projects
diminishes.
Correspondingly, a 5% increase in real estate annual results stems from commercial space
turnover in the real estate segment.
B1: The shock, which was localized in node A1, spreads throughout the CEE region as asset managers
rebalance their portfolios, and as there is a generalized sell-off of CEE financial assets. GDP growth
becomes negative through the region, Germany. While Germany meets the 2011 GDP growth forecast
24 | P a g e
25. outlined in Appendix 2, the rest of the region posts GDP growth figures in line with 2009 results. Net
trading income and income from financial investments decline as a result.
Net trading income and income from financial investments for the CEE region recede to 2009
levels. These losses are ascribed to the financial markets and investment book segments as
outlined in Appendix 3.
B2: The secondary effect of the industrial plant closures in core Eurozone countries for the banking
sector overall and specifically for Volksbank, is decline in core-EU-based retail, real estate, and corporate
banking.
A generalized 20% decline in net interest income, fee and commission income derived from
Austrian operations.
A 10% decline net interest income, fee and commission income, representing the German
market.
C: The combination of downturns in retail and corporate banking in the core Eurozone and the spread
of financial crises across Central and Eastern Europe transmit to Western European equity markets. The
result is a drop in Western European equity markets. For Volksbank, the effects are multi-faceted.
Trading and financial income take a haircut avoid going negative. Increases in cost of capital cause
liabilities to increase while assets from both the trading book and held-to-maturity segments of
Volksbank.
Liabilities increase as financing costs increase. Amount owed to credit institutions increases by
15%.
Assets of the Trading Book, Financial Market, and Corporate segmental assets fall in value by
20% (this amounts to a 12% decline on total assets).
Net income from financial investments becomes zero.
D: Volksbank is forced to deleverage and unwind its positions at a loss in order to attempt to maintain
solvency as well as to rebuild its capital buffers and risk provisions. No specific assumptions are made
vis-à-vis the makeup of the liquidated assets.
Total assets fall by an additional 15%. The losses are proportionally distributed across the
segments.
Shareholder’s Equity declines by offsetting amount.
25 | P a g e
26. Node Loss/Gain Amount ('000) To/From
A1 Total assets and annual result before taxes suffer a 10% haircut vis-à-vis 2010 -4,655,567 • Total Assets
figures. • Annual result before
taxes
A2 • A 5% decrease in corporate segment annual result before taxes, as the flow of -1,360 • Corp. result before
projects diminishes. taxes
• Correspondingly, a 5% increase in real estate annual results stems from • RE result before taxes
commercial space turnover in the real estate segment.
B1 Net trading income and income from financial investments for the CEE region -15,125 • Net Trading Income
recede to 2009 levels. These losses are ascribed to the financial markets and • Income from Fin. Inv.
investment book segments
B2 • A generalized 20% decline in fee and commission income derived from Austrian -23,735 • Fee and commission
operations. income
• A 10% decline in fee and commission income, representing the German market.
C • Liabilities increase as financing costs increase. Amount owed to credit -6,329,424 • Amount owed to
institutions increases by 15%. credit institutions
• Assets of the Trading Book, Financial Market, and Corporate segmental assets • Assets
fall in value by 20% (this amounts to a 12% decline on total assets). • Annual result before
• Net income from financial investments becomes zero. taxes
D Total assets fall by an additional 15%. The losses are proportionally distributed -5,652,794 Total Assets
across the segments.
THE BAYESIAN NET
26 | P a g e
27. Conclusion
The intention of this research is to suggest improvements to commonly-used stress-testing
methodologies in order to address what have been identified as methodological shortcomings,
particularly in the European context, wherein the European Commission has already expressed
dissatisfaction with both the 2009 and the 2010 stress tests.
The key missing ingredient from stress testing procedures is a solid way of capturing the co-relationships
between the various stress events. The co-relationship between the stress events should be assigned by
experts, and informed by as broad a range as possible of indicators or future occurrences, events, and
vulnerabilities. By finding such a way, we would be able to generate statistical information about stress
losses that are more realistic than losses captured by conventional stress testing methodologies.
The Bayesian net approach to stress testing proposed here is based on the work of Dr. Rebonato. We
developed a teaching tool based on this material in the form of a Powerpoint presentation, with
contents that should take one workshop day to cover. In addition, we developed a program written in
Excel and Visual Basic for Applications (VBA) that allows a risk manager to enter a Bayesian scenario with
a structure of choice and accompanying subjective probabilities and potential losses. The program
checks the entered data for consistency, and then generates the full joint probability table and an
accompanying conditional losses table that allows the risk manager to assign capital positions to his
scenario. Finally, we developed a realistic case that demonstrates the usefulness of the approach to
potential clients with the example of Volksbank. The scenario which we construct for Volksbank is a
multi-stage stress scenario. Essentially, it is a meta-stress scenario. The subjective probabilities in the
scenario are based on, as well as drawn from the sources of potential vulnerability included in the
scenario analysis.
In creating these contents, we had to revise some points from the practical procedure of resolving a
Bayesian net in the book that turned out to be problematic. We feel that our work is a useful addition to
the book.
What we suggest in this paper is a viable, more complete and comprehensive way of stress testing
which can be easily implemented by banks and regulators in order to cope with the causality and
correlation among economic shocks. The step towards a more complete methodology for stress testing,
which is both updating and includes forward-looking information is necessary going into the future. If
we have learned anything from the 1998 Asian financial crisis and the 2008 global financial crisis, it is
that economics shocks are often correlated and that a severe crisis comes in stages.
27 | P a g e
28. References
Basel Committee on Banking Supervision, “Principles for Sound Stress Testing and Supervision”,
Consultative Document, Basel, January, 2009
Bloomber Businessweek
http://investing.businessweek.com/research/stocks/private/snapshot.asp?privcapId=875308
De Jonghe, Frank, “Financial Risk Management”, Lecture Series, Ghent University, 2010
De Jonghe, Frank and Nikolas Vander Vennet, “Some New Approaches to Stress Testing and Scenarios
Analysis”, Deloitte, 2011
Rebonato, Ricardo “Coherent Stress Testing: A Bayesian Approach to the Analysis of Financial Risk” 2010
Reinhart and Rogoff, “This Time it’s Different: A Panoramic View of Eight Centuries of Financial Crises”
NBER, 2008
Skidelsky, Robert “Keynes, Return of the Master” Allen Lane, 2009
Taleb, Nassim, “The Black Swan: The impact of the Highly Improbable” Allen Lane, 2007
Volksbank, “2010 Annual Report”, Vienna, 2010
28 | P a g e
33. Appendix 2
2010 Volksbank segmental breakdown taken form page 156 of Volksbank’s 2010 Annual Report
33 | P a g e
34. Appendix 3
2010 Volksbank regional breakdown, domestic vs. foreign markets, taken from page 157 of Volksbank’s
2010 Annual Report
34 | P a g e
35. Appendix 4
2010 Income Statement, taken from page 98 of Volksbank’s Annual Report
35 | P a g e
36. Appendix 5
Volksbank Statement of Financial Position (Balance Sheet), taken from page 99 of 2010 Annual Report
36 | P a g e
37. Appendix 6
Economic Growth outlooks and construction activity outlook in the CEE region, taken from pages 34 and
48 of the 2010 Volksbank Annual Report
37 | P a g e
38. Appendix 7
Visual Basic for Applications code of the program
Option Explicit
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Author: Kevin Hoefman, 22 June 2011, contact: kevin.hoefman@howest.be
' Notes:
' - I am using one-based array counting throughout this program. In a variable Values(4), I will use Values(1), Values(2), Values(3) and Values(4)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sub CheckTopology()
'Select Topology range and dimensions
Dim Topology As Range
Set Topology = Worksheets(1).Cells(1, 1).CurrentRegion
Dim Message As String
CheckTopology_Range Topology, Message
MsgBox (Message)
End Sub
Function CheckTopology_Range(ByVal MyRange As Range, ByRef Message As String) As Boolean
Dim RowCount, ColumnCount
RowCount = MyRange.Rows.Count
ColumnCount = MyRange.Columns.Count
'Check matrix symmetry, abort if not
If RowCount <> ColumnCount Then
Message = "Fail: Matrix is not symmetric"
CheckTopology_Range = False
Exit Function
End If
'Check if cells are filled in properly, abort if not
If Trim(MyRange.Cells(1, 1)) <> "" Then
MsgBox ("Fail: Improperly formed topology - Top left cell should be empty")
CheckTopology_Range = False
Exit Function
End If
Dim Count
For Count = 2 To RowCount
If Trim(MyRange.Cells(1, Count)) <> Trim(MyRange.Cells(Count, 1)) Then
Message = "Fail: Improperly formed topology - Column titles don't match row titles"
CheckTopology_Range = False
Exit Function
End If
Next
Dim SubTopology As Range
Set SubTopology = Range(MyRange.Cells(2, 2), MyRange.Cells(RowCount, ColumnCount))
Dim Cell
For Each Cell In SubTopology
If Trim(Cell) <> "0" And Trim(Cell) <> "1" Then
Message = "Fail: Improperly formed topology - At least one inner field is neither 0 nor 1"
CheckTopology_Range = False
Exit Function
End If
Next
'If all was successful, report dimension of topology
Message = "This is a " & (RowCount - 1) & " event topology"
CheckTopology_Range = True
End Function
38 | P a g e
39. Sub GenerateJointProbabilities()
'Select Topology range
Dim Topology As Range
Set Topology = Worksheets(1).Cells(1, 1).CurrentRegion
'Select SubTopology range
Dim SubTopology As Range
Set SubTopology = Range(Topology.Cells(3, 2), Topology.Cells(Topology.Rows.Count, Topology.Columns.Count - 1))
'Select full sheet
Dim FullRange As Range
Set FullRange = Worksheets(1).UsedRange
'Check the Topology just to be sure TODO: checktopology hier insteken
Dim Message As String
If CheckTopology_Range(Topology, Message) = False Then
MsgBox ("Malformed topology - use the CheckTopology button for more information")
Exit Sub
End If
'Extract the event names from the topology
Dim EventNames() As String
ExtractEventNames Topology, EventNames
'Create arrays to hold marginal probabilities, single conditioned probabilities and double conditioned probabilities
ReDim MarginalProbArr(UBound(EventNames)) As MarginalProb
ReDim SingleCondProbArr(1) As SingleCondProb ' will be redimmed
ReDim DoubleCondProbArr(1) As DoubleCondProb ' will be redimmed
'Extract required marginal probabilities and report missing values if any, exit function if missing values
If ExtractMarginalProbabilities(EventNames, MarginalProbArr, FullRange) = False Then Exit Sub
'Extract required single conditioned probabilities
If ExtractSingleConditionedProbs(EventNames, SingleCondProbArr, SubTopology, FullRange, MarginalProbArr) = False Then Exit Su b
'Extract required double conditioned probabilities and their corresponding extra single conditioned probability
If ExtractDoubleConditionedProbs(EventNames, DoubleCondProbArr, SubTopology, FullRange, MarginalProbArr, SingleCondProbArr) = False
Then Exit Sub
'Do Sanity Checks
If CheckSanity(MarginalProbArr, SingleCondProbArr, DoubleCondProbArr) = False Then Exit Sub
'Determine the functional form of the topology
ReDim Functional_MarginalProbArr(1) As MarginalProb
ReDim Functional_SingleCondProbArr(1) As SingleCondProb
Dim SingleConditioned_Count, Marginal_Count, CountSingle, CountMarginal, CountDouble As Integer
SingleConditioned_Count = 0
'Extract the functional single conditioned probability nodes
For CountSingle = 1 To UBound(SingleCondProbArr)
If SingleCondProbArr(CountSingle).IsFunctional() = True Then SingleConditioned_Count = SingleConditioned_Count + 1
Next
ReDim Functional_SingleCondProbArr(SingleConditioned_Count)
SingleConditioned_Count = 1
For CountSingle = 1 To UBound(SingleCondProbArr)
If SingleCondProbArr(CountSingle).IsFunctional() = True Then
Set Functional_SingleCondProbArr(SingleConditioned_Count) = SingleCondProbArr(CountSingle)
SingleConditioned_Count = SingleConditioned_Count + 1
End If
Next
'Determine functional top nodes
If UBound(EventNames) = 1 Then
MsgBox ("Topology is of only 1 dimension, not much to be done here... exiting.")
Exit Sub
Else
Dim CountEmptyRows, CountOnes, CountColumns As Integer
39 | P a g e
40. Dim IsEmptyRow As Boolean
CountEmptyRows = 0
IsEmptyRow = True
Do While IsEmptyRow = True And CountEmptyRows + 3 <= Topology.Rows.Count
CountOnes = 0
For CountColumns = 1 To UBound(EventNames) + 1
If Topology.Cells(3 + CountEmptyRows, CountColumns) = 1 Then CountOnes = CountOnes + 1
If CountOnes > 1 Then IsEmptyRow = False
Next
If CountOnes = 1 Then CountEmptyRows = CountEmptyRows + 1
Loop
'Number of top nodes is 1 more than the number of empty rows
ReDim Functional_MarginalProbArr(CountEmptyRows + 1)
For CountMarginal = 1 To CountEmptyRows + 1
Set Functional_MarginalProbArr(CountMarginal) = MarginalProbArr(CountMarginal)
Next
End If
'Locate the target worksheet
Dim ResultsSheet As Worksheet
Set ResultsSheet = Worksheets(2)
'Clear the results sheet
ResultsSheet.UsedRange.Clear
'Center the range, set titles to desired style, make each column autofit, set the number formats
Dim BottomRow As Integer
BottomRow = 1 + Power(2, UBound(EventNames))
Range(ResultsSheet.Cells(1, 1), ResultsSheet.Cells(BottomRow, UBound(EventNames))).HorizontalAlignment = xlCenter
Range(ResultsSheet.Cells(1, 1), ResultsSheet.Cells(1, 3 + UBound(EventNames))).HorizontalAlignment = xlCenter
Range(ResultsSheet.Cells(1, 1), ResultsSheet.Cells(1, 3 + UBound(EventNames))).Font.Bold = True
Dim Cell As Range
For Each Cell In Range(ResultsSheet.Cells(1, 1), ResultsSheet.Cells(1, 3 + UBound(EventNames)))
Cell.EntireColumn.AutoFit
Next Cell
Range(ResultsSheet.Cells(2, 1 + UBound(EventNames)), ResultsSheet.Cells(BottomRow, 1 + UBound(EventNames))).NumberFormat =
"0.00000000 "
Range(ResultsSheet.Cells(2, 2 + UBound(EventNames)), ResultsSheet.Cells(BottomRow, 3 + UBound(EventNames))).NumberFormat =
"###,###,###,###,##0.00 "
'Fill in Titles
FillInTitles EventNames, ResultsSheet
'Write other table titles
Dim TitleCount As Integer
Dim Title As String
Title = "P("
For TitleCount = 1 To UBound(EventNames) - 1
Title = Title & EventNames(TitleCount) & ", "
Next
Title = Title & EventNames(TitleCount) & ")"
ResultsSheet.Cells(1, UBound(EventNames) + 1) = Title
ResultsSheet.Cells(1, UBound(EventNames) + 2) = "Gain/Loss"
ResultsSheet.Cells(1, UBound(EventNames) + 3) = "Conditional Gain/Loss"
'Write Zeros and Ones
FillInZerosAndOnes EventNames, ResultsSheet
'Calculate and write the joint probabilities
CalculateJointProbabilities EventNames, Functional_MarginalProbArr, Functional_SingleCondProbArr, DoubleCondProbArr, ResultsSheet
'Calculate gain/losses
40 | P a g e
41. CalculateGainLosses MarginalProbArr, ResultsSheet
'Write the capital
Dim CapitalCell As Range
Set CapitalCell = ResultsSheet.Cells(2 + BottomRow, UBound(EventNames) + 3)
CapitalCell.Formula = "=Min(" & ResultsSheet.Cells(2, 3 + UBound(EventNames)).Address & ":" & ResultsSheet.Cells(BottomRow, 3 +
UBound(EventNames)).Address & ") * -1"
CapitalCell.NumberFormat = "###,###,###,###,##0.00 "
CapitalCell.Font.Bold = True
CapitalCell.Offset(0, -1) = "Capital:"
CapitalCell.Offset(0, -1).Font.Bold = True
CapitalCell.Offset(0, -1).HorizontalAlignment = xlRight
Range(CapitalCell.Offset(0, -1), CapitalCell).BorderAround xlContinuous, xlThick, xlColorIndexAutomatic
'Set results sheet active
ResultsSheet.Activate
End Sub
Sub ExtractEventNames(ByVal MyRange As Range, ByRef EventNames() As String)
'Select Topology range and dimensions
Dim RowCount, ColumnCount
RowCount = MyRange.Rows.Count
ColumnCount = MyRange.Columns.Count
'Check matrix symmetry, abort if not
If RowCount <> ColumnCount Then
MsgBox ("Fail: Matrix is not symmetric")
Exit Sub
End If
ReDim EventNames(RowCount - 1)
Dim Count
For Count = 2 To RowCount
EventNames(Count - 1) = MyRange.Cells(Count, 1)
Next
End Sub
Function ExtractMarginalProbabilities(ByRef EventNames() As String, ByRef MarginalProbArr() As MarginalProb, ByRef FullRange As Range) As
Boolean
'Create the necessary amount of objects
Dim Count As Integer
For Count = 1 To UBound(EventNames)
Set MarginalProbArr(Count) = New MarginalProb
MarginalProbArr(Count).Create (EventNames(Count))
Next
'Find their values and exit with either true if all values are found or false if not
ExtractMarginalProbabilities = ScanRangeForMarginalProbs(MarginalProbArr, FullRange)
End Function
Function ScanRangeForMarginalProbs(ByRef MarginalProbArr() As MarginalProb, ByRef FullRange As Range)
Dim MessageMissing As String
Dim CountMarginals, CountFound, RowCount As Integer
Dim Found As Boolean
CountFound = 0
For CountMarginals = 1 To UBound(MarginalProbArr)
Found = False
RowCount = 1
Do While RowCount <= FullRange.Rows.Count And Found = False
If Replace(FullRange.Cells(RowCount, 1), " ", "") = MarginalProbArr(CountMarginals).Name() Then
MarginalProbArr(CountMarginals).CreateValues FullRange.Cells(RowCount, 2), FullRange.Cells(RowCount, 3)
Found = True
End If
RowCount = RowCount + 1
41 | P a g e
42. Loop
If Found = False Then
MessageMissing = MessageMissing & vbCrLf & MarginalProbArr(CountMarginals).Name
Else
CountFound = CountFound + 1
End If
Next
If CountFound = UBound(MarginalProbArr) Then
ScanRangeForMarginalProbs = True
Else
MsgBox ("Missing marginal probabilities:" & MessageMissing)
ScanRangeForMarginalProbs = False
End If
End Function
Function ExtractSingleConditionedProbs(ByRef EventNames() As String, ByRef SingleCondProbArr() As SingleCondProb, ByRef SubTopology As
Range, ByRef FullRange As Range, ByRef MarginalProbArr() As MarginalProb) As Boolean
'Determine necessary space in array
Dim ConditionalCount As Integer
ConditionalCount = 0
Dim CountRows, CountColumns As Integer
For CountRows = 1 To SubTopology.Rows.Count
For CountColumns = 1 To CountRows
If SubTopology.Cells(CountRows, CountColumns) = 1 Then ConditionalCount = ConditionalCount + 1
Next
Next
'Resize array
ReDim SingleCondProbArr(ConditionalCount)
'Create the objects
Dim Position As Integer
Position = 1
For CountRows = 1 To SubTopology.Rows.Count
For CountColumns = 1 To CountRows
If SubTopology.Cells(CountRows, CountColumns) = 1 Then
Set SingleCondProbArr(Position) = New SingleCondProb
SingleCondProbArr(Position).Create EventNames(CountRows + 1), EventNames(CountColumns)
Position = Position + 1
End If
Next
Next
'Find their values and exit with either true if all values are found or false if not
ExtractSingleConditionedProbs = ScanRangeForSinglecondProbs(SingleCondProbArr, FullRange, MarginalProbArr)
End Function
Function ScanRangeForSinglecondProbs(ByRef SingleCondProbArr() As SingleCondProb, ByRef FullRange As Range, ByRef MarginalProbArr() As
MarginalProb)
Dim MessageMissing As String
Dim CountSingleConds, CountMarginals, CountFound, RowCount, PositionChild, PositionParent As Integer
Dim Found As Boolean
CountFound = 0
For CountSingleConds = 1 To UBound(SingleCondProbArr)
Found = False
RowCount = 1
Do While RowCount <= FullRange.Rows.Count And Found = False
If Replace(FullRange.Cells(RowCount, 1), " ", "") = SingleCondProbArr(CountSingleConds).Name() Then
'find the corresponding marginal probabilities
For CountMarginals = 1 To UBound(MarginalProbArr)
If MarginalProbArr(CountMarginals).Node = SingleCondProbArr(CountSingleConds).ChildNode Then PositionChild = CountMarginals
If MarginalProbArr(CountMarginals).Node = SingleCondProbArr(CountSingleConds).ParentNode Then PositionParent =
CountMarginals
42 | P a g e
43. Next
SingleCondProbArr(CountSingleConds).CreateValues FullRange.Cells(RowCount, 2), MarginalProbArr(PositionChild),
MarginalProbArr(PositionParent)
Found = True
End If
RowCount = RowCount + 1
Loop
If Found = False Then
MessageMissing = MessageMissing & vbCrLf & SingleCondProbArr(CountSingleConds).Name
Else
CountFound = CountFound + 1
End If
Next
If CountFound = UBound(SingleCondProbArr) Then
ScanRangeForSinglecondProbs = True
Else
MsgBox ("Missing single-conditional probabilities:" & MessageMissing)
ScanRangeForSinglecondProbs = False
End If
End Function
Function ExtractDoubleConditionedProbs(ByRef EventNames() As String, ByRef DoubleCondProbArr() As DoubleCondProb, ByRef SubTopology
As Range, ByRef FullRange As Range, ByRef MarginalProbArr() As MarginalProb, ByRef SingleCondProbArr() As SingleCondProb) As Boolean
'Determine necessary space in array
Dim DoubleConditionalCount As Integer
DoubleConditionalCount = 0
Dim CountOnes As Integer
Dim CountRows, CountColumns As Integer
For CountRows = 1 To SubTopology.Rows.Count
CountOnes = 0
For CountColumns = 1 To CountRows
If SubTopology.Cells(CountRows, CountColumns) = 1 Then CountOnes = CountOnes + 1
Next
If CountOnes = 2 Then DoubleConditionalCount = DoubleConditionalCount + 1
Next
'Resize array
ReDim DoubleCondProbArr(DoubleConditionalCount)
'Create array for corresponding single conditionals
ReDim DoubleCondBridgeArr(DoubleConditionalCount) As SingleCondProb
'Create the objects
Dim Position As Integer
Position = 1
Dim PositionOfOnes(2) As Integer
For CountRows = 1 To SubTopology.Rows.Count
CountOnes = 0
For CountColumns = 1 To CountRows
If SubTopology.Cells(CountRows, CountColumns) = 1 Then
CountOnes = CountOnes + 1
PositionOfOnes(CountOnes) = CountColumns
End If
Next
If CountOnes = 2 Then
'double conditioned probability found
Set DoubleCondProbArr(Position) = New DoubleCondProb
DoubleCondProbArr(Position).Create EventNames(CountRows + 1), EventNames(PositionOfOnes(1)), EventNames(PositionOfOnes(2))
Set DoubleCondBridgeArr(Position) = New SingleCondProb
DoubleCondBridgeArr(Position).Create EventNames(PositionOfOnes(1)), EventNames(PositionOfOnes(2))
Position = Position + 1
End If
43 | P a g e
44. Next
'Find their values and exit with either true if all values are found or false if not
ExtractDoubleConditionedProbs = ScanRangeForDoublecondProbs(DoubleCondProbArr, DoubleCondBridgeArr, FullRange,
SingleCondProbArr, MarginalProbArr)
End Function
Function ScanRangeForDoublecondProbs(ByRef DoubleCondProbArr() As DoubleCondProb, ByRef DoubleCondBridgeArr() As SingleCondProb,
ByRef FullRange As Range, ByRef SingleCondProbArr() As SingleCondProb, ByRef MarginalProbArr() As MarginalProb) As Boolean
Dim MessageMissing As String
Dim CountDoubleConds, CountMarginals, CountSingleConds, CountFound, RowCount, PositionChild, PositionParentLeft, PositionParentRight,
PositionSingleLeft, PositionSingleRight As Integer
Dim Found As Boolean
CountFound = 0
'First, find the bridge single conditional probabilities, abort if not found
If ScanRangeForSinglecondProbs(DoubleCondBridgeArr, FullRange, MarginalProbArr) = False Then
ScanRangeForDoublecondProbs = False
Exit Function
End If
'If found, find the double conditional probabilities
For CountDoubleConds = 1 To UBound(DoubleCondProbArr)
Found = False
RowCount = 1
Do While RowCount <= FullRange.Rows.Count And Found = False
If Replace(FullRange.Cells(RowCount, 1), " ", "") = DoubleCondProbArr(CountDoubleConds).Name() Then
'find the corresponding marginal probabilities
For CountMarginals = 1 To UBound(MarginalProbArr)
If MarginalProbArr(CountMarginals).Node = DoubleCondProbArr(CountDoubleConds).ChildNode Then PositionChild =
CountMarginals
If MarginalProbArr(CountMarginals).Node = DoubleCondProbArr(CountDoubleConds).ParentNodeLeft Then PositionParentLeft =
CountMarginals
If MarginalProbArr(CountMarginals).Node = DoubleCondProbArr(CountDoubleConds).ParentNodeRight Then PositionParentRight =
CountMarginals
Next
'find the corresponding single conditioned probabilities
For CountSingleConds = 1 To UBound(SingleCondProbArr)
If SingleCondProbArr(CountSingleConds).ChildNode = DoubleCondProbArr(CountDoubleConds).ChildNode And
SingleCondProbArr(CountSingleConds).ParentNode = DoubleCondProbArr(CountDoubleConds).ParentNodeLeft Then PositionSingleLeft =
CountSingleConds
If SingleCondProbArr(CountSingleConds).ChildNode = DoubleCondProbArr(CountDoubleConds).ChildNode And
SingleCondProbArr(CountSingleConds).ParentNode = DoubleCondProbArr(CountDoubleConds).ParentNodeRight Then PositionSingleRight =
CountSingleConds
Next
DoubleCondProbArr(CountDoubleConds).CreateValues FullRange.Cells(RowCount, 2), MarginalProbArr(PositionChild),
MarginalProbArr(PositionParentLeft), MarginalProbArr(PositionParentRight), _
SingleCondProbArr(PositionSingleLeft), SingleCondProbArr(PositionSingleRight),
DoubleCondBridgeArr(CountDoubleConds)
Found = True
End If
RowCount = RowCount + 1
Loop
If Found = False Then
MessageMissing = MessageMissing & vbCrLf & DoubleCondProbArr(CountDoubleConds).Name
Else
CountFound = CountFound + 1
End If
Next
If CountFound = UBound(DoubleCondProbArr) Then
ScanRangeForDoublecondProbs = True
Else
MsgBox ("Missing double-conditional probabilities:" & MessageMissing)
ScanRangeForDoublecondProbs = False
44 | P a g e
45. End If
End Function
Sub CalculateJointProbabilities(ByRef EventNames() As String, ByRef Functional_MarginalProbArr() As MarginalProb, ByRef
Functional_SingleCondProbArr() As SingleCondProb, ByRef DoubleCondProbArr() As DoubleCondProb, ByRef ResultsSheet As Worksheet)
ReDim States(UBound(EventNames)) As Boolean
Dim CountRows, CountColumns, CountMarginals, CountSingles, CountDoubles As Integer
Dim Result As Double
'Do for every row
For CountRows = 2 To ResultsSheet.UsedRange.Rows.Count
'Determine the states that correspond with this row
For CountColumns = 1 To UBound(EventNames)
If ResultsSheet.Cells(CountRows, CountColumns) = "1" Then
States(CountColumns) = True
Else
States(CountColumns) = False
End If
Next
'Calculate the joint probability
Result = 1
For CountMarginals = 1 To UBound(Functional_MarginalProbArr)
Result = Result * Functional_MarginalProbArr(CountMarginals).GetValueByStates(EventNames, States)
Next
For CountSingles = 1 To UBound(Functional_SingleCondProbArr)
Result = Result * Functional_SingleCondProbArr(CountSingles).GetValueByStates(EventNames, States)
Next
For CountDoubles = 1 To UBound(DoubleCondProbArr)
Result = Result * DoubleCondProbArr(CountDoubles).GetValueByStates(EventNames, States)
Next
'Write it to the sheet
ResultsSheet.Cells(CountRows, UBound(EventNames) + 1) = Result
Next
End Sub
Sub CalculateGainLosses(ByRef MarginalProbArr() As MarginalProb, ByRef ResultsSheet As Worksheet)
Dim CountRows, CountColumns, CountMarginals As Integer
Dim Result As Double
'Do for every row
For CountRows = 2 To ResultsSheet.UsedRange.Rows.Count
'Calculate the total gain/loss for this row
Result = 0
For CountColumns = 1 To UBound(MarginalProbArr)
Result = Result + ResultsSheet.Cells(CountRows, CountColumns) * MarginalProbArr(CountColumns).GainLoss
Next
'Write it to the sheet
ResultsSheet.Cells(CountRows, UBound(MarginalProbArr) + 2) = Result
'Write the conditional result to the sheet
ResultsSheet.Cells(CountRows, UBound(MarginalProbArr) + 3) = ResultsSheet.Cells(CountRows, UBound(MarginalProbArr) + 1) * Result
Next
End Sub
Sub PrintSingleCondProb(ByRef MySingleCondProb As SingleCondProb, ByRef Nodes() As String)
Dim Message As String
Message = MySingleCondProb.Name
Dim States(2) As Boolean
States(1) = True
States(2) = True
Message = Message & vbCrLf & Nodes(1) & "=" & States(1) & ", " & Nodes(2) & "=" & States(2) & ": " &
MySingleCondProb.GetValueByStates(Nodes, States)
45 | P a g e
47. ResultsSheet.Cells(1, NamesCount) = EventNames(NamesCount)
Next
End Sub
Sub FillInZerosAndOnes(ByRef EventNames() As String, ByRef ResultsSheet As Worksheet)
Dim ColumnCount, IterationCount, WriteCount, RowCount As Integer
For ColumnCount = UBound(EventNames) To 1 Step -1
RowCount = 2
For IterationCount = 1 To Power(2, ColumnCount - 1)
For WriteCount = 1 To Power(2, UBound(EventNames) - ColumnCount)
ResultsSheet.Cells(RowCount, ColumnCount) = "1"
RowCount = RowCount + 1
Next
For WriteCount = 1 To Power(2, UBound(EventNames) - ColumnCount)
ResultsSheet.Cells(RowCount, ColumnCount) = "0"
RowCount = RowCount + 1
Next
Next
Next
End Sub
Function Power(ByRef Number As Integer, ByRef Pow As Integer)
If Pow = 0 Then
Power = 1
Exit Function
End If
Dim PowCount As Integer
Dim Result As Integer
Result = 1
For PowCount = 1 To Pow
Result = Result * Number
Next
Power = Result
End Function
Function CheckSanity(ByRef MarginalProbArr() As MarginalProb, ByRef SingleCondProbArr() As SingleCondProb, ByRef DoubleCondPr obArr() As
DoubleCondProb) As Boolean
Dim Message As String
Dim IsSane As Boolean
IsSane = True
Dim CountMarginal, CountSingle, CountDouble As Integer
For CountMarginal = 1 To UBound(MarginalProbArr)
If MarginalProbArr(CountMarginal).CheckSanity(Message) = False Then IsSane = False
Next
For CountSingle = 1 To UBound(SingleCondProbArr)
If SingleCondProbArr(CountSingle).CheckSanity(Message) = False Then IsSane = False
Next
For CountDouble = 1 To UBound(DoubleCondProbArr)
If DoubleCondProbArr(CountDouble).CheckSanity(Message) = False Then IsSane = False
Next
If IsSane = False Then
MsgBox ("Performing sanity check..." & vbCrLf & vbCrLf & "Sanity check failed." & Message & vbCrLf & vbCrLf & "Aborting proce dure.")
CheckSanity = False
Else
MsgBox ("Performing sanity check..." & vbCrLf & "Sanity check succeeded.")
CheckSanity = True
End If
End Function
Sub UnitTest_MarginalProb()
Dim MargA As MarginalProb
Set MargA = New MarginalProb
47 | P a g e
48. MargA.Create ("A")
MargA.CreateValues (0.01)
MsgBox (MargA.Name & ":" & vbCrLf & MargA.GetValue(True) & vbCrLf & MargA.GetValue(False))
Dim Nodes(3) As String
Nodes(1) = "D"
Nodes(2) = "C"
Nodes(3) = "A"
Dim States(3) As Boolean
States(1) = True
States(2) = True
States(3) = True
Dim ATrue, AFalse As Double
ATrue = MargA.GetValueByStates(Nodes, States)
States(3) = False
AFalse = MargA.GetValueByStates(Nodes, States)
MsgBox (MargA.Name & ":" & vbCrLf & ATrue & vbCrLf & AFalse)
Nodes(3) = "E"
ATrue = MargA.GetValueByStates(Nodes, States)
End Sub
Sub UnitTest_SingleCondProb()
Dim MargA As MarginalProb
Set MargA = New MarginalProb
MargA.Create ("A")
MargA.CreateValues (0.01)
Dim MargD As MarginalProb
Set MargD = New MarginalProb
MargD.Create ("D")
MargD.CreateValues (0.015)
Dim P_D_A As SingleCondProb
Set P_D_A = New SingleCondProb
P_D_A.Create "D", "A"
P_D_A.CreateValues 0.6, MargD, MargA
MsgBox (P_D_A.Name & ":" & vbCrLf & P_D_A.GetValue(True, True) & vbCrLf & P_D_A.GetValue(True, False) & vbCrLf &
P_D_A.GetValue(False, True) & vbCrLf & P_D_A.GetValue(False, False))
Dim Nodes(3) As String
Nodes(1) = "C"
Nodes(2) = "D"
Nodes(3) = "A"
Dim States(3) As Boolean
States(1) = True
Dim DATrueTrue, DATrueFalse, DAFalseTrue, DAFalseFalse As Double
States(2) = True
States(3) = True
DATrueTrue = P_D_A.GetValueByStates(Nodes, States)
States(2) = True
States(3) = False
DATrueFalse = P_D_A.GetValueByStates(Nodes, States)
States(2) = False
States(3) = True
DAFalseTrue = P_D_A.GetValueByStates(Nodes, States)
States(2) = False
States(3) = False
DAFalseFalse = P_D_A.GetValueByStates(Nodes, States)
48 | P a g e
49. MsgBox (P_D_A.Name & ":" & vbCrLf & DATrueTrue & vbCrLf & DATrueFalse & vbCrLf & DAFalseTrue & vbCrLf & DAFalseFalse)
Nodes(2) = "E"
Nodes(3) = "F"
DAFalseFalse = MargA.GetValueByStates(Nodes, States)
End Sub
Sub UnitTest_DoubleCondProb()
Dim MargD As MarginalProb
Set MargD = New MarginalProb
MargD.Create ("D")
MargD.CreateValues (0.015)
Dim MargC As MarginalProb
Set MargC = New MarginalProb
MargC.Create ("C")
MargC.CreateValues (0.02)
Dim MargE As MarginalProb
Set MargE = New MarginalProb
MargE.Create ("E")
MargE.CreateValues (0.01)
Dim P_E_D As SingleCondProb
Set P_E_D = New SingleCondProb
P_E_D.Create "E", "D"
P_E_D.CreateValues 0.03, MargE, MargD
Dim P_E_C As SingleCondProb
Set P_E_C = New SingleCondProb
P_E_C.Create "E", "C"
P_E_C.CreateValues 0.2, MargE, MargC
Dim P_D_C As SingleCondProb
Set P_D_C = New SingleCondProb
P_D_C.Create "D", "C"
P_D_C.CreateValues 0.001885, MargD, MargC
Dim P_E_DC As DoubleCondProb
Set P_E_DC = New DoubleCondProb
P_E_DC.Create "E", "D", "C"
P_E_DC.CreateValues 0.4, MargE, MargD, MargC, P_E_D, P_E_C, P_D_C
MsgBox (P_E_DC.Name & ":" & vbCrLf & P_E_DC.GetValue(True, True, True) & vbCrLf & P_E_DC.GetValue(True, True, False) & vbCrLf &
P_E_DC.GetValue(True, False, True) & vbCrLf & P_E_DC.GetValue(True, False, False) & _
vbCrLf & P_E_DC.GetValue(False, True, True) & vbCrLf & P_E_DC.GetValue(False, True, False) & vbCrLf & P_E_DC.GetValue(False,
False, True) & vbCrLf & P_E_DC.GetValue(False, False, False))
Dim Nodes(3) As String
Nodes(1) = "E"
Nodes(2) = "D"
Nodes(3) = "C"
Dim States(3) As Boolean
Dim EDC(8) As Double
States(1) = True
States(2) = True
States(3) = True
EDC(1) = P_E_DC.GetValueByStates(Nodes, States)
States(1) = True
States(2) = True
States(3) = False
EDC(2) = P_E_DC.GetValueByStates(Nodes, States)
States(1) = True
49 | P a g e
50. States(2) = False
States(3) = True
EDC(3) = P_E_DC.GetValueByStates(Nodes, States)
States(1) = True
States(2) = False
States(3) = False
EDC(4) = P_E_DC.GetValueByStates(Nodes, States)
States(1) = False
States(2) = True
States(3) = True
EDC(5) = P_E_DC.GetValueByStates(Nodes, States)
States(1) = False
States(2) = True
States(3) = False
EDC(6) = P_E_DC.GetValueByStates(Nodes, States)
States(1) = False
States(2) = False
States(3) = True
EDC(7) = P_E_DC.GetValueByStates(Nodes, States)
States(1) = False
States(2) = False
States(3) = False
EDC(8) = P_E_DC.GetValueByStates(Nodes, States)
MsgBox (P_E_DC.Name & ":" & vbCrLf & EDC(1) & vbCrLf & EDC(2) & vbCrLf & EDC(3) & vbCrLf & EDC(4) & _
vbCrLf & EDC(5) & vbCrLf & EDC(6) & vbCrLf & EDC(7) & vbCrLf & EDC(8))
Nodes(1) = "B"
Nodes(2) = "C"
Nodes(3) = "A"
EDC(8) = P_E_DC.GetValueByStates(Nodes, States)
End Sub
Sub Test_Independence()
Dim MargA As MarginalProb
Set MargA = New MarginalProb
MargA.Create ("A")
MargA.CreateValues (0.01)
Dim MargB As MarginalProb
Set MargB = New MarginalProb
MargB.Create ("D")
MargB.CreateValues (0.015)
Dim P_A_B As SingleCondProb
Set P_A_B = New SingleCondProb
P_A_B.Create "A", "B"
P_A_B.CreateValues MargA.GetValue(True), MargA, MargB
MsgBox (P_A_B.Name & ":" & vbCrLf & P_A_B.GetValue(True, True) & vbCrLf & P_A_B.GetValue(True, False) & vbCrLf &
P_A_B.GetValue(False, True) & vbCrLf & P_A_B.GetValue(False, False))
End Sub
50 | P a g e