void LgmSwaptionEngineAD::calculate() const {

    // collect data needed for core computation routine

    QL_REQUIRE(arguments_.settlementType == Settlement::Physical,
               "cash-settled swaptions not yet implemented ...");

    Date settlement = model_->termStructure()->referenceDate();

    if (arguments_.exercise->dates().back() <=
        settlement) { // swaption is expired, possibly generated swap is not
                      // valued
        results_.value = 0.0;
        return;
    }

    int idxMax = static_cast<int>(arguments_.exercise->dates().size()) - 1;
    int minIdxAlive = static_cast<int>(
        std::upper_bound(arguments_.exercise->dates().begin(),
                         arguments_.exercise->dates().end(), settlement) -
        arguments_.exercise->dates().begin());

    VanillaSwap swap = *arguments_.swap;

    int callput = arguments_.type == VanillaSwap::Payer ? 1 : -1;

    Schedule fixedSchedule = swap.fixedSchedule();
    Schedule floatSchedule = swap.floatingSchedule();

    Date expiry0;

    std::vector<int> fix_startidxes, float_startidxes;
    std::vector<Date> expiryDates;

    for (int idx = minIdxAlive; idx <= idxMax; ++idx) {
        expiry0 = arguments_.exercise->dates()[idx];
        expiryDates.push_back(expiry0);

        Size j1 = std::upper_bound(fixedSchedule.dates().begin(),
                                   fixedSchedule.dates().end(), expiry0 - 1) -
                  fixedSchedule.dates().begin();
        Size k1 = std::upper_bound(floatSchedule.dates().begin(),
                                   floatSchedule.dates().end(), expiry0 - 1) -
                  floatSchedule.dates().begin();

        fix_startidxes.push_back(j1);
        float_startidxes.push_back(k1);
    }

    std::vector<double> float_mults, index_acctimes, float_spreads, fix_cpn;
    std::vector<Date> floatt1Dates, floatt2Dates, floattpDates;
    std::vector<Date> fixtpDates;

    for (Size i = 0; i < arguments_.floatingFixingDates.size(); ++i) {
        float_mults.push_back(arguments_.nominal *
                              arguments_.floatingAccrualTimes[i]);
        float_spreads.push_back(arguments_.floatingSpreads[i]);
        boost::shared_ptr<IborIndex> index = arguments_.swap->iborIndex();
        Date d1 = index->valueDate(arguments_.floatingFixingDates[i]);
        Date d2 = index->maturityDate(d1);
        double acctime = index->dayCounter().yearFraction(d1, d2, d1, d2);
        floatt1Dates.push_back(d1);
        floatt2Dates.push_back(d2);
        floattpDates.push_back(arguments_.floatingPayDates[i]);
        index_acctimes.push_back(acctime);
    }

    for (Size i = 0; i < arguments_.fixedCoupons.size(); ++i) {
        fix_cpn.push_back(arguments_.fixedCoupons[i]);
        fixtpDates.push_back(arguments_.fixedPayDates[i]);
    }

    // join all dates and fill index vectors

    std::vector<Date> allDates;
    std::vector<double> allTimes; // with settlement as first entry !
    std::vector<int> expiries, floatt1s, floatt2s, floattps, fixtps;
    std::vector<double> modpar;

    allDates.reserve(expiryDates.size() + floatt1Dates.size() +
                     floatt2Dates.size() + floattpDates.size() +
                     fixtpDates.size());

    allTimes.reserve(allDates.size());
    modpar.reserve(3 * allDates.size());

    allDates.push_back(settlement);
    allDates.insert(allDates.end(), expiryDates.begin(), expiryDates.end());
    allDates.insert(allDates.end(), floatt1Dates.begin(), floatt1Dates.end());
    allDates.insert(allDates.end(), floatt2Dates.begin(), floatt2Dates.end());
    allDates.insert(allDates.end(), floattpDates.begin(), floattpDates.end());
    allDates.insert(allDates.end(), fixtpDates.begin(), fixtpDates.end());

    std::sort(allDates.begin(), allDates.end());
    allDates.erase(unique(allDates.begin(), allDates.end()), allDates.end());

    for (Size i = 0; i < allDates.size(); ++i) {
        allTimes.push_back(
            model_->termStructure()->timeFromReference(allDates[i]));
    }

    for (Size i = 0; i < allDates.size(); ++i) {
        modpar.push_back(model_->parametrization()->H(allTimes[i]));
    }
    for (Size i = 0; i < allDates.size(); ++i) {
        modpar.push_back(model_->parametrization()->zeta(allTimes[i]));
    }
    for (Size i = 0; i < allDates.size(); ++i) {
        modpar.push_back(model_->termStructure()->discount(allTimes[i]));
    }

    for (Size i = 0; i < expiryDates.size(); ++i) {
        expiries.push_back(
            std::find(allDates.begin(), allDates.end(), expiryDates[i]) -
            allDates.begin());
    }
    for (Size i = 0; i < floatt1Dates.size(); ++i) {
        floatt1s.push_back(
            std::find(allDates.begin(), allDates.end(), floatt1Dates[i]) -
            allDates.begin());
    }
    for (Size i = 0; i < floatt2Dates.size(); ++i) {
        floatt2s.push_back(
            std::find(allDates.begin(), allDates.end(), floatt2Dates[i]) -
            allDates.begin());
    }
    for (Size i = 0; i < floattpDates.size(); ++i) {
        floattps.push_back(
            std::find(allDates.begin(), allDates.end(), floattpDates[i]) -
            allDates.begin());
    }
    for (Size i = 0; i < fixtpDates.size(); ++i) {
        fixtps.push_back(
            std::find(allDates.begin(), allDates.end(), fixtpDates[i]) -
            allDates.begin());
    }

    // call core computation routine and set results

    int ntimes = allTimes.size();
    int nexpiries = expiries.size();
    int nfloats = floatt1s.size();
    int nfixs = fix_cpn.size();

    double res = 0.0;
    std::vector<Real> dres(3*ntimes);
    int integration_pts = integrationPoints_;
    double std_devs = stddevs_;
    lgm_swaption_engine_ad_(&ntimes, &allTimes[0], &modpar[0], &nexpiries,
                         &expiries[0], &callput, &nfloats, &float_startidxes[0],
                         &float_mults[0], &index_acctimes[0], &float_spreads[0],
                         &floatt1s[0], &floatt2s[0], &floattps[0],
                         &fix_startidxes[0], &nfixs, &fix_cpn[0], &fixtps[0],
                         &integration_pts, &std_devs, &res, &dres[0]);

    results_.value = res;

    std::vector<Real> H_sensitivity(dres.begin(),dres.begin()+ntimes);
    std::vector<Real> zeta_sensitivity(dres.begin()+ntimes,dres.begin()+2*ntimes);
    std::vector<Real> discount_sensitivity(dres.begin()+2*ntimes,dres.begin()+3*ntimes);

    results_.additionalResults["sensitivityTimes"] = allTimes;
    results_.additionalResults["sensitivityH"] = H_sensitivity;
    results_.additionalResults["sensitivityZeta"] = zeta_sensitivity;
    results_.additionalResults["sensitivityDiscount"] = discount_sensitivity;

}
예제 #2
0
void tet_hp::rsdl(int stage) {  
	/* ONLY NEED TO CALL FOR MOVEMENT BETWEEN MESHES INHERIT FROM THIS FOR SPECIFIC PHYSICS */
//    if (mmovement == coupled_deformable && stage == gbl->nstage && log2p == 0) r_tet_mesh::rsdl(); 
	
	FLT oneminusbeta = 1.0-gbl->beta(stage);
	gbl->res.v(Range(0,npnt-1),Range::all()) = 0.0;
	gbl->res_r.v(Range(0,npnt-1),Range::all()) *= oneminusbeta;

	if (basis::tet(log2p).em) {
		gbl->res.e(Range(0,nseg-1),Range(0,basis::tet(log2p).em-1),Range::all()) = 0.0;
		gbl->res_r.e(Range(0,nseg-1),Range(0,basis::tet(log2p).em-1),Range::all()) *= oneminusbeta;
		
		if (basis::tet(log2p).fm) {
			gbl->res.f(Range(0,ntri-1),Range(0,basis::tet(log2p).fm-1),Range::all()) = 0.0;
			gbl->res_r.f(Range(0,ntri-1),Range(0,basis::tet(log2p).fm-1),Range::all()) *= oneminusbeta;
			
			if (basis::tet(log2p).im) {
				gbl->res.i(Range(0,ntet-1),Range(0,basis::tet(log2p).im-1),Range::all()) = 0.0;
				gbl->res_r.i(Range(0,ntet-1),Range(0,basis::tet(log2p).im-1),Range::all()) *= oneminusbeta;
			}
		}
	}
	
	for(int i=0;i<nfbd;++i)
		hp_fbdry(i)->rsdl(stage);

	for(int i=0;i<nebd;++i)
		hp_ebdry(i)->rsdl(stage);

	for(int i=0;i<nvbd;++i)
		hp_vbdry(i)->rsdl(stage);
		
	helper->rsdl(stage);
			
	Array<TinyVector<FLT,MXTM>,1> lf_re(NV),lf_im(NV); 
	
	for(int tind = 0; tind<ntet;++tind) {
		
		/* LOAD SOLUTION COEFFICIENTS FOR THIS ELEMENT */
		ugtouht(tind);
		
		/* call rsdl for element */
		element_rsdl(tind,stage,uht,lf_re,lf_im);
		
		/* load imaginary local residual into global residual */
		for (int m = 0; m < basis::tet(log2p).tm; ++m) 
			for (int n = 0; n < NV; ++n)
				lf(n)(m) = lf_im(n)(m);
		
		lftog(tind,gbl->res);
		
		/* load real local residual into global residual */
		for (int m = 0; m < basis::tet(log2p).tm; ++m) 
			for (int n = 0; n < NV; ++n)
				lf(n)(m) = lf_re(n)(m);
		
		lftog(tind,gbl->res_r);
	}
	
	
	/* ADD IN VISCOUS/DISSIPATIVE FLUX */
	gbl->res.v(Range(0,npnt-1),Range::all()) += gbl->res_r.v(Range(0,npnt-1),Range::all());
	if (basis::tet(log2p).em > 0) {
		gbl->res.e(Range(0,nseg-1),Range(0,basis::tet(log2p).em-1),Range::all()) += gbl->res_r.e(Range(0,nseg-1),Range(0,basis::tet(log2p).em-1),Range::all());          
		if (basis::tet(log2p).fm > 0) {
			gbl->res.f(Range(0,ntri-1),Range(0,basis::tet(log2p).fm-1),Range::all()) += gbl->res_r.f(Range(0,ntri-1),Range(0,basis::tet(log2p).fm-1),Range::all());      
			if (basis::tet(log2p).im > 0) {
				gbl->res.i(Range(0,ntet-1),Range(0,basis::tet(log2p).im-1),Range::all()) += gbl->res_r.i(Range(0,ntet-1),Range(0,basis::tet(log2p).im-1),Range::all());      
			}
		}
	}
	

#ifdef DEBUG
	if (coarse_flag) {
		for(int i=0;i<npnt;++i) {
			printf("rsdl v: %d ",i);
			for (int n=0;n<NV;++n) 
				printf("%e ",gbl->res.v(i,n));
			printf("\n");
		}
		
		for(int i=0;i<nseg;++i) {
			for(int m=0;m<basis::tet(log2p).em;++m) {
				printf("rsdl s: %d %d ",i,m); 
				for(int n=0;n<NV;++n)
					printf("%e ",gbl->res.e(i,m,n));
				printf("\n");
			}
		}
		
		for(int i=0;i<ntri;++i) {
			for(int m=0;m<basis::tet(log2p).fm;++m) {
				printf("rsdl i: %d %d ",i,m);
				for(int n=0;n<NV;++n) 
					printf("%e \n",gbl->res.f(i,m,n));
				printf("\n");
			}
		}
	}
#endif
	
	/*********************************************/
	/* MODIFY RESIDUALS ON COARSER MESHES            */
	/*********************************************/    
	if (coarse_flag) {
		/* CALCULATE DRIVING TERM ON FIRST ENTRY TO COARSE MESH */
		if(isfrst) {
			dres(log2p).v(Range(0,npnt-1),Range::all()) = fadd*gbl->res0.v(Range(0,npnt-1),Range::all()) -gbl->res.v(Range(0,npnt-1),Range::all());
			if (basis::tet(log2p).em) dres(log2p).e(Range(0,nseg-1),Range(0,basis::tet(log2p).em-1),Range::all()) = fadd*gbl->res0.e(Range(0,nseg-1),Range(0,basis::tet(log2p).em-1),Range::all()) -gbl->res.e(Range(0,nseg-1),Range(0,basis::tet(log2p).em-1),Range::all());      
			if (basis::tet(log2p).fm) dres(log2p).f(Range(0,ntri-1),Range(0,basis::tet(log2p).fm-1),Range::all()) = fadd*gbl->res0.f(Range(0,ntri-1),Range(0,basis::tet(log2p).fm-1),Range::all()) -gbl->res.f(Range(0,ntri-1),Range(0,basis::tet(log2p).fm-1),Range::all());
			if (basis::tet(log2p).im) dres(log2p).i(Range(0,ntet-1),Range(0,basis::tet(log2p).im-1),Range::all()) = fadd*gbl->res0.i(Range(0,ntet-1),Range(0,basis::tet(log2p).im-1),Range::all()) -gbl->res.i(Range(0,ntet-1),Range(0,basis::tet(log2p).im-1),Range::all());
			isfrst = false;
		}
		gbl->res.v(Range(0,npnt-1),Range::all()) += dres(log2p).v(Range(0,npnt-1),Range::all()); 
		if (basis::tet(log2p).em) gbl->res.e(Range(0,nseg-1),Range(0,basis::tet(log2p).em-1),Range::all()) += dres(log2p).e(Range(0,nseg-1),Range(0,basis::tet(log2p).em-1),Range::all());
		if (basis::tet(log2p).fm) gbl->res.f(Range(0,ntri-1),Range(0,basis::tet(log2p).fm-1),Range::all()) += dres(log2p).f(Range(0,ntri-1),Range(0,basis::tet(log2p).fm-1),Range::all());  
		if (basis::tet(log2p).im) gbl->res.i(Range(0,ntet-1),Range(0,basis::tet(log2p).im-1),Range::all()) += dres(log2p).i(Range(0,ntet-1),Range(0,basis::tet(log2p).im-1),Range::all());  
	}

	
	return;
}