예제 #1
0
        public void DoTestBiNormalCdfWest(double x, double y, double rho)
        {
            var A = NormalCdf.NormalCdfGenz(x, y, rho);
            var B = NormalCdf.NormalBiCdfWest(x, y, rho);

            Assert.AreEqual(A, B, 1e-8);
        }
예제 #2
0
            //West on wilmott
            private double WestBestOfAssetsOrCash(double S1, double S2, double T, double r, double b1, double b2, double sigma1, double sigma2, double rho)
            {
                WestModel(S1, S2, T, r, b1, b2, sigma1, sigma2, rho,
                          out double d1, out double d1_, out double d2, out double d2_, out double rho1, out double rho2,
                          out double d21, out double d12, out double q1, out double q2);

                return(S1 * Math.Exp(-q1 * T) * NormalCdf.NormalCdfGenz(-d21, d1, rho1)
                       + S2 * Math.Exp(-q2 * T) * NormalCdf.NormalCdfGenz(-d12, d2, rho2)
                       + _X1 * Math.Exp(-r * T) * NormalCdf.NormalCdfGenz(-d1_, -d2_, rho));
            }
예제 #3
0
            private double CalcPV(double S1, double S2, double T, double r, double b1, double b2, double sigma1, double sigma2, double rho)
            {
                //for two asset cash or nothing option
                var d11 = (Math.Log(S1 / _X1) + (b1 - sigma1 * sigma1 * 0.5) * T) / sigma1 / Math.Sqrt(T);
                var d22 = (Math.Log(S2 / _X2) + (b2 - sigma2 * sigma2 * 0.5) * T) / sigma2 / Math.Sqrt(T);

                switch (_rainbowType)
                {
                //Haug
                case RainbowType.TwoAssetsCashOrNothing:
                    return((_optionType == OptionType.Call) ?
                           _K * Math.Exp(-r * T) * NormalCdf.NormalCdfGenz(d11, d22, rho) :
                           _K *Math.Exp(-r *T) * NormalCdf.NormalCdfGenz(-d11, -d22, rho));

                case RainbowType.TwoAssetsCashOrNothingUpDown:
                    return(_K * Math.Exp(-r * T) * NormalCdf.NormalCdfGenz(d11, -d22, -rho));

                case RainbowType.TwoAssetsCashOrNothingDownUp:
                    return(_K * Math.Exp(-r * T) * NormalCdf.NormalCdfGenz(-d11, d22, -rho));

                case RainbowType.BestCashOrNothing:
                case RainbowType.WorstCashOrNothing:
                    return(BestOrWorst(S1, S2, T, r, b1, b2, sigma1, sigma2, rho));

                //west
                case RainbowType.BestOfAssetsOrCash:
                    return(WestBestOfAssetsOrCash(S1, S2, T, r, b1, b2, sigma1, sigma2, rho));

                case RainbowType.Min:
                case RainbowType.Max:
                    if (_optionType == OptionType.Call)
                    {
                        return(WestRainbowCall(S1, S2, T, r, b1, b2, sigma1, sigma2, rho));
                    }
                    else
                    {       //put,  use put/call parity to price
                        double q1  = r - b1;
                        double q2  = r - b2;
                        var    vol = Math.Sqrt(sigma1 * sigma1 + sigma2 * sigma2 - 2.0 * rho * sigma1 * sigma2);
                        var    d21 = (Math.Log(S2 / S1) + (q1 - q2 - 0.5 * vol * vol) * T) / vol / Math.Sqrt(T);
                        var    d12 = (Math.Log(S1 / S2) + (q2 - q1 - 0.5 * vol * vol) * T) / vol / Math.Sqrt(T);

                        var VC0max = S1 * Math.Exp(-q1 * T) * NormalCdf.NormalCdfHart(-d21) + S2 * Math.Exp(-q2 * T) * NormalCdf.NormalCdfHart(-d12);
                        var VC0min = S1 * Math.Exp(-q1 * T) * NormalCdf.NormalCdfHart(d21) + S2 * Math.Exp(-q2 * T) * NormalCdf.NormalCdfHart(d12);

                        return((_rainbowType == RainbowType.Max) ?
                               WestRainbowCall(S1, S2, T, r, b1, b2, sigma1, sigma2, rho) - VC0max + _X1 * Math.Exp(-r * T) :
                               WestRainbowCall(S1, S2, T, r, b1, b2, sigma1, sigma2, rho) - VC0min + _X1 * Math.Exp(-r * T));
                    }

                default:
                    throw new PricingLibraryException("Unsupported rainbow option type");
                }
            }
예제 #4
0
            //West on wilmott
            private double WestRainbowCall(double S1, double S2, double T, double r, double b1, double b2, double sigma1, double sigma2, double rho)
            {
                WestModel(S1, S2, T, r, b1, b2, sigma1, sigma2, rho,
                          out double d1, out double d1_, out double d2, out double d2_, out double rho1, out double rho2,
                          out double d21, out double d12, out double q1, out double q2);

                return((_rainbowType == RainbowType.Max) ?
                       S1 * Math.Exp(-q1 * T) * NormalCdf.NormalCdfGenz(-d21, d1, rho1)
                       + S2 * Math.Exp(-q2 * T) * NormalCdf.NormalCdfGenz(-d12, d2, rho2)
                       - _X1 * Math.Exp(-r * T) * (1 - NormalCdf.NormalCdfGenz(-d1_, -d2_, rho)) :

                       S1 *Math.Exp(-q1 *T) * NormalCdf.NormalCdfGenz(d21, d1, -rho1)
                       + S2 * Math.Exp(-q2 * T) * NormalCdf.NormalCdfGenz(d12, d2, -rho2)
                       - _X1 * Math.Exp(-r * T) * NormalCdf.NormalCdfGenz(d1_, d2_, rho));
            }
        private double Ksi(double S, double T, double gamma, double h, double i2, double i1, double t1, double r, double b, double sigma)
        {
            double e1 = (Math.Log(S / i1) + (b + (gamma - 0.5) * sigma * sigma) * t1) / sigma / Math.Sqrt(t1);
            double e2 = (Math.Log(i2 * i2 / S / i1) + (b + (gamma - 0.5) * sigma * sigma) * t1) / sigma / Math.Sqrt(t1);
            double e3 = (Math.Log(S / i1) - (b + (gamma - 0.5) * sigma * sigma) * t1) / sigma / Math.Sqrt(t1);
            double e4 = (Math.Log(i2 * i2 / S / i1) - (b + (gamma - 0.5) * sigma * sigma) * t1) / sigma / Math.Sqrt(t1);

            double f1 = (Math.Log(S / h) + (b + (gamma - 0.5) * sigma * sigma) * T) / sigma / Math.Sqrt(T);
            double f2 = (Math.Log(i2 * i2 / S / h) + (b + (gamma - 0.5) * sigma * sigma) * T) / sigma / Math.Sqrt(T);
            double f3 = (Math.Log(i1 * i1 / S / h) + (b + (gamma - 0.5) * sigma * sigma) * T) / sigma / Math.Sqrt(T);
            double f4 = (Math.Log(S * i1 * i1 / i2 / i2 / h) + (b + (gamma - 0.5) * sigma * sigma) * T) / sigma / Math.Sqrt(T);

            double rho    = Math.Sqrt(t1 / T);
            double lambda = -r + gamma * b + 0.5 * gamma * (gamma - 1) * sigma * sigma;
            double kappa  = 2 * b / sigma / sigma + (2 * gamma - 1);
            double ksi    = Math.Exp(lambda * T) * Math.Pow(S, gamma) * (NormalCdf.NormalCdfGenz(-e1, -f1, rho)
                                                                         - Math.Pow(i2 / S, kappa) * NormalCdf.NormalCdfGenz(-e2, -f2, rho) - Math.Pow(i1 / S, kappa) * NormalCdf.NormalCdfGenz(-e3, -f3, -rho)
                                                                         + Math.Pow(i1 / i2, kappa) * NormalCdf.NormalCdfGenz(-e4, -f4, -rho));

            return(ksi);
        }
예제 #6
0
            //Haug 2007
            private double BestOrWorst(double S1, double S2, double T, double r, double b1, double b2, double sigma1, double sigma2, double rho)
            {
                double vol  = Math.Sqrt(sigma1 * sigma1 + sigma2 * sigma2 - 2.0 * rho * sigma1 * sigma2);
                double y    = 1.0 / vol / Math.Sqrt(T) * (Math.Log(S1 / S2) + T * (b1 - b2 + vol * vol / 2.0));
                double z1   = 1.0 / sigma1 / Math.Sqrt(T) * (Math.Log(S1 / _X1) + T * (b1 + sigma1 * sigma1 / 2.0));
                double z2   = 1.0 / sigma2 / Math.Sqrt(T) * (Math.Log(S2 / _X1) + T * (b2 + sigma2 * sigma2 / 2.0));
                double rho1 = (sigma1 - sigma2 * rho) / vol;
                double rho2 = (sigma2 - rho * sigma1) / vol;
                double pv   = 0;

                if (_rainbowType == RainbowType.BestCashOrNothing)
                {
                    pv = (_optionType == OptionType.Call) ?
                         _K * _notional * Math.Exp(-r * T) * (NormalCdf.NormalCdfGenz(y, z1, -rho1) + NormalCdf.NormalCdfGenz(-y, z2, -rho2)) :
                         _K *_notional *Math.Exp(-r *T) * (1 - NormalCdf.NormalCdfGenz(y, z1, -rho1) - NormalCdf.NormalCdfGenz(-y, z2, -rho2));
                }
                if (_rainbowType == RainbowType.WorstCashOrNothing)
                {
                    pv = (_optionType == OptionType.Call) ?
                         _K * _notional * Math.Exp(-r * T) * (NormalCdf.NormalCdfGenz(-y, z1, rho1) + NormalCdf.NormalCdfGenz(y, z2, rho2)) :
                         _K *_notional *Math.Exp(-r *T) * (1 - NormalCdf.NormalCdfGenz(-y, z1, rho1) + NormalCdf.NormalCdfGenz(y, z2, rho2));
                }
                return(pv);
            }
예제 #7
0
            //Haug 2007: Chapter 4.9 & 4.10
            //Payoff: max((S-X)/X,0) or max(S-X,0)
            private double CalcPV(double S, double T, double r, double b, double sigma, double t)
            {
                double rho = Math.Sqrt(t / T);
                double a1  = (Math.Log(S / _X) + (b + sigma * sigma * 0.5) * t) / sigma / Math.Sqrt(t);
                double a2  = a1 - sigma * Math.Sqrt(t);
                double z1  = (b + sigma * sigma * 0.5) * (T - t) / sigma / Math.Sqrt(T - t);
                double z2  = z1 - sigma * Math.Sqrt(T - t);
                double y1  = (Math.Log(S / _X) + (b + sigma * sigma * 0.5) * T) / sigma / Math.Sqrt(T);
                double y2  = y1 - sigma * Math.Sqrt(T);

                double C1 = Math.Exp((b - r) * (T - t)) * NormalCdf.NormalCdfHart(-a2) * NormalCdf.NormalCdfHart(z1) * Math.Exp(-r * t)
                            - Math.Exp(-r * T) * NormalCdf.NormalCdfHart(-a2) * NormalCdf.NormalCdfHart(z2) - Math.Exp(-r * T) * NormalCdf.NormalCdfGenz(a2, y2, rho)
                            + (S / _X) * Math.Exp((b - r) * T) * NormalCdf.NormalCdfGenz(a1, y1, rho);

                double P1 = -Math.Exp((b - r) * (T - t)) * NormalCdf.NormalCdfHart(a2) * NormalCdf.NormalCdfHart(-z1) * Math.Exp(-r * t)
                            + Math.Exp(-r * T) * NormalCdf.NormalCdfHart(a2) * NormalCdf.NormalCdfHart(-z2) + Math.Exp(-r * T) * NormalCdf.NormalCdfGenz(-a2, -y2, rho)
                            - (S / _X) * Math.Exp((b - r) * T) * NormalCdf.NormalCdfGenz(-a1, -y1, rho);

                double C2 = S * Math.Exp((b - r) * T) * NormalCdf.NormalCdfGenz(a1, y1, rho) - _X * Math.Exp(-r * T) * NormalCdf.NormalCdfGenz(a2, y2, rho)
                            - S * Math.Exp((b - r) * t) * NormalCdf.NormalCdfHart(-a1) * NormalCdf.NormalCdfHart(z2) * Math.Exp(-r * (T - t)) + S * Math.Exp((b - r) * T) * NormalCdf.NormalCdfHart(-a1) * NormalCdf.NormalCdfHart(z1);

                double P2 = -S *Math.Exp((b - r) *T) * NormalCdf.NormalCdfGenz(-a1, -y1, rho) + _X * Math.Exp(-r * T) * NormalCdf.NormalCdfGenz(-a2, -y2, rho)
                            + S * Math.Exp((b - r) * t) * NormalCdf.NormalCdfHart(a1) * NormalCdf.NormalCdfHart(-z2) * Math.Exp(-r * (T - t)) - S * Math.Exp((b - r) * T) * NormalCdf.NormalCdfHart(a1) * NormalCdf.NormalCdfHart(-z1);

                switch (_resetstrikeType)
                {
                case ResetStrikeType.PercentagePayoff:
                    return((_optionType == OptionType.Call) ? _notional * C1 : _notional *P1);

                case ResetStrikeType.NormalPayoff:
                    return((_optionType == OptionType.Call) ? _notional * C2 : _notional *P2);

                default:
                    throw new PricingLibraryException("Unsupported reset strike option type");
                }
            }
예제 #8
0
        public void DoTestNormalCdfGenz(double x, double y, double rho, double actual)
        {
            var A = NormalCdf.NormalCdfGenz(x, y, rho);

            Assert.AreEqual(A, actual, 1e-8);
        }