public void C9_9_6_TwoFactor_Spread_European() { // Declare and initialise the parameters var myData = new TwoFactorBinomialParameters { sigma1 = 0.2, sigma2 = 0.3, T = 1.0, r = 0.06, K = 1.0, div1 = 0.03, div2 = 0.04, rho = 0.5, exercise = false }; // Clewlow and Strickland p. 47 // false; var S1 = 100.0; var S2 = 100.0; var w1 = 1.0; var w2 = -1.0; var cp = 1; myData.pay = new SpreadStrategy(cp, myData.K, w1, w2); var myTree = new TwoFactorBinomial(myData, numberOfSteps, S1, S2); var price = myTree.Price(); Assert.AreEqual(price, 10.13757, 0.001); }
public void C9_9_6_TwoFactor_Basket_European() { double Price(double T, double sig1, double sig2) { var myData = new TwoFactorBinomialParameters { sigma1 = sig1, sigma2 = sig2, T = T, r = 0.1, K = 40.0, div1 = 0.0, div2 = 0.0, rho = 0.5, exercise = false }; var S1 = 18.0; var S2 = 20.0; var w1 = 1.0; var w2 = 1.0; var cp = -1; // Weights; put option myData.pay = new BasketStrategy(myData.K, cp, w1, w2); var myTree = new TwoFactorBinomial(myData, 500, S1, S2); return(myTree.Price()); } Assert.AreEqual(Price(0.95, 0.1, 0.1), 0.6032, 0.001); Assert.AreEqual(Price(0.95, 0.1, 0.2), 1.2402, 0.001); Assert.AreEqual(Price(0.95, 0.1, 0.3), 1.9266, 0.001); Assert.AreEqual(Price(0.95, 0.2, 0.1), 1.1597, 0.001); Assert.AreEqual(Price(0.95, 0.2, 0.2), 1.7749, 0.001); Assert.AreEqual(Price(0.95, 0.2, 0.3), 2.4383, 0.001); Assert.AreEqual(Price(0.95, 0.3, 0.1), 1.7639, 0.001); Assert.AreEqual(Price(0.95, 0.3, 0.2), 2.355, 0.001); Assert.AreEqual(Price(0.95, 0.3, 0.3), 2.9976, 0.001); Assert.AreEqual(Price(0.05, 0.1, 0.1), 1.8025, 0.001); Assert.AreEqual(Price(0.05, 0.1, 0.2), 1.8332, 0.001); Assert.AreEqual(Price(0.05, 0.1, 0.3), 1.9117, 0.001); Assert.AreEqual(Price(0.05, 0.2, 0.1), 1.8270, 0.001); Assert.AreEqual(Price(0.05, 0.2, 0.2), 1.8859, 0.001); Assert.AreEqual(Price(0.05, 0.2, 0.3), 1.9817, 0.001); Assert.AreEqual(Price(0.05, 0.3, 0.1), 1.8906, 0.001); Assert.AreEqual(Price(0.05, 0.3, 0.2), 1.9682, 0.001); Assert.AreEqual(Price(0.05, 0.3, 0.3), 2.0737, 0.001); }
// Accuracy of price on number of steps public static Vector <double> Prices(TwoFactorBinomialParameters optionData, Vector <int> meshSizes, double S1, double S2) { // Caculates the price for a number of step sizes (usually increasing) Vector <double> result = new Vector <double> (meshSizes.Size); //print (result); // TwoFactorBinomial(TwoFactorBinomialParameters optinData,long NSteps, // double S1, double S2); TwoFactorBinomial local; for (int j = result.MinIndex; j <= result.MaxIndex; j++) { local = new TwoFactorBinomial(optionData, meshSizes[j], S1, S2); result[j] = local.Price(); //cout << local.Price() << ";;"; } return(result); }
public static void Main() { // Declare and initialise the parameters TwoFactorBinomialParameters myData = new TwoFactorBinomialParameters(); // Clewlow and Strickland p. 47 myData.sigma1 = 0.2; myData.sigma2 = 0.3; myData.T = 1.0; myData.r = 0.06; myData.K = 1.0; myData.div1 = 0.03; myData.div2 = 0.04; myData.rho = 0.5; myData.exercise = true; // false; double S1 = 100.0; double S2 = 100.0; double w1 = 1.0; double w2 = -1.0; int cp = 1; myData.pay = new SpreadStrategy(cp, myData.K, w1, w2); // Min-max option /* myData.sigma1 = 0.3; * myData.sigma2 = 0.3; * * myData.T = 10.0; * myData.r = 0.1; * myData.K = 40.0; * myData.div1 = 0.0; * myData.div2 = 0.0; * myData.rho = 0.5; * myData.exercise = true; * double S1 = 40.0; * double S2 = 40.0; * * * int cp = 1; * int dMinMax = 1; // 1 == Max, else Min * myData.pay = new RainbowStrategy(cp, myData.K, dMinMax);*/ // Topper 2005 page 198 /* myData.sigma1 = 0.1; myData.sigma2 = 0.1; * myData.T = 0.05; myData.r = 0.1; myData.K = 40.0; * myData.div1 = 0.0; myData.div2 = 0.0; * myData.rho = 0.5; myData.exercise = false; * * double S1 = 18.0; double S2 = 20.0; * double w1 = 1.0; double w2 = 1.0; int cp = -1; // Weights; put option * myData.pay = new BasketStrategy(myData.K, cp, w1, w2);*/ /* myData.sigma1 = 0.2; myData.sigma2 = 0.2; * myData.T = 0.5; myData.r = 0.1; myData.K = 10.0; * myData.div1 = 0.0; myData.div2 = 0.0; * myData.rho = 0.5; myData.exercise = false;*/ // double S1 = 122.0; double S2 = 120.0; // int a = 1; int b = -1; int pp = 1; // myData.pay = new BasketStrategy(myData.K, pp, a, b); // myData.pay = new BestofTwoStrategy(myData.K, pp); // myData.pay = new WorstofTwoStrategy(myData.K, -1); // myData.pay = new SpreadStrategy(-pp, myData.K, 1,-1); // cout << "How many timesteps: "; int NumberOfSteps = 50; // cin >> NumberOfSteps; // myData.sigma1 = 0.3; myData.sigma2 = 0.2; // myData.T = 0.95; myData.r = Math.Log(1.1); // myData.div1 = Math.Log(1.05); myData.div2 = Math.Log(1.05); //// myData.div1 = 0; myData.div2 = 0; // myData.rho = 0.99; myData.exercise = false; // double S1 = 100; double S2 = 100; // double w1 = 1.0; double w2 = 1.0; int cp = -1; // Weights; put option // myData.pay = new BasketStrategy(myData.K, cp, w1, w2); //double strike, int cp,double weight1, double weight2) // myData.pay = new WorstofTwoStrategy(myData.K, cp); //myData.pay = new RainbowStrategy(cp, myData.K, 1); //(int cp, double strike, int DMinDMax) // myData.pay = new DualStrikeStrategy(110, 100, +1, -1); //(int cp, double strike, int DMinDMax) //myData.pay = new ExchangeStrategy(); // int n1 = 1; int n2 = 1; myData.K = 40.0; // myData.pay = new PortfolioStrategy(n1, n2, myData.K, -1); Console.WriteLine("Computing..."); TwoFactorBinomial myTree = new TwoFactorBinomial(myData, NumberOfSteps, S1, S2); Console.WriteLine("Price is now: {0}", myTree.Price()); // Console.WriteLine(myTree.Price()); // Now examine the convergence of 2-factor Binomial method /* int size = 12; * Vector<int> meshSizes = new Vector<int>(size); * int N = 2; * for (int j = meshSizes.MinIndex; j <= meshSizes.MaxIndex; j++) * { * meshSizes[j] = N; * N *= 2; * * } * //print(meshSizes); * * Vector<double> result = TwoFactorBinomial.Prices(myData, meshSizes, S1, S2); * for (int j = meshSizes.MinIndex ; j <= meshSizes.MaxIndex; j++) * { * Console.WriteLine(result[j]); * } */ }
public TwoFactorBinomial(TwoFactorBinomialParameters optionData, int NSteps, double S1, double S2) { // The most important constuctor par = optionData; N = NSteps; // Mesh sizes, Clewlow (2.43)-(2.44) delta_T = par.T / N; // DeltaT h1 = par.sigma1 * Math.Sqrt(delta_T); // DeltaX1 h2 = par.sigma2 * Math.Sqrt(delta_T); // DeltaX2 //cout << "deltas t, S... " << k << ", " << h1 << ", " << h2 << endl; // Parameters (prob) double nu1 = par.r - par.div1 - (0.5 * par.sigma1 * par.sigma1); double nu2 = par.r - par.div2 - (0.5 * par.sigma2 * par.sigma2); //cout << "nu1... " << nu1 << ", " << nu2 << endl; double a = h1 * h2; double b = h2 * nu1 * delta_T; double c = h1 * nu2 * delta_T; double d = par.rho * par.sigma1 * par.sigma2 * delta_T; //cout << "a ..." << a << ", " << b << ", " << c << ", " << d << endl; double disc = Math.Exp(-(par.r) * delta_T); puu = disc * 0.25 * (a + b + c + d) / a; // eq. (2.45) pud = disc * 0.25 * (a + b - c - d) / a; pdu = disc * 0.25 * (a - b + c - d) / a; pdd = disc * 0.25 * (a - b - c + d) / a; //cout << "puu ..." << puu << ", " << pud << ", " << pdu << ", " << pdd << endl; // Asset arrays // Initialise asset prices at *maturity*. Norice that the start index is a negative number asset1 = new Vector <double>(2 * N + 1, -N); asset2 = new Vector <double>(2 * N + 1, -N); asset1[-N] = S1 * Math.Exp(-N * h1); asset2[-N] = S2 * Math.Exp(-N * h2); double edx1 = Math.Exp(h1); double edx2 = Math.Exp(h2); //cout << "edx1... disc " << edx1 << ", " << edx2 << ", " << disc << endl; for (int n = -N + 1; n <= N; n++) { asset1[n] = asset1[n - 1] * edx1; asset2[n] = asset2[n - 1] * edx2; } //print(asset1); //print(asset2); option = new NumericMatrix <double>(2 * N + 1, 2 * N + 1, -N, -N); // Calculate option price at the expiry date for (int j = option.MinRowIndex; j <= option.MaxRowIndex; j += 2) { //cout << j << ", "; for (int k = option.MinColumnIndex; k <= option.MaxColumnIndex; k += 2) { option[j, k] = Payoff(asset1[j], asset2[k]); } } }