The function name is very nice. The docstring adds nothing to that. Consider describing one or more arguments, especially if there are tricky details about their validity. Definitely add a URL describing the math approach.
Sorry, I didn't notice how the wikipedia page on Capital_requirement relates to the details of the formula.
Overall the code is clear. If you really wanted to delete the b1
temp variable for some reason you might write this two-liner:
return ((lgd * stat.norm.cdf(a1) - lgd * pd)
* (1 + ((tenor - tsub) * madj)) / (1- madjcoeff * madj))
(I suppose lgd could be factored out, if desired.) In any event, the a1
temp definitely helps with readability, you'll want to hang on to that. Something to keep in mind is that subexpressions can raise exceptions. If you're concerned that might happen, it may be useful to break out several temp variables, each on its own line, so the stack trace will pinpoint where things went south.
tsub
is a perfectly nice concise name to choose, but please add a comment:
tsub = 2.5 # tenor subtrahend
Not sure how "constant" these two are, but you might allow callers to change them:
def capital_requirement(r, lgd, pd, madj, tenor, madjcoeff=1.5, tsub=2.5):
It's pretty clear that stat.norm.ppf(0.999)
is not implementing the .99 given in your formula.
You might validate r
:
assert 0 < r < 1
If out-of-range values sneak in, be aware that math.sqrt()
will raise ValueError, which you probably want, while ** 0.5
will return an imaginary root.