Assembla home | Assembla project page
 

Changeset 138

Show
Ignore:
Timestamp:
04/29/08 08:54:24 (7 months ago)
Author:
Vice
Message:

Synch Commit

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/QLNet/QLNet/Instruments/CapFloor.cs

    r130 r138  
    335335   /// \ingroup instruments 
    336336   /// </summary> 
    337    class Cap : CapFloor  
     337   public class Cap : CapFloor  
    338338   { 
    339339      public Cap(List<CashFlow> floatingLeg,List<double> exerciseRates) 
     
    345345   /// \ingroup instruments  
    346346   /// </summary> 
    347     class Floor : CapFloor  
     347   public class Floor : CapFloor  
    348348    { 
    349349      public Floor(List<CashFlow> floatingLeg,List<double> exerciseRates) 
     
    355355   /// \ingroup instruments 
    356356   /// </summary> 
    357     class Collar : CapFloor  
     357   public class Collar : CapFloor  
    358358    { 
    359359      public Collar(List<CashFlow> floatingLeg,List<double> capRates, List<double> floorRates) 
  • trunk/QLNet/QLNet/Pricingengines/CapFloor/BlackCapFloorEngine.cs

    r112 r138  
    1212   public class BlackCapFloorEngine : CapFloorEngine 
    1313   { 
     14      private  Handle<YieldTermStructure> termStructure_; 
     15      private Handle<OptionletVolatilityStructure> volatility_; 
     16 
    1417      public BlackCapFloorEngine(Handle<YieldTermStructure> termStructure, double vol) 
    1518         : this(termStructure, vol, new Actual365Fixed()) { } 
     
    1720                                 double vol, DayCounter dc ) 
    1821      { 
     22         termStructure_ = termStructure; 
     23         volatility_ = new Handle<OptionletVolatilityStructure>(new ConstantOptionletVolatility(0, new NullCalendar(), BusinessDayConvention.Following, vol, dc)); 
     24         termStructure_.registerWith(update );// registerWith(termStructure_); 
    1925      } 
    2026 
     
    2531                                 Handle<Quote> vol, DayCounter dc) 
    2632      { 
    27  
     33         termStructure_ = termStructure; 
     34         volatility_ = new Handle<OptionletVolatilityStructure> (new ConstantOptionletVolatility( 
     35                             0, new NullCalendar(), BusinessDayConvention.Following, vol, dc)); 
     36         termStructure_.registerWith(update); 
     37         volatility_.registerWith(update); 
    2838      } 
    2939 
     
    3141                                 Handle<OptionletVolatilityStructure> vol) 
    3242      { 
     43         termStructure_ = discountCurve; 
     44         volatility_ = vol; 
     45         termStructure_.registerWith(update); 
     46         volatility_.registerWith(update); 
    3347      } 
     48 
     49      public void calculate()  
     50      { 
     51         double value = 0.0; 
     52         double vega = 0.0; 
     53         int optionlets = arguments_.startDates.Count; 
     54         List<double> values = new List<double>(optionlets); 
     55         List<double> vegas = new List<double>(optionlets); 
     56         List<double> stdDevs = new List<double>(optionlets); 
     57         CapFloorType type = arguments_.type; 
     58         Date today = volatility_.link.referenceDate(); 
     59         Date settlement = termStructure_.link.referenceDate(); 
     60 
     61         for (int i=0; i<optionlets; ++i)  
     62         { 
     63            Date paymentDate = arguments_.endDates[i]; 
     64            if (paymentDate > settlement)  
     65            {  
     66               // discard expired caplets 
     67               double d = arguments_.nominals[i] * 
     68                          arguments_.gearings[i] * 
     69                          termStructure_.link.discount(paymentDate) * 
     70                          arguments_.accrualTimes[i]; 
     71 
     72               double? forward = arguments_.forwards[i]; 
     73 
     74               Date fixingDate = arguments_.fixingDates[i]; 
     75               double sqrtTime = 0.0; 
     76               if (fixingDate > today) 
     77                  sqrtTime = Math.Sqrt( volatility_.link.timeFromReference(fixingDate)); 
     78 
     79               if (type == CapFloorType.Cap || type == CapFloorType.Collar)  
     80               { 
     81                  double? strike = arguments_.capRates[i]; 
     82                  if (sqrtTime>0.0)  
     83                  { 
     84                     stdDevs[i] = Math.Sqrt(volatility_.link.blackVariance(fixingDate, strike)); 
     85                     vegas[i] = blackFormulaStdDevDerivative(strike, forward, stdDevs[i], d) * sqrtTime; 
     86                  } 
     87                  // include caplets with past fixing date 
     88                  values[i] = blackFormula(Option.Type.Call, strike, 
     89                                             forward, stdDevs[i], d); 
     90                } 
     91                if (type == CapFloorType.Floor || type == CapFloorType.Collar)  
     92                { 
     93                  double? strike = arguments_.floorRates[i]; 
     94                  double floorletVega = 0.0; 
     95                     
     96                  if (sqrtTime>0.0)  
     97                  { 
     98                     stdDevs[i] = Math.Sqrt(volatility_.blackVariance(fixingDate, strike)); 
     99                     floorletVega = blackFormulaStdDevDerivative(strike, forward, stdDevs[i], d) * sqrtTime; 
     100                  } 
     101                  double floorlet = blackFormula(Option.Type.Put, strike, 
     102                                                 forward, stdDevs[i], d); 
     103                  if (type == CapFloorType.Floor)  
     104                  { 
     105                     values[i] = floorlet; 
     106                     vegas[i] = floorletVega; 
     107                  }  
     108                  else  
     109                  { 
     110                     // a collar is long a cap and short a floor 
     111                     values[i] -= floorlet; 
     112                     vegas[i] -= floorletVega; 
     113                  } 
     114                } 
     115                value += values[i]; 
     116                vega += vegas[i]; 
     117            } 
     118        } 
     119        results_.value = value; 
     120        results_.additionalResults["vega"] = vega; 
     121 
     122        results_.additionalResults["optionletsPrice"] = values; 
     123        results_.additionalResults["optionletsVega"] = vegas; 
     124        results_.additionalResults["optionletsAtmForward"] = arguments_.forwards; 
     125        if (type != CapFloorType.Collar) 
     126            results_.additionalResults["optionletsStdDev"] = stdDevs; 
     127    } 
    34128   } 
    35129} 
  • trunk/QLNet/Test2008/T_CapFloor.cs

    r130 r138  
    3333      { 
    3434         // common data 
    35          Date settlement; 
    36          List<double> nominals; 
    37          BusinessDayConvention convention; 
    38          Frequency frequency; 
    39          IborIndex index; 
    40          Calendar calendar; 
    41          int fixingDays; 
    42          RelinkableHandle<YieldTermStructure> termStructure
     35         public Date settlement; 
     36         public List<double> nominals; 
     37         public BusinessDayConvention convention; 
     38         public Frequency frequency; 
     39         public IborIndex index; 
     40         public Calendar calendar; 
     41         public int fixingDays; 
     42         public RelinkableHandle<YieldTermStructure> termStructure = new RelinkableHandle<YieldTermStructure> ()
    4343 
    4444         // cleanup 
    45          SavedSettings backup; 
     45         public SavedSettings backup; 
    4646 
    4747         // setup 
     
    6464 
    6565         // utilities 
    66          List<CashFlow> makeLeg(Date startDate, int length) 
     66         public List<CashFlow> makeLeg(Date startDate, int length) 
    6767         { 
    6868            Date endDate = calendar.advance(startDate, new Period(length , TimeUnit.Years), convention); 
     
    8282 
    8383            return (IPricingEngine) new BlackCapFloorEngine(termStructure, vol); 
    84         } 
     84 
     85         } 
     86          
     87         public CapFloor makeCapFloor(CapFloorType type, 
     88                               List<CashFlow> leg, 
     89                               double strike, 
     90                               double volatility)  
     91         { 
     92            CapFloor result; 
     93            switch (type)  
     94            { 
     95              case CapFloorType.Cap: 
     96                result = (CapFloor) new Cap(leg, new List<double>(){strike}); 
     97                break; 
     98              case CapFloorType.Floor: 
     99                result = (CapFloor)new Floor(leg, new List<double>() { strike }); 
     100                break; 
     101              default: 
     102                throw new ArgumentException("unknown cap/floor type"); 
     103            } 
     104            result.setPricingEngine(makeEngine(volatility)); 
     105            return result; 
     106         } 
     107 
    85108      } 
    86109 
     110      bool checkAbsError(double x1, double x2, double tolerance) 
     111      { 
     112         return Math.Abs(x1 - x2) < tolerance; 
     113      } 
     114 
     115      string typeToString(CapFloorType type)  
     116      { 
     117        switch (type) { 
     118          case CapFloorType.Cap: 
     119            return "cap"; 
     120          case CapFloorType.Floor: 
     121            return "floor"; 
     122          case CapFloorType.Collar: 
     123            return "collar"; 
     124          default: 
     125            throw new ArgumentException("unknown cap/floor type"); 
     126        } 
     127     
     128      } 
     129 
     130      [TestMethod()] 
     131      public void testVega()  
     132      { 
     133         CommonVars vars = new CommonVars(); 
     134 
     135         int[] lengths = { 1, 2, 3, 4, 5, 6, 7, 10, 15, 20, 30 }; 
     136         double[] vols = { 0.01, 0.05, 0.10, 0.15, 0.20 }; 
     137         double[] strikes = { 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09 }; 
     138         CapFloorType[] types = { CapFloorType.Cap, CapFloorType.Floor}; 
     139 
     140         Date startDate = vars.termStructure.link.referenceDate(); 
     141         double shift = 1e-8; 
     142         double tolerance = 0.005; 
     143 
     144         for (int i=0; i<lengths.Length; i++)  
     145         { 
     146            for (int j=0; j<vols.Length; j++)  
     147            { 
     148               for (int k=0; k<strikes.Length; k++)  
     149               { 
     150                  for (int h=0; h<types.Length; h++)  
     151                  { 
     152                     List<CashFlow> leg = vars.makeLeg(startDate, lengths[i]); 
     153                     CapFloor capFloor = vars.makeCapFloor(types[h],leg, strikes[k],vols[j]); 
     154                     CapFloor shiftedCapFloor2 = vars.makeCapFloor(types[h],leg,strikes[k],vols[j]+shift); 
     155                     CapFloor shiftedCapFloor1 = vars.makeCapFloor(types[h],leg,strikes[k],vols[j]-shift); 
     156 
     157                     double value1 = shiftedCapFloor1.NPV(); 
     158                     double value2 = shiftedCapFloor2.NPV(); 
     159 
     160                     double numericalVega = (value2 - value1) / (2*shift); 
     161 
     162                           
     163                     if (numericalVega>1.0e-4)  
     164                     { 
     165                              double analyticalVega = capFloor.result("vega"); 
     166                              double discrepancy = Math.Abs(numericalVega - analyticalVega); 
     167                              discrepancy /= numericalVega; 
     168                              if (discrepancy > tolerance) 
     169                                  Assert.Fail( 
     170                                      "failed to compute cap/floor vega:" + 
     171                                      "\n   lengths:     " + new Period(lengths[j],TimeUnit.Years) + 
     172                                      "\n   strike:      " + strikes[k] + 
     173                                      "\n   types:       " + types[h] + 
     174                                      "\n   calculated:  " + analyticalVega + 
     175                                      "\n   expected:    " + numericalVega + 
     176                                      "\n   discrepancy: " + discrepancy + 
     177                                      "\n   tolerance:   " + tolerance); 
     178                            
     179                     } 
     180                  } 
     181               } 
     182            } 
     183         } 
     184      } 
    87185   } 
    88186}