LocalvolSurface.cpp

classic Classic list List threaded Threaded
14 messages Options
Reply | Threaded
Open this post in threaded view
|

LocalvolSurface.cpp

MH_quant

Hello everybody,

 

i recently did a lot of testing with the localvolSurface class (which contains Gatherals Dupire Formula) and i am not very happy with the results. Ok, the class is (regarding to the documentation) untested, so I guess I cant expect it to work properly. But I figured that numerical problems cause this class to return the error message “negative local vol …  the black vol surface is not smooth enough”. This also happens for very smooth black vol surfaces. The Problem lies in this code:

 

 

 

 

 

Real forwardValue = underlying *

            (dividendTS->discount(t, true)/

             riskFreeTS->discount(t, true));

 

        // strike derivatives

        Real strike, y, dy, strikep, strikem;

        Real w, wp, wm, dwdy, d2wdy2;

        strike = underlyingLevel;

        y = std::log(strike/forwardValue);

        dy = ((y!=0.0) ? y*0.000001 : 0.000001);

        strikep=strike*std::exp(dy);

        strikem=strike/std::exp(dy);

        w  = blackTS->blackVariance(t, strike,  true);

        wp = blackTS->blackVariance(t, strikep, true);

        wm = blackTS->blackVariance(t, strikem, true);

        dwdy = (wp-wm)/(2.0*dy);

        d2wdy2 = (wp-2.0*w+wm)/(dy*dy);

 

        // time derivative

        Real dt, wpt, wmt, dwdt;

        if (t==0.0) {

            dt = 0.0001;

            wpt = blackTS->blackVariance(t+dt, strike, true);

            QL_ENSURE(wpt>=w,

                      "decreasing variance at strike " << strike

                      << " between time " << t << " and time " << t+dt);

            dwdt = (wpt-w)/dt;

        } else {

            dt = std::min<Time>(0.0001, t/2.0);

            wpt = blackTS->blackVariance(t+dt, strike, true);

            wmt = blackTS->blackVariance(t-dt, strike, true);

            QL_ENSURE(wpt>=w,

                      "decreasing variance at strike " << strike

                      << " between time " << t << " and time " << t+dt);

            QL_ENSURE(w>=wmt,

                      "decreasing variance at strike " << strike

                      << " between time " << t-dt << " and time " << t);

            dwdt = (wpt-wmt)/(2.0*dt);

        }

 

        if (dwdy==0.0 && d2wdy2==0.0) { // avoid /w where w might be 0.0

            return std::sqrt(dwdt);

        } else {

            Real den1 = 1.0 - y/w*dwdy;

            Real den2 = 0.25*(-0.25 - 1.0/w + y*y/w/w)*dwdy*dwdy;

            Real den3 = 0.5*d2wdy2;

            Real den = den1+den2+den3;

            Real result = dwdt / den;

            QL_ENSURE(result>=0.0,

                      "negative local vol^2 at strike " << strike

                      << " and time " << t

                      << "; the black vol surface is not smooth enough");

            return std::sqrt(result);

            // return std::sqrt(dwdt / (1.0 - y/w*dwdy +

            //    0.25*(-0.25 - 1.0/w + y*y/w/w)*dwdy*dwdy + 0.5*d2wdy2));

        }

 

 

 

 

To be a bit more precise  the problem lies in the second derivative of the black variance with respect to the strike. Even if I take surfaces without Smile/Skew, i.e. flat ones, I still get the problem there. This is because (wp-2.0*w+wm) is not exactly zero but very very small. And this gets devided by 0. 000000000001. So if it is not exactly zero but very very little negative, it can blow up the whole calculations and we end up with this error message. To avoid these numerical problems I now decreased the accuracy in the derivatives a little bit and also introduced a check that sets this term to zero if it is very very very small (smaller than 1.0e-12). Furthermore I changed the derivative with respect to the time. This was not necessary but I wanted to make it equal to the localvolcurve.cpp code which works just fine. The modified code now looks like:

 

 

 

 

 

