Changeset 208
- Timestamp:
- 06/16/08 21:53:12 (5 months ago)
- Files:
-
- trunk/QLNet/QLNet/Math/Interpolations/convexmonotoneinterpolation.cs (modified) (2 diffs)
- trunk/QLNet/QLNet/Termstructures/Yield/Bootstraptraits.cs (modified) (1 diff)
- trunk/QLNet/QLNet/Termstructures/Yield/PiecewiseYieldCurve.cs (modified) (6 diffs)
- trunk/QLNet/QLNet/Termstructures/localbootstrap.cs (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/QLNet/QLNet/Math/Interpolations/convexmonotoneinterpolation.cs
r207 r208 49 49 } 50 50 public double primitive(double x) { 51 double result = (quadraticity_ * quadraticHelper_.primitive(x) + (1.0 - quadraticity_) * convMonoHelper_.primitive(x));52 51 return (quadraticity_ * quadraticHelper_.primitive(x) + (1.0 - quadraticity_) * convMonoHelper_.primitive(x)); 53 52 } … … 721 720 public Interpolation localInterpolate(List<double> xBegin, int size, List<double> yBegin, int localisation, 722 721 ConvexMonotoneInterpolation prevInterpolation, int finalSize) { 723 int length = xBegin.Count;722 int length = size; 724 723 if (length - localisation == 1) { // the first time this 725 724 // function is called trunk/QLNet/QLNet/Termstructures/Yield/Bootstraptraits.cs
r144 r208 114 114 //! Forward-curve traits 115 115 public class ForwardRate : ITraits { 116 const double avgRate = 0.05; 117 116 118 public Date initialDate(YieldTermStructure c) { return c.referenceDate(); } // start of curve data 117 public double initialValue(YieldTermStructure c) { return 0.02; } // dummy value at reference date119 public double initialValue(YieldTermStructure c) { return avgRate; } // dummy value at reference date 118 120 public bool dummyInitialValue() { return true; } // true if the initialValue is just a dummy value 119 public double initialGuess() { return 0.02; } // initial guess121 public double initialGuess() { return avgRate; } // initial guess 120 122 // further guesses 121 123 public double guess(YieldTermStructure c, Date d) { trunk/QLNet/QLNet/Termstructures/Yield/PiecewiseYieldCurve.cs
r202 r208 23 23 24 24 namespace QLNet { 25 // this is the abstract class to give access to all properties and methods of PiecewiseYieldCurve and avoiding generics 26 public abstract class IPiecewiseYieldCurve : YieldTermStructure, ITraits { 27 #region Properties 28 public List<double> data_; 29 30 public List<BootstrapHelper<YieldTermStructure>> instruments_; 31 32 public Interpolation interpolation_; 33 #endregion 34 35 // two constructors to forward down the ctor chain 36 public IPiecewiseYieldCurve(Date referenceDate, Calendar cal, DayCounter dc) : base(referenceDate, cal, dc) { } 37 public IPiecewiseYieldCurve(int settlementDays, Calendar cal, DayCounter dc) : base(settlementDays, cal, dc) { } 38 39 #region Traits wrapper 40 public abstract Date initialDate(YieldTermStructure c); 41 public abstract double initialValue(YieldTermStructure c); 42 public abstract bool dummyInitialValue(); 43 public abstract double initialGuess(); 44 public abstract double guess(YieldTermStructure c, Date d); 45 public abstract double minValueAfter(int s, List<double> l); 46 public abstract double maxValueAfter(int s, List<double> l); 47 public abstract void updateGuess(List<double> data, double discount, int i); 48 public abstract int maxIterations(); 49 50 protected abstract override double discountImpl(double t); 51 protected abstract double zeroYieldImpl(double t); 52 protected abstract double forwardImpl(double t); 53 54 // these are dummy methods (for the sake of ITraits and should not be called directly 55 public abstract double discountImpl(Interpolation i, double t); 56 public abstract double zeroYieldImpl(Interpolation i, double t); 57 public abstract double forwardImpl(Interpolation i, double t); 58 #endregion 59 } 60 61 25 62 public class PiecewiseYieldCurve<Traits, Interpolator> 26 63 : PiecewiseYieldCurve<Traits, Interpolator, IterativeBootstrap> … … 51 88 } 52 89 53 public class PiecewiseYieldCurve<Traits, Interpolator, BootStrap> : YieldTermStructure // , ITraits 90 91 public class PiecewiseYieldCurve<Traits, Interpolator, BootStrap> : IPiecewiseYieldCurve, ITraits 54 92 where Traits : ITraits, new() 55 93 where Interpolator : IInterpolationFactory, new() … … 59 97 public List<Date> dates_; 60 98 public List<double> times_ = new List<double>(); 61 public List<double> data_;62 99 63 100 protected Handle<Quote> turnOfYearEffect_; … … 66 103 protected double turnOfYear_; 67 104 68 public List<BootstrapHelper<YieldTermStructure>> instruments_;69 70 public Interpolation interpolation_;71 105 public Interpolator interpolator_; 72 106 … … 76 110 #region Traits wrapper 77 111 protected ITraits traits_ = new Traits(); 78 public Date initialDate(YieldTermStructure c) { return traits_.initialDate(c); }79 public double initialValue(YieldTermStructure c) { return traits_.initialValue(c); }80 public bool dummyInitialValue() { return traits_.dummyInitialValue(); }81 public double initialGuess() { return traits_.initialGuess(); }82 public double guess(YieldTermStructure c, Date d) { return traits_.guess(c, d); }83 public double minValueAfter(int s, List<double> l) { return traits_.minValueAfter(s, l); }84 public double maxValueAfter(int s, List<double> l) { return traits_.maxValueAfter(s, l); }85 public void updateGuess(List<double> data, double discount, int i) { traits_.updateGuess(data, discount, i); }86 public int maxIterations() { return traits_.maxIterations(); }112 public override Date initialDate(YieldTermStructure c) { return traits_.initialDate(c); } 113 public override double initialValue(YieldTermStructure c) { return traits_.initialValue(c); } 114 public override bool dummyInitialValue() { return traits_.dummyInitialValue(); } 115 public override double initialGuess() { return traits_.initialGuess(); } 116 public override double guess(YieldTermStructure c, Date d) { return traits_.guess(c, d); } 117 public override double minValueAfter(int s, List<double> l) { return traits_.minValueAfter(s, l); } 118 public override double maxValueAfter(int s, List<double> l) { return traits_.maxValueAfter(s, l); } 119 public override void updateGuess(List<double> data, double discount, int i) { traits_.updateGuess(data, discount, i); } 120 public override int maxIterations() { return traits_.maxIterations(); } 87 121 88 122 protected override double discountImpl(double t) { … … 101 135 return traits_.discountImpl(interpolation_, t); 102 136 } 103 protected double zeroYieldImpl(double t) { return traits_.zeroYieldImpl(interpolation_, t); }104 protected double forwardImpl(double t) { return traits_.forwardImpl(interpolation_, t); }137 protected override double zeroYieldImpl(double t) { return traits_.zeroYieldImpl(interpolation_, t); } 138 protected override double forwardImpl(double t) { return traits_.forwardImpl(interpolation_, t); } 105 139 106 140 // these are dummy methods (for the sake of ITraits and should not be called directly 107 // publicdouble discountImpl(Interpolation i, double t) { throw new NotSupportedException(); }108 // publicdouble zeroYieldImpl(Interpolation i, double t) { throw new NotSupportedException(); }109 // publicdouble forwardImpl(Interpolation i, double t) { throw new NotSupportedException(); }141 public override double discountImpl(Interpolation i, double t) { throw new NotSupportedException(); } 142 public override double zeroYieldImpl(Interpolation i, double t) { throw new NotSupportedException(); } 143 public override double forwardImpl(Interpolation i, double t) { throw new NotSupportedException(); } 110 144 #endregion 111 145 trunk/QLNet/QLNet/Termstructures/localbootstrap.cs
r202 r208 23 23 24 24 namespace QLNet { 25 // penalty function class for solving using a multi-dimensional solver 26 public class PenaltyFunction<Curve> : CostFunction where Curve : IPiecewiseYieldCurve { 27 //typedef typename Curve::traits_type Traits; 28 //typedef typename Traits::helper helper; 29 //typedef typename std::vector< boost::shared_ptr<helper> >::const_iterator helper_iterator; 30 31 private Curve curve_; 32 private int initialIndex_; 33 private int localisation_, start_, end_; 34 private List<BootstrapHelper<YieldTermStructure>> rateHelpers_; 35 36 public PenaltyFunction(Curve curve, int initialIndex, List<BootstrapHelper<YieldTermStructure>> rateHelpers, int start, int end) { 37 curve_ = curve; 38 initialIndex_ = initialIndex; 39 rateHelpers_ = rateHelpers; 40 start_ = start; 41 end_ = end; 42 localisation_ = end - start; 43 } 44 45 public override double value(Vector x) { 46 int i = initialIndex_; 47 x.ForEach(z => { 48 curve_.updateGuess(curve_.data_, z, i); 49 ++i; 50 }); 51 52 curve_.interpolation_.update(); 53 54 double penalty = 0.0; 55 for(int j = start_; j < end_; j++) { 56 double quoteError = rateHelpers_[j].quoteError(); 57 penalty += Math.Abs(quoteError); 58 } 59 return penalty; 60 } 61 62 public override Vector values(Vector x) { 63 int i = initialIndex_; 64 x.ForEach(z => { 65 curve_.updateGuess(curve_.data_, z, i); 66 ++i; 67 }); 68 69 curve_.interpolation_.update(); 70 71 Vector penalties = new Vector(localisation_); 72 var instIt = start_; 73 int penIt = 0; 74 while (instIt != end_) { 75 double quoteError = rateHelpers_[instIt].quoteError(); 76 penalties[penIt] = Math.Abs(quoteError); 77 ++instIt; 78 ++penIt; 79 } 80 return penalties; 81 } 82 } 83 84 25 85 //! Localised-term-structure bootstrapper for most curve types. 26 86 /*! This algorithm enables a localised fitting for non-local … … 83 143 84 144 validCurve_ = false; 85 int n = ts_.instruments_.Count;145 int nInsts = ts_.instruments_.Count; 86 146 87 147 // ensure rate helpers are sorted … … 89 149 90 150 // check that there is no instruments with the same maturity 91 for (int i = 1; i < n ; ++i) {151 for (int i = 1; i < nInsts; ++i) { 92 152 Date m1 = ts_.instruments_[i - 1].latestDate(), 93 153 m2 = ts_.instruments_[i].latestDate(); … … 96 156 97 157 // check that there is no instruments with invalid quote 98 for (int i = 0; i < n ; ++i)158 for (int i = 0; i < nInsts; ++i) 99 159 if (!ts_.instruments_[i].quoteIsValid()) 100 160 throw new ArgumentException("instrument " + i + " (maturity: " + ts_.instruments_[i].latestDate() + … … 102 162 103 163 // setup instruments and register with them 104 for (int i = 0; i < n; ++i) { 105 // There is a significant interaction with observability. 106 ts_.instruments_[i].setTermStructure(ts_); 164 ts_.instruments_.ForEach(i => i.setTermStructure(ts_)); 165 166 // set initial guess only if the current curve cannot be used as guess 167 if (validCurve_) { 168 if (ts_.data_.Count != nInsts + 1) 169 throw new ArgumentException("dimension mismatch: expected " + nInsts + 1 + ", actual " + ts_.data_.Count); 170 } else { 171 ts_.data_ = new InitializedList<double>(nInsts + 1); 172 ts_.data_[0] = ts_.initialValue(ts_); 107 173 } 108 174 109 175 // calculate dates and times 110 ts_.dates_ = new InitializedList<Date>(n + 1);111 ts_.times_ = new InitializedList<double>(n + 1);176 ts_.dates_ = new InitializedList<Date>(nInsts + 1); 177 ts_.times_ = new InitializedList<double>(nInsts + 1); 112 178 ts_.dates_[0] = ts_.initialDate(ts_); 113 179 ts_.times_[0] = ts_.timeFromReference(ts_.dates_[0]); 114 for (int i = 0; i < n ; ++i) {180 for (int i = 0; i < nInsts; ++i) { 115 181 ts_.dates_[i + 1] = ts_.instruments_[i].latestDate(); 116 182 ts_.times_[i + 1] = ts_.timeFromReference(ts_.dates_[i + 1]); … … 119 185 } 120 186 121 // set initial guess only if the current curve cannot be used as guess122 if (validCurve_) {123 if (ts_.data_.Count != n + 1)124 throw new ArgumentException("dimension mismatch: expected " + n + 1 + ", actual " + ts_.data_.Count);125 } else {126 ts_.data_ = new InitializedList<double>(n + 1);127 ts_.data_[0] = ts_.initialValue(ts_);128 }129 130 throw new NotImplementedException();131 132 187 LevenbergMarquardt solver = new LevenbergMarquardt(ts_.accuracy_, ts_.accuracy_, ts_.accuracy_); 133 188 EndCriteria endCriteria = new EndCriteria(100, 10, 0.00, ts_.accuracy_, 0.00); 134 //PositiveConstraint posConstraint; 135 //NoConstraint noConstraint; 136 //Constraint& solverConstraint = forcePositive_ ? 137 // static_cast<Constraint&>(posConstraint) : 138 // static_cast<Constraint&>(noConstraint); 139 140 //// now start the bootstrapping. 141 //Size iInst = localisation_-1; 142 143 //Size dataAdjust = Curve::interpolator_type::dataSizeAdjustment; 144 145 //do { 146 // Size initialDataPt = iInst+1-localisation_+dataAdjust; 147 // Array startArray(localisation_+1-dataAdjust); 148 // for (Size j = 0; j < startArray.size()-1; ++j) 149 // startArray[j] = ts_->data_[initialDataPt+j]; 150 151 // // here we are extending the interpolation a point at a 152 // // time... but the local interpolator can make an 153 // // approximation for the final localisation period. 154 // // e.g. if the localisation is 2, then the first section 155 // // of the curve will be solved using the first 2 156 // // instruments... with the local interpolator making 157 // // suitable boundary conditions. 158 // ts_->interpolation_ = 159 // ts_->interpolator_.localInterpolate( 160 // ts_->times_.begin(), 161 // ts_->times_.begin()+(iInst + 2), 162 // ts_->data_.begin(), 163 // localisation_, 164 // ts_->interpolation_, 165 // nInsts+1); 166 167 // if (iInst >= localisation_) { 168 // startArray[localisation_-dataAdjust] = 169 // Traits::guess(ts_, ts_->dates_[iInst]); 170 // } else { 171 // startArray[localisation_-dataAdjust] = ts_->data_[0]; 172 // } 173 174 // PenaltyFunction<Curve> currentCost( 175 // ts_, 176 // initialDataPt, 177 // ts_->instruments_.begin() + (iInst - localisation_+1), 178 // ts_->instruments_.begin() + (iInst+1)); 179 180 // Problem toSolve(currentCost, solverConstraint, startArray); 181 182 // EndCriteria::Type endType = solver.minimize(toSolve, endCriteria); 183 184 // // check the end criteria 185 // QL_REQUIRE(endType == EndCriteria::StationaryFunctionAccuracy || 186 // endType == EndCriteria::StationaryFunctionValue, 187 // "Unable to strip yieldcurve to required accuracy " ); 188 // ++iInst; 189 //} while ( iInst < nInsts ); 190 //validCurve_ = true; 189 PositiveConstraint posConstraint = new PositiveConstraint(); 190 NoConstraint noConstraint = new NoConstraint(); 191 Constraint solverConstraint = forcePositive_ ? (Constraint)posConstraint : (Constraint)noConstraint; 192 193 // now start the bootstrapping. 194 int iInst = localisation_ - 1; 195 196 int dataAdjust = (ts_.interpolator_ as ConvexMonotone).dataSizeAdjustment; 197 198 do { 199 int initialDataPt = iInst+1-localisation_+dataAdjust; 200 Vector startArray = new Vector(localisation_+1-dataAdjust); 201 for (int j = 0; j < startArray.size()-1; ++j) 202 startArray[j] = ts_.data_[initialDataPt+j]; 203 204 // here we are extending the interpolation a point at a 205 // time... but the local interpolator can make an 206 // approximation for the final localisation period. 207 // e.g. if the localisation is 2, then the first section 208 // of the curve will be solved using the first 2 209 // instruments... with the local interpolator making 210 // suitable boundary conditions. 211 ts_.interpolation_ = (ts_.interpolator_ as ConvexMonotone).localInterpolate(ts_.times_, iInst + 2, ts_.data_, 212 localisation_, ts_.interpolation_ as ConvexMonotoneInterpolation, nInsts + 1); 213 214 if (iInst >= localisation_) { 215 startArray[localisation_-dataAdjust] = ts_.guess(ts_, ts_.dates_[iInst]); 216 } else { 217 startArray[localisation_-dataAdjust] = ts_.data_[0]; 218 } 219 220 var currentCost = new PenaltyFunction<PiecewiseYieldCurve<T, I, B>>(ts_, initialDataPt, ts_.instruments_, 221 iInst - localisation_ + 1, iInst + 1); 222 Problem toSolve = new Problem(currentCost, solverConstraint, startArray); 223 EndCriteria.Type endType = solver.minimize(toSolve, endCriteria); 224 225 // check the end criteria 226 if (!(endType == EndCriteria.Type.StationaryFunctionAccuracy || 227 endType == EndCriteria.Type.StationaryFunctionValue)) 228 throw new ApplicationException("Unable to strip yieldcurve to required accuracy "); 229 ++iInst; 230 } while (iInst < nInsts); 231 232 validCurve_ = true; 191 233 } 192 234 }