//! rerun every time instruments/referenceDate changes internal virtual void init() { // yield conventions DayCounter yieldDC = curve_.dayCounter(); Compounding yieldComp = Compounding.Compounded; Frequency yieldFreq = Frequency.Annual; int n = curve_.bondHelpers_.Count; costFunction_ = new FittingCost(this); costFunction_.firstCashFlow_ = new InitializedList <int>(n); for (int i = 0; i < curve_.bondHelpers_.Count; ++i) { Bond bond = curve_.bondHelpers_[i].bond(); List <CashFlow> cf = bond.cashflows(); Date bondSettlement = bond.settlementDate(); for (int k = 0; k < cf.Count; ++k) { if (!cf[k].hasOccurred(bondSettlement, false)) { costFunction_.firstCashFlow_[i] = k; break; } } } if (calculateWeights_) { //if (weights_.empty()) weights_ = new Vector(n); double squaredSum = 0.0; for (int i = 0; i < curve_.bondHelpers_.Count; ++i) { Bond bond = curve_.bondHelpers_[i].bond(); double cleanPrice = curve_.bondHelpers_[i].quote().link.value(); Date bondSettlement = bond.settlementDate(); double ytm = BondFunctions.yield(bond, cleanPrice, yieldDC, yieldComp, yieldFreq, bondSettlement); double dur = BondFunctions.duration(bond, ytm, yieldDC, yieldComp, yieldFreq, Duration.Type.Modified, bondSettlement); weights_[i] = 1.0 / dur; squaredSum += weights_[i] * weights_[i]; } weights_ /= Math.Sqrt(squaredSum); } Utils.QL_REQUIRE(weights_.size() == n, () => "Given weights do not cover all boostrapping helpers"); }
protected override void performCalculations() { List <BTP> btps = basket_.btps(); List <Handle <Quote> > quotes = basket_.cleanPriceQuotes(); Date bondSettlementDate = btps[0].settlementDate(); for (int i = 0; i < basket_.size(); ++i) { yields_[i] = BondFunctions.yield(btps[i], quotes[i].link.value(), new ActualActual(ActualActual.Convention.ISMA), Compounding.Compounded, Frequency.Annual, bondSettlementDate, // accuracy, maxIterations, guess 1.0e-10, 100, yields_[i]); durations_[i] = BondFunctions.duration(btps[i], yields_[i], new ActualActual(ActualActual.Convention.ISMA), Compounding.Compounded, Frequency.Annual, Duration.Type.Modified, bondSettlementDate); } duration_ = 0; basket_.weights().ForEach((ii, vv) => duration_ += vv * yields()[ii]); int settlDays = 2; DayCounter fixedDayCount = swaps_[0].fixedDayCount(); equivalentSwapIndex_ = nSwaps_ - 1; swapRates_[0] = swaps_[0].fairRate(); FixedRateBond swapBond = new FixedRateBond(settlDays, 100.0, // faceAmount swaps_[0].fixedSchedule(), new List <double>() { swapRates_[0].Value }, fixedDayCount, BusinessDayConvention.Following, // paymentConvention 100.0); // redemption swapBondYields_[0] = BondFunctions.yield(swapBond, 100.0, // floating leg NPV including end payment new ActualActual(ActualActual.Convention.ISMA), Compounding.Compounded, Frequency.Annual, bondSettlementDate, // accuracy, maxIterations, guess 1.0e-10, 100, swapBondYields_[0].Value); swapBondDurations_[0] = BondFunctions.duration(swapBond, swapBondYields_[0].Value, new ActualActual(ActualActual.Convention.ISMA), Compounding.Compounded, Frequency.Annual, Duration.Type.Modified, bondSettlementDate); for (int i = 1; i < nSwaps_; ++i) { swapRates_[i] = swaps_[i].fairRate(); FixedRateBond swapBond2 = new FixedRateBond(settlDays, 100.0, // faceAmount swaps_[i].fixedSchedule(), new List <double>() { swapRates_[i].Value }, fixedDayCount, BusinessDayConvention.Following, // paymentConvention 100.0); // redemption swapBondYields_[i] = BondFunctions.yield(swapBond2, 100.0, // floating leg NPV including end payment new ActualActual(ActualActual.Convention.ISMA), Compounding.Compounded, Frequency.Annual, bondSettlementDate, // accuracy, maxIterations, guess 1.0e-10, 100, swapBondYields_[i].Value); swapBondDurations_[i] = BondFunctions.duration(swapBond2, swapBondYields_[i].Value, new ActualActual(ActualActual.Convention.ISMA), Compounding.Compounded, Frequency.Annual, Duration.Type.Modified, bondSettlementDate); if (swapBondDurations_[i] > duration_) { equivalentSwapIndex_ = i - 1; break; // exit the loop } } return; }