Changeset 138
- Timestamp:
- 04/29/08 08:54:24 (7 months ago)
- Files:
-
- trunk/QLNet/QLNet/Instruments/CapFloor.cs (modified) (3 diffs)
- trunk/QLNet/QLNet/Pricingengines/CapFloor/BlackCapFloorEngine.cs (modified) (4 diffs)
- trunk/QLNet/Test2008/T_CapFloor.cs (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/QLNet/QLNet/Instruments/CapFloor.cs
r130 r138 335 335 /// \ingroup instruments 336 336 /// </summary> 337 class Cap : CapFloor337 public class Cap : CapFloor 338 338 { 339 339 public Cap(List<CashFlow> floatingLeg,List<double> exerciseRates) … … 345 345 /// \ingroup instruments 346 346 /// </summary> 347 class Floor : CapFloor347 public class Floor : CapFloor 348 348 { 349 349 public Floor(List<CashFlow> floatingLeg,List<double> exerciseRates) … … 355 355 /// \ingroup instruments 356 356 /// </summary> 357 class Collar : CapFloor357 public class Collar : CapFloor 358 358 { 359 359 public Collar(List<CashFlow> floatingLeg,List<double> capRates, List<double> floorRates) trunk/QLNet/QLNet/Pricingengines/CapFloor/BlackCapFloorEngine.cs
r112 r138 12 12 public class BlackCapFloorEngine : CapFloorEngine 13 13 { 14 private Handle<YieldTermStructure> termStructure_; 15 private Handle<OptionletVolatilityStructure> volatility_; 16 14 17 public BlackCapFloorEngine(Handle<YieldTermStructure> termStructure, double vol) 15 18 : this(termStructure, vol, new Actual365Fixed()) { } … … 17 20 double vol, DayCounter dc ) 18 21 { 22 termStructure_ = termStructure; 23 volatility_ = new Handle<OptionletVolatilityStructure>(new ConstantOptionletVolatility(0, new NullCalendar(), BusinessDayConvention.Following, vol, dc)); 24 termStructure_.registerWith(update );// registerWith(termStructure_); 19 25 } 20 26 … … 25 31 Handle<Quote> vol, DayCounter dc) 26 32 { 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); 28 38 } 29 39 … … 31 41 Handle<OptionletVolatilityStructure> vol) 32 42 { 43 termStructure_ = discountCurve; 44 volatility_ = vol; 45 termStructure_.registerWith(update); 46 volatility_.registerWith(update); 33 47 } 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 } 34 128 } 35 129 } trunk/QLNet/Test2008/T_CapFloor.cs
r130 r138 33 33 { 34 34 // 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> (); 43 43 44 44 // cleanup 45 SavedSettings backup;45 public SavedSettings backup; 46 46 47 47 // setup … … 64 64 65 65 // utilities 66 List<CashFlow> makeLeg(Date startDate, int length)66 public List<CashFlow> makeLeg(Date startDate, int length) 67 67 { 68 68 Date endDate = calendar.advance(startDate, new Period(length , TimeUnit.Years), convention); … … 82 82 83 83 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 85 108 } 86 109 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 } 87 185 } 88 186 }