Beispiel #1
0
 public static object AmericanFutureOptionImpliedVol(
     [ExcelArgument(Description = "Time-to-expiry")] double T,
     [ExcelArgument(Description = "Strike")] double K,
     [ExcelArgument(Description = "Forward")] double F,
     [ExcelArgument(Description = "Discounting rate")] double R,
     [ExcelArgument(Description = "Option Premium")] double PV,
     [ExcelArgument(Description = "Call or Put")] string CP,
     [ExcelArgument(Description = "Pricing method (Defult Trinomial)")] string Method)
 {
     return(ExcelHelper.Execute(_logger, () =>
     {
         if (!Enum.TryParse(CP, out OptionType optType))
         {
             return $"Could not parse call or put flag - {CP}";
         }
         if (!Enum.TryParse(Method, out AmericanPricingType method))
         {
             return $"Could not parse pricing type - {Method}";
         }
         if (method == AmericanPricingType.Binomial)
         {
             return BinomialTree.AmericanFuturesOptionImpliedVol(F, K, R, T, PV, optType);
         }
         else
         {
             return TrinomialTree.AmericanFuturesOptionImpliedVol(F, K, R, T, PV, optType);
         }
     }));
 }
Beispiel #2
0
        private static void Execute(Options options)
        {
            var model  = new BinomialTree(options.S0, options.NbTimes, options.T, options.Sigma, options.R, options.NbSimus);
            var QSpace = options.CreateQSpace();

            var distrCalc = new DistributionCalculator(model, QSpace, options.Q0, -0.15, +0.15, 5, 0.05, 0.5, 5);

            distrCalc.Calculate();

            //Func<double, double> drift = t => 0.05 - .02 * t + .03 * Math.Sin(4.0 * Math.PI * t);
            //var model = new BinomialTreeWithDrift(options.S0, options.NbTimes, options.T,
            //options.Sigma, options.R, options.NbSimus, drift);

            //Func<double, double> deterministicPath = t => 2.0 - .5 * t + .25 * Math.Sin(4.0 * Math.PI * t);
            //var model = new DeterministicPath(deterministicPath, 100, 1.0);

            /*
             * model.Simulate();
             *
             * var QSpace = options.CreateQSpace();
             *
             * var optimalController = new OptimalController(model, QSpace);
             * optimalController.Control();
             *
             * var qSteps = optimalController.RollOut(0, options.Q0);
             *
             * FileWriter.WriteToFile(qSteps, "q_Steps.csv");
             */
        }
    /// <summary>
    /// Merges two binomial trees together by simply adding the tree whose root
    /// value is largest as a subtree of the other tree's root.
    /// </summary>
    /// <remarks>
    /// Complexity: O(1)
    /// </remarks>
    /// <param name="a">First binomial tree.</param>
    /// <param name="b">Second binomial tree.</param>
    /// <returns>The merged binomial tree.</returns>
    public static BinomialTree <T> Merge(BinomialTree <T> a, BinomialTree <T> b)
    {
        BinomialTree <T> mergedTree = new BinomialTree <T>();

        if ((null == a) || (null == b))
        {
            //-- If one of the trees is null, attempt to return the one
            //   that isn't null if any
            if (null != a)
            {
                mergedTree.AddSubTree(a);
            }
            else if (null != b)
            {
                mergedTree.AddSubTree(b);
            }

            return(mergedTree);
        }

        //-- If both trees are valid...
        if (a.Root.CompareTo(b.Root) <= 0)
        {
            //-- a's root wins, add b to it
            return(a.AddSubTree(b));
        }
        else
        {
            //-- b's root wins, add a to it
            return(b.AddSubTree(a));
        }
    }
Beispiel #4
0
    static void TestBinomialTree()
    {
        Console.Out.WriteLine("BINOMIAL TREES");
        Console.Out.WriteLine();

        //-- Create a list of elements
        List <int> elements = new List <int>(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 });

        //-- Suffle the elements into an array
        int[] shuffledElements = new int[elements.Count];
        for (int i = 0; i < shuffledElements.Length; ++i)
        {
            int nextElementIndex = rand.Next(0, elements.Count);
            shuffledElements[i] = elements.ElementAt(nextElementIndex);
            elements.RemoveAt(nextElementIndex);
        }

        //-- Print the shuffled elements
        Console.Out.WriteLine("Element Set:");
        foreach (int element in shuffledElements)
        {
            Console.Out.Write(element + " ");
        }
        Console.Out.WriteLine("\n");

        //-- Create a large binomial tree with all of the elements
        BinomialTree <int> resultingTree = TestBinomialTree(shuffledElements, 0, shuffledElements.Length - 1);

        //-- Print the result
        Console.Out.WriteLine("Result:");
        resultingTree.Print();
        Console.Out.WriteLine();
    }
        public DistributionCalculator(BinomialTree model, QSpace qSpace, double q0, double rMin,
                                      double rMax, int nbStepsR, double sigmaMin, double sigmaMax, int nbStepsSigma)
        {
            m_model        = model;
            m_qSpace       = qSpace;
            m_q0           = q0;
            m_nbStepsR     = nbStepsR;
            m_nbStepsSigma = nbStepsSigma;

            m_configurationSpace = new Tuple <double, double> [nbStepsR][];

            var deltaR     = (rMax - rMin) / m_nbStepsR;
            var deltaSigma = (sigmaMax - sigmaMin) / m_nbStepsSigma;

            for (int iR = 0; iR < m_nbStepsR; iR++)
            {
                m_configurationSpace[iR] = new Tuple <double, double> [m_nbStepsSigma];

                for (int jSigma = 0; jSigma < m_nbStepsSigma; jSigma++)
                {
                    m_configurationSpace[iR][jSigma] = new Tuple <double, double>(rMin + iR * deltaR, sigmaMin + jSigma * deltaSigma);
                }
            }

            m_results = new Tuple <double, double> [m_nbStepsR][];

            for (int iR = 0; iR < m_nbStepsR; iR++)
            {
                m_results[iR] = new Tuple <double, double> [m_nbStepsSigma];
            }
        }
Beispiel #6
0
 public BinomialTreeWithNoDividend(BinomialTree binomialTree, IOption option,
                                   int steps, double tExStart, double tExEnd)
 {
     _binomialTree = binomialTree;
     _option       = option;
     _steps        = steps;
     _tExStart     = tExStart;
     _tExEnd       = tExEnd;
 }
Beispiel #7
0
        public void PVFacts()
        {
            var t   = 1.0;
            var k   = 0;
            var f   = 100;
            var vol = 0.32;
            var rf  = 0.05;
            var cp  = OptionType.P;
            var df  = System.Math.Exp(-rf * t);

            //zero strike put is worthless
            var PV = BinomialTree.AmericanFutureOptionPV(f, k, rf, t, vol, cp);

            Assert.Equal(0, PV, 10);
            PV = TrinomialTree.AmericanFutureOptionPV(f, k, rf, t, vol, cp);
            Assert.Equal(0, PV, 10);

            //zero strike call is worth fwd with no discounting
            cp = OptionType.C;
            PV = BinomialTree.AmericanFutureOptionPV(f, k, rf, t, vol, cp);
            Assert.Equal(f, PV, 10);
            PV = TrinomialTree.AmericanFutureOptionPV(f, k, rf, t, vol, cp);
            Assert.Equal(f, PV, 10);

            //and has delta = 1.0
            var greeks = TrinomialTree.AmericanFutureOption(f, k, rf, t, vol, cp);

            Assert.Equal(1.0, (double)greeks[1, 0], 10);
            greeks = BinomialTree.AmericanFutureOption(f, k, rf, t, vol, cp);
            Assert.Equal(1.0, (double)greeks[1, 0], 10);

            //OTM option with zero vol is worthless
            vol = 0.0;
            k   = f + 1;
            PV  = BinomialTree.AmericanFutureOptionPV(f, k, rf, t, vol, cp);
            Assert.Equal(0, PV, 10);
            PV = TrinomialTree.AmericanFutureOptionPV(f, k, rf, t, vol, cp);
            Assert.Equal(0, PV, 10);

            //option worth >= black in all cases for same inputs
            vol = 0.32;
            k   = f + 20;
            var PVBlack = BlackFunctions.BlackPV(f, k, rf, t, vol, cp);

            PV = BinomialTree.AmericanFutureOptionPV(f, k, rf, t, vol, cp);
            Assert.True(PV >= PVBlack);
            PV = TrinomialTree.AmericanFutureOptionPV(f, k, rf, t, vol, cp);
            Assert.True(PV >= PVBlack);
        }
Beispiel #8
0
        public void PVFacts()
        {
            var t   = 1.0;
            var k   = 0.0;
            var f   = 100.0;
            var vol = 0.32;
            var rf  = 0.05;
            var cp  = OptionType.P;

            //zero strike put is worthless
            var PV = TrinomialTree.AmericanAssetOptionPV(f, k, rf, f, t, vol, cp);

            Assert.Equal(0, PV, 10);
            PV = BinomialTree.AmericanPV(t, f, k, rf, vol, cp, rf, 100);
            Assert.Equal(0, PV, 10);
            var flatInterp    = new DummyPointInterpolator(new[] { 1.0 }, new[] { rf });
            var flatFwdInterp = new DummyPointInterpolator(new[] { 1.0 }, new[] { f });

            PV = TrinomialTree.VanillaPV(t, f, k, flatInterp, vol, cp, flatFwdInterp, 100, true);
            Assert.Equal(0, PV, 10);

            //zero strike call is worth fwd with no discounting
            cp = OptionType.C;
            PV = TrinomialTree.AmericanAssetOptionPV(f, k, rf, f, t, vol, cp);
            Assert.Equal(f, PV, 10);
            PV = BinomialTree.AmericanPV(t, f, k, rf, vol, cp, rf, 100);
            Assert.Equal(f, PV, 10);

            //OTM option with zero vol is worthless
            vol = 0.0;
            k   = f + 1.0;
            PV  = BinomialTree.AmericanPV(t, f, k, rf, vol, cp, rf, 100);
            Assert.Equal(0, PV, 10);
            PV = TrinomialTree.AmericanAssetOptionPV(f, k, rf, f, t, vol, cp);
            Assert.Equal(0, PV, 10);

            //option worth >= black in all cases for same inputs
            vol = 0.32;
            k   = f + 20;
            var PVBlack = BlackFunctions.BlackPV(f, k, rf, t, vol, cp);

            PV = BinomialTree.AmericanPV(t, f, k, rf, vol, cp, rf, 100);
            Assert.True(PV >= PVBlack);
            PV = TrinomialTree.AmericanAssetOptionPV(f, k, rf, f, t, vol, cp);
            Assert.True(PV >= PVBlack);
        }
Beispiel #9
0
    static BinomialTree <int> TestBinomialTree(int[] elements, int start, int end)
    {
        if (start == end)
        {
            //-- Create a new tree of size 1
            BinomialTree <int> newTree = new BinomialTree <int>(elements[start]);
            return(newTree);
        }

        //-- Combine two sub-trees
        int middle = (start + end) / 2;
        BinomialTree <int> intermediateTreeA = TestBinomialTree(elements, start, middle);
        BinomialTree <int> intermediateTreeB = TestBinomialTree(elements, middle + 1, end);
        BinomialTree <int> merger            = BinomialTree <int> .Merge(intermediateTreeA, intermediateTreeB);

        return(merger);
    }
