Assembla home | Assembla project page
 

Changeset 148

Show
Ignore:
Timestamp:
05/05/08 14:39:01 (2 months ago)
Author:
Vice
Message:

All Cap&Floor test . Need to fix only the Volatility one.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/QLNet/QLNet.sln

    r128 r148  
    66                localtestrun.testrunconfig = localtestrun.testrunconfig 
    77                QLNet.vsmdi = QLNet.vsmdi 
     8                QLNet1.vsmdi = QLNet1.vsmdi 
     9                QLNet2.vsmdi = QLNet2.vsmdi 
    810        EndProjectSection 
    911EndProject 
     
    2830Global 
    2931        GlobalSection(TestCaseManagementSettings) = postSolution 
    30                 CategoryFile = QLNet.vsmdi 
     32                CategoryFile = QLNet2.vsmdi 
    3133        EndGlobalSection 
    3234        GlobalSection(SolutionConfigurationPlatforms) = preSolution 
  • trunk/QLNet/QLNet/Instruments/CapFloor.cs

    r139 r148  
    242242      } 
    243243 
    244       //public double impliedVolatility( 
    245       //                        double targetValue, 
    246       //                        Handle<YieldTermStructure> discountCurve, 
    247       //                        double guess, 
    248       //                        double accuracy, 
    249       //                        int maxEvaluations, 
    250       //                        double minVol, 
    251       //                        double maxVol)  
    252       //{ 
    253       //   calculate(); 
    254       //   if (isExpired())  
    255       //      throw new ArgumentException("instrument expired"); 
    256  
    257       //   //ImpliedVolHelper f = new ImpliedVolHelper(this, discountCurve, targetValue); 
    258       //   //Brent solver; 
    259       //   NewtonSafe solver; 
    260       //   solver.setMaxEvaluations(maxEvaluations); 
    261       //   return solver.solve(f, accuracy, guess, minVol, maxVol); 
    262       //} 
     244      public double impliedVolatility( 
     245                              double targetValue, 
     246                              Handle<YieldTermStructure> discountCurve, 
     247                              double guess, 
     248                              double accuracy, 
     249                              int maxEvaluations) 
     250      { 
     251         return impliedVolatility(targetValue, discountCurve, guess, accuracy, maxEvaluations, 
     252                                  1.0e-7, 4.0); 
     253      } 
     254 
     255 
     256      public double impliedVolatility( 
     257                              double targetValue, 
     258                              Handle<YieldTermStructure> discountCurve, 
     259                              double guess, 
     260                              double accuracy, 
     261                              int maxEvaluations, 
     262                              double minVol, 
     263                              double maxVol)  
     264      { 
     265         calculate(); 
     266         if (isExpired())  
     267            throw new ArgumentException("instrument expired"); 
     268 
     269         ImpliedVolHelper f = new ImpliedVolHelper(this, discountCurve, targetValue); 
     270         //Brent solver; 
     271         NewtonSafe solver = new NewtonSafe(); 
     272         solver.setMaxEvaluations(maxEvaluations); 
     273         //return solver.solve(f, accuracy, guess, minVol, maxVol); 
     274         return 0; 
     275      } 
    263276 
    264277      #endregion 
     
    364377   public abstract class CapFloorEngine  
    365378        : GenericEngine<CapFloor.Arguments, CapFloor.Results> {}; 
     379    
     380   public class ImpliedVolHelper  
     381   { 
     382      private IPricingEngine engine_; 
     383      private Handle<YieldTermStructure> discountCurve_; 
     384      private double targetValue_; 
     385      private SimpleQuote vol_; 
     386      private Instrument.Results results_; 
     387 
     388      public ImpliedVolHelper(CapFloor cap,Handle<YieldTermStructure> discountCurve, 
     389                              double targetValue) 
     390      { 
     391         discountCurve_ = discountCurve; 
     392         targetValue_ = targetValue; 
     393 
     394         Handle<Quote> h = new Handle<Quote>(vol_); 
     395         engine_ = (IPricingEngine)new BlackCapFloorEngine(discountCurve_, h); 
     396         cap.setupArguments(engine_.getArguments()); 
     397         results_ = engine_.getResults() as Instrument.Results; 
     398 
     399      } 
     400 
     401      //Real operator()(Volatility x) const; 
     402      //Real derivative(Volatility x) const; 
     403 
     404 
     405       
     406      //double ImpliedVolHelper::operator()(Volatility x) const  
     407      //{ 
     408      //      if (x!=vol_->value()) { 
     409      //          vol_->setValue(x); 
     410      //          engine_->calculate(); 
     411      //      } 
     412      //      return results_->value-targetValue_; 
     413      //  } 
     414 
     415      public double derivative(double x)  
     416      { 
     417         if (x!=vol_.value())  
     418         { 
     419            vol_.setValue(x); 
     420            engine_.calculate(); 
     421         } 
     422         if ( ! results_.additionalResults.Keys.Contains("vega") ) 
     423            throw new Exception("vega not provided"); 
     424 
     425         return (double) results_.additionalResults["vega"]; 
     426      } 
     427   } 
    366428} 
  • trunk/QLNet/Test2008/T_CapFloor.cs

    r140 r148  
    7777         } 
    7878 
    79          IPricingEngine makeEngine(double volatility)  
     79         public IPricingEngine makeEngine(double volatility)  
    8080         { 
    8181            Handle<Quote> vol = new Handle<Quote>(new SimpleQuote(volatility)) ; 
     
    212212                                         strikes[k],vols[j]); 
    213213                   floor_values.Add(floor.NPV()); 
    214            
    215             // and check that they go the right way 
    216             for ( int k = 0 ; k < cap_values.Count-1 ; k++ ) 
    217            
    218                if (cap_values[k] < cap_values[k+1]) 
    219                 Assert.Fail( 
     214               
     215               // and check that they go the right way 
     216               for ( int k = 0 ; k < cap_values.Count-1 ; k++ ) 
     217               
     218                  if (cap_values[k] < cap_values[k+1]) 
     219                  Assert.Fail( 
    220220                    "NPV is increasing with the strike in a cap: \n" 
    221221                    + "    length:     " + lengths[i] + " years\n" 
     
    225225                    + "    value:      " + cap_values[k+1] 
    226226                    + " at strike: " + strikes[k+1]); 
    227            
    228  
    229             // same for floors 
    230             for ( int k = 0 ; k < floor_values.Count-1 ; k++ ) 
    231            
    232                if (floor_values[k] > floor_values[k+1]) 
    233                 Assert.Fail( 
     227               
     228 
     229               // same for floors 
     230               for ( int k = 0 ; k < floor_values.Count-1 ; k++ ) 
     231               
     232                  if (floor_values[k] > floor_values[k+1]) 
     233                  Assert.Fail( 
    234234                    "NPV is decreasing with the strike in a floor: \n" 
    235235                    + "    length:     " + lengths[i] + " years\n" 
     
    239239                    + "    value:      " + floor_values[k+1] 
    240240                    + " at strike: " + strikes[k+1]); 
     241               } 
    241242            } 
    242         } 
    243     } 
    244 
    245  
     243         } 
     244      } 
     245 
     246      [TestMethod()] 
     247      public void testConsistency()  
     248      { 
     249          CommonVars vars = new CommonVars(); 
     250 
     251          int[] lengths = { 1, 2, 3, 5, 7, 10, 15, 20 }; 
     252          double[] cap_rates = { 0.03, 0.04, 0.05, 0.06, 0.07 }; 
     253          double[] floor_rates = { 0.03, 0.04, 0.05, 0.06, 0.07 }; 
     254          double[] vols = { 0.01, 0.05, 0.10, 0.15, 0.20 }; 
     255 
     256          Date startDate = vars.termStructure.link.referenceDate(); 
     257 
     258          for (int i=0; i<lengths.Length; i++) { 
     259            for (int j=0; j<cap_rates.Length; j++) { 
     260              for (int k=0; k<floor_rates.Length; k++) { 
     261                for (int l=0; l<vols.Length; l++) { 
     262 
     263                    List<CashFlow> leg = vars.makeLeg(startDate,lengths[i]); 
     264                    Instrument cap = vars.makeCapFloor(CapFloorType.Cap,leg, 
     265                                          cap_rates[j],vols[l]); 
     266                    Instrument floor = vars.makeCapFloor(CapFloorType.Floor,leg, 
     267                                          floor_rates[k],vols[l]); 
     268                    Collar collar = new Collar(leg,new InitializedList<double>(1,cap_rates[j]), 
     269                                  new InitializedList<double>(1,floor_rates[k])); 
     270                    collar.setPricingEngine(vars.makeEngine(vols[l])); 
     271 
     272                    if (Math.Abs((cap.NPV()-floor.NPV())-collar.NPV()) > 1e-10) { 
     273                        Assert.Fail( 
     274                          "inconsistency between cap, floor and collar:\n" 
     275                          + "    length:       " + lengths[i] + " years\n" 
     276                          + "    volatility:   " + vols[l] + "\n" 
     277                          + "    cap value:    " + cap.NPV() 
     278                          + " at strike: " + cap_rates[j] + "\n" 
     279                          + "    floor value:  " + floor.NPV() 
     280                          + " at strike: " + floor_rates[k] + "\n" 
     281                          + "    collar value: " + collar.NPV()); 
     282                    } 
     283                } 
     284              } 
     285            } 
     286          } 
     287      } 
     288 
     289      [TestMethod()] 
     290      public void testParity()  
     291      { 
     292          CommonVars vars = new CommonVars(); 
     293 
     294          int[] lengths = { 1, 2, 3, 5, 7, 10, 15, 20 }; 
     295          double[] strikes = { 0.0, 0.03, 0.04, 0.05, 0.06, 0.07 }; 
     296          double[] vols = { 0.01, 0.05, 0.10, 0.15, 0.20 }; 
     297 
     298          Date startDate = vars.termStructure.link.referenceDate(); 
     299 
     300          for (int i=0; i<lengths.Length; i++) { 
     301            for (int j=0; j<strikes.Length; j++) { 
     302              for (int k=0; k<vols.Length; k++) { 
     303 
     304                  List<CashFlow> leg = vars.makeLeg(startDate,lengths[i]); 
     305                  Instrument cap = vars.makeCapFloor(CapFloorType.Cap,leg,strikes[j],vols[k]); 
     306                  Instrument floor = vars.makeCapFloor(CapFloorType.Floor,leg,strikes[j],vols[k]); 
     307                  Date maturity = vars.calendar.advance(startDate,lengths[i],TimeUnit.Years,vars.convention); 
     308                  Schedule schedule = new Schedule(startDate,maturity, 
     309                                                   new Period(vars.frequency),vars.calendar, 
     310                                                   vars.convention,vars.convention, 
     311                                                   DateGeneration.Rule.Forward,false); 
     312                  VanillaSwap swap = new VanillaSwap(VanillaSwap.Type.Payer, vars.nominals[0], 
     313                                                     schedule, strikes[j], vars.index.dayCounter(), 
     314                                                     schedule, vars.index, 0.0, 
     315                                                     vars.index.dayCounter()); 
     316                  swap.setPricingEngine((IPricingEngine)new DiscountingSwapEngine(vars.termStructure)); 
     317                  // FLOATING_POINT_EXCEPTION 
     318                  if (Math.Abs((cap.NPV()-floor.NPV()) - swap.NPV()) > 1.0e-10)  
     319                  { 
     320                      Assert.Fail( 
     321                          "put/call parity violated:\n" 
     322                          + "    length:      " + lengths[i] + " years\n" 
     323                          + "    volatility:  " + vols[k] + "\n" 
     324                          + "    strike:      " + strikes[j] + "\n" 
     325                          + "    cap value:   " + cap.NPV() + "\n" 
     326                          + "    floor value: " + floor.NPV() + "\n" 
     327                          + "    swap value:  " + swap.NPV()); 
     328                  } 
     329              } 
     330            } 
     331          } 
     332      } 
     333 
     334      [TestMethod()] 
     335      public void testATMRate()  
     336      { 
     337         CommonVars vars = new CommonVars(); 
     338 
     339         int[] lengths = { 1, 2, 3, 5, 7, 10, 15, 20 }; 
     340         double[] strikes = { 0.0, 0.03, 0.04, 0.05, 0.06, 0.07 }; 
     341         double[] vols = { 0.01, 0.05, 0.10, 0.15, 0.20 }; 
     342 
     343         Date startDate = vars.termStructure.link.referenceDate(); 
     344 
     345         for (int i=0; i<lengths.Length; i++)  
     346         { 
     347            List<CashFlow> leg = vars.makeLeg(startDate,lengths[i]); 
     348            Date maturity = vars.calendar.advance(startDate,lengths[i],TimeUnit.Years,vars.convention); 
     349            Schedule schedule = new Schedule(startDate,maturity, 
     350                                             new Period(vars.frequency),vars.calendar, 
     351                                             vars.convention,vars.convention, 
     352                                             DateGeneration.Rule.Forward,false); 
     353 
     354            for (int j=0; j<strikes.Length; j++)  
     355            { 
     356               for (int k=0; k<vols.Length; k++)  
     357               { 
     358                 
     359                  CapFloor cap = vars.makeCapFloor(CapFloorType.Cap, leg, strikes[j],vols[k]); 
     360                  CapFloor floor = vars.makeCapFloor(CapFloorType.Floor, leg, strikes[j],vols[k]); 
     361                  double capATMRate = cap.atmRate(vars.termStructure); 
     362                  double floorATMRate = floor.atmRate(vars.termStructure); 
     363                       
     364                  if (!checkAbsError(floorATMRate, capATMRate, 1.0e-10)) 
     365                          Assert.Fail( 
     366                            "Cap ATM Rate and floor ATM Rate should be equal :\n" 
     367                            + "   length:        " + lengths[i] + " years\n" 
     368                            + "   volatility:    " + vols[k] + "\n" 
     369                            + "   strike:        " + strikes[j] + "\n" 
     370                            + "   cap ATM rate:  " + capATMRate + "\n" 
     371                            + "   floor ATM rate:" + floorATMRate + "\n" 
     372                            + "   relative Error:" 
     373                            + Utilities.relativeError(capATMRate, floorATMRate,capATMRate)*100 + "%" ); 
     374                      VanillaSwap swap = new VanillaSwap(VanillaSwap.Type.Payer, vars.nominals[0], 
     375                                                         schedule, floorATMRate, 
     376                                                         vars.index.dayCounter(), 
     377                                                         schedule, vars.index, 0.0, 
     378                                                         vars.index.dayCounter()); 
     379                      swap.setPricingEngine((IPricingEngine)( 
     380                                             new DiscountingSwapEngine(vars.termStructure))); 
     381                      double swapNPV = swap.NPV(); 
     382                      if (!checkAbsError(swapNPV, 0, 1.0e-10)) 
     383                          Assert.Fail( 
     384                            "the NPV of a Swap struck at ATM rate "  
     385                            + "should be equal to 0:\n"  
     386                            + "   length:        " + lengths[i] + " years\n" 
     387                            + "   volatility:    " + vols[k] + "\n" 
     388                            + "   ATM rate:      " + floorATMRate + "\n" 
     389                            + "   swap NPV:      " + swapNPV); 
     390               
     391               } 
     392            } 
     393         } 
     394      } 
     395 
     396      [TestMethod()] 
     397      public void testImpliedVolatility()  
     398      { 
     399         CommonVars vars = new CommonVars(); 
     400 
     401         int maxEvaluations = 100; 
     402         double tolerance = 1.0e-6; 
     403 
     404         CapFloorType[] types = { CapFloorType.Cap, CapFloorType.Floor }; 
     405         double[] strikes = { 0.02, 0.03, 0.04 }; 
     406         int[] lengths = { 1, 5, 10 }; 
     407 
     408         // test data 
     409         double[] rRates = { 0.02, 0.03, 0.04 }; 
     410         double[] vols = { 0.01, 0.20, 0.30, 0.70, 0.90 }; 
     411 
     412         for (int k=0; k<lengths.Length; k++)  
     413         { 
     414           List<CashFlow> leg = vars.makeLeg(vars.settlement, lengths[k]); 
     415 
     416           for (int i=0; i<types.Length; i++)  
     417           { 
     418               for (int j=0; j<strikes.Length; j++)  
     419               { 
     420                   CapFloor capfloor = vars.makeCapFloor(types[i], leg, strikes[j], 0.0); 
     421 
     422                   for (int n=0; n<rRates.Length; n++)  
     423                   { 
     424                       for (int m=0; m<vols.Length; m++)  
     425                       { 
     426                           double r = rRates[n]; 
     427                           double v = vols[m]; 
     428                           vars.termStructure.linkTo(Utilities.flatRate(vars.settlement,r,new Actual360())); 
     429                           capfloor.setPricingEngine(vars.makeEngine(v)); 
     430 
     431                           double value = capfloor.NPV(); 
     432                           double implVol = 0.0; 
     433 
     434                           try  
     435                           { 
     436                               implVol = capfloor.impliedVolatility(value, 
     437                                                                    vars.termStructure, 
     438                                                                    0.10, 
     439                                                                    tolerance, 
     440                                                                    maxEvaluations); 
     441                           }  
     442                           catch (Exception e)  
     443                           { 
     444                               Assert.Fail(typeToString(types[i]) + 
     445                                   "  strike:     " + strikes[j] + 
     446                                   "  risk-free:  " + r + 
     447                                   "  length:     " + lengths[k] + "Y" + 
     448                                   "  volatility: " + v + e.Message); 
     449                           } 
     450                           if (Math.Abs(implVol-v) > tolerance)  
     451                           { 
     452                               // the difference might not matter 
     453                               capfloor.setPricingEngine(vars.makeEngine(implVol)); 
     454                               double value2 = capfloor.NPV(); 
     455                               if (Math.Abs(value-value2) > tolerance)  
     456                               { 
     457                                   Assert.Fail( 
     458                                       typeToString(types[i]) + ":" 
     459                                       + "    strike:           " 
     460                                       + strikes[j] + "\n" 
     461                                       + "    risk-free rate:   " 
     462                                       + r + "\n" 
     463                                       + "    length:         " 
     464                                       + lengths[k] + " years\n\n" 
     465                                       + "    original volatility: " 
     466                                       + v + "\n" 
     467                                       + "    price:               " 
     468                                       + value + "\n" 
     469                                       + "    implied volatility:  " 
     470                                       + implVol + "\n" 
     471                                       + "    corresponding price: " + value2); 
     472                               } 
     473                           } 
     474                       } 
     475                   } 
     476               } 
     477           } 
     478         } 
     479      } 
     480 
     481      [TestMethod()] 
     482      public void testCachedValue()  
     483      { 
     484         CommonVars vars = new CommonVars(); 
     485 
     486         Date cachedToday = new Date(14, Month.March, 2002), 
     487              cachedSettlement = new Date(18, Month.March, 2002); 
     488         Settings.setEvaluationDate(cachedToday); 
     489         vars.termStructure.linkTo(Utilities.flatRate(cachedSettlement, 0.05, new Actual360())); 
     490         Date startDate = vars.termStructure.link.referenceDate(); 
     491         List<CashFlow> leg = vars.makeLeg(startDate,20); 
     492         Instrument cap = vars.makeCapFloor(CapFloorType.Cap,leg,0.07,0.20); 
     493         Instrument floor = vars.makeCapFloor(CapFloorType.Floor,leg,0.03,0.20); 
     494 
     495         // par coupon price 
     496         double cachedCapNPV   = 6.87570026732, 
     497                cachedFloorNPV = 2.65812927959; 
     498          
     499         // index fixing price 
     500         //Real cachedCapNPV   = 6.87630307745, 
     501         //   cachedFloorNPV = 2.65796764715; 
     502 
     503         // test Black cap price against cached value 
     504         if (Math.Abs(cap.NPV()-cachedCapNPV) > 1.0e-11) 
     505           Assert.Fail("failed to reproduce cached cap value:\n" 
     506                       + "    calculated: " + cap.NPV() + "\n" 
     507                       + "    expected:   " + cachedCapNPV); 
     508          
     509         // test Black floor price against cached value 
     510         if (Math.Abs(floor.NPV()-cachedFloorNPV) > 1.0e-11) 
     511           Assert.Fail("failed to reproduce cached floor value:\n" 
     512                       + "    calculated: " + floor.NPV() + "\n" 
     513                       + "    expected:   " + cachedFloorNPV); 
     514         } 
    246515   } 
    247516}