1 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 
3 /*
4  Copyright (C) 2014 Master IMAFA - Polytech'Nice Sophia - Université de Nice Sophia Antipolis
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/experimental/exoticoptions/analytictwoassetcorrelationengine.hpp>
21 #include <ql/math/distributions/bivariatenormaldistribution.hpp>
22 #include <ql/exercise.hpp>
23 
24 using std::log;
25 
26 namespace QuantLib {
27 
AnalyticTwoAssetCorrelationEngine(const ext::shared_ptr<GeneralizedBlackScholesProcess> & p1,const ext::shared_ptr<GeneralizedBlackScholesProcess> & p2,const Handle<Quote> & correlation)28     AnalyticTwoAssetCorrelationEngine::AnalyticTwoAssetCorrelationEngine(
29         const ext::shared_ptr<GeneralizedBlackScholesProcess>& p1,
30         const ext::shared_ptr<GeneralizedBlackScholesProcess>& p2,
31         const Handle<Quote>& correlation)
32     : p1_(p1), p2_(p2), correlation_(correlation) {
33         registerWith(p1_);
34         registerWith(p2_);
35         registerWith(correlation_);
36     }
37 
calculate() const38     void AnalyticTwoAssetCorrelationEngine::calculate() const {
39         BivariateCumulativeNormalDistributionDr78 M(correlation_->value());
40 
41         const ext::shared_ptr<PlainVanillaPayoff> payoff =
42             ext::dynamic_pointer_cast<PlainVanillaPayoff>(arguments_.payoff);
43         QL_REQUIRE(payoff, "non-plain payoff given");
44         QL_REQUIRE(payoff->strike()>0.0, "strike must be positive");
45         ext::shared_ptr<Exercise> exercise = arguments_.exercise;
46         Real strike = payoff->strike();//X1
47         Real spot = p1_->x0();
48         QL_REQUIRE(spot >= 0.0, "negative or null underlying given");
49 
50         Volatility sigma1 =
51             p1_->blackVolatility()->blackVol(p1_->time(exercise->lastDate()),
52                                              payoff->strike());
53         Volatility sigma2 =
54             p2_->blackVolatility()->blackVol(p2_->time(exercise->lastDate()),
55                                              payoff->strike());
56 
57         Time T = p2_->time(arguments_.exercise->lastDate());
58 
59         Real s1=p1_->x0();
60         Real s2=p2_->x0();
61         Rate q1= p1_->dividendYield()->zeroRate(T, Continuous, NoFrequency);
62         Rate q2= p2_->dividendYield()->zeroRate(T, Continuous, NoFrequency);
63         Rate r=p1_->riskFreeRate()->zeroRate(T, Continuous, NoFrequency);
64         Rate b1=r-q1;
65         Rate b2=r-q2;
66         Real rho = correlation_->value();
67 
68         Real y1=(log(s1/strike)+(b1-(sigma1*sigma1)/2)*T)/(sigma1*std::sqrt(T));
69         Real y2=(log(s2/arguments_.X2)+(b2-(sigma2*sigma2)/2)*T)/(sigma2*std::sqrt(T));
70 
71         switch (payoff->optionType()) {
72           case Option::Call:
73             results_.value=s2*std::exp((b2-r)*T)*M(y2+sigma2*std::sqrt(T),y1+rho*sigma2*std::sqrt(T))-arguments_.X2*std::exp(-r*T)*M(y2,y1);
74             break;
75           case Option::Put:
76             results_.value=arguments_.X2*std::exp(-r*T)*M(-y2,-y1)-s2*std::exp((b2-r)*T)*M(-y2-sigma2*std::sqrt(T),-y1-rho*sigma2*std::sqrt(T));
77             break;
78           default:
79             QL_FAIL("unknown option type");
80         }
81     }
82 
83 }
84