Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        public static double FindZeroCostCall(ZeroCurve myZero, DivList myDiv, OrcWingVol myVol, double t,
                                              double strike, double spot, string style, string paystyle, double gridsteps)
        {
            //compute the cost of the put
            double callPrice = 0.0;
            double putPrice  = FindPrice(myZero, myDiv, myVol, t, strike, spot, style, "p", gridsteps);
            //start looking for the call using the ATM strike
            //double callStrike = GetATMfwd(myZero, myDiv, spot, t);
            double       callStrike = strike;
            const double tol        = 0.0001;

            for (int idx = 0; idx < 1000; idx++)
            {
                callPrice = FindPrice(myZero, myDiv, myVol, t, callStrike, spot, style, "c", gridsteps);
                if (Math.Abs(callPrice - putPrice) < tol)
                {
                    break;
                }
                //apply newton
                double dk          = 0.001 * callStrike;
                double callPriceUp = FindPrice(myZero, myDiv, myVol, t, callStrike + dk, spot, style, "c", gridsteps);
                callStrike -= (callPrice - putPrice) * dk / (callPriceUp - callPrice);
            }
            if (Math.Abs(callPrice - putPrice) > tol)
            {
                throw new Exception("Price did not converge");
            }
            return(callStrike);
        }
Ejemplo n.º 3
0
        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);
        }
Ejemplo n.º 4
0
        //public spotStar
        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));
                        }
                    }
                    set_div(idx, temp, dt * idx);
                }
            }
            else //missing either div or zero, load in 0 for _div on tree
            {
                for (int idx = 0; idx <= Gridsteps; idx++)
                {
                    set_div(idx, 0.0, dt * idx);
                }
            }
        }
Ejemplo n.º 5
0
        //public MakeGrid
        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 + get_div(0));

            //now march forward in time
            for (int idx = 1; idx <= Gridsteps; idx++)
            {
                for (int jdx = 0; jdx <= idx; jdx++)
                {
                    sv  = Spotstar * Math.Pow(get_up(idx - 1), jdx) * Math.Pow(get_dn(idx - 1), idx - jdx);
                    sv += (idx == Gridsteps) ? 0.0 : get_div(idx);
                    //get_div(idx);
                    SetSpotMatrix(idx, jdx, sv);
                }
            }
        }
Ejemplo n.º 6
0
        public void MakeTheta(Tree SpotT, Pricer PriceT, ZeroCurve myZero, DivList myDiv)
        {
            SetParam(SpotT, PriceT);
            Tree T1 = new Tree(), T2 = new Tree();

            T1.Tau       = tau;
            T1.Gridsteps = Gridsteps;
            T1.Sig       = sig;
            T1.Spot      = spot;
            T1.MakeGrid(myZero, myDiv);

            PriceT.MakeGrid(T1);
            double P1 = PriceT.Price();

            double t = tau - 1.00 / 365.00;

            T2.Tau       = t;
            T2.Gridsteps = Gridsteps;
            T2.Sig       = sig;
            T2.Spot      = spot;
            T2.MakeGrid(myZero, myDiv);

            PriceT.MakeGrid(T2);
            double P2 = PriceT.Price();

            Theta = (P2 - P1);
        }
Ejemplo n.º 7
0
        public void MakeDeltaGamma(Tree SpotT, Pricer PriceT, ZeroCurve myZero, DivList myDiv)
        {
            SetParam(SpotT, PriceT);
            Tree treeD = new Tree
            {
                Gridsteps = Gridsteps + 2,
                Spot      = spot,
                Sig       = sig,
                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.Get_PriceMatrix(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]);
        }
Ejemplo n.º 8
0
        public void MakeVega(Tree SpotT, Pricer PriceT, ZeroCurve myZero, DivList myDiv)
        {
            SetParam(SpotT, PriceT);
            Tree T1 = new Tree(), T2 = new Tree();

            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);
            }
        }
Ejemplo n.º 9
0
        //compute Sstar for the BC's
        private double ComputeDiscDiv(double tTemp, double T, ZeroCurve myZero, DivList mydiv)
        {
            double temp = 0.0;

            for (int idx = 0; idx < mydiv.Divpoints; idx++)
            {
                if ((tTemp < mydiv.GetT(idx)) && (mydiv.GetT(idx) < T))
                {
                    double fwdRate = myZero.ForwardRate(tTemp, mydiv.GetT(idx));
                    temp += mydiv.GetD(idx) * Math.Exp(-fwdRate * (mydiv.GetT(idx) - tTemp));
                }
            }
            return(temp);
        }
Ejemplo n.º 10
0
        //determine if dt needs adjusted because a div occurs in proposed interval
        private double CheckBetweenDiv(double t1, double t2, ref double discDiv, DivList myDiv)   //t1 & t2 are real times
        {
            double temp = t2 - t1;

            for (int idx = 0; idx < myDiv.Divpoints; idx++)
            {
                if ((t1 <= myDiv.GetT(idx)) && (t2 > myDiv.GetT(idx)))
                {
                    temp    = t2 - myDiv.GetT(idx);
                    discDiv = myDiv.GetD(idx);
                    break;
                }
            }

            return(temp);
        }
Ejemplo n.º 11
0
        //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;
                    }
                }
            }
        }
Ejemplo n.º 12
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="price"></param>
        /// <param name="myZero"></param>
        /// <param name="myDiv"></param>
        /// <returns></returns>
        public double ImpVol(double price, ZeroCurve myZero, DivList myDiv)
        {
            double[] greeks = new double[4];
            double   temp   = Pricer(myZero, myDiv, ref greeks, false);

            for (int idx = 0; idx < 20; idx++)
            {
                temp = Pricer(myZero, myDiv, ref greeks, false);
                if (Math.Abs(temp - price) < 0.0001)
                {
                    break;
                }

                double sigold = Sig;
                double dsig   = 0.01 * Sig;
                Sig += dsig;
                double tempUp = Pricer(myZero, myDiv, ref greeks, false);
                sigold -= (temp - price) * dsig / (tempUp - temp);
                Sig     = sigold;
            }
            return(Sig);
        }
Ejemplo n.º 13
0
        public static double FindPrice(ZeroCurve myZero, DivList myDiv, OrcWingVol myVol, double t,
                                       double strike, double spot, string style, string paystyle, double gridsteps)
        {
            //get the atfwd
            double atFwd = GetATMfwd(myZero, myDiv, spot, t);
            //set up the tree
            var myTree     = new Tree();
            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);
        }
Ejemplo n.º 14
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="today"></param>
        /// <param name="spot"></param>
        /// <param name="strike"></param>
        /// <param name="sig"></param>
        /// <param name="dexp"></param>
        /// <param name="sPay"></param>
        /// <param name="sStyle"></param>
        /// <param name="nGrid"></param>
        /// <param name="tStep"></param>
        /// <param name="iNum"></param>
        /// <param name="divamsAsArray"></param>
        /// <param name="divdatesAsArray"></param>
        /// <param name="zeramsAsArray"></param>
        /// <param name="zerdatesAsArray"></param>
        /// <returns></returns>
        public double GetEquityGreeks(DateTime today,
                                      double spot,
                                      double strike,
                                      double sig,
                                      DateTime dexp,
                                      string sPay,
                                      string sStyle,
                                      int nGrid,
                                      double tStep,
                                      int iNum,
                                      Excel.Range divamsAsArray,
                                      Excel.Range divdatesAsArray,
                                      Excel.Range zeramsAsArray,
                                      Excel.Range zerdatesAsArray
                                      )
        {
            //Map the ranges
            var divams   = DataRangeHelper.StripDoubleRange(divamsAsArray);
            var divdates = DataRangeHelper.StripDateTimeRange(divamsAsArray);
            var zerams   = DataRangeHelper.StripDoubleRange(zeramsAsArray);
            var zerdates = DataRangeHelper.StripDateTimeRange(zerdatesAsArray);
            //set up the DivList
            int nd    = divdates.Count; //GetUpperBound(0) + 1;
            var myDiv = new DivList {
                Divpoints = nd
            };

            myDiv.MakeArrays();
            for (int idx = 0; idx != nd; idx++)
            {
                double   r  = divams[idx];
                DateTime dp = divdates[idx];
                TimeSpan ts = dp - today;
                myDiv.SetD(idx, r, ts.Days / 365.0);
            }
            //set up the zero
            int nz     = zerdates.Count;//GetUpperBound(0) + 1;
            var myZero = new ZeroCurve {
                Ratepoints = nz
            };

            myZero.MakeArrays();
            for (int idx = 0; idx != nz; idx++)
            {
                double   r  = zerams[idx];
                DateTime dp = zerdates[idx];
                TimeSpan ts = dp - today;
                myZero.SetR(idx, r, ts.Days / 365.0);
            }
            //compute the discounted dividends to  expiry and work out continuous
            TimeSpan tsE  = dexp - today;
            double   texp = tsE.Days / 365.0;

            for (int idx = 0; idx != nd; idx++)
            {
                if (myDiv.GetT(idx) <= texp)
                {
                    double d = myDiv.GetD(idx) * Math.Exp(-myDiv.GetT(idx) * myZero.LinInterp(myDiv.GetT(idx)));
                }
            }
            //double qc = -Math.Log((spot - sum) / spot) / texp;
            //double rc = myZero.linInterp(texp);
            var myG = new Grid
            {
                XL     = Math.Log(spot) - 8.0 * sig * Math.Sqrt(texp),
                Xu     = Math.Log(spot) + 8.0 * sig * Math.Sqrt(texp),
                Steps  = nGrid,
                Strike = strike,
                Spot   = spot,
                SPay   = sPay,
                SStyle = sStyle,
                T      = texp
            };

            myG.NTsteps = Convert.ToInt32(myG.T / tStep);
            myG.Sig     = sig;
            var    greeks = new double[4];
            double price  = myG.Pricer(myZero, myDiv, ref greeks, true);

            myG.Sig += 0.01;
            double priceUp = myG.Pricer(myZero, myDiv, ref greeks, false);

            greeks[3] = priceUp - price;
            return(greeks[iNum]);
        }
Ejemplo n.º 15
0
        /// <summary>
        /// main pricer
        /// </summary>
        /// <param name="myZero"></param>
        /// <param name="myDiv"></param>
        /// <param name="greeks"></param>
        /// <param name="bGreeks"></param>
        /// <returns></returns>
        public double Pricer(ZeroCurve myZero, DivList myDiv, ref double[] greeks, bool bGreeks)
        {
            _x = new List <double>();
            _v = new List <double>();

            double tTemp = T;     //real time
            double tau   = 0.0;   //backward time

            double dtnom   = T / (double)NTsteps;
            double dt      = dtnom;
            double tempInt = 0.0;

            //start the pricer

            CreateGrid();
            TerminalCondition();

            while (tau < T)
            {
                //set the increment
                double t1 = tTemp - dtnom;
                t1 = (t1 >= 0.0) ? t1 : 0.0;  //make sure t1 >= 0.0
                double divPay = 0.0;
                dt = CheckBetweenDiv(t1, tTemp, ref divPay, myDiv);


                //compute the real time and backward time tau
                tTemp -= dt;
                tau    = T - tTemp;

                //compute the increment forward rate
                _domR = myZero.ForwardRate(tTemp, tTemp + dt);
                _forR = 0.0;

                //compute the forward rate from real time tTemp to expiry for the BC'c
                double domRbc = myZero.ForwardRate(tTemp, T);

                //compute discounted dividends for the bc's
                double DiscDiv = ComputeDiscDiv(tTemp, T, myZero, myDiv);

                //save the value at the spot for use in theta calcuation
                int    nKeyInt = (int)((Math.Log(Spot) - XL) / _dx);
                double fracInt = (Math.Log(Spot) - _x[nKeyInt]) / (_x[nKeyInt + 1] - _x[nKeyInt]);
                tempInt = _v[nKeyInt] * (1.0 - fracInt) + _v[nKeyInt + 1] * fracInt;


                //get the fwd
                _lnfwd = Math.Log(GetATMfwd(myZero, myDiv, tTemp));

                //build the matrix
                OneStepSetUp(dt, tTemp);

                //compute the q vec
                MakeQVec();


                if (SStyle.ToUpper().Equals("E"))
                {
                    // set the exlicit BC
                    _v[0]         = MakeLowerBC(tau, Math.Exp(_x[0]), domRbc, DiscDiv);
                    _v[Steps - 1] = MakeUpperBC(tau, Math.Exp(_x[Steps - 1]), domRbc, DiscDiv);
                    SORmethod();

                    //subract from q(1) and q(_steps-2) for explicit BC
                    //'_q[1] -= _SubDiagL[0] * _v[0];
                    //'_q[_msteps - 1] -= _SuperDiagL[_steps - 1] * _v[_steps - 1];

                    //this commented out info is used for the zero curvature condition
                    //_DiagL[1] += 2.0 * _SubDiagL[1];
                    //_SuperDiagL[1] -= _SubDiagL[1];
                    //_DiagL[_steps - 2] += 2.0 * _SuperDiagL[_steps - 2];
                    //_SubDiagL[_steps - 2] -= _SuperDiagL[_steps - 2];

                    //call LU decomp
                    //LUDecomp();
                    //Call the LU sOlver
                    //LUSolution();

                    //for zero curvature
                    //_v[0] = 2.0 * _v[1] - _v[2];
                    //_v[_steps - 1] = 2.0 * _v[_steps - 2] - _v[_steps - 3];
                }
                else
                {
                    _v[0]         = MakeLowerBC(tau, Math.Exp(_x[0]), domRbc, DiscDiv);
                    _v[Steps - 1] = MakeUpperBC(tau, Math.Exp(_x[Steps - 1]), domRbc, DiscDiv);
                    SORmethod();
                }

                //after having incremented back,  apply a grid shift if needed
                if (divPay != 0.0)
                {
                    ApplyGridShift(tau, divPay, domRbc, DiscDiv);
                }
            }

            int    nKey = (int)((Math.Log(Spot) - XL) / _dx);
            double frac = (Math.Log(Spot) - _x[nKey]) / (_x[nKey + 1] - _x[nKey]);
            double temp = _v[nKey] * (1.0 - frac) + _v[nKey + 1] * frac;

            if (bGreeks)
            {
                double[,] a = new double[4, 4];
                double[] b = new double[4];

                a[0, 0] = 1.0;
                a[1, 0] = 1.0;
                a[2, 0] = 1.0;
                a[3, 0] = 1.0;

                a[0, 1] = Math.Exp(_x[nKey - 1]);
                a[1, 1] = Math.Exp(_x[nKey]);
                a[2, 1] = Math.Exp(_x[nKey + 1]);
                a[3, 1] = Math.Exp(_x[nKey + 2]);

                a[0, 2] = Math.Exp(_x[nKey - 1]) * Math.Exp(_x[nKey - 1]);
                a[1, 2] = Math.Exp(_x[nKey]) * Math.Exp(_x[nKey]);
                a[2, 2] = Math.Exp(_x[nKey + 1]) * Math.Exp(_x[nKey + 1]);
                a[3, 2] = Math.Exp(_x[nKey + 2]) * Math.Exp(_x[nKey + 1]);

                a[0, 3] = Math.Exp(_x[nKey - 1]) * Math.Exp(_x[nKey - 1]) * Math.Exp(_x[nKey - 1]);
                a[1, 3] = Math.Exp(_x[nKey]) * Math.Exp(_x[nKey]) * Math.Exp(_x[nKey]);
                a[2, 3] = Math.Exp(_x[nKey + 1]) * Math.Exp(_x[nKey + 1]) * Math.Exp(_x[nKey + 1]);
                a[3, 3] = Math.Exp(_x[nKey + 2]) * Math.Exp(_x[nKey + 2]) * Math.Exp(_x[nKey + 2]);

                b[0] = _v[nKey - 1];
                b[1] = _v[nKey];
                b[2] = _v[nKey + 1];
                b[3] = _v[nKey + 2];


                int info = NewtonGauss(4, ref a, ref b);

                greeks[0] = b[1] + 2.0 * b[2] * Spot + 3.0 * b[3] * Spot * Spot;
                greeks[1] = 2.0 * b[2] + 6.0 * b[3] * Spot;
                greeks[2] = (tempInt - temp) / (365.0 * dt);

                /*
                 * nKey = (int)((Math.Log(_spot) * 1.001 - _xl) / _dx);
                 * frac = (Math.Log(_spot )* 1.001 - _x[nKey]) / (_x[nKey + 1] - _x[nKey]);
                 * double tempUp = _v[nKey] * (1.0 - frac) + _v[nKey + 1] * frac;
                 *
                 * nKey = (int)((Math.Log(_spot) * 0.999 - _xl) / _dx);
                 * frac = (Math.Log(_spot) * 0.999 - _x[nKey]) / (_x[nKey + 1] - _x[nKey]);
                 * double tempDn = _v[nKey] * (1.0 - frac) + _v[nKey + 1] * frac;
                 *
                 * greeks[0] = (tempUp - tempDn) / (0.002 *Math.Log(spot))/spot ;
                 * greeks[1] = (tempUp + tempDn - 2.0 * temp) / Math.Pow(0.001 * _spot * Math.Log(_spot), 2.0) - greeks[0]/_spot;
                 * greeks[2] = (tempInt - temp) / (365.0 * dt);
                 */
            }


            return(temp);
        }