コード例 #1
0
ファイル: Hmm1.cs プロジェクト: StarlangSoftware/Hmm-CS
        /**
         * <summary>logOfColumn calculates the logarithm of each value in a specific column in the transition probability matrix.</summary>
         *
         * <param name="column">Column index of the transition probability matrix.</param>
         * <returns>A vector consisting of the logarithm of each value in the column in the transition probability matrix.</returns>
         */
        private Vector LogOfColumn(int column)
        {
            var result = new Vector(0, 0);
            int i;

            for (i = 0; i < StateCount; i++)
            {
                result.Add(SafeLog(TransitionProbabilities.GetValue(i, column)));
            }

            return(result);
        }
コード例 #2
0
        public int CreateObservation(ICRFNodeData node, int label)
        {
            var index = TransitionProbabilities.ChooseTransition(label, Random);

            return(index);
        }
コード例 #3
0
        public static TimeSeries <T, IReadOnlyList <TreeNode> > CreateTree <T>([NotNull] TimeSeries <T, double> forwardCurve, double meanReversion,
                                                                               [NotNull] TimeSeries <T, double> spotVolatilityCurve, double onePeriodTimeDelta)
            where T : ITimePeriod <T>
        {
            if (forwardCurve == null)
            {
                throw new ArgumentNullException(nameof(forwardCurve));
            }
            if (spotVolatilityCurve == null)
            {
                throw new ArgumentNullException(nameof(spotVolatilityCurve));
            }

            if (meanReversion <= 0)
            {
                throw new ArgumentException("Mean reversion must be positive.", nameof(meanReversion));
            }

            if (onePeriodTimeDelta <= 0)
            {
                throw new ArgumentException("Time delta must be positive.", nameof(onePeriodTimeDelta));
            }

            if (forwardCurve.Count < 2)
            {
                throw new ArgumentException("Forward curve must contain at least 2 points.", nameof(forwardCurve));
            }

            // TODO replace the two conditions below with call to new method on TimeSeries, e.g. indices are subset
            if (spotVolatilityCurve.IsEmpty)
            {
                throw new ArgumentException("Volatility curve is empty.", nameof(spotVolatilityCurve));
            }

            if (spotVolatilityCurve.Start.CompareTo(forwardCurve.Start) > 0 || spotVolatilityCurve.End.CompareTo(forwardCurve.End) < 0)
            {
                throw new ArgumentException("Volatility curve does not contain a point for every point on the forward curve.", nameof(spotVolatilityCurve));
            }

            int numPeriods = forwardCurve.Count;

            double expectedOuReturn    = Math.Exp(-meanReversion * onePeriodTimeDelta) - 1; // Equal to M in Hull & White 1994, as calculated in end note 5, p16
            double onePeriodOuVariance = (1 - Math.Exp(-2 * meanReversion * onePeriodTimeDelta)) / (2.0 * meanReversion);
            double treeSpacing         = Math.Sqrt(3 * onePeriodOuVariance);

            // For jMax calc see Hull & White p12
            int jMax = Convert.ToInt32(Math.Ceiling(-0.184 / expectedOuReturn));

            int maxNumTreeLevels = jMax * 2 + 1;

            var middleNodeTypeTransitionProbabilities = new Dictionary <int, TransitionProbabilities>();
            TransitionProbabilities bottomEdgeTransitionProbabilities = null;
            TransitionProbabilities topEdgeTransitionProbabilities    = null;

            // Calculate the probability of reaching each node using forward induction
            var nodeProbabilities = new double[numPeriods][];

            nodeProbabilities[0] = new[] { 1.0 };    // Current point as probability 1

            for (int i = 0; i < numPeriods - 1; i++) // Loop forward through time
            {
                int currentStepNumLevels = Math.Min(i * 2 + 1, maxNumTreeLevels);
                int indexAdjustToJ       = (currentStepNumLevels - 1) / 2;

                int nextStepNumLevels = Math.Min((i + 1) * 2 + 1, maxNumTreeLevels);

                nodeProbabilities[i + 1] = new double[nextStepNumLevels];
                bool treeHasReachedWidestPoint = currentStepNumLevels == maxNumTreeLevels;

                for (int priceLevelIndex = 0; priceLevelIndex < currentStepNumLevels; priceLevelIndex++) // Loop through the tree price levels
                {
                    double currentNodeProbability = nodeProbabilities[i][priceLevelIndex];
                    (int nextStepTopIndex, int nextStepMiddleIndex, int nextStepBottomIndex) =
                        GetNextStepIndexPositions(priceLevelIndex, treeHasReachedWidestPoint, maxNumTreeLevels);

                    int j = priceLevelIndex - indexAdjustToJ;

                    TransitionProbabilities transitionProbabilities = GetTransitionProbabilities(j, priceLevelIndex,
                                                                                                 maxNumTreeLevels, treeHasReachedWidestPoint, expectedOuReturn,
                                                                                                 ref bottomEdgeTransitionProbabilities, middleNodeTypeTransitionProbabilities,
                                                                                                 ref topEdgeTransitionProbabilities);

                    nodeProbabilities[i + 1][nextStepTopIndex]    += currentNodeProbability * transitionProbabilities.TopProbability;
                    nodeProbabilities[i + 1][nextStepMiddleIndex] += currentNodeProbability * transitionProbabilities.MiddleProbability;
                    nodeProbabilities[i + 1][nextStepBottomIndex] += currentNodeProbability * transitionProbabilities.BottomProbability;
                }
            }

            // Populate results looping backward from end in order to populate transitions from the next time step
            var resultNodes = new TreeNode[numPeriods][];

            for (int i = numPeriods - 1; i >= 0; i--)
            {
                int numPriceLevels = nodeProbabilities[i].Length;
                int indexAdjustToJ = (numPriceLevels - 1) / 2;

                // Calculate adjustment factor to ensure expected spot price equals current forward price
                // See Clewlow and Strickland equation 4.10 with discount factor cancelled out
                double expectedExponentialOfOu = 0;
                double spotVolatility          = spotVolatilityCurve[i];
                for (int priceLevelIndex = 0; priceLevelIndex < numPriceLevels; priceLevelIndex++)
                {
                    int    j = priceLevelIndex - indexAdjustToJ;
                    double ouProcessValue = treeSpacing * j;
                    expectedExponentialOfOu += nodeProbabilities[i][priceLevelIndex] * Math.Exp(spotVolatility * ouProcessValue);
                }

                double forwardPrice   = forwardCurve[i];
                double adjustmentTerm = Math.Log(forwardPrice / expectedExponentialOfOu);

                // Populate tree nodes
                resultNodes[i] = new TreeNode[numPriceLevels];
                bool treeHasReachedWidestPoint = numPriceLevels == maxNumTreeLevels;
                for (int priceLevelIndex = 0; priceLevelIndex < numPriceLevels; priceLevelIndex++) // Loop through price levels
                {
                    NodeTransition[] nodeTransitions;
                    int j = priceLevelIndex - indexAdjustToJ;
                    if (i == numPeriods - 1)
                    {
                        nodeTransitions = new NodeTransition[0];
                    }
                    else
                    {
                        TransitionProbabilities transitionProbabilities = GetTransitionProbabilities(j, priceLevelIndex,
                                                                                                     maxNumTreeLevels, treeHasReachedWidestPoint, expectedOuReturn,
                                                                                                     ref bottomEdgeTransitionProbabilities, middleNodeTypeTransitionProbabilities,
                                                                                                     ref topEdgeTransitionProbabilities);

                        (int nextPeriodTopNodeIndex, int nextPeriodMiddleNodeIndex, int nextPeriodBottomNodeIndex) =
                            GetNextStepIndexPositions(priceLevelIndex, treeHasReachedWidestPoint, maxNumTreeLevels);

                        var topTransition = new NodeTransition(transitionProbabilities.TopProbability,
                                                               resultNodes[i + 1][nextPeriodTopNodeIndex]);
                        var middleTransition = new NodeTransition(transitionProbabilities.MiddleProbability,
                                                                  resultNodes[i + 1][nextPeriodMiddleNodeIndex]);
                        var bottomTransition = new NodeTransition(transitionProbabilities.BottomProbability,
                                                                  resultNodes[i + 1][nextPeriodBottomNodeIndex]);
                        nodeTransitions = new[] { bottomTransition, middleTransition, topTransition };
                    }
                    double ouProcessValue = treeSpacing * j;
                    double nodeSpotPrice  = Math.Exp(ouProcessValue * spotVolatility + adjustmentTerm);

                    resultNodes[i][priceLevelIndex] = new TreeNode(nodeSpotPrice, nodeProbabilities[i][priceLevelIndex], priceLevelIndex, nodeTransitions);
                }
            }

            return(new TimeSeries <T, IReadOnlyList <TreeNode> >(forwardCurve.Indices, resultNodes));
        }
