cmsmarket.cpp

来自「有很多的函数库」· C++ 代码 · 共 459 行 · 第 1/2 页

CPP
459
字号


    Real CmsMarket::weightedError(const Matrix& weights){
        priceSpotFromForwardStartingCms();
        return weightedMean(spreadErrors_,weights);
    }

    Real CmsMarket::weightedPriceError(const Matrix& weights){
        priceSpotFromForwardStartingCms();
        return weightedMean(priceErrors_,weights);
    }

    Real CmsMarket::weightedForwardPriceError(const Matrix& weights){
        return weightedMean(forwardPriceErrors_,weights);
    }

    // return an array of errors to be used for Levenberg-Marquardt optimization.

    Disposable<Array> CmsMarket::weightedErrors(const Matrix& weights){
        priceSpotFromForwardStartingCms();
        return weightedMeans(spreadErrors_,weights);
    }

    Disposable<Array> CmsMarket::weightedPriceErrors(const Matrix& weights){
        priceSpotFromForwardStartingCms();
        return weightedMeans(priceErrors_,weights);
    }

    Disposable<Array> CmsMarket::weightedForwardPriceErrors(
                                                        const Matrix& weights){
        return weightedMeans(forwardPriceErrors_,weights);
    }

    Real CmsMarket::weightedMean(const Matrix& var, const Matrix& weights){
        Real mean=0.;
        for(Size i=0;i<nExercise_;i++){
            for(Size j=0;j<nSwapTenors_;j++){
                mean += weights[i][j]*var[i][j]*var[i][j];
            }
        }
        mean=std::sqrt(mean/(nExercise_*nSwapTenors_));
        return mean;
    }

    Disposable<Array> CmsMarket::weightedMeans(const Matrix& var,
                                                       const Matrix& weights){
        Array  weightedVars(nExercise_*nSwapTenors_);
        for(Size i=0; i<nExercise_; i++) {
            for(Size j=0; j<nSwapTenors_; j++) {
                weightedVars[i*nSwapTenors_+j] = std::sqrt(weights[i][j])*var[i][j];
            }
        }
        return weightedVars;
    }

    Matrix CmsMarket::browse() const{
        calculate();
        Matrix result(nExercise_*nSwapTenors_,19,0.);
            for(Size j=0;j<nSwapTenors_;j++){
                for(Size i=0;i<nExercise_;i++){
                result[j*nSwapTenors_+i][0]= swapTenors_[j].length();
                result[j*nSwapTenors_+i][1]= expiries_[i].length();

                // Spreads
                result[j*nSwapTenors_+i][2]= bids_[i][j]*10000;
                result[j*nSwapTenors_+i][3]= asks_[i][j]*10000;
                result[j*nSwapTenors_+i][4]= mids_[i][j]*10000;
                result[j*nSwapTenors_+i][5]= modelCmsSpreads_[i][j]*10000;
                result[j*nSwapTenors_+i][6]= spreadErrors_[i][j]*10000;
                if(modelCmsSpreads_[i][j]>asks_[i][j]){
                    result[j*nSwapTenors_+i][7]= (modelCmsSpreads_[i][j]-asks_[i][j])*10000;
                }
                else if(modelCmsSpreads_[i][j]<bids_[i][j]){
                    result[j*nSwapTenors_+i][7]= (bids_[i][j]-modelCmsSpreads_[i][j])*10000;
                }
                else{ result[j*nSwapTenors_+i][7]= 0.; }

                // Prices of cms
                result[j*nSwapTenors_+i][8]= marketBidCmsLegValues_[i][j];
                result[j*nSwapTenors_+i][9]= marketAskCmsLegValues_[i][j];
                result[j*nSwapTenors_+i][10]= marketMidCmsLegValues_[i][j];
                result[j*nSwapTenors_+i][11]= modelCmsLegValues_[i][j];
                result[j*nSwapTenors_+i][12]= priceErrors_[i][j];

                // Prices of forward cms
                result[j*nSwapTenors_+i][13]= marketBidForwardCmsLegValues_[i][j];
                result[j*nSwapTenors_+i][14]= marketAskForwardCmsLegValues_[i][j];
                result[j*nSwapTenors_+i][15]= marketMidForwardCmsLegValues_[i][j];
                result[j*nSwapTenors_+i][16]= modelForwardCmsLegValues_[i][j];
                result[j*nSwapTenors_+i][17]= forwardPriceErrors_[i][j];

                // mean reversions
                result[j*nSwapTenors_+i][18]= meanReversions_[i][j];

            }
        }
        return result;
    }

    //===========================================================================//
    //                       CmsMarketCalibration                                //
    //===========================================================================//

    CmsMarketCalibration::CmsMarketCalibration(
        Handle<SwaptionVolatilityStructure>& volCube,
        boost::shared_ptr<CmsMarket>& cmsMarket,
        const Matrix& weights,
        CalibrationType calibrationType):
    volCube_(volCube),
    cmsMarket_(cmsMarket),
    weights_(weights),
    calibrationType_(calibrationType){
    }

    Array CmsMarketCalibration::compute(
            const boost::shared_ptr<EndCriteria>& endCriteria,
            const boost::shared_ptr<OptimizationMethod>& method,
            const Array& guess,
            bool isMeanReversionFixed){
        Array result;
        if(isMeanReversionFixed){
            Size nBeta = guess.size()-1;
            ParametersConstraintWithFixedMeanReversion constraint(nBeta);
            Real fixedMeanReversion = guess[nBeta];
            Array betasGuess(nBeta);
            for(Size i=0;i<nBeta;i++)
                betasGuess[i] = guess[i];
            ObjectiveFunctionWithFixedMeanReversion costFunction(this, fixedMeanReversion);
            Problem problem(costFunction, constraint,betasGuess);
            endCriteria_ = method->minimize(problem, *endCriteria);
            result = problem.currentValue();
            error_ = costFunction.value(result);
        }
        else {
            ParametersConstraint constraint(guess.size()-1);
            ObjectiveFunction costFunction(this);
            Problem problem(costFunction, constraint,guess);
            endCriteria_ = method->minimize(problem, *endCriteria);
            result = problem.currentValue();
            error_ = costFunction.value(result);
        }
        const boost::shared_ptr<SwaptionVolCube1> volCubeBySabr =
            boost::dynamic_pointer_cast<SwaptionVolCube1>(volCube_.currentLink());
        sparseSabrParameters_ = volCubeBySabr->sparseSabrParameters();
        denseSabrParameters_ = volCubeBySabr->denseSabrParameters();
        browseCmsMarket_ = cmsMarket_->browse();

        return result;
    }

    //===========================================================================//
    //                   CmsMarketCalibration::ObjectiveFunction                 //
    //===========================================================================//

    Real CmsMarketCalibration::ObjectiveFunction::value(const Array& x) const {
        updateVolatilityCubeAndCmsMarket(x);
        return switchErrorFunctionOnCalibrationType();
    }

    Disposable<Array> CmsMarketCalibration::ObjectiveFunction::values(const Array& x) const {
        updateVolatilityCubeAndCmsMarket(x);
        return switchErrorsFunctionOnCalibrationType();
    }

    void CmsMarketCalibration::ObjectiveFunction::
                    updateVolatilityCubeAndCmsMarket(const Array& x) const {
        const Array y = x;
        const std::vector<Period>& swapTenors = cmsMarket_->swapTenors();
        Size nSwapTenors = swapTenors.size();
        QL_REQUIRE(nSwapTenors+1 == x.size(),"bad calibration guess nSwapTenors+1 != x.size()");
        const boost::shared_ptr<SwaptionVolCube1> volCubeBySabr =
               boost::dynamic_pointer_cast<SwaptionVolCube1>(volCube_.currentLink());
        for (Size i=0; i<nSwapTenors; i++){
            Real beta = y[i];
            volCubeBySabr->recalibration(beta, swapTenors[i]);
        }
        Real meanReversion = y[nSwapTenors];
        cmsMarket_->reprice(volCube_, meanReversion);
    }

    Real CmsMarketCalibration::ObjectiveFunction::switchErrorFunctionOnCalibrationType() const {
        switch (calibrationType_) {
            case OnSpread:
                return cmsMarket_->weightedError(weights_);
            case OnPrice:
                return cmsMarket_->weightedPriceError(weights_);
            case OnForwardCmsPrice:
                return cmsMarket_->weightedForwardPriceError(weights_);
            default:
                QL_FAIL("unknown/illegal calibration type");
        }
    }

    Disposable<Array> CmsMarketCalibration::ObjectiveFunction::
                                    switchErrorsFunctionOnCalibrationType() const {
        switch (calibrationType_) {
            case OnSpread:
                return cmsMarket_->weightedErrors(weights_);
            case OnPrice:
                return cmsMarket_->weightedPriceErrors(weights_);
            case OnForwardCmsPrice:
                return cmsMarket_->weightedForwardPriceErrors(weights_);
            default:
                QL_FAIL("unknown/illegal calibration type");
        }
    }

    //===========================================================================//
    //       CmsMarketCalibration::ObjectiveFunctionWithFixedMeanReversion       //
    //===========================================================================//

    void CmsMarketCalibration::ObjectiveFunctionWithFixedMeanReversion::
                                updateVolatilityCubeAndCmsMarket(const Array& x) const {
        const Array y = x;
        const std::vector<Period>& swapTenors = cmsMarket_->swapTenors();
        Size nSwapTenors = swapTenors.size();
        QL_REQUIRE(nSwapTenors == x.size(),"bad calibration guess nSwapTenors != x.size()");
        const boost::shared_ptr<SwaptionVolCube1> volCubeBySabr =
               boost::dynamic_pointer_cast<SwaptionVolCube1>(volCube_.currentLink());
        for (Size i=0; i<nSwapTenors; i++){
            Real beta = y[i];
            volCubeBySabr->recalibration(beta, swapTenors[i]);
        }
        cmsMarket_->reprice(volCube_, fixedMeanReversion_);
    }


}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?