/// <summary> /// Gets the theta. /// </summary> /// <returns></returns> public double GetTheta() { double spot = Tree.Underlying(0, 0); double _tau = Tree.Time; int n1 = _divdays.Length; int n2 = _ratedays.Length; BinomialTreePricer lhs1 = new BinomialTreePricer(spot, Strike, Payoff.ToLower()[0] == 'p', _tau, _vol, Tree.Columns, _flatFlag, Style, Smoothing, _ratedays, _rateamts, _divdays, _divamts, _treeType); int[] _divdays1 = new int[n1]; for (int idx = 0; idx < n1; idx++) { _divdays1[idx] = Math.Max(_divdays[idx] - 1, 0); } int[] _ratedays1 = new int[n2]; for (int idx = 0; idx < n2; idx++) { _ratedays1[idx] = Math.Max(_ratedays[idx] - 1, 0); } BinomialTreePricer lhs2 = new BinomialTreePricer(spot, Strike, Payoff.ToLower()[0] == 'p', _tau - 1.0 / 365.0, _vol, Tree.Columns, _flatFlag, Style, Smoothing, _ratedays1, _rateamts, _divdays1, _divamts, _treeType); double p1 = lhs1.GetPrice(); double p2 = lhs2.GetPrice(); double theta = lhs2.GetPrice() - lhs1.GetPrice(); return(theta); }
//Smoothing as describe in Orc quant guide. private void Smooth(string str, ITree spotTree) { if (str != null) { double dt = spotTree.Tau / spotTree.Gridsteps; if ((str.ToLower() == "y") | (str.ToLower() == "yes")) { int centre = 0; int k, j; int idx = Gridsteps - 1; for (k = 1; spotTree.GetSpotMatrix(idx, k - 1) <= Strike && spotTree.GetSpotMatrix(idx, k) <= Strike && k <= Gridsteps - 1; k++) { } if (k == 1) { centre = 2; } else if (k >= Gridsteps - 1) { centre = Gridsteps - 2; } else if (k <= Gridsteps - 2 && (k > 1)) { if (Math.Abs(spotTree.GetSpotMatrix(idx, k - 2) / Strike - 1) > Math.Abs(spotTree.GetSpotMatrix(idx, k + 1) / Strike - 1)) { centre = k; } else { centre = k - 1; } } for (j = centre - 1; j <= centre + 1; j++) { double temp; if (Payoff.ToLower() == "c" || (Payoff.ToLower() == "call")) { //temp = BSprice(SpotTree.Get_SpotMatrix(idx, j) //, dt, Strike, get_r(idx), SpotTree.sig, "C"); double fwd = spotTree.GetSpotMatrix(idx, j) - spotTree.GetDiv(idx); fwd *= Math.Exp(spotTree.GetR(idx) * dt); temp = BSprice(fwd, dt, Strike, spotTree.GetR(idx), spotTree.Sig, "C"); SetPriceMatrix(idx, j, temp); } else if ((Payoff.ToLower() == "p") || (Payoff.ToLower() == "put")) { //temp = BSprice(SpotTree.Get_SpotMatrix(idx, j) //, dt, Strike, get_r(idx), SpotTree.sig, "P"); double fwd = spotTree.GetSpotMatrix(idx, j) - spotTree.GetDiv(idx); fwd *= Math.Exp(spotTree.GetR(idx) * dt); temp = BSprice(fwd, dt, Strike, spotTree.GetR(idx), spotTree.Sig, "P"); SetPriceMatrix(idx, j, temp); } } } } }
//Make grid passing in a tree object. public void MakeGrid(ITree spotTree) { Gridsteps = spotTree.Gridsteps; EmptyArrays(); MakeArrays(); FillRates(spotTree); TermValue(spotTree); FillP(spotTree); PreTermValue(spotTree); Smooth(Smoothing, spotTree); //Iterate backward through tree to price American or Euro calls or puts. double temp; double dt = spotTree.Tau / spotTree.Gridsteps; if ((Style.ToLower() == "a") | (Style.ToLower() == "american")) { for (int i = Gridsteps - 2; i >= 0; i--) { for (int j = 0; j <= i; j++) { if ((Payoff.ToLower() == "c") | (Payoff.ToLower() == "call")) { temp = Math.Max(Math.Exp(-spotTree.GetR(i) * dt) * (GetP(i) * GetPriceMatrix(i + 1, j + 1) + (1 - GetP(i)) * GetPriceMatrix(i + 1, j)), spotTree.GetSpotMatrix(i, j) - Strike); SetPriceMatrix(i, j, temp); } else if ((Payoff.ToLower() == "p") | (Payoff.ToLower() == "put")) { temp = Math.Max(Math.Exp(-spotTree.GetR(i) * dt) * (GetP(i) * GetPriceMatrix(i + 1, j + 1) + (1 - GetP(i)) * GetPriceMatrix(i + 1, j)), Strike - spotTree.GetSpotMatrix(i, j)); SetPriceMatrix(i, j, temp); } } } } else if ((Style.ToLower() == "e") | (Style.ToLower() == "european")) { for (int i = Gridsteps - 2; i >= 0; i--) { for (int j = 0; j <= i; j++) { temp = Math.Exp(-spotTree.GetR(i) * dt) * (GetP(i) * GetPriceMatrix(i + 1, j + 1) + (1 - GetP(i)) * GetPriceMatrix(i + 1, j)); SetPriceMatrix(i, j, temp); } } } }
/// <summary> /// Makes the grid. /// </summary> private void MakeGrid() { EmptyArrays(); MakeArrays(); TermValue(); PreTermValue(); Smooth(Smoothing); //Iterate backward through tree to price American or Euro calls or puts. int n = Tree.Columns; double _tau = Tree.Time; double temp = 0; double dt = _tau / Tree.Columns; if ((Style.ToLower() == "a") | (Style.ToLower() == "american")) { for (int i = n - 2; i >= 0; i--) { for (int j = 0; j <= i; j++) { if ((Payoff.ToLower() == "c") | (Payoff.ToLower() == "call")) { temp = Math.Max(Math.Exp(-Tree.Rate(i) * dt) * (GetP(i) * GetPriceMatrix(i + 1, j + 1) + (1 - GetP(i)) * GetPriceMatrix(i + 1, j)), Tree.Underlying(i, j) - Strike); SetPriceMatrix(i, j, temp); } else if ((Payoff.ToLower() == "p") | (Payoff.ToLower() == "put")) { temp = Math.Max(Math.Exp(-Tree.Rate(i) * dt) * (GetP(i) * GetPriceMatrix(i + 1, j + 1) + (1 - GetP(i)) * GetPriceMatrix(i + 1, j)), Strike - Tree.Underlying(i, j)); SetPriceMatrix(i, j, temp); } } } } else if ((Style.ToLower() == "e") | (Style.ToLower() == "european")) { for (int i = n - 2; i >= 0; i--) { for (int j = 0; j <= i; j++) { temp = Math.Exp(-Tree.Rate(i) * dt) * (GetP(i) * GetPriceMatrix(i + 1, j + 1) + (1 - GetP(i)) * GetPriceMatrix(i + 1, j)); SetPriceMatrix(i, j, temp); } } } }
/// <summary> /// Gets the vega. /// </summary> /// <returns></returns> public double GetVega() { double spot = Tree.Underlying(0, 0); double _tau = Tree.Time; BinomialTreePricer lhs1 = new BinomialTreePricer(spot, Strike, Payoff.ToLower()[0] == 'p', _tau, 0.99 * _vol, Tree.Columns, _flatFlag, Style, Smoothing, _ratedays, _rateamts, _divdays, _divamts, _treeType); BinomialTreePricer lhs2 = new BinomialTreePricer(spot, Strike, Payoff.ToLower()[0] == 'p', _tau, 1.01 * _vol, Tree.Columns, _flatFlag, Style, Smoothing, _ratedays, _rateamts, _divdays, _divamts, _treeType); double P1 = lhs1.GetPrice(); double P2 = lhs2.GetPrice(); double vega = 0.0; if (_vol != 0) { vega = 0.01 * (P2 - P1) / (2 * 0.01 * _vol); } return(vega); }
/// <summary> /// Gets the vega. /// </summary> /// <returns></returns> public double GetVega() { double spot = Tree.Underlying(0, 0); double tau = Tree.Time; BinomialTreePricer lhs1 = new BinomialTreePricer(spot, Strike, Payoff.ToLower()[0] == 'p', tau, 0.99 * _volatility, Tree.Columns, _flatFlag, Style, Smoothing, _rateDays, _rateAmounts, _dividendDays, _dividendAmounts, _treeType); BinomialTreePricer lhs2 = new BinomialTreePricer(spot, Strike, Payoff.ToLower()[0] == 'p', tau, 1.01 * _volatility, Tree.Columns, _flatFlag, Style, Smoothing, _rateDays, _rateAmounts, _dividendDays, _dividendAmounts, _treeType); double p1 = lhs1.GetPrice(); double p2 = lhs2.GetPrice(); double vega = 0.0; if (_volatility != 0) { vega = 0.01 * (p2 - p1) / (2 * 0.01 * _volatility); } return(vega); }
/// <summary> /// Gets the gamma. /// </summary> /// <returns></returns> public double GetGamma() { double spot = Tree.Underlying(0, 0); int steps = Tree.Columns + 2; double tau = Tree.Time * (1 + 2 / steps); BinomialTreePricer clone = new BinomialTreePricer(spot, Strike, Payoff.ToLower()[0] == 'p', tau, _vol, steps, _flatFlag, Style, Smoothing, _ratedays, _rateamts, _divdays, _divamts, _treeType); double[] S = new double[3]; double[] C = new double[3]; for (int i = 0; i <= 2; ++i) { S[i] = clone.Tree.Underlying(2, i); C[i] = clone.GetPriceMatrix(2, i); } double gamma = 2 * (S[0] * (C[1] - C[2]) + S[1] * (C[2] - C[0]) + S[2] * (C[0] - C[1])) / (S[1] - S[0]) / (S[2] - S[0]) / (S[2] - S[1]); return(gamma); }
/// <summary> /// Gets the gamma. /// </summary> /// <returns></returns> public double GetGamma() { double spot = Tree.Underlying(0, 0); int steps = Tree.Columns + 2; double tau = Tree.Time * (1 + 2 / steps); BinomialTreePricer clone = new BinomialTreePricer(spot, Strike, Payoff.ToLower()[0] == 'p', tau, _volatility, steps, _flatFlag, Style, Smoothing, _rateDays, _rateAmounts, _dividendDays, _dividendAmounts, _treeType); double[] s = new double[3]; double[] c = new double[3]; for (int i = 0; i <= 2; ++i) { s[i] = clone.Tree.Underlying(2, i); c[i] = clone.GetPriceMatrix(2, i); } double gamma = 2 * (s[0] * (c[1] - c[2]) + s[1] * (c[2] - c[0]) + s[2] * (c[0] - c[1])) / (s[1] - s[0]) / (s[2] - s[0]) / (s[2] - s[1]); return(gamma); }
//Assign terminal payoff condition. private void TermValue(ITree spotTree) { if (spotTree != null) { for (int j = 0; j <= Gridsteps; j++) { double temp; Payoff = Payoff.ToLower(); if ((Payoff == "c") | (Payoff == "call")) { temp = Math.Max(spotTree.GetSpotMatrix(Gridsteps, j) - Strike, 0); SetPriceMatrix(Gridsteps, j, temp); } else if ((Payoff.ToLower() == "p") | (Payoff.ToLower() == "put")) { temp = Math.Max(Strike - spotTree.GetSpotMatrix(Gridsteps, j), 0); SetPriceMatrix(Gridsteps, j, temp); } } } }
private double Bisection(double prem, double fwdPrice) { double right = 0.75; double left = 0.35; double mid; var cp = Payoff.ToLower() == "c" ? 1 : -1; int days = Expiry.Subtract(Today).Days; double t = days / 365.0; var priceClone = (AmOptionAnalytics)Clone(); if (fwdPrice <= 0 || Strike <= 0 || t <= 0 || prem <= 0) { return(0); } double df = Convert.ToDouble(RateCurve.GetDf(days)); if (prem < Math.Max(cp * df * (fwdPrice - priceClone.Strike), 0)) { throw new System.Exception("No solution for volatility"); } do { mid = (right + left) / 2; priceClone.Sig = left; double fleft = priceClone.Price() - prem; priceClone.Sig = right; double fright = priceClone.Price() - prem; priceClone.Sig = mid; double fmid = priceClone.Price() - prem; if (fleft * fmid < 0) { right = mid; } else if (fright * fmid < 0) { left = mid; } } while (Math.Abs(right - left) > 2 * Eps); return(mid); }
//Assign values at Gridsteps-1 node. private void PreTermValue(Tree SpotTree) { if (SpotTree != null) { double temp = 0; double dt = SpotTree.Tau / SpotTree.Gridsteps; int idx = Gridsteps - 1; for (int j = 0; j <= Gridsteps - 1; j++) { if ((Style.ToLower() == "a") | (Style.ToLower() == "american")) { if ((Payoff.ToLower() == "c") | (Payoff.ToLower() == "call")) { temp = Math.Max(Math.Exp(-SpotTree.GetR(idx) * dt) * (Get_P(idx) * Get_PriceMatrix(idx + 1, j + 1) + (1 - Get_P(idx)) * Get_PriceMatrix(idx + 1, j)), SpotTree.GetSpotMatrix(idx, j) - Strike); Set_PriceMatrix(idx, j, temp); } else if ((Payoff.ToLower() == "p") | (Payoff.ToLower() == "put")) { temp = Math.Max(Math.Exp(-SpotTree.GetR(idx) * dt) * (Get_P(idx) * Get_PriceMatrix(idx + 1, j + 1) + (1 - Get_P(idx)) * Get_PriceMatrix(idx + 1, j)), -SpotTree.GetSpotMatrix(idx, j) + Strike); Set_PriceMatrix(idx, j, temp); } } else if ((Style.ToLower() == "e") | (Style.ToLower() == "european")) { temp = Math.Exp(-SpotTree.GetR(idx) * dt) * (Get_P(idx) * Get_PriceMatrix(idx + 1, j + 1) + (1 - Get_P(idx)) * Get_PriceMatrix(idx + 1, j)); Set_PriceMatrix(idx, j, temp); } } } }
private double Newton(double prem, double fwdPrice) { double dvol; var cp = Payoff.ToLower() == "c" ? 1 : -1; int days = Expiry.Subtract(Today).Days; double t = days / 365.0; var priceClone = (AmOptionAnalytics)Clone(); if (fwdPrice <= 0 || Strike <= 0 || t <= 0 || prem <= 0) { return(0); } //double df = Convert.ToDouble(_rateCurve.getDf(days)); if (prem < Math.Max(cp * (fwdPrice - priceClone.Strike), 0)) { throw new System.Exception("No solution for volatility"); } int idx = 0; do { var price = priceClone.Price(); priceClone.MakeVega(); var vega = priceClone.Vega; if (vega == 0 || idx > Maxits) { throw new System.Exception("No volatility solution"); } dvol = (price - prem) / (100 * vega); priceClone.Sig -= dvol; if (priceClone.Sig < 0) { priceClone.Sig = 0; } idx++; } while (Math.Abs(dvol) > Eps); return(priceClone.Sig); }
/// <summary> /// Assign terminal payoff condition. /// </summary> private void TermValue() { int n = Tree.Columns; if (Tree != null) { for (int j = 0; j <= n; j++) { double temp = 0.0; Payoff = Payoff.ToLower(); if ((Payoff == "c") | (Payoff == "call")) { temp = Math.Max(Tree.Underlying(n, j) - Strike, 0); SetPriceMatrix(n, j, temp); } else if ((Payoff.ToLower() == "p") | (Payoff.ToLower() == "put")) { temp = Math.Max(Strike - Tree.Underlying(n, j), 0); SetPriceMatrix(n, j, temp); } } } }
/// <summary> /// Assign values at Gridsteps-1 node. /// </summary> private void PreTermValue() { if (Tree != null) { int n = Tree.Columns; double temp = 0; double dt = Tree.Time / n; int idx = n - 1; for (int j = 0; j <= n - 1; j++) { if ((Style.ToLower() == "a") | (Style.ToLower() == "american")) { if ((Payoff.ToLower() == "c") | (Payoff.ToLower() == "call")) { temp = Math.Max(Math.Exp(-Tree.Rate(idx) * dt) * (GetP(idx) * GetPriceMatrix(idx + 1, j + 1) + (1 - GetP(idx)) * GetPriceMatrix(idx + 1, j)), Tree.Underlying(idx, j) - Strike); SetPriceMatrix(idx, j, temp); } else if ((Payoff.ToLower() == "p") | (Payoff.ToLower() == "put")) { temp = Math.Max(Math.Exp(-Tree.Rate(idx) * dt) * (GetP(idx) * GetPriceMatrix(idx + 1, j + 1) + (1 - GetP(idx)) * GetPriceMatrix(idx + 1, j)), -Tree.Underlying(idx, j) + Strike); SetPriceMatrix(idx, j, temp); } } else if ((Style.ToLower() == "e") | (Style.ToLower() == "european")) { temp = Math.Exp(-Tree.Rate(idx) * dt) * (GetP(idx) * GetPriceMatrix(idx + 1, j + 1) + (1 - GetP(idx)) * GetPriceMatrix(idx + 1, j)); SetPriceMatrix(idx, j, temp); } } } }
/// <summary> ///Here we Smooth the 3 -closest nodes to the strike at the second last timestep. This involves ///replacing the tree calculated price with the BS price. This has minimal effect on the price ///but significant effect on smoothness of spatial derivatives especially second order like gamma /// </summary> /// <param name="str">The STR.</param> private void Smooth(string str) { double _tau = Tree.Time; int n = Tree.Columns; if (str != null) { double dt = _tau / Tree.Columns; if ((str.ToLower() == "y") | (str.ToLower() == "yes")) { int Centre = 0; int k, j; int idx = Tree.Columns - 1; k = 1; for (k = 1; ((Tree.Underlying(idx, k - 1) <= Strike) && ((Tree.Underlying(idx, k) <= Strike)) && ((k <= n - 1))); k++) { } if (k == 1) { Centre = 2; } else if (k >= n - 1) { Centre = n - 2; } else if ((k <= n - 2) && (k > 1)) { if (Math.Abs(Tree.Underlying(idx, k - 2) / Strike - 1) > Math.Abs(Tree.Underlying(idx, k + 1) / Strike - 1)) { Centre = k; } else { Centre = k - 1; } } for (j = Centre - 1; j <= Centre + 1; j++) { double temp = 0; if ((Payoff.ToLower() == "c") || (Payoff.ToLower() == "call")) { //temp = BSprice(tree.Get_SpotMatrix(idx, j) //, dt, Strike, get_r(idx), tree.sig, "C"); double fwd = Tree.Underlying(idx, j) - Tree.Dividend(idx); fwd *= Math.Exp(Tree.Rate(idx) * dt); temp = BSprice(fwd, dt, Strike, Tree.Rate(idx), Tree.Volatility, "C"); SetPriceMatrix(idx, j, temp); } else if ((Payoff.ToLower() == "p") || (Payoff.ToLower() == "put")) { //temp = BSprice(tree.Get_SpotMatrix(idx, j) //, dt, Strike, get_r(idx), tree.sig, "P"); double fwd = Tree.Underlying(idx, j) - Tree.Dividend(idx); fwd *= Math.Exp(Tree.Rate(idx) * dt); temp = BSprice(fwd, dt, Strike, Tree.Rate(idx), Tree.Volatility, "P"); SetPriceMatrix(idx, j, temp); } } } } }
//Smoothing as describe in Orc quant guide. private void Smooth(string str, Tree SpotTree) { if (str != null) { double dt = SpotTree.Tau / SpotTree.Gridsteps; if ((str.ToLower() == "y") | (str.ToLower() == "yes")) { int Centre = 0; int k, j; int idx = Gridsteps - 1; k = 1; for (k = 1; ((SpotTree.GetSpotMatrix(idx, k - 1) <= Strike) && ((SpotTree.GetSpotMatrix(idx, k) <= Strike)) && ((k <= Gridsteps - 1))); k++) { } if (k == 1) { Centre = 2; } else if (k >= Gridsteps - 1) { Centre = Gridsteps - 2; } else if ((k <= Gridsteps - 2) && (k > 1)) { if (Math.Abs(SpotTree.GetSpotMatrix(idx, k - 2) / Strike - 1) > Math.Abs(SpotTree.GetSpotMatrix(idx, k + 1) / Strike - 1)) { Centre = k; } else { Centre = k - 1; } } for (j = Centre - 1; j <= Centre + 1; j++) { double temp = 0; if ((Payoff.ToLower() == "c") || (Payoff.ToLower() == "call")) { //temp = BSprice(SpotTree.Get_SpotMatrix(idx, j) //, dt, Strike, get_r(idx), SpotTree.sig, "C"); double fwd = SpotTree.GetSpotMatrix(idx, j) - SpotTree.get_div(idx); fwd *= Math.Exp(SpotTree.GetR(idx) * dt); temp = BSprice(fwd, dt, Strike, SpotTree.GetR(idx), SpotTree.Sig, "C"); Set_PriceMatrix(idx, j, temp); } else if ((Payoff.ToLower() == "p") || (Payoff.ToLower() == "put")) { //temp = BSprice(SpotTree.Get_SpotMatrix(idx, j) //, dt, Strike, get_r(idx), SpotTree.sig, "P"); double fwd = SpotTree.GetSpotMatrix(idx, j) - SpotTree.get_div(idx); fwd *= Math.Exp(SpotTree.GetR(idx) * dt); temp = BSprice(fwd, dt, Strike, SpotTree.GetR(idx), SpotTree.Sig, "P"); Set_PriceMatrix(idx, j, temp); } } } } }