Beispiel #10
0
        public void ImpliedVolFacts()
        {
            var t   = 1.0;
            var k   = 120;
            var f   = 100;
            var vol = 0.32;
            var rf  = 0.05;
            var cp  = OptionType.P;

            var PVbi  = BinomialTree.AmericanFutureOptionPV(f, k, rf, t, vol, cp);
            var PVtri = TrinomialTree.AmericanFutureOptionPV(f, k, rf, t, vol, cp);

            var impliedVolBi  = BinomialTree.AmericanFuturesOptionImpliedVol(f, k, rf, t, PVbi, cp);
            var impliedVolTri = TrinomialTree.AmericanFuturesOptionImpliedVol(f, k, rf, t, PVtri, cp);

            Assert.Equal(vol, impliedVolBi, 10);
            Assert.Equal(vol, impliedVolTri, 10);
        }
        /// <summary>
        /// Добавляет элемент в кучу
        /// </summary>
        /// <param name="data"></param>
        public void Add(T data = default(T))
        {
            // сделаем дерево из одного элемента (порядок = 0)
            BinomialTree <T> binomialTree = new BinomialTree <T>(new Node <T>(0, data)); // хз зачем мне ключ???

            if (binomialTreesList[0] == null)
            {
                binomialTreesList[0] = BinomialTree <T> .Merge(binomialTreesList[0], binomialTree);

                binomialTreesList[0].Order = 0;
            }
            else
            {
                binomialTreesList[0] = BinomialTree <T> .Merge(binomialTreesList[0], binomialTree);

                binomialTreesList[0].Order += 1;

                int currentbinomialTree = 0;
                int nexBinomialTree     = 1;

                while (nexBinomialTree < MAX_SIZE)
                {
                    if (binomialTreesList[nexBinomialTree] == null)  // просто сливаем и не паримся
                    {
                        binomialTreesList[nexBinomialTree] = BinomialTree <T> .Merge(binomialTreesList[nexBinomialTree], binomialTreesList[currentbinomialTree]);

                        binomialTreesList[currentbinomialTree]   = null;
                        binomialTreesList[nexBinomialTree].Order = nexBinomialTree;
                        break;
                    }
                    else    // после слияния, цикл выполнится еще раз, пока не зайдет в пункт выше
                    {
                        binomialTreesList[nexBinomialTree] = BinomialTree <T> .Merge(binomialTreesList[nexBinomialTree], binomialTreesList[currentbinomialTree]);

                        binomialTreesList[currentbinomialTree]   = null;
                        binomialTreesList[nexBinomialTree].Order = nexBinomialTree + 1;
                        currentbinomialTree = nexBinomialTree;
                        nexBinomialTree++;
                    }
                }
            }
        }
Beispiel #12
0
        public void EuropeanOnGridFacts()
        {
            var t   = 1.0;
            var k   = 120;
            var f   = 100;
            var vol = 0.32;
            var rf  = 0.05;
            var cp  = OptionType.P;

            var PVBlack = BlackFunctions.BlackPV(f, k, rf, t, vol, cp);
            var PVbi    = BinomialTree.EuropeanPV(t, f, k, rf, vol, cp, rf, 100);
            var PVtri   = TrinomialTree.EuropeanPV(t, f, k, rf, vol, cp, rf, 100);

            Assert.Equal(PVBlack, PVbi, 1);
            Assert.Equal(PVBlack, PVtri, 1);

            PVbi  = BinomialTree.EuropeanFuturePV(t, f, k, rf, vol, cp, 100);
            PVtri = TrinomialTree.EuropeanFuturePV(t, f, k, rf, vol, cp, 100);

            Assert.Equal(PVBlack, PVbi, 1);
            Assert.Equal(PVBlack, PVtri, 1);
        }
