1 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 
3 /*
4  Copyright (C) 2010 Klaus Spanderen
5 
6  This file is part of QuantLib, a free-software/open-source library
7  for financial quantitative analysts and developers - http://quantlib.org/
8 
9  QuantLib is free software: you can redistribute it and/or modify it
10  under the terms of the QuantLib license.  You should have received a
11  copy of the license along with this program; if not, please email
12  <quantlib-dev@lists.sf.net>. The license is also available online at
13  <http://quantlib.org/license.shtml>.
14 
15  This program is distributed in the hope that it will be useful, but WITHOUT
16  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  FOR A PARTICULAR PURPOSE.  See the license for more details.
18 */
19 
20 #include <ql/pricingengines/basket/kirkengine.hpp>
21 #include <ql/pricingengines/blackcalculator.hpp>
22 #include <ql/pricingengines/blackformula.hpp>
23 #include <ql/math/functional.hpp>
24 #include <ql/exercise.hpp>
25 
26 namespace QuantLib {
27 
KirkEngine(const ext::shared_ptr<BlackProcess> & process1,const ext::shared_ptr<BlackProcess> & process2,Real correlation)28     KirkEngine::KirkEngine(
29             const ext::shared_ptr<BlackProcess>& process1,
30             const ext::shared_ptr<BlackProcess>& process2,
31             Real correlation)
32     : process1_(process1), process2_(process2), rho_(correlation) {
33         registerWith(process1_);
34         registerWith(process2_);
35     }
36 
calculate() const37     void KirkEngine::calculate() const {
38 
39         QL_REQUIRE(arguments_.exercise->type() == Exercise::European,
40                    "not a European option");
41 
42         ext::shared_ptr<EuropeanExercise> exercise =
43             ext::dynamic_pointer_cast<EuropeanExercise>(arguments_.exercise);
44         QL_REQUIRE(exercise, "not a European exercise");
45 
46         ext::shared_ptr<SpreadBasketPayoff> spreadPayoff =
47             ext::dynamic_pointer_cast<SpreadBasketPayoff>(arguments_.payoff);
48         QL_REQUIRE(spreadPayoff," spread payoff expected");
49 
50         ext::shared_ptr<PlainVanillaPayoff> payoff =
51             ext::dynamic_pointer_cast<PlainVanillaPayoff>(
52                                                    spreadPayoff->basePayoff());
53         QL_REQUIRE(payoff, "non-plain payoff given");
54         const Real strike = payoff->strike();
55 
56         const Real f1 = process1_->stateVariable()->value();
57         const Real f2 = process2_->stateVariable()->value();
58 
59         // use atm vols
60         const Real variance1 = process1_->blackVolatility()->blackVariance(
61                                                 exercise->lastDate(), f1);
62         const Real variance2 = process2_->blackVolatility()->blackVariance(
63                                                 exercise->lastDate(), f2);
64 
65         const DiscountFactor riskFreeDiscount =
66             process1_->riskFreeRate()->discount(exercise->lastDate());
67 
68         const Real f = f1/(f2 + strike);
69         const Real v
70             = std::sqrt(variance1
71                         + variance2*square<Real>()(f2/(f2+strike))
72                         - 2*rho_*std::sqrt(variance1*variance2)
73                             *(f2/(f2+strike)));
74 
75         BlackCalculator black(
76              ext::make_shared<PlainVanillaPayoff>(
77                  payoff->optionType(),1.0),
78              f, v, riskFreeDiscount);
79 
80         results_.value = (f2 + strike)*black.value();
81     }
82 }
83 
84