Assembla home | Assembla project page
 

Changeset 208

Show
Ignore:
Timestamp:
06/16/08 21:53:12 (5 months ago)
Author:
snovik
Message:

New: QL 15018 (localbootstrap)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/QLNet/QLNet/Math/Interpolations/convexmonotoneinterpolation.cs

    r207 r208  
    4949        } 
    5050        public double primitive(double x) { 
    51             double result = (quadraticity_ * quadraticHelper_.primitive(x) + (1.0 - quadraticity_) * convMonoHelper_.primitive(x)); 
    5251            return (quadraticity_ * quadraticHelper_.primitive(x) + (1.0 - quadraticity_) * convMonoHelper_.primitive(x)); 
    5352        } 
     
    721720        public Interpolation localInterpolate(List<double> xBegin, int size, List<double> yBegin, int localisation, 
    722721                                              ConvexMonotoneInterpolation prevInterpolation, int finalSize) { 
    723             int length = xBegin.Count
     722            int length = size
    724723            if (length - localisation == 1) { // the first time this 
    725724                                              // function is called 
  • trunk/QLNet/QLNet/Termstructures/Yield/Bootstraptraits.cs

    r144 r208  
    114114    //! Forward-curve traits 
    115115    public class ForwardRate : ITraits { 
     116        const double avgRate = 0.05; 
     117 
    116118        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 date 
     119        public double initialValue(YieldTermStructure c) { return avgRate; } // dummy value at reference date 
    118120        public bool dummyInitialValue() { return true; }    // true if the initialValue is just a dummy value 
    119         public double initialGuess() { return 0.02; } // initial guess 
     121        public double initialGuess() { return avgRate; } // initial guess 
    120122        // further guesses 
    121123        public double guess(YieldTermStructure c, Date d) { 
  • trunk/QLNet/QLNet/Termstructures/Yield/PiecewiseYieldCurve.cs

    r202 r208  
    2323 
    2424namespace 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 
    2562    public class PiecewiseYieldCurve<Traits, Interpolator> 
    2663        : PiecewiseYieldCurve<Traits, Interpolator, IterativeBootstrap> 
     
    5188    } 
    5289 
    53     public class PiecewiseYieldCurve<Traits, Interpolator, BootStrap> : YieldTermStructure // , ITraits 
     90 
     91    public class PiecewiseYieldCurve<Traits, Interpolator, BootStrap> : IPiecewiseYieldCurve, ITraits 
    5492        where Traits : ITraits, new() 
    5593        where Interpolator : IInterpolationFactory, new() 
     
    5997        public List<Date> dates_; 
    6098        public List<double> times_ = new List<double>(); 
    61         public List<double> data_; 
    6299 
    63100        protected Handle<Quote> turnOfYearEffect_; 
     
    66103        protected double turnOfYear_; 
    67104 
    68         public List<BootstrapHelper<YieldTermStructure>> instruments_; 
    69  
    70         public Interpolation interpolation_; 
    71105        public Interpolator interpolator_; 
    72106 
     
    76110        #region Traits wrapper 
    77111        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(); } 
    87121 
    88122        protected override double discountImpl(double t) { 
     
    101135            return traits_.discountImpl(interpolation_, t); 
    102136        } 
    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); } 
    105139 
    106140        // these are dummy methods (for the sake of ITraits and should not be called directly 
    107         // public double discountImpl(Interpolation i, double t) { throw new NotSupportedException(); } 
    108         // public double zeroYieldImpl(Interpolation i, double t) { throw new NotSupportedException(); } 
    109         // public double 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(); } 
    110144        #endregion 
    111145 
  • trunk/QLNet/QLNet/Termstructures/localbootstrap.cs

    r202 r208  
    2323 
    2424namespace 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 
    2585    //! Localised-term-structure bootstrapper for most curve types. 
    2686    /*! This algorithm enables a localised fitting for non-local 
     
    83143 
    84144            validCurve_ = false; 
    85             int n = ts_.instruments_.Count; 
     145            int nInsts = ts_.instruments_.Count; 
    86146 
    87147            // ensure rate helpers are sorted 
     
    89149 
    90150            // 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) { 
    92152                Date m1 = ts_.instruments_[i - 1].latestDate(), 
    93153                     m2 = ts_.instruments_[i].latestDate(); 
     
    96156 
    97157            // 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) 
    99159                if (!ts_.instruments_[i].quoteIsValid()) 
    100160                    throw new ArgumentException("instrument " + i + " (maturity: " + ts_.instruments_[i].latestDate() + 
     
    102162 
    103163            // 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_); 
    107173            } 
    108174 
    109175            // 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); 
    112178            ts_.dates_[0] = ts_.initialDate(ts_); 
    113179            ts_.times_[0] = ts_.timeFromReference(ts_.dates_[0]); 
    114             for (int i = 0; i < n; ++i) { 
     180            for (int i = 0; i < nInsts; ++i) { 
    115181                ts_.dates_[i + 1] = ts_.instruments_[i].latestDate(); 
    116182                ts_.times_[i + 1] = ts_.timeFromReference(ts_.dates_[i + 1]); 
     
    119185            } 
    120186 
    121             // set initial guess only if the current curve cannot be used as guess 
    122             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  
    132187            LevenbergMarquardt solver = new LevenbergMarquardt(ts_.accuracy_, ts_.accuracy_, ts_.accuracy_); 
    133188            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; 
    191233        } 
    192234    }