コード例 #4
0
        private static TransitionProbabilities GetTransitionProbabilities(
            int j,
            int arrayIndex,
            int maxNumTreePriceLevels,
            bool treeHasReachedWidestPoint,
            double expectedOuReturn,
            ref TransitionProbabilities bottomEdgeTransitionProbabilities,
            Dictionary <int, TransitionProbabilities> middleNodeTypeTransitionProbabilities,
            ref TransitionProbabilities topEdgeTransitionProbabilities)
        {
            TransitionProbabilities transitionProbabilities;

            if (treeHasReachedWidestPoint && arrayIndex == 0)
            {
                // Bottom node
                if (bottomEdgeTransitionProbabilities != null)
                {
                    transitionProbabilities = bottomEdgeTransitionProbabilities;
                }
                else
                {
                    double jSquaredTimesMSquared = j * j * expectedOuReturn * expectedOuReturn;
                    double jTimesM = j * expectedOuReturn;

                    double probabilityUp     = 1.0 / 6.0 + (jSquaredTimesMSquared - jTimesM) / 2.0;
                    double probabilityMiddle = -1.0 / 3.0 - jSquaredTimesMSquared + 2 * jTimesM;
                    double probabilityDown   = 7.0 / 6.0 + (jSquaredTimesMSquared - 3.0 * jTimesM) / 2.0;

                    transitionProbabilities           = new TransitionProbabilities(probabilityUp, probabilityMiddle, probabilityDown);
                    bottomEdgeTransitionProbabilities = transitionProbabilities;
                }
            }
            else if (treeHasReachedWidestPoint && arrayIndex == maxNumTreePriceLevels - 1)
            {
                // Top node
                if (topEdgeTransitionProbabilities != null)
                {
                    transitionProbabilities = topEdgeTransitionProbabilities;
                }
                else
                {
                    double jSquaredTimesMSquared = j * j * expectedOuReturn * expectedOuReturn;
                    double jTimesM = j * expectedOuReturn;

                    double probabilityUp     = 7.0 / 6.0 + (jSquaredTimesMSquared + 3.0 * jTimesM) / 2.0;
                    double probabilityMiddle = -1.0 / 3.0 - jSquaredTimesMSquared - 2.0 * jTimesM;
                    double probabilityDown   = 1.0 / 6.0 + (jSquaredTimesMSquared + jTimesM) / 2.0;

                    transitionProbabilities =
                        new TransitionProbabilities(probabilityUp, probabilityMiddle, probabilityDown);
                    topEdgeTransitionProbabilities = transitionProbabilities;
                }
            }
            else
            {
                // Central node
                if (middleNodeTypeTransitionProbabilities.TryGetValue(j, out transitionProbabilities))
                {
                    return(transitionProbabilities);
                }

                double jSquaredTimesMSquared = j * j * expectedOuReturn * expectedOuReturn;
                double jTimesM = j * expectedOuReturn;

                double probabilityUp     = 1.0 / 6.0 + (jSquaredTimesMSquared + jTimesM) / 2.0;
                double probabilityMiddle = 2.0 / 3.0 - jSquaredTimesMSquared;
                double probabilityDown   = 1.0 / 6.0 + (jSquaredTimesMSquared - jTimesM) / 2.0;

                transitionProbabilities = new TransitionProbabilities(probabilityUp, probabilityMiddle, probabilityDown);
                middleNodeTypeTransitionProbabilities.Add(j, transitionProbabilities);
            }
            return(transitionProbabilities);
        }