Real forwardValue = underlying *

          (dividendTS->discount(t, true)/

           riskFreeTS->discount(t, true));

 

 

        // strike derivatives

        Real strike, y, dy, strikep, strikem;

        Real w, wp, wm, dwdy, d2wdy2;

            Real z1,z2;

       

            // strike ist gegeben

            strike = underlyingLevel;

       

            // log(strike/forwardValue)

            y = std::log(strike/forwardValue);

            std::cout << "y: "    << y << std::endl;

       

            // wir leiten blackScholesVariance nach y ab, bilde daher diskrete kleine unterteilung

            dy = ((y!=0.0) ? y*0.0001 : 0.0001);

            std::cout << "dy: "    << dy << std::endl;

 

 

        strikep=strike*std::exp(dy);

        strikem=strike/std::exp(dy);

        w  = blackTS->blackVariance(t, strike,  true);

        wp = blackTS->blackVariance(t, strikep, true);

        wm = blackTS->blackVariance(t, strikem, true);

        z1=wp-wm;

            if (std::abs(z1) < 1.0e-12)

                  z1=0;

        dwdy = (z1)/(2.0*dy);

        z2=wp-2.0*w+wm;

        if (std::abs(z2) < 1.0e-12)

                  z2=0;

        d2wdy2 = (z2)/(dy*dy);

           

           

 

 

        // time derivative

        Real dt, wpt, wmt, dwdt;

 

            dt = (1.0/365.0);

        wpt = blackTS->blackVariance(t+dt, strike, true);

            QL_ENSURE(wpt>=w,

                      "decreasing variance at strike " << strike

                      << " between time " << t << " and time " << t+dt);

        dwdt = (wpt-w)/dt;

       

 

        if (dwdy==0.0 && d2wdy2==0.0) { // avoid /w where w might be 0.0

            return std::sqrt(dwdt);

        } else {

            Real den1 = 1.0 - y/w*dwdy;

            Real den2 = 0.25*(-0.25 - 1.0/w + y*y/w/w)*dwdy*dwdy;

            Real den3 = 0.5*d2wdy2;

            Real den = den1+den2+den3;

            Real result = dwdt / den;

            QL_ENSURE(result>=0.0,

                      "negative local vol^2 at strike " << strike

                      << " and time " << t

                      << "; the black vol surface is not smooth enough");

            return std::sqrt(result);

            // return std::sqrt(dwdt / (1.0 - y/w*dwdy +

            //    0.25*(-0.25 - 1.0/w + y*y/w/w)*dwdy*dwdy + 0.5*d2wdy2));

        }

 

 

 

 

So far all the testing I did I received much better and more stable results. But since I am not an expert in computational and numerical methods regarding precision, can anybody who is a bit more experienced with c++ numerical issues give me some advice and probably check this out?

 

 

Greetings

Michael


------------------------------------------------------------------------------
Stay on top of everything new and different, both inside and
around Java (TM) technology - register by April 22, and save
$200 on the JavaOne (SM) conference, June 2-5, 2009, San Francisco.
300 plus technical and hands-on sessions. Register today.
Use priority code J9JMT32. http://p.sf.net/sfu/p
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev
Reply | Threaded
Open this post in threaded view
|

Re: LocalvolSurface.cpp

Ferdinando Ametrano-4
Hi Michael

> i recently did a lot of testing with the localvolSurface class (which
> contains Gatherals Dupire Formula) and i am not very happy with the results.
> Ok, the class is (regarding to the documentation) untested, so I guess I
> cant expect it to work properly.

Last week Klaus fixed time derivative (now performed at constant
moneyness instead of constant strike) and added tests.

> But I figured that numerical problems cause
> this class to return the error message “negative local vol …  the black vol
> surface is not smooth enough”. [...]
> the problem lies in the second derivative of the
> black variance with respect to the strike.

you are right. I will fix it, probably moving time/strike (numerical)
derivatives in the BlackVolTermStructure base interface, allowing for
overloading in derived classes which might provide exact derivatives.