Beispiel #13
0
        public static void ImplyVols(List <ListedOptionSettlementRecord> optionSettlements, Dictionary <string, double> futuresPrices, IIrCurve discountCurve = null)
        {
            var o = new Dictionary <DateTime, IInterpolator1D>();

            foreach (var s in optionSettlements)
            {
                if (!futuresPrices.TryGetValue(s.UnderlyingFuturesCode, out var fut))
                {
                    throw new Exception($"No future price found for contract {s}");
                }

                var t = s.ValDate.CalculateYearFraction(s.ExpiryDate, DayCountBasis.ACT365F);
                var r = 0.0;

                if (s.MarginType == OptionMarginingType.Regular)
                {
                    if (discountCurve == null)
                    {
                        throw new Exception("To strip vols from options with regular margining, a discount curve must be supplied");
                    }
                    r = discountCurve.GetRate(s.ExpiryDate);
                }

                if (s.ExerciseType == OptionExerciseType.European || s.MarginType == OptionMarginingType.FuturesStyle)
                {
                    s.ImpliedVol = BlackFunctions.BlackImpliedVol(fut, s.Strike, r, t, s.PV, s.CallPut);
                }
                else if (s.ExerciseType == OptionExerciseType.American)
                {
                    s.ImpliedVol = BinomialTree.AmericanFuturesOptionImpliedVol(fut, s.Strike, r, t, s.PV, s.CallPut);
                }
                else
                {
                    throw new Exception("Unable to handle option in stripper");
                }
            }
        }
    /// <summary>
    /// Adds a specified binomial tree of the same order as a
    /// sub-tree of this one by adding its root node as a child of
    /// this tree's root node.
    /// </summary>
    /// <remarks>
    /// Complexity: O(1)
    /// </remarks>
    /// <param name="other">Tree to add.</param>
    /// <returns>The resulting tree (this tree).</returns>
    public BinomialTree <T> AddSubTree(BinomialTree <T> other)
    {
        if (m_Order != other.m_Order)
        {
            //-- Only merge binomial trees of the same order
            return(this);
        }

        //-- Add the other tree's root as a child of our own
        if (null != m_Root)
        {
            other.Root.m_Parent = m_Root;
            m_Root.Children.Append(other.Root);
        }
        else
        {
            m_Root = other.Root;
        }

        //-- Our binomial tree is now one level "deeper"
        ++m_Order;

        return(this);
    }
 public DistributionCalculator(BinomialTree model, QSpace qSpace, double q0)
 {
     new DistributionCalculator(model, qSpace, q0, model.R, model.R, 1, model.Sigma, model.Sigma, 1);
 }
    /// <summary>
    /// Combines the trees from two binomial heaps into one list. The trees in the returned
    /// list are ordered by their binomial treee "order" and each tree has an order unique
    /// from the other trees in the list. Trees in the two heaps having the same order are
    /// merged into a single tree whereas one-offs are simply added to the resulting list.
    /// </summary>
    /// <remarks>
    /// Complexity: O(log n)
    /// </remarks>
    /// <param name="a">First binomial heap.</param>
    /// <param name="b">Second binomial heap.</param>
    /// <returns>A list of merged trees from both input heaps.</returns>
    private static LinkedList <BinomialTree <T> > Merge(BinomialHeap <T> a, BinomialHeap <T> b)
    {
        LinkedList <BinomialTree <T> > mergedTrees = new LinkedList <BinomialTree <T> >();

        LinkedListNode <BinomialTree <T> > aIter = a.TreeList.First;
        LinkedListNode <BinomialTree <T> > bIter = b.TreeList.First;

        BinomialTree <T> pendingTree = null;

        //-- Iterate through the trees of both heaps at once
        while ((null != aIter) || (null != bIter))
        {
            if ((null == aIter) || (null == bIter))
            {
                //-- Only one of the trees is good. Store it and nudge
                //   the corresponding iterator.
                if (null != aIter)
                {
                    pendingTree = aIter.Value;
                    aIter       = aIter.Next;
                }

                if (null != bIter)
                {
                    pendingTree = bIter.Value;
                    bIter       = bIter.Next;
                }
            }
            else
            {
                if (aIter.Value.Order < bIter.Value.Order)
                {
                    //-- Advance A since B is ahead
                    pendingTree = aIter.Value;
                    aIter       = aIter.Next;
                }
                else if (aIter.Value.Order > bIter.Value.Order)
                {
                    //-- Advance B since A is ahead
                    pendingTree = bIter.Value;
                    bIter       = bIter.Next;
                }
                else
                {
                    //-- A and B have mathing order, merge them and advance both
                    pendingTree = BinomialTree <T> .Merge(aIter.Value, bIter.Value);

                    aIter = aIter.Next;
                    bIter = bIter.Next;
                }
            }

            //-- Try to combine with a list we've already merged if possible
            if ((0 < mergedTrees.Count) && (pendingTree.Order == mergedTrees.Last.Value.Order))
            {
                pendingTree = BinomialTree <T> .Merge(pendingTree, mergedTrees.Last.Value);

                mergedTrees.RemoveLast();
            }

            //-- Add the new tree to the merged tree list
            mergedTrees.AddLast(pendingTree);
        }

        return(mergedTrees);
    }