//public spotStar /// <summary> /// /// </summary> /// <param name="myZero"></param> /// <param name="myDivList"></param> private void MakeDivArray(ZeroCurve myZero, DivList myDivList) { double dt = Tau / Gridsteps; if ((myDivList != null) && (myZero != null)) { for (int idx = 0; idx < Gridsteps; idx++) { double temp = 0.0; for (int kdx = 0; kdx < myDivList.Divpoints; kdx++) { if ((myDivList.GetT(kdx) > idx * dt) && (myDivList.GetT(kdx) < Tau)) { temp += myDivList.GetD(kdx) * Math.Exp(-myZero.ForwardRate(idx * dt, myDivList.GetT(kdx)) * (myDivList.GetT(kdx) - idx * dt)); } } SetDiv(idx, temp, dt * idx); } } else //missing either div or zero, load in 0 for _div on tree { for (int idx = 0; idx <= Gridsteps; idx++) { SetDiv(idx, 0.0, dt * idx); } } }
//public MakeGrid /// <summary> /// /// </summary> /// <param name="myZero"></param> /// <param name="myDivList"></param> public void MakeGrid(ZeroCurve myZero, DivList myDivList) { EmptyArrays(); MakeArrays(); MakeSpotStar(myZero, myDivList); MakeDivArray(myZero, myDivList); FillForwardRate(myZero); FillUpDown(Sig); //make the spot grid double sv = _spotstar; SetSpotMatrix(0, 0, sv + GetDiv(0)); //now march foraward in time for (int idx = 1; idx <= Gridsteps; idx++) { for (int jdx = 0; jdx <= idx; jdx++) { sv = _spotstar * Math.Pow(GetUp(idx - 1), jdx) * Math.Pow(GetDn(idx - 1), idx - jdx); sv += idx == Gridsteps ? 0.0 : GetDiv(idx); //get_div(idx); SetSpotMatrix(idx, jdx, sv); } } }
/// <summary> /// /// </summary> /// <param name="spotT"></param> /// <param name="priceT"></param> /// <param name="myZero"></param> /// <param name="myDiv"></param> public void MakeTheta(ITree spotT, Pricer priceT, ZeroCurve myZero, DivList myDiv) { SetParam(spotT, priceT); var type = spotT.GetType(); ITree t1 = (ITree)Activator.CreateInstance(type); ITree t2 = (ITree)Activator.CreateInstance(type); t1.Tau = Tau; t1.Gridsteps = Gridsteps; t1.Sig = Sig; t1.Spot = Spot; t1.MakeGrid(myZero, myDiv); priceT.MakeGrid(t1); double p1 = priceT.Price(); DivList shiftDiv = new DivList { Divpoints = myDiv.Divpoints }; shiftDiv.MakeArrays(); for (int idx = 0; idx < myDiv.Divpoints; idx++) { shiftDiv.SetD(idx, myDiv.GetD(idx), myDiv.GetT(idx) - 1 / 365.0); } double t = Tau - 1.00 / 365.00; t2.Tau = t; t2.Gridsteps = Gridsteps; t2.Sig = Sig; t2.Spot = Spot; t2.MakeGrid(myZero, shiftDiv); priceT.MakeGrid(t2); double p2 = priceT.Price(); Theta = (p2 - p1); }
/// <summary> /// /// </summary> /// <param name="myZero"></param> /// <param name="myDivList"></param> /// <param name="spot"></param> /// <param name="t"></param> /// <returns></returns> public static double GetATMfwd(ZeroCurve myZero, DivList myDivList, double spot, double t) { double spotstar = spot; //compute the discounted dividends and take off spot if ((myDivList != null) && (myZero != null)) { for (int idx = 0; idx < myDivList.Divpoints; idx++) { if (myDivList.GetT(idx) <= t) { double d1 = myDivList.GetD(idx); double r1 = myZero.LinInterp(myDivList.GetT(idx)); double t1 = Math.Exp(-r1 * myDivList.GetT(idx)); spotstar -= d1 * t1; } } } //gross up to expiry to get atfwd if (myZero != null) { double r = myZero.LinInterp(t); return(spotstar * Math.Exp(r * t)); } return(0); }
/// <summary> /// /// </summary> /// <param name="spotT"></param> /// <param name="priceT"></param> /// <param name="myZero"></param> /// <param name="myDiv"></param> public void MakeVega(ITree spotT, Pricer priceT, ZeroCurve myZero, DivList myDiv) { SetParam(spotT, priceT); var type = spotT.GetType(); ITree t1 = (ITree)Activator.CreateInstance(type); ITree t2 = (ITree)Activator.CreateInstance(type); t1.Tau = Tau; t1.Gridsteps = Gridsteps; t1.Sig = .99 * Sig; t1.Spot = Spot; t1.MakeGrid(myZero, myDiv); priceT.MakeGrid(t1); double p1 = priceT.Price(); t2.Tau = Tau; t2.Gridsteps = Gridsteps; t2.Sig = 1.01 * Sig; t2.Spot = Spot; t2.MakeGrid(myZero, myDiv); priceT.MakeGrid(t2); double p2 = priceT.Price(); if (Sig != 0) { Vega = 0.01 * (p2 - p1) / (2 * 0.01 * Sig); } }
/// <summary> /// /// </summary> /// <param name="spotT"></param> /// <param name="priceT"></param> /// <param name="myZero"></param> /// <param name="myDiv"></param> public void MakeDeltaGamma(ITree spotT, Pricer priceT, ZeroCurve myZero, DivList myDiv) { SetParam(spotT, priceT); var type = spotT.GetType(); ITree treeD = (ITree)Activator.CreateInstance(type); treeD.Gridsteps = Gridsteps + 2; treeD.Spot = Spot; treeD.Sig = Sig; treeD.Tau = Tau * (1 + 2 / Gridsteps); treeD.MakeGrid(myZero, myDiv); priceT.MakeGrid(treeD); double[] s = new double[3]; double[] c = new double[3]; for (int i = 0; i <= 2; ++i) { s[i] = treeD.GetSpotMatrix(2, i); c[i] = priceT.GetPriceMatrix(2, i); } //Delta = (S[0] * (2 * S[1] - S[0]) * (C[1] - C[2]) + // (S[1] * S[1]) * (C[2] - C[0]) + S[2] * (2 * S[1] - S[2]) * (C[0] - C[1])) // / (S[1] - S[0]) / (S[2] - S[0]) / (S[2] - S[1]); //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]); double u = treeD.GetUp(0); double d = treeD.GetDn(0); double est1 = (c[2] - c[0]) / (s[2] - s[0]); double est2 = (priceT.GetPriceMatrix(4, 4) - priceT.GetPriceMatrix(4, 0)) / (treeD.GetSpotMatrix(4, 4) - treeD.GetSpotMatrix(4, 0)); double est3 = (priceT.GetPriceMatrix(6, 6) - priceT.GetPriceMatrix(6, 0)) / (treeD.GetSpotMatrix(6, 6) - treeD.GetSpotMatrix(6, 0)); double temp = (Math.Pow(u, 2) + Math.Pow(d, 2) + Math.Pow(u, 2) * Math.Pow(d, 2)) * est1 - (Math.Pow(u, 2) + Math.Pow(d, 2) + 1) * est2 + est3; Delta = 1 / Math.Pow(u, 2) / Math.Pow(d, 2) * temp; //Delta = 1/ }
/// <summary> /// /// </summary> /// <param name="today"></param> /// <param name="expiry"></param> /// <param name="dates"></param> /// <param name="amts"></param> /// <returns></returns> /// <exception cref="Exception"></exception> public DivList UnpackDiv(DateTime today, DateTime expiry, DateTime[] dates, double[] amts) { int n1 = dates.Length; int n2 = dates.Length; double timetoexp = expiry.Subtract(today).Days / 365.0; if (n1 != n2) { throw new Exception("Rate ranges must be of the same length"); } var dl = new DivList { Divpoints = n1 }; dl.MakeArrays(); for (int idx = 0; idx < n1; idx++) { double time = dates[idx].Subtract(today).Days / 365.0; double rate = amts[idx]; if (time > 0 & time <= timetoexp) { dl.SetD(_kdx, rate, time); _kdx++; } } return(dl); }
/// <summary> /// Gets the AT mforward. /// </summary> /// <param name="zeroDates"></param> /// <param name="zeroRates">The zero curve.</param> /// <param name="divDates"></param> /// <param name="divAms">The div curve.</param> /// <param name="expiry"></param> /// <param name="spot">The spot.</param> /// <param name="today"></param> /// <returns></returns> public static double GetForward(DateTime today, DateTime expiry, double spot, DateTime[] zeroDates, double[] zeroRates, DateTime[] divDates, double[] divAms) { var wrapper = new Wrapper(); ZeroCurve myZero = wrapper.UnpackZero(today, zeroDates, zeroRates); DivList myDiv = wrapper.UnpackDiv(today, expiry, divDates, divAms); double t = expiry.Subtract(today).Days / 365.0; double temp = Collar.GetATMfwd(myZero, myDiv, spot, t); return(temp); }
/// <summary> /// /// </summary> /// <param name="spot"></param> /// <param name="strike"></param> /// <param name="vol"></param> /// <param name="paystyle"></param> /// <param name="today"></param> /// <param name="expiry"></param> /// <param name="zeroDates"></param> /// <param name="zeroRates"></param> /// <param name="divDates"></param> /// <param name="divAms"></param> /// <returns></returns> public static double BlackScholesPricer(double spot, double strike, double vol, string paystyle, DateTime today, DateTime expiry, DateTime[] zeroDates, double[] zeroRates, DateTime[] divDates, double[] divAms) { double t = expiry.Subtract(today).Days / 365.0; var wrapper = new Wrapper(); ZeroCurve myZero = wrapper.UnpackZero(today, zeroDates, zeroRates); DivList myDiv = wrapper.UnpackDiv(today, expiry, divDates, divAms); double fwd = Collar.GetATMfwd(myZero, myDiv, spot, t); double r = myZero.LinInterp(t); //create default pricer var myPrice = new Pricer { Strike = strike, Payoff = paystyle }; double pr = myPrice.BSprice(fwd, t, strike, r, vol, paystyle); return(pr); }
//public spotStar private void MakeSpotStar(ZeroCurve myZero, DivList myDivList) { _spotstar = Spot; if (myDivList != null && myZero != null) { for (int idx = 0; idx < myDivList.Divpoints; idx++) { if (myDivList.GetT(idx) <= Tau) { double d1 = myDivList.GetD(idx); double r1 = myZero.LinInterp(myDivList.GetT(idx)); double t1 = Math.Exp(-r1 * myDivList.GetT(idx)); _spotstar -= d1 * t1; } } } }
/// <summary> /// /// </summary> /// <param name="style"></param> /// <param name="spot"></param> /// <param name="strike"></param> /// <param name="vol"></param> /// <param name="today"></param> /// <param name="expiry"></param> /// <param name="paystyle"></param> /// <param name="zeroDates"></param> /// <param name="zeroRates"></param> /// <param name="divDates"></param> /// <param name="divAms"></param> /// <param name="gridsteps"></param> /// <param name="smoo"></param> /// <param name="flatFlag"></param> /// <returns></returns> public static double[,] BinomialRelativeGetGreeks(string style, double spot, double strike, double vol, DateTime today, DateTime expiry, string paystyle, DateTime[] zeroDates, double[] zeroRates, DateTime[] divDates, double[] divAms, double gridsteps, string smoo, bool flatFlag) { const int arrsize = 4; gridsteps = (gridsteps == 0.0) ? 20 : gridsteps; int nGridsteps = Convert.ToInt32(gridsteps); string smoothing = (smoo.ToLower().Equals("n")) ? "n" : "y"; var retArray = new double[arrsize, arrsize]; double t = expiry.Subtract(today).Days / 365.0; ZeroCurve myZero = (new Wrapper()).UnpackZero(today, zeroDates, zeroRates); DivList myDiv = (new Wrapper()).UnpackDiv(today, expiry, divDates, divAms); //create the tree var myTree = new PropTree(t, vol, spot, nGridsteps, true) { Gridsteps = nGridsteps }; myTree.MakeGrid(myZero, myDiv); //create pricer var myPrice = new Pricer(strike, paystyle, smoothing, style); myPrice.MakeGrid(myTree); myPrice.Price(); var myGreeks = new Greeks(); myGreeks.MakeDeltaGamma(myTree, myPrice, myZero, myDiv); double delta = myGreeks.Delta; double gamma = myGreeks.Gamma; myGreeks.MakeVega(myTree, myPrice, myZero, myDiv); double vega = myGreeks.Vega; myGreeks.MakeTheta(myTree, myPrice, myZero, myDiv); double theta = myGreeks.Theta; retArray[0, 0] = delta; retArray[0, 1] = gamma; retArray[0, 2] = vega; retArray[0, 3] = theta; return(retArray); }
/// <summary> /// /// </summary> /// <param name="myZero"></param> /// <param name="myDivList"></param> public void MakeGrid(ZeroCurve myZero, DivList myDivList) { EmptyArrays(); MakeArrays(); MakeSpotZero(myZero, myDivList); MakeDivArray(myZero, myDivList); FillForwardRate(myZero); FillUpDown(Sig); decimal deltaT = Convert.ToDecimal(Tau) / Convert.ToDecimal(Gridsteps); //make the spot grid SetSpotMatrix(0, 0, _spot0); //now march foraward in time for (int idx = 1; idx <= Gridsteps; idx++) { for (int jdx = 0; jdx <= idx; jdx++) { var sv = _spot0 * Math.Pow(GetUp(idx - 1), jdx) * Math.Pow(GetDn(idx - 1), idx - jdx); //sv += (idx == Gridsteps) ? 0.0 : get_div(idx); //get_div(idx); SetSpotMatrix(idx, jdx, sv); } } for (int idx = 1; idx <= Gridsteps; idx++) { for (int jdx = 0; jdx <= idx; jdx++) { int kdx = myDivList.Divpoints - 1; while (kdx >= 0) { decimal t1 = Convert.ToDecimal(myDivList.GetT(kdx)); if (t1 / idx > deltaT) { SetSpotMatrix(idx, jdx, GetSpotMatrix(idx, jdx) / (1 - _ratio[kdx])); } kdx--; } } } SetSpotMatrix(0, 0, Spot); }
/// <summary> /// /// </summary> /// <param name="myZero"></param> /// <param name="myDiv"></param> /// <param name="orcParams"></param> /// <param name="t"></param> /// <param name="strike"></param> /// <param name="spot"></param> /// <param name="style"></param> /// <param name="paystyle"></param> /// <param name="gridsteps"></param> /// <returns></returns> public static double FindPrice(ZeroCurve myZero, DivList myDiv, double[] orcParams, double t, double strike, double spot, string style, string paystyle, double gridsteps) { //get the atfwd double atFwd = GetATMfwd(myZero, myDiv, spot, t); //unpack the orc paramters //double currentVol = OrcParams[0]; //double slopeRef = OrcParams[1]; //double putCurve = OrcParams[2]; //double callCurve = OrcParams[3]; //double dnCutOff = OrcParams[4]; //double upCutOff = OrcParams[5]; //double refFwd = OrcParams[6]; //double refVol = OrcParams[7]; //double vcr = OrcParams[8]; //double scr = OrcParams[9]; //double ssr = OrcParams[10]; //double dsr = OrcParams[11]; //double usr = OrcParams[12]; //set up the tree var myTree = new DiscreteTree(); var myVol = new OrcWingVol(); int nGridsteps = (gridsteps < 20.0) ? 20 : Convert.ToInt32(gridsteps); myTree.Gridsteps = nGridsteps; myTree.Tau = t; myTree.Sig = myVol.Orcvol(atFwd, strike); myTree.Spot = spot; myTree.MakeGrid(myZero, myDiv); //create pricer var myPrice = new Pricer { Strike = strike, Payoff = paystyle, Smoothing = "y", Style = style }; myPrice.MakeGrid(myTree); double pr = myPrice.Price(); return(pr); }
/// <summary> /// /// </summary> /// <param name="style"></param> /// <param name="spot"></param> /// <param name="strike"></param> /// <param name="vol"></param> /// <param name="today"></param> /// <param name="expiry"></param> /// <param name="paystyle"></param> /// <param name="zeroDates"></param> /// <param name="zeroRates"></param> /// <param name="divDates"></param> /// <param name="divAms"></param> /// <param name="gridsteps"></param> /// <param name="smoo"></param> /// <param name="flatFlag"></param> /// <returns></returns> public static double BinomialRelativePricer(string style, double spot, double strike, double vol, DateTime today, DateTime expiry, string paystyle, DateTime[] zeroDates, double[] zeroRates, DateTime[] divDates, double[] divAms, double gridsteps, string smoo, bool flatFlag) { gridsteps = (gridsteps == 0.0) ? 20 : gridsteps; int nGridsteps = Convert.ToInt32(gridsteps); string smoothing = (smoo.ToLower().Equals("n")) ? "n" : "y"; double t = expiry.Subtract(today).Days / 365.0; var wrapper = new Wrapper(); ZeroCurve myZero = wrapper.UnpackZero(today, zeroDates, zeroRates); DivList myDiv = wrapper.UnpackDiv(today, expiry, divDates, divAms); //create the tree var myTree = new PropTree(t, vol, spot, nGridsteps, true); myTree.MakeGrid(myZero, myDiv); //create pricer var myPrice = new Pricer(strike, paystyle, smoothing, style); myPrice.MakeGrid(myTree); double pr = myPrice.Price(); return(pr); }
//public spotStar private void MakeSpotZero(ZeroCurve myZero, DivList myDivList) { _spot0 = Spot; _ratio = new double[myDivList.Divpoints]; if (myZero != null) { for (int idx = 0; idx < myDivList.Divpoints; idx++) { if (myDivList.GetT(idx) <= Tau) { double d1 = myDivList.GetD(idx); double r1 = myZero.LinInterp(myDivList.GetT(idx)); double t1 = Math.Exp(-r1 * myDivList.GetT(idx)); _ratio[idx] = d1 * t1 / _spot0; if (_ratio[idx] > 1) { throw new Exception("Dividend greater than spot"); } _spot0 = _spot0 * (1 - _ratio[idx]); } } } }
/// <summary> /// /// </summary> /// <param name="myZero"></param> /// <param name="myDiv"></param> /// <param name="orcParams"></param> /// <param name="t"></param> /// <param name="strike"></param> /// <param name="spot"></param> /// <param name="style"></param> /// <param name="paystyle"></param> /// <param name="gridsteps"></param> /// <returns></returns> public static double FindZeroCostPut(ZeroCurve myZero, DivList myDiv, double[] orcParams, double t, double strike, double spot, string style, string paystyle, double gridsteps) { //compute the cost of the put double putPrice = 0.0; double callPrice = FindPrice(myZero, myDiv, orcParams, t, strike, spot, style, "c", gridsteps); //start looking for the call using the ATM strike double putStrike = GetATMfwd(myZero, myDiv, spot, t); const double tol = 0.0001; for (int idx = 0; idx < 20; idx++) { putPrice = FindPrice(myZero, myDiv, orcParams, t, putStrike, spot, style, "p", gridsteps); if (Math.Abs(callPrice - putPrice) < tol) { break; } //apply newton double dk = 0.01 * putStrike; double putPriceUp = FindPrice(myZero, myDiv, orcParams, t, putStrike - dk, spot, style, "p", gridsteps); putStrike += (callPrice - putPrice) * dk / (putPriceUp - putPrice); } return(putPrice); }