Login  Register

Re: re "BS call option price lower than intrinsic value - bug #3417114"

Posted by Luigi Ballabio on Oct 03, 2011; 4:00pm
URL: http://quantlib.414.s1.nabble.com/re-BS-call-option-price-lower-than-intrinsic-value-bug-3417114-tp9130p9131.html

On Mon, 2011-10-03 at 20:31 +0800, R Y wrote:
> The bug report was invalidated and closed too soon that I haven't been
> able to put a comment on that one, so let me post it here...
>
> The bug was that the result of BS() formula, c=BS(F,K,sigma,"call")
> for a call option doesn't satisfy c>=F-K for certain K<<F (i.e. deep
> in the money strike).

Yes.  The returned value was below the lower bound by about 1e-16, which
suggested a floating-point issue.  Indeed, this turned out to be the
case.


> The issue is caused by floating point precision. That is true. But I
> was hoping the dev team could dig a bit further for the cause but it
> seems I have to do that myself and lay out the answer here...
>
> The root cause is that there is a flaw in the implementation of the
> cumulative normal CDF function such that the function f(x) is not
> monotonically increasing in x.

I did dig for the cause.  The root cause is simply that tests for strict
floating-point equality are ill-formed.  The same problem is triggered
by the following program, which is similar to yours, has the same input
data, but does not use a cdf at all:

#include <iostream>

int main() {
        double F = 1.35;
        double K = 0.39;
        double diff = 0.96;
        if (diff < F-K)
        {
                std::cerr << "Error: diff = " << diff << ", F-K = "
                        << (F - K) << std::endl;
        }
}

The above fails when compiled with VC++10 Express.  QuantLib is not even
included.


> I'm not an expert in numerical analysis so I don't know what's wrong
> exactly with the implementation. But if we use the cdf function in
> boost::math, we fix the problem.

We do fix this particular test case, but not the problem.  The
boost::math implementation passes the test with F = 1.35 and K = 0.39,
but fails, for instance, for F = 1.98 and K = 0.74.  The implementation
is different, so it results in different roundings and the error is
triggered by different values; but the problem is not in either
implementation, but underneath both of them.

Unfortunately, the punchline is that floating-point comparisons must
allow for rounding.  A simplistic way to do this would be to write the
test like:

if (c < (F - K) - epsilon)

with epsilon depending on the byte size of the floating point numbers on
one's machine.  A more sophisticated approach can be found by googling
for "Knuth floating-point comparison".

Later,
        Luigi


P.S.  I'm afraid I've rejected at least a couple of suggestions of yours
in the past few days.  That's just an accident---please don't be
discouraged by this and keep them coming.  I might seem a cranky old
conservative, but I do appreciate the effort you're putting into this.


>  A sketch of code below (assuming discount factor 1.0):
>
>   // Compute call value manually.
>   double d1 = std::log(F/K)/(sigma*sqrt(T)) + 0.5*sigma*sqrt(T);
>   double d2 = d1 - sigma*sqrt(T);
>   boost::math::normal N;
>   double nd1 = boost::math::cdf(N, d1);
>   double nd2 = boost::math::cdf(N, d2);
>   double c = F * nd1 - K * nd2;
> ------------------------------------------------------------------------------
> All the data continuously generated in your IT infrastructure contains a
> definitive record of customers, application performance, security
> threats, fraudulent activity and more. Splunk takes this data and makes
> sense of it. Business sense. IT sense. Common sense.
> http://p.sf.net/sfu/splunk-d2dcopy1
> _______________________________________________ QuantLib-dev mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-dev

--

All generalizations are dangerous, even this one.
-- Alexandre Dumas



------------------------------------------------------------------------------
All the data continuously generated in your IT infrastructure contains a
definitive record of customers, application performance, security
threats, fraudulent activity and more. Splunk takes this data and makes
sense of it. Business sense. IT sense. Common sense.
http://p.sf.net/sfu/splunk-d2dcopy1
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev