public virtual void test_optionPrice()
        {
            double tol = 1.0e-12;
            EuropeanVanillaOptionFunction test = EuropeanVanillaOptionFunction.of(STRIKE, TIME_TO_EXPIRY, PutCall.PUT, NUM);
            double spot = 100d;
            double u    = 1.05;
            double d    = 0.98;
            double m    = Math.Sqrt(u * d);
            double up   = 0.29;
            double dp   = 0.25;
            double mp   = 1d - up - dp;
            // test getPayoffAtExpiryTrinomial
            DoubleArray computedPayoff = test.getPayoffAtExpiryTrinomial(spot, d, m);
            int         expectedSize   = 2 * NUM + 1;

            assertEquals(computedPayoff.size(), expectedSize);
            for (int i = 0; i < expectedSize; ++i)
            {
                double price          = spot * Math.Pow(u, 0.5 * i) * Math.Pow(d, NUM - 0.5 * i);
                double expectedPayoff = Math.Max(STRIKE - price, 0d);
                assertEquals(computedPayoff.get(i), expectedPayoff, tol);
            }
            // test getNextOptionValues
            double      df                 = 0.92;
            int         n                  = 2;
            DoubleArray values             = DoubleArray.of(1.4, 0.9, 0.1, 0.05, 0.0, 0.0, 0.0);
            DoubleArray computedNextValues = test.getNextOptionValues(df, up, mp, dp, values, spot, d, m, n);
            DoubleArray expectedNextValues = DoubleArray.of(df * (1.4 * dp + 0.9 * mp + 0.1 * up), df * (0.9 * dp + 0.1 * mp + 0.05 * up), df * (0.1 * dp + 0.05 * mp), df * 0.05 * dp, 0.0);

            assertTrue(DoubleArrayMath.fuzzyEquals(computedNextValues.toArray(), expectedNextValues.toArray(), tol));
        }
        public virtual void test_trinomialTree()
        {
            int nSteps = 135;

            LatticeSpecification[] lattices = new LatticeSpecification[]
            {
                new CoxRossRubinsteinLatticeSpecification(),
                new TrigeorgisLatticeSpecification()
            };
            double tol = 5.0e-3;

            foreach (bool isCall in new bool[] { true, false })
            {
                foreach (double strike in STRIKES)
                {
                    foreach (double interest in INTERESTS)
                    {
                        foreach (double vol in VOLS)
                        {
                            foreach (double dividend in DIVIDENDS)
                            {
                                OptionFunction function = EuropeanVanillaOptionFunction.of(strike, TIME, PutCall.ofPut(!isCall), nSteps);
                                double         exact    = BlackScholesFormulaRepository.price(SPOT, strike, TIME, vol, interest, interest - dividend, isCall);
                                foreach (LatticeSpecification lattice in lattices)
                                {
                                    double computed = TRINOMIAL_TREE.optionPrice(function, lattice, SPOT, vol, interest, dividend);
                                    assertEquals(computed, exact, Math.Max(exact, 1d) * tol);
                                }
                            }
                        }
                    }
                }
            }
        }
        public virtual void test_of()
        {
            EuropeanVanillaOptionFunction test = EuropeanVanillaOptionFunction.of(STRIKE, TIME_TO_EXPIRY, PutCall.PUT, NUM);

            assertEquals(test.Sign, -1d);
            assertEquals(test.Strike, STRIKE);
            assertEquals(test.TimeToExpiry, TIME_TO_EXPIRY);
            assertEquals(test.NumberOfSteps, NUM);
        }
예제 #4
0
 //-----------------------------------------------------------------------
 public override bool Equals(object obj)
 {
     if (obj == this)
     {
         return(true);
     }
     if (obj != null && obj.GetType() == this.GetType())
     {
         EuropeanVanillaOptionFunction other = (EuropeanVanillaOptionFunction)obj;
         return(JodaBeanUtils.equal(strike, other.strike) && JodaBeanUtils.equal(timeToExpiry, other.timeToExpiry) && JodaBeanUtils.equal(sign, other.sign) && (numberOfSteps == other.numberOfSteps));
     }
     return(false);
 }
예제 #5
0
        /// <summary>
        /// Test consistency between price methods, and Greek via finite difference.
        /// </summary>
        public virtual void test_trinomialTree()
        {
            int    nSteps = 135;
            double dt     = TIME / nSteps;
            LatticeSpecification lattice = new CoxRossRubinsteinLatticeSpecification();
            double fdEps = 1.0e-4;

            foreach (bool isCall in new bool[] { true, false })
            {
                foreach (double strike in STRIKES)
                {
                    foreach (double interest in INTERESTS)
                    {
                        foreach (double vol in VOLS)
                        {
                            foreach (double dividend in DIVIDENDS)
                            {
                                OptionFunction function   = EuropeanVanillaOptionFunction.of(strike, TIME, PutCall.ofPut(!isCall), nSteps);
                                double[]       @params    = lattice.getParametersTrinomial(vol, interest - dividend, dt).toArray();
                                DoubleArray    time       = DoubleArray.of(nSteps + 1, i => dt * i);
                                DoubleArray    df         = DoubleArray.of(nSteps, i => Math.Exp(-interest * dt));
                                double[][]     stateValue = new double[nSteps + 1][];
                                stateValue[0] = new double[] { SPOT };
                                IList <DoubleMatrix> prob  = new List <DoubleMatrix>();
                                double[]             probs = new double[] { @params[5], @params[4], @params[3] };
                                for (int i = 0; i < nSteps; ++i)
                                {
                                    int index = i;
                                    stateValue[i + 1] = DoubleArray.of(2 * i + 3, j => SPOT * Math.Pow(@params[2], index + 1 - j) * Math.Pow(@params[1], j)).toArray();
                                    double[][] probMatrix = new double[2 * i + 1][];
                                    Arrays.fill(probMatrix, probs);
                                    prob.Add(DoubleMatrix.ofUnsafe(probMatrix));
                                }
                                RecombiningTrinomialTreeData treeData = RecombiningTrinomialTreeData.of(DoubleMatrix.ofUnsafe(stateValue), prob, df, time);
                                double priceData   = TRINOMIAL_TREE.optionPrice(function, treeData);
                                double priceParams = TRINOMIAL_TREE.optionPrice(function, lattice, SPOT, vol, interest, dividend);
                                assertEquals(priceData, priceParams);
                                ValueDerivatives priceDeriv = TRINOMIAL_TREE.optionPriceAdjoint(function, treeData);
                                assertEquals(priceDeriv.Value, priceData);
                                double priceUp = TRINOMIAL_TREE.optionPrice(function, lattice, SPOT + fdEps, vol, interest, dividend);
                                double priceDw = TRINOMIAL_TREE.optionPrice(function, lattice, SPOT - fdEps, vol, interest, dividend);
                                double fdDelta = 0.5 * (priceUp - priceDw) / fdEps;
                                assertEquals(priceDeriv.getDerivative(0), fdDelta, 3.0e-2);
                            }
                        }
                    }
                }
            }
        }