BTW I have a related question. Black ATM variance must be increasing
in time; I've always taken for granted that this is also true for
every (not just ATM) constant moneyness section of the Black surface.
Is this a non-arbitrage result or shaky common sense?

ciao -- Nando

------------------------------------------------------------------------------
Stay on top of everything new and different, both inside and
around Java (TM) technology - register by April 22, and save
$200 on the JavaOne (SM) conference, June 2-5, 2009, San Francisco.
300 plus technical and hands-on sessions. Register today.
Use priority code J9JMT32. http://p.sf.net/sfu/p
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev
Reply | Threaded
Open this post in threaded view
|

Re: LocalvolSurface.cpp

Klaus Spanderen-2
In reply to this post by MH_quant
Hi Michael,

you wrote
> To be a bit more precise  the problem lies in the second derivative of the
> black variance with respect to the strike. Even if I take surfaces without
> Smile/Skew, i.e. flat ones, I still get the problem there. This is because
> (wp-2.0*w+wm) is not exactly zero but very very small. And this gets
> devided by 0. 000000000001.

To me the root of the problem was the line

        dy = ((y!=0.0) ? y*0.000001 : 0.000001);

For ve y small y this code leads to unrealistic small dy and to numerical
problems during the calculation of the difference quotient. Therfore I've
changed it into

        dy = ((std::fabs(y) > 0.001) ? y*0.0001 : 0.000001);

and at least for my tests the numerical problems with the difference quotient
disappeared. (pls see the latest version of localvolsurface.cpp in the SVN
repository). Could you test this fix using your test cases?

regards
 Klaus


------------------------------------------------------------------------------
Crystal Reports &#45; New Free Runtime and 30 Day Trial
Check out the new simplified licensign option that enables unlimited
royalty&#45;free distribution of the report engine for externally facing
server and web deployment.
http://p.sf.net/sfu/businessobjects
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev
Reply | Threaded
Open this post in threaded view
|

Re: LocalvolSurface.cpp

MH_quant
Hallo Klaus,

I checked out your new version of the localvolsurface.cpp from the SVN and
run some extensive tests.

First of all I found some minor errors in your code which are:

1. (Line 116): Real strikept = strike*dr*dq/(drpt*dqpt);
This should be:
        Real strikept = strike*dr*dqpt/(drpt*dq);

2. (same in line 130 and 131):
        Real strikept = strike*dr*dq/(drpt*dqpt);
        Real strikemt = strike*dr*dq/(drmt*dqmt);
This should be:
        Real strikept = strike*dr*dqpt/(drpt*dq);
        Real strikemt = strike*dr*dqmt/(drmt*dq);


Just minor things, but think it over. You divide through the risk free
discount and multiply with the dividend discount. And if you do this from t
to t+dt then this is what you get.


Now a few words what I figured out by extensive testing. I ran tests with MC
with 100 thousand of paths. And your Bug-Fix brought some slight
improvements but the problem with the second derivative still remains.

It happens very often that the program crashes and tells me "negative local
vol^2 at ..."

The black vol surface I am using is very smooth. So this is not the reason
for the problems. Much more is the problem again the numerical instability
when taking the second derivative of the implied variance surface with
respect to the log-moneyness.

Let me introduce 2 more variables:

Real z1,z2;

Where

z1=wp-wm;

z2=wp-2.0*w+wm;


Then the first derivative of w with respect to log-moneyness is:

dwdy = (z1)/(2.0*dy);

And the second is:

d2wdy2 = (z2)/(dy*dy);


It happens at different strikes and moneyness under some conditions that the
d2wdy2 blows up and becomes something like -4231,12

Like a really big negative number. This obviously makes the denominator
which consists of  den1+den2+den3  negative and the whole program crashes.

The numerator is always positive since we make sure that the implied
variance is monotone increasing.

So the only thing we have to take care about is that our denominator is not
getting negative.

I figured out (by extensive testing and only empirically) that

0.4 < den1+den2<1.3

So at least for the surfaces I was testing, this was always given. So
basically we have to make sure that den3 is not getting smaller then -0.4 in
order for the program not to crash.

But my tests showed that den3 is either in the green zone or it blows up
dramatically which gives me the suppression that we encounter some numerical
problems under certain conditions.

The only way how I managed for the program to run stable is by controlling
z1,z2 by setting:

if ((std::abs(z1) < std::abs(dy)/1000 && z1!=0.0) || std::abs(z1) >
2*std::abs(dy))
                        z1=0;

and


if ((std::abs(z2) < dy*dy/1000 && z2!=0.0) || std::abs(z2) > dy*dy)
                        z2=0;


So what I basically do is setting the first derivative to zero when it is
getting so small that it doesn't really affect our result anymore anyways.
Same with the second derivative.

But the more critical part is setting the derivative to zero when it blows
up. I just cut off all critical values.

This makes (obviously) the program run stable.

On the off-side I cant really say for sure (at least till now) how big the
impacts of this manipulation are for the precision of our results. I figured
that we basically never get problems with z1 which means with the first
derivative. But we set the second derivative which means z2 quit often to
zero when it falls out of the good range.

For some reason I don't get rid of the feeling that we would be better of to
work completely without the second derivative since it seems to be
impossible to get this numerically under control. But would that probably
make the dupire formula useless to us?

Do you have any Ideas? Or can I help you with this issue any further?

Greetings,
Michael


PS: is it possible to write a paper which examines under which conditions
(what range for what variables and what interdependencies of the variables
and what restrictions to the shape of the black vol surface) the formula is
theoretically/mathematically possible (i.e. doesn't get negative) and then
use this new gained knowledge to make our code stable with the smallest
impact possible to the precision of the result?



-----Original Message-----
From: Klaus Spanderen [mailto:[hidden email]]
Sent: Freitag, 24. April 2009 00:07
To: [hidden email]
Cc: Michael Heckl; Ferdinando Ametrano
Subject: Re: [Quantlib-dev] LocalvolSurface.cpp

Hi Michael,

you wrote
> To be a bit more precise  the problem lies in the second derivative of the
> black variance with respect to the strike. Even if I take surfaces without
> Smile/Skew, i.e. flat ones, I still get the problem there. This is because
> (wp-2.0*w+wm) is not exactly zero but very very small. And this gets
> devided by 0. 000000000001.

To me the root of the problem was the line

        dy = ((y!=0.0) ? y*0.000001 : 0.000001);

For ve y small y this code leads to unrealistic small dy and to numerical
problems during the calculation of the difference quotient. Therfore I've
changed it into

        dy = ((std::fabs(y) > 0.001) ? y*0.0001 : 0.000001);

and at least for my tests the numerical problems with the difference
quotient
disappeared. (pls see the latest version of localvolsurface.cpp in the SVN
repository). Could you test this fix using your test cases?

regards
 Klaus


------------------------------------------------------------------------------
Crystal Reports &#45; New Free Runtime and 30 Day Trial
Check out the new simplified licensign option that enables unlimited
royalty&#45;free distribution of the report engine for externally facing
server and web deployment.
http://p.sf.net/sfu/businessobjects
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev
Reply | Threaded
Open this post in threaded view
|

Re: LocalvolSurface.cpp

Klaus Spanderen-2
Hi Micheal

> First of all I found some minor errors in your code which are:

yes, you are obviously right. I've changed the code in the SVN repository
accordingly. Thanks for the hint!

>
> It happens at different strikes and moneyness under some conditions that
> the d2wdy2 blows up and becomes something like -4231,12
>

Which interpolation scheme do you use for the volatility surface. The standard
interpolation is linear in the variance which very often leads to problems
with the second derivative. Therefore I've used BicubicSplineInterpolation

    volTS->setInterpolation<Bicubic>();

 
Does this happen only for deep ITM or OTM paths? (Is this a extrapolation
problem for very large (very small) spots?) At least for "extrem"
extrapolations" I found simillar problems and "solved" it be setting negative
variances to zero.

Can I get access to the parameters of your test-surface?

> For some reason I don't get rid of the feeling that we would be better of
> to work completely without the second derivative since it seems to be
> impossible to get this numerically under control.

No, IMO the second derivative is needed.

> But would that probably
> make the dupire formula useless to us?

People your using e.g. splines together with an optimization technique like in

Reconstructing The Unknown Local Volatility Function, Thomas F. Coleman,
Yuying Li, ARUN VERMA,
http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.41.6202

to solve the instability. But a lot of code is needed to implemented this;-(.
For the time being I think we should give Nando's approach a try and use the
first and second derivatives taken from the interpolation method


regards
 Klaus

------------------------------------------------------------------------------
Crystal Reports &#45; New Free Runtime and 30 Day Trial
Check out the new simplified licensign option that enables unlimited
royalty&#45;free distribution of the report engine for externally facing
server and web deployment.
http://p.sf.net/sfu/businessobjects
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev
Reply | Threaded
Open this post in threaded view
|

Re: LocalvolSurface.cpp

MH_quant

Hallo Klaus,

I ran my tests with both. BiLinear and BiCubic intrapolation. I encountered
the instability issues with both.

You are right that the problems appear far ITM and OTM. But I cant really
figure out why, since I set up a constant extrapolation for both, Strike and
Maturity in my BlackVarianceSurface.

I attached the cpp file that I use for my tests as well as a small jpg of
the surface that is included in my test cases.

I hope this gives you all the information you need and you can give me some
feedback on my test cases.

Thank you also for the link. To me it seem like if we want to use the dupire
formula efficient, stable and productive, we wont get around implementing
some fancy optimization-splines and smoothing algorithm.

I am looking forward to hear back from you.

Greetings,
Michael



-----Original Message-----
From: Klaus Spanderen [mailto:[hidden email]]
Sent: Sonntag, 26. April 2009 22:01
To: [hidden email]
Cc: Michael Heckl
Subject: Re: [Quantlib-dev] LocalvolSurface.cpp

>
> It happens at different strikes and moneyness under some conditions that
> the d2wdy2 blows up and becomes something like -4231,12
>

Which interpolation scheme do you use for the volatility surface. The
standard
interpolation is linear in the variance which very often leads to problems
with the second derivative. Therefore I've used BicubicSplineInterpolation

    volTS->setInterpolation<Bicubic>();

 
Does this happen only for deep ITM or OTM paths? (Is this a extrapolation
problem for very large (very small) spots?) At least for "extrem"
extrapolations" I found simillar problems and "solved" it be setting
negative
variances to zero.

Can I get access to the parameters of your test-surface?

> But would that probably
> make the dupire formula useless to us?

People your using e.g. splines together with an optimization technique like
in

Reconstructing The Unknown Local Volatility Function, Thomas F. Coleman,
Yuying Li, ARUN VERMA,
http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.41.6202

to solve the instability. But a lot of code is needed to implemented
this;-(.
For the time being I think we should give Nando's approach a try and use the

first and second derivatives taken from the interpolation method


regards
 Klaus

------------------------------------------------------------------------------
Register Now & Save for Velocity, the Web Performance & Operations
Conference from O'Reilly Media. Velocity features a full day of
expert-led, hands-on workshops and two days of sessions from industry
leaders in dedicated Performance & Operations tracks. Use code vel09scf
and Save an extra 15% before 5/3. http://p.sf.net/sfu/velocityconf
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev

LocalSurfaceIssue.cpp (33K) Download Attachment
qlSurface.jpg (1M) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: LocalvolSurface.cpp

Ferdinando Ametrano-4
On Mon, Apr 27, 2009 at 11:20 AM, Michael Heckl <[hidden email]> wrote:
> I set up a constant extrapolation for both, Strike and
> Maturity in my BlackVarianceSurface.

I don't work on equities but constant variance extrapolation in strike
and maturity seems plain wrong to me. In time it implies zero forward
volatility, in strike it violates concavity smile requirement

ciao -- Nando

------------------------------------------------------------------------------
Register Now & Save for Velocity, the Web Performance & Operations
Conference from O'Reilly Media. Velocity features a full day of
expert-led, hands-on workshops and two days of sessions from industry
leaders in dedicated Performance & Operations tracks. Use code vel09scf
and Save an extra 15% before 5/3. http://p.sf.net/sfu/velocityconf
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev
Reply | Threaded
Open this post in threaded view
|

Re: LocalvolSurface.cpp

MH_quant
Hallo Nando,



-----Original Message-----
On Mon, Apr 27, 2009 at 11:20 AM, Michael Heckl <[hidden email]>
wrote:
> I set up a constant extrapolation for both, Strike and
> Maturity in my BlackVarianceSurface.

I don't work on equities but constant variance extrapolation in strike
and maturity seems plain wrong to me. In time it implies zero forward
volatility, in strike it violates concavity smile requirement

ciao -- Nando

--------------------------


What is done with the time extrapolation is the following:

if (t<=times_.back())
            return varianceSurface_(t, strike, true);
else // t>times_.back() || extrapolate
           return varianceSurface_(times_.back(), strike, true) *
                t/times_.back();


I.e. the implied variance surface is not extrapolated constant in time, but
the implied volatility surface.

What exactly do you mean by zero forward volatility. IMHO the forward
volatility would be in that case (between two dates past at extrapolation)
exactly the constant extrapolated volatility (analog as with interest rates
for instance).


And at Strikes past the maximum/minimum Strike the implied variance surface
is indeed extrapolated flat, i.e.


// enforce constant extrapolation when required
        if (strike < strikes_.front()
            && lowerExtrapolation_ == ConstantExtrapolation)
            strike = strikes_.front();
        if (strike > strikes_.back()
            && upperExtrapolation_ == ConstantExtrapolation)
            strike = strikes_.back();



Well, I don't know what you mean with your concavity smile requirement. But
I cant see what the problem should be with this extrapolation?

If you look at the No-Arbitrage requirements for the implied volatility
surface they only give limites to the slope.

But constant extrapolation means zero slope. So I cant see any restrictions
to that.

You can find no-arbitrage restrictions for the implied volatility for
instance at Roger W. Lee ("Implied Volatility: Statics, Dynamics, and
Probabalistic Interpretation")

The paper is online here:

http://www.math.uchicago.edu/~rl/



Can you send me a paper which works out the arguments you stated?


Greetings,
Michael


------------------------------------------------------------------------------
Register Now & Save for Velocity, the Web Performance & Operations
Conference from O'Reilly Media. Velocity features a full day of
expert-led, hands-on workshops and two days of sessions from industry
leaders in dedicated Performance & Operations tracks. Use code vel09scf
and Save an extra 15% before 5/3. http://p.sf.net/sfu/velocityconf
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev
Reply | Threaded
Open this post in threaded view
|

Re: LocalvolSurface.cpp

Klaus Spanderen-2
In reply to this post by MH_quant
Hi

> I ran my tests with both. BiLinear and BiCubic intrapolation. I encountered
> the instability issues with both.

BiLinear interpolation doesn't work due to the jumps in the first derivative.
BiCubic should be much better.

> You are right that the problems appear far ITM and OTM. But I cant really
> figure out why, since I set up a constant extrapolation for both, Strike
> and Maturity in my BlackVarianceSurface.

Constant extrapolation could introduce arbitrage violations far ITM or far OTM
and these arbitrage violations can lead to negative variances. Is this part
of the problem in your tests?

> Thank you also for the link. To me it seem like if we want to use the
> dupire formula efficient, stable and productive, we wont get around
> implementing some fancy optimization-splines and smoothing algorithm.

yes.;-)

regards
 Klaus

------------------------------------------------------------------------------
Register Now & Save for Velocity, the Web Performance & Operations
Conference from O'Reilly Media. Velocity features a full day of
expert-led, hands-on workshops and two days of sessions from industry
leaders in dedicated Performance & Operations tracks. Use code vel09scf
and Save an extra 15% before 5/3. http://p.sf.net/sfu/velocityconf
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev
Reply | Threaded
Open this post in threaded view
|

Re: LocalvolSurface.cpp

Dimathematician

Just a remark regarding interpolation. I've implemented kernel
interpolation (its in the trunk), which can be made sufficiently smooth 
by choosing a proper standard deviation of the gaussian kernel. I've heard 
that this smoothness property makes it a good choice for local vol calibrations.
I don't have any personal experience with that though.



2009/4/29 Klaus Spanderen <[hidden email]>
Hi

> I ran my tests with both. BiLinear and BiCubic intrapolation. I encountered
> the instability issues with both.

BiLinear interpolation doesn't work due to the jumps in the first derivative.
BiCubic should be much better.

> You are right that the problems appear far ITM and OTM. But I cant really
> figure out why, since I set up a constant extrapolation for both, Strike
> and Maturity in my BlackVarianceSurface.

Constant extrapolation could introduce arbitrage violations far ITM or far OTM
and these arbitrage violations can lead to negative variances. Is this part
of the problem in your tests?

> Thank you also for the link. To me it seem like if we want to use the
> dupire formula efficient, stable and productive, we wont get around
> implementing some fancy optimization-splines and smoothing algorithm.

yes.;-)

regards
 Klaus

------------------------------------------------------------------------------
Register Now & Save for Velocity, the Web Performance & Operations
Conference from O'Reilly Media. Velocity features a full day of
expert-led, hands-on workshops and two days of sessions from industry
leaders in dedicated Performance & Operations tracks. Use code vel09scf
and Save an extra 15% before 5/3. http://p.sf.net/sfu/velocityconf
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev


------------------------------------------------------------------------------
Register Now & Save for Velocity, the Web Performance & Operations
Conference from O'Reilly Media. Velocity features a full day of
expert-led, hands-on workshops and two days of sessions from industry
leaders in dedicated Performance & Operations tracks. Use code vel09scf
and Save an extra 15% before 5/3. http://p.sf.net/sfu/velocityconf
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev
Reply | Threaded
Open this post in threaded view
|

Re: LocalvolSurface.cpp

MH_quant
In reply to this post by Klaus Spanderen-2

Hallo Klaus,


> BiLinear interpolation doesn't work due to the jumps in the first
derivative.
> BiCubic should be much better.

I totally agree that BiLinear interpolation is not the smoothest
interpolation out there. And you are right that in theorie you would get
points of discontinuity exactly everywhere where the linear slope changes.
Moreover the first derivative would look like a step function. That would in
theory lead to a sum of dirac delta functions in the second derivative. But
this is only in theory. Since we do discrete approximations in quantlib, I
doubt that we have this effect ...

Anyways, I do also have problems with BiCubic Interpolation. My hope is now
that the newly implemented kernel interpolation (thanks to Dima) gives
better test results.



> Constant extrapolation could introduce arbitrage violations far ITM or far
OTM
> and these arbitrage violations can lead to negative variances. Is this
part
> of the problem in your tests?


I would love to not use the constant extrapolation but instead the
InterpolatorDefaultExtrapolation. But this doesn't work since I run into
another problem by doing this. That is very far ITM/OTM the monoton variance
criteria is violated at some point and the program crashes due to this
issue. I have now Idea how to encounter this problem?? So I cant really say
if that would make it better ...


Anyways, can you send me a link or a paper with more information about the
arbitrage violations due to constant extrapolation? I still cant see why
constant extrapolation is violating the arbitrage criteria. At least it
doesn't violate any of the arbitrage criterias that I know (see Roger Lee or
Gatheral or Musiela/Rutkowski) ...


Greetings from Munich
Michael


------------------------------------------------------------------------------
Register Now & Save for Velocity, the Web Performance & Operations
Conference from O'Reilly Media. Velocity features a full day of
expert-led, hands-on workshops and two days of sessions from industry
leaders in dedicated Performance & Operations tracks. Use code vel09scf
and Save an extra 15% before 5/3. http://p.sf.net/sfu/velocityconf
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev
Reply | Threaded
Open this post in threaded view
|

Re: LocalvolSurface.cpp

MH_quant
In reply to this post by Dimathematician

Hallo Dima,

 

I am very curious about your new kernel interpolation. Sounds like this is something that can help me a lot right now. I would like to try around a bit with different interpolation methods to overcome my numerical problems. If I can make my surface smoother with kernel interpolation I will give it a go and would like to do some testing on it.

 

How do I get your new kernel interpolation running?  Can I check it out from the SVN?  I checked the trunk and I found a file called kernelinterpolation.hpp.   Does it work for 2-dimensions or just for one because for the surface I need it for two dimensions. Can you please also send me a link or a paper with more informations about it so I can build up some theoretical knowledge before I start testing.

 

Greetings,

Michael

 


From: Dima [mailto:[hidden email]]
Sent: Mittwoch, 29. April 2009 11:55
To: Klaus Spanderen
Cc: [hidden email]
Subject: Re: [Quantlib-dev] LocalvolSurface.cpp

 

 

Just a remark regarding interpolation. I've implemented kernel

interpolation (its in the trunk), which can be made sufficiently smooth 

by choosing a proper standard deviation of the gaussian kernel. I've heard 

that this smoothness property makes it a good choice for local vol calibrations.

I don't have any personal experience with that though.

 

 

 

 


------------------------------------------------------------------------------
Register Now & Save for Velocity, the Web Performance & Operations
Conference from O'Reilly Media. Velocity features a full day of
expert-led, hands-on workshops and two days of sessions from industry
leaders in dedicated Performance & Operations tracks. Use code vel09scf
and Save an extra 15% before 5/3. http://p.sf.net/sfu/velocityconf
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev
Reply | Threaded
Open this post in threaded view
|

Re: LocalvolSurface.cpp

Klaus Spanderen-2
In reply to this post by MH_quant
Hi Michael,

> Anyways, can you send me a link or a paper with more information about the
> arbitrage violations due to constant extrapolation? I still cant see why
> constant extrapolation is violating the arbitrage criteria.

Please find attached a small program, where the constant extrapolation as
implemented in BlackVarianceSurface generates an arbitrage violation  -
negative call spread price when the maturity becomes large enough. To get it
running you have to enable extrapolation in analyticeuopeanengine.hpp at line
45. (Hope I got everything right with the example;-)
 
regards
 Klaus

------------------------------------------------------------------------------
Register Now & Save for Velocity, the Web Performance & Operations
Conference from O'Reilly Media. Velocity features a full day of
expert-led, hands-on workshops and two days of sessions from industry
leaders in dedicated Performance & Operations tracks. Use code vel09scf
and Save an extra 15% before 5/3. http://p.sf.net/sfu/velocityconf
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev

europeanoption.cpp (3K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: LocalvolSurface.cpp

Andrew Kolesnikov
In reply to this post by MH_quant
Hi.
Was it any feedback from Dima?
I'm also curious about this issue with respect to extrapolation problem during local vol calculation.

By the way, regarding main topic - you should keep in mind, that Duperi formula is used in continuous case calculation, so dt in lattice method must be really short (for instance, 3000 per year). I use LocalVolSurface class in QL PDE framework and it produces good results (see also http://www.nabble.com/LocalVolSurface-class-to20896055.html#a20896055)

MH_quant wrote
Hallo Dima,

I am very curious about your new kernel interpolation. Sounds like this is
something that can help me a lot right now. I would like to try around a bit
with different interpolation methods to overcome my numerical problems. If I
can make my surface smoother with kernel interpolation I will give it a go
and would like to do some testing on it.

 
How do I get your new kernel interpolation running?  Can I check it out from
the SVN?  I checked the trunk and I found a file called
kernelinterpolation.hpp.   Does it work for 2-dimensions or just for one
because for the surface I need it for two dimensions. Can you please also
send me a link or a paper with more informations about it so I can build up
some theoretical knowledge before I start testing.