Login  Register

Bermudan swaption patch (was Re: Possible problem on bermuda swaptions)

Posted by Luigi Ballabio on Feb 24, 2005; 3:19am
URL: http://quantlib.414.s1.nabble.com/Possible-problem-on-bermuda-swaptions-2-tp3621p3624.html

On 02/24/05 11:52:05, Luca Berardi wrote:
>
> >Instead, the problem in the new release seems to be some date
> >synchronization: namely, due to date adjustment it may happens that an
> >exercise date is one or two days earlier than a fixed-coupon payment.
>
> This is an extremely interesting issue, and I had the chance to
> discuss it thoroughly with a trader recently. He explained to me that
> the very successive cashflow of the underlying swap after the exercise
> date should NEVER be considered in the bermuda swaption pricing.

Yes, that is the correct behavior. The following patch (tested on the  
BermudanSwaption example, which did give different results in 0.3.7 and  
0.3.8---somehow this escaped testing) should fix this; you can try and  
apply it to the QuantLib 0.3.8 sources to see if you get the correct  
figures.

Later,
        Luigi

diff -r -C 3 QuantLib-0.3.8/ql/Instruments/swaption.cpp QuantLib-0.3.8-
patched/ql/Instruments/swaption.cpp
*** QuantLib-0.3.8/ql/Instruments/swaption.cpp Mon Oct 25 16:00:28 2004
--- QuantLib-0.3.8-patched/ql/Instruments/swaption.cpp Thu Feb 24 10:53:17  
2005
***************
*** 85,90 ****
--- 85,120 ----
                     "fair swap rate null or not set");
          QL_REQUIRE(fixedBPS != Null<Real>(),
                     "fixed swap BPS null or not set");
+     }
+
+     namespace {
+
+         inline bool withinPreviousWeek(Time t1, Time t2) {
+             static const Time dt = 1.0/52;
+             return t1-dt <= t2 && t2 <= t1;
+         }
+
+         inline bool withinNextWeek(Time t1, Time t2) {
+             static const Time dt = 1.0/52;
+             return t1 <= t2 && t2 <= t1+dt;
+         }
+
+     }
+
+     void Swaption::arguments::adjust() {
+         // Date adjustments can get time vectors out of synch.
+         // Here, we try and collapse similar dates.
+         for (Size i=0; i<stoppingTimes.size(); i++) {
+             Time exercise = stoppingTimes[i];
+             for (Size j=0; j<fixedPayTimes.size(); j++){
+                 if (withinNextWeek(exercise, fixedPayTimes[j]))
+                     fixedPayTimes[j] = exercise;
+             }
+             for (Size k=0; k<floatingResetTimes.size(); k++) {
+                 if (withinPreviousWeek(exercise,floatingResetTimes[k]))
+                     floatingResetTimes[k] = exercise;
+             }
+         }
      }

  }
diff -r -C 3 QuantLib-0.3.8/ql/Instruments/swaption.hpp QuantLib-0.3.8-
patched/ql/Instruments/swaption.hpp
*** QuantLib-0.3.8/ql/Instruments/swaption.hpp Fri Sep 17 12:05:42 2004
--- QuantLib-0.3.8-patched/ql/Instruments/swaption.hpp Thu Feb 24 10:36:14  
2005
***************
*** 77,82 ****
--- 77,83 ----
  //        Exercise::Type exerciseType;
  //        std::vector<Time> exerciseTimes;
          void validate() const;
+         void adjust();
      };

      //! %Results from swaption calculation
diff -r -C 3 QuantLib-0.3.8/ql/argsandresults.hpp QuantLib-0.3.8-patched/
ql/argsandresults.hpp
*** QuantLib-0.3.8/ql/argsandresults.hpp Wed Apr 21 17:00:26 2004
--- QuantLib-0.3.8-patched/ql/argsandresults.hpp Thu Feb 24 10:30:49  
2005
***************
*** 36,41 ****
--- 36,42 ----
        public:
          virtual ~Arguments() {}
          virtual void validate() const = 0;
+         virtual void adjust() {}
      };

      //! base class for generic result groups
diff -r -C 3 QuantLib-0.3.8/ql/instrument.hpp QuantLib-0.3.8-patched/ql/
instrument.hpp
*** QuantLib-0.3.8/ql/instrument.hpp Fri Sep 17 12:05:40 2004
--- QuantLib-0.3.8-patched/ql/instrument.hpp Thu Feb 24 10:31:10 2005
***************
*** 137,142 ****
--- 137,143 ----
          engine_->reset();
          setupArguments(engine_->arguments());
          engine_->arguments()->validate();
+         engine_->arguments()->adjust();
          engine_->calculate();
          const Value* results = dynamic_cast<const Value*>(engine_-
>results());
          QL_ENSURE(results != 0,