OptionletStripper question

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

OptionletStripper question

Nathan Abbott

Hello,

I am looking at the optionletStripper1 class. As an input it uses a volatility term structure. Inside of it, it converts these volatilities into prices. Here in the US the ICAP service provides me with prices and no longer with volatilities (i.e. a grid of cap prices for given maturities and strikes). Any suggestions on how to handle this?

My first thought was to extend the optionletStripper1 class to accept a matrix of prices. Or the CapFloorTermVolSurface could be renamed such that it can also hold prices. Any pointers on how to implement this in a way such that it can become part of the library would be appreciated.

Thank You


-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference
Don't miss this year's exciting event. There's still time to save $100.
Use priority code J8TL2D2.
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users
Reply | Threaded
Open this post in threaded view
|

Re: OptionletStripper question

Ferdinando M. Ametrano-3
Hi Nathan

> I am looking at the optionletStripper1 class. As an input it uses a
> volatility term structure. Inside of it, it converts these volatilities into
> prices. Here in the US the ICAP service provides me with prices and no
> longer with volatilities (i.e. a grid of cap prices for given maturities and
> strikes). Any suggestions on how to handle this?
>
> My first thought was to extend the optionletStripper1 class to accept a
> matrix of prices. Or the CapFloorTermVolSurface could be renamed such that
> it can also hold prices. Any pointers on how to implement this in a way such
> that it can become part of the library would be appreciated.

I had to stop my volatility coding due to more urgent (yield curve)
priorities, but you're right that prices should be supported; given
the recent yield curve turmoil, brokers are kinda shifting towards
prices instead of vols.

I haven't thought in detail about the issue but I see the optionlet
stripper classes as disposable helper classes (btw this is the reason
why they are not fully documented, as they might undergo some major
refactoring). I would probably focus on CapFloorTermVolSurface and
expanding their interface to fully support both prices and vols
inspectors. When it comes to choice between prices and vols as input
parameters I would probably settle for prices, delegating vol handling
to some adapter class which would then turn vols into prices.

ciao -- Nando

-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference
Don't miss this year's exciting event. There's still time to save $100.
Use priority code J8TL2D2.
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users
Reply | Threaded
Open this post in threaded view
|

Re: OptionletStripper question

Nathan Abbott
Sorry I have not gotten back to you earlier, because I have been sick. The short term solution I decide to use is to convert the prices into implied volatilities. Now I have this new problem. When the optionletStripper1 class is deleted after it been calculated, it takes 21 seconds to delete. Is this normal.

Here is an example I have written. It was written with Visual Studio 2005 and boost 1.34.1


#include <ql/quantlib.hpp>

#ifdef BOOST_MSVC
#endif

#include <boost/timer.hpp>
#include <iostream>
#include <iomanip>

using namespace QuantLib;

#if defined(QL_ENABLE_SESSIONS)
namespace QuantLib {

    Integer sessionId() { return 0; }

}
#endif


int main(int, char* []) {

    try {
        boost::timer timer;

        std::cout << "Test optionletstripper1 & StrippedOptionletAdapter deletion...";

        Real accuracy = 1.0e-6;
        Real tolerance = 1.0e-5;

        // create yield curve
        Calendar calendar;
        DayCounter dayCounter;

        RelinkableHandle<YieldTermStructure> yieldTermStructure;

        calendar = TARGET();
        Date today = calendar.adjust(Date::todaysDate());
        Settings::instance().evaluationDate() = today;

        dayCounter = Actual365Fixed();

        Rate flatFwdRate = 0.04;
        yieldTermStructure.linkTo(
            boost::shared_ptr<FlatForward>(new FlatForward(0,
                                                           calendar,
                                                           flatFwdRate,
                                                           dayCounter)));

        // create vol surface
        std::vector<Rate> strikes;
        std::vector<Period> optionTenors;
        Matrix termV;
        boost::shared_ptr<CapFloorTermVolSurface> capFloorVolSurface;

        // tenors vector
        optionTenors = std::vector<Period>();
        optionTenors.push_back(Period(1, Years));
        optionTenors.push_back(Period(18, Months));
        optionTenors.push_back(Period(2, Years));
        optionTenors.push_back(Period(3, Years));
        optionTenors.push_back(Period(4, Years));
        optionTenors.push_back(Period(5, Years));
        optionTenors.push_back(Period(6, Years));
        optionTenors.push_back(Period(7, Years));
        optionTenors.push_back(Period(8, Years));
        optionTenors.push_back(Period(9, Years));
        optionTenors.push_back(Period(10, Years));
        optionTenors.push_back(Period(12, Years));
        optionTenors.push_back(Period(15, Years));
        optionTenors.push_back(Period(20, Years));
        optionTenors.push_back(Period(25, Years));
        optionTenors.push_back(Period(30, Years));

        // strikes vector
        strikes = std::vector<Rate>();
        strikes.push_back(0.015);
        strikes.push_back(0.0175);
        strikes.push_back(0.02);
        strikes.push_back(0.0225);
        strikes.push_back(0.025);
        strikes.push_back(0.03);
        strikes.push_back(0.035);
        strikes.push_back(0.04);
        strikes.push_back(0.05);
        strikes.push_back(0.06);
        strikes.push_back(0.07);
        strikes.push_back(0.08);
        strikes.push_back(0.1);
       
        // volatilities matrix
        termV = Matrix(optionTenors.size(), strikes.size());
        termV[0][0]=0.287;  termV[0][1]=0.274;  termV[0][2]=0.256;  termV[0][3]=0.245;  termV[0][4]=0.227;  termV[0][5]=0.148;  termV[0][6]=0.096;  termV[0][7]=0.09;   termV[0][8]=0.11;   termV[0][9]=0.139;  termV[0][10]=0.166;  termV[0][11]=0.19;   termV[0][12]=0.214;
        termV[1][0]=0.303;  termV[1][1]=0.258;  termV[1][2]=0.22;   termV[1][3]=0.203;  termV[1][4]=0.19;   termV[1][5]=0.153;  termV[1][6]=0.126;  termV[1][7]=0.118;  termV[1][8]=0.147;  termV[1][9]=0.165;  termV[1][10]=0.18;   termV[1][11]=0.192;  termV[1][12]=0.212;
        termV[2][0]=0.303;  termV[2][1]=0.257;  termV[2][2]=0.216;  termV[2][3]=0.196;  termV[2][4]=0.182;  termV[2][5]=0.154;  termV[2][6]=0.134;  termV[2][7]=0.127;  termV[2][8]=0.149;  termV[2][9]=0.166;  termV[2][10]=0.18;   termV[2][11]=0.192;  termV[2][12]=0.212;
        termV[3][0]=0.305;  termV[3][1]=0.266;  termV[3][2]=0.226;  termV[3][3]=0.203;  termV[3][4]=0.19;   termV[3][5]=0.167;  termV[3][6]=0.151;  termV[3][7]=0.144;  termV[3][8]=0.16;   termV[3][9]=0.172;  termV[3][10]=0.183;  termV[3][11]=0.193;  termV[3][12]=0.209;
        termV[4][0]=0.294;  termV[4][1]=0.261;  termV[4][2]=0.216;  termV[4][3]=0.201;  termV[4][4]=0.19;   termV[4][5]=0.171;  termV[4][6]=0.158;  termV[4][7]=0.151;  termV[4][8]=0.163;  termV[4][9]=0.172;  termV[4][10]=0.181;  termV[4][11]=0.188;  termV[4][12]=0.201;
        termV[5][0]=0.276;  termV[5][1]=0.248;  termV[5][2]=0.212;  termV[5][3]=0.199;  termV[5][4]=0.189;  termV[5][5]=0.172;  termV[5][6]=0.16;   termV[5][7]=0.155;  termV[5][8]=0.162;  termV[5][9]=0.17;   termV[5][10]=0.177;  termV[5][11]=0.183;  termV[5][12]=0.195;
        termV[6][0]=0.26;   termV[6][1]=0.237;  termV[6][2]=0.21;   termV[6][3]=0.198;  termV[6][4]=0.188;  termV[6][5]=0.172;  termV[6][6]=0.161;  termV[6][7]=0.156;  termV[6][8]=0.161;  termV[6][9]=0.167;  termV[6][10]=0.173;  termV[6][11]=0.179;  termV[6][12]=0.19;
        termV[7][0]=0.25;   termV[7][1]=0.231;  termV[7][2]=0.208;  termV[7][3]=0.196;  termV[7][4]=0.187;  termV[7][5]=0.172;  termV[7][6]=0.162;  termV[7][7]=0.156;  termV[7][8]=0.16;   termV[7][9]=0.165;  termV[7][10]=0.17;   termV[7][11]=0.175;  termV[7][12]=0.185;
        termV[8][0]=0.244;  termV[8][1]=0.226;  termV[8][2]=0.206;  termV[8][3]=0.195;  termV[8][4]=0.186;  termV[8][5]=0.171;  termV[8][6]=0.161;  termV[8][7]=0.156;  termV[8][8]=0.158;  termV[8][9]=0.162;  termV[8][10]=0.166;  termV[8][11]=0.171;  termV[8][12]=0.18;
        termV[9][0]=0.239;  termV[9][1]=0.222;  termV[9][2]=0.204;  termV[9][3]=0.193;  termV[9][4]=0.185;  termV[9][5]=0.17;   termV[9][6]=0.16;   termV[9][7]=0.155;  termV[9][8]=0.156;  termV[9][9]=0.159;  termV[9][10]=0.163;  termV[9][11]=0.168;  termV[9][12]=0.177;
        termV[10][0]=0.235; termV[10][1]=0.219; termV[10][2]=0.202; termV[10][3]=0.192; termV[10][4]=0.183; termV[10][5]=0.169; termV[10][6]=0.159; termV[10][7]=0.154; termV[10][8]=0.154; termV[10][9]=0.156; termV[10][10]=0.16;  termV[10][11]=0.164; termV[10][12]=0.173;
        termV[11][0]=0.227; termV[11][1]=0.212; termV[11][2]=0.197; termV[11][3]=0.187; termV[11][4]=0.179; termV[11][5]=0.166; termV[11][6]=0.156; termV[11][7]=0.151; termV[11][8]=0.149; termV[11][9]=0.15;  termV[11][10]=0.153; termV[11][11]=0.157; termV[11][12]=0.165;
        termV[12][0]=0.22;  termV[12][1]=0.206; termV[12][2]=0.192; termV[12][3]=0.183; termV[12][4]=0.175; termV[12][5]=0.162; termV[12][6]=0.153; termV[12][7]=0.147; termV[12][8]=0.144; termV[12][9]=0.144; termV[12][10]=0.147; termV[12][11]=0.151; termV[12][12]=0.158;
        termV[13][0]=0.211; termV[13][1]=0.197; termV[13][2]=0.185; termV[13][3]=0.176; termV[13][4]=0.168; termV[13][5]=0.156; termV[13][6]=0.147; termV[13][7]=0.142; termV[13][8]=0.138; termV[13][9]=0.138; termV[13][10]=0.14;  termV[13][11]=0.144; termV[13][12]=0.151;
        termV[14][0]=0.204; termV[14][1]=0.192; termV[14][2]=0.18;  termV[14][3]=0.171; termV[14][4]=0.164; termV[14][5]=0.152; termV[14][6]=0.143; termV[14][7]=0.138; termV[14][8]=0.134; termV[14][9]=0.134; termV[14][10]=0.137; termV[14][11]=0.14;  termV[14][12]=0.148;
        termV[15][0]=0.2;   termV[15][1]=0.187; termV[15][2]=0.176; termV[15][3]=0.167; termV[15][4]=0.16;  termV[15][5]=0.148; termV[15][6]=0.14;  termV[15][7]=0.135; termV[15][8]=0.131; termV[15][9]=0.132; termV[15][10]=0.135; termV[15][11]=0.139; termV[15][12]=0.146;

        // create a capfloor volatility surface based upon tenors/strike/volatility
        capFloorVolSurface = boost::shared_ptr<CapFloorTermVolSurface>(new
            CapFloorTermVolSurface(0, calendar,
                                    optionTenors,
                                    strikes,
                                    termV,
                                    Following,
                                    dayCounter));

        // floating rate index
        boost::shared_ptr<IborIndex> iborIndex(new Euribor6M(yieldTermStructure));

        OptionletStripper* optionletStripper1 = new
            OptionletStripper1(capFloorVolSurface,
                               iborIndex,
                               Null<Rate>(),
                               accuracy);

        optionletStripper1->recalculate();

        delete optionletStripper1;

        Real seconds = timer.elapsed();
        Integer hours = int(seconds/3600);
        seconds -= hours * 3600;
        Integer minutes = int(seconds/60);
        seconds -= minutes * 60;
        std::cout << " \nRun completed in ";
        if (hours > 0)
            std::cout << hours << " h ";
        if (hours > 0 || minutes > 0)
            std::cout << minutes << " m ";
        std::cout << std::fixed << std::setprecision(0)
                  << seconds << " s\n" << std::endl;

        //// create an optionlet stripper based upon the capfloor volatility surface
        //boost::shared_ptr<OptionletStripper> optionletStripper1(new
        //    OptionletStripper1(capFloorVolSurface,
        //                       iborIndex,
        //                       Null<Rate>(),
        //                       accuracy));

        //StrippedOptionletAdapter* pAdapter = new
        //        StrippedOptionletAdapter(optionletStripper1);
        //pAdapter->performCalculations();
        //delete pAdapter;

        // create an optionlet adapter based upon the optionlet stripper
        //boost::shared_ptr<StrippedOptionletAdapter> strippedOptionletAdapter =
        //    boost::shared_ptr<StrippedOptionletAdapter>(new
        //        StrippedOptionletAdapter(optionletStripper1));
        //strippedOptionletAdapter->performCalculations();

    } catch (std::exception& e) {
        std::cout << e.what() << std::endl;
        return 1;
    } catch (...) {
        std::cout << "unknown error" << std::endl;
        return 1;
    }

    std::cout << "Done";
}



On Fri, Apr 18, 2008 at 1:53 AM, Ferdinando Ametrano <[hidden email]> wrote:
Hi Nathan

> I am looking at the optionletStripper1 class. As an input it uses a
> volatility term structure. Inside of it, it converts these volatilities into
> prices. Here in the US the ICAP service provides me with prices and no
> longer with volatilities (i.e. a grid of cap prices for given maturities and
> strikes). Any suggestions on how to handle this?
>
> My first thought was to extend the optionletStripper1 class to accept a
> matrix of prices. Or the CapFloorTermVolSurface could be renamed such that
> it can also hold prices. Any pointers on how to implement this in a way such
> that it can become part of the library would be appreciated.

I had to stop my volatility coding due to more urgent (yield curve)
priorities, but you're right that prices should be supported; given
the recent yield curve turmoil, brokers are kinda shifting towards
prices instead of vols.

I haven't thought in detail about the issue but I see the optionlet
stripper classes as disposable helper classes (btw this is the reason
why they are not fully documented, as they might undergo some major
refactoring). I would probably focus on CapFloorTermVolSurface and
expanding their interface to fully support both prices and vols
inspectors. When it comes to choice between prices and vols as input
parameters I would probably settle for prices, delegating vol handling
to some adapter class which would then turn vols into prices.

ciao -- Nando


-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference
Don't miss this year's exciting event. There's still time to save $100.
Use priority code J8TL2D2.
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users
Reply | Threaded
Open this post in threaded view
|

Re: OptionletStripper question

Ferdinando M. Ametrano-3
Hi Nathan

> Now I have this new problem. When the optionletStripper1 class
> is deleted after it been calculated, it takes 21 seconds to delete. Is this
> normal.

Yes, you're right, and no, it isn't normal. The effect is noticeable
in the test-suite too. I hoped to take a look into it but I didn't.
Anyone willing to help?

ciao -- Nando

-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference
Don't miss this year's exciting event. There's still time to save $100.
Use priority code J8TL2D2.
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users