Example #1
0
        /// <summary> Returns an issue when the given tick rate does not align with any integer value, 1/2, 3/2 or 4/3.
        /// Rounds the value to the closest 1/100th to avoid precision errors. </summary>
        private Issue GetTickRateIssue(float tickRate, string type, Beatmap beatmap)
        {
            double approxTickRate = Math.Round(tickRate * 1000) / 1000;

            if (tickRate - Math.Floor(tickRate) != 0 &&
                !approxTickRate.AlmostEqual(0.5) &&
                !approxTickRate.AlmostEqual(1.333) &&
                !approxTickRate.AlmostEqual(1.5))
            {
                return(new Issue(GetTemplate("Tick Rate"), beatmap,
                                 approxTickRate, type));
            }

            return(null);
        }
Example #2
0
        /// <summary>Find a solution of the equation f(x)=0.</summary>
        /// <param name="f">The function to find roots from.</param>
        /// <param name="lowerBound">The low value of the range where the root is supposed to be.</param>
        /// <param name="upperBound">The high value of the range where the root is supposed to be.</param>
        /// <param name="accuracy">Desired accuracy. The root will be refined until the accuracy or the maximum number of iterations is reached.</param>
        /// <param name="maxIterations">Maximum number of iterations. Usually 100.</param>
        /// <param name="root">The root that was found, if any. Undefined if the function returns false.</param>
        /// <returns>True if a root with the specified accuracy was found, else false.</returns>
        public static bool TryFindRoot(Func <double, double> f, double lowerBound, double upperBound, double accuracy, int maxIterations, out double root)
        {
            double fmin = f(lowerBound);
            double fmax = f(upperBound);

            // already there?
            if (Math.Abs(fmin) < accuracy)
            {
                root = lowerBound;
                return(true);
            }
            if (Math.Abs(fmax) < accuracy)
            {
                root = upperBound;
                return(true);
            }

            root = 0.5 * (lowerBound + upperBound);

            // bad bracketing?
            if (Math.Sign(fmin) == Math.Sign(fmax))
            {
                return(false);
            }

            for (int i = 0; i <= maxIterations; i++)
            {
                if (Math.Abs(fmax - fmin) < 0.5 * accuracy && upperBound.AlmostEqual(lowerBound))
                {
                    return(true);
                }

                if ((lowerBound == root) || (upperBound == root))
                {
                    // accuracy not sufficient, but cannot be improved further
                    return(false);
                }

                double midval = f(root);

                if (Math.Sign(midval) == Math.Sign(fmin))
                {
                    lowerBound = root;
                    fmin       = midval;
                }
                else if (Math.Sign(midval) == Math.Sign(fmax))
                {
                    upperBound = root;
                    fmax       = midval;
                }
                else
                {
                    return(true);
                }

                root = 0.5 * (lowerBound + upperBound);
            }

            return(false);
        }
        // Решает уравнение −ξz0 + ηa − (ξλ1^2z0)a^2 + (ηλ1λ2)a^3 = 0 относительно "a"
        public static IEnumerable <double> SolveEquation(double eta, double lambda1, double lambda2, double xi, double z)
        {
            if (!lambda1.AlmostEqual(0))
            {
                // FindRoots.Cubic находит все (и комплексные) корни уравнения вида d + c*x + b*x^2 + a*x^3 = 0
                var allRoots = FindRoots.Cubic(-xi * z, eta, -lambda1 * lambda1 * xi * z, eta * lambda1 * lambda2);

                //отбрасываем комплесные корни (мнимая часть бывает очень маленькой, но ненулевой, тк считаем на double)
                if (allRoots.Item1.Imaginary.AlmostEqual(0))
                {
                    yield return(allRoots.Item1.Real);
                }
                if (allRoots.Item2.Imaginary.AlmostEqual(0))
                {
                    yield return(allRoots.Item2.Real);
                }
                if (allRoots.Item3.Imaginary.AlmostEqual(0))
                {
                    yield return(allRoots.Item3.Real);
                }
            }
            else
            {
                yield return(xi * z / eta);
            }
        }
Example #4
0
        public FxSpot(Date startDate,
                      Date maturityDate,
                      double fxRate,
                      ICalendar domCalendar,
                      CurrencyCode domCcy,
                      double notionalInDomCcy,
                      ICalendar fgnCalendar,
                      CurrencyCode fgnCcy,
                      double notionalInFgnCcy,
                      CurrencyCode settlementCcy
                      )
        {
            StartDate = startDate;
            UnderlyingMaturityDate = maturityDate;
            FxRate = fxRate;

            DomCalendar = domCalendar;
            DomCcy      = domCcy;
            Notional    = notionalInDomCcy;

            FgnCalendar      = fgnCalendar;
            FgnCcy           = fgnCcy;
            NotionalInFgnCcy = notionalInFgnCcy;

            SettlementCcy = settlementCcy;
            SettlmentGap  = new DayGap("0BD");

            if (!notionalInDomCcy.AlmostEqual(notionalInFgnCcy / fxRate))
            {
                throw new PricingBaseException("Fx spot's domCcyAmt, fgnCcyAmt, and Fx spot rate does not match!");
            }
        }
Example #5
0
        /// <summary>
        /// Inverts this quaternion.
        /// </summary>
        public Quaternion Inverse()
        {
            if (_abs.AlmostEqual(1))
            {
                return(new Quaternion(_w, -_x, -_y, -_z));
            }

            return(new Quaternion(_w / _norm, -_x / _norm, -_y / _norm, -_z / _norm));
        }
        /// <summary>
        /// Interpolate at point t.
        /// </summary>
        /// <param name="t">Point t to interpolate at.</param>
        /// <returns>Interpolated value x(t).</returns>
        public double Interpolate(double t)
        {
            const double Tiny = 1.0e-25;
            int          n    = _points.Count;

            double[] c = new double[n];
            double[] d = new double[n];

            int    nearestIndex    = 0;
            double nearestDistance = Math.Abs(t - _points[0]);

            for (int i = 0; i < n; i++)
            {
                double distance = Math.Abs(t - _points[i]);
                if (distance.AlmostEqual(0.0))
                {
                    return(_values[i]);
                }

                if (distance < nearestDistance)
                {
                    nearestIndex    = i;
                    nearestDistance = distance;
                }

                c[i] = _values[i];
                d[i] = _values[i] + Tiny;
            }

            double x = _values[nearestIndex];

            for (int level = 1; level < n; level++)
            {
                for (int i = 0; i < n - level; i++)
                {
                    double hp = _points[i + level] - t;
                    double ho = (_points[i] - t) * d[i] / hp;

                    double den = ho - c[i + 1];
                    if (den.AlmostEqual(0.0))
                    {
                        return(double.NaN); // zero-div, singularity
                    }

                    den  = (c[i + 1] - d[i]) / den;
                    d[i] = c[i + 1] * den;
                    c[i] = ho * den;
                }

                x += (2 * nearestIndex) < (n - level)
                    ? c[nearestIndex]
                    : d[--nearestIndex];
            }

            return(x);
        }
Example #7
0
        private bool ABumperIsHit(double[] newRow, ref bool aBumperHasJustBeenHit, ref int noOfLinearHits)
        {
            if (noOfLinearHits > 4)
            {
                return(false);
            }
            double xPosition = newRow[0];
            double yPosition = newRow[1];
            double xVelocity = newRow[2];
            double yVelocity = newRow[3];

            NewBumper.FindLeftAndRightBumperPositions();

            if (xPosition < NewBumper.LeftBumperX || xPosition > NewBumper.RightBumperX)
            {
                aBumperHasJustBeenHit = false;
                return(false);
            }

            double m = (NewBumper.RightBumperY - NewBumper.LeftBumperY) /
                       (NewBumper.RightBumperX - NewBumper.LeftBumperX);
            double c       = (NewBumper.RightBumperY - m * NewBumper.RightBumperX);
            double yBumper = m * xPosition + c;

            //If the horizontal distance between the bumpers are small, assume that if the shot is in vertical range, it hits the bumper

            if (Math.Abs(NewBumper.LeftBumperX - NewBumper.RightBumperX) < 6 &&
                yPosition > Math.Min(NewBumper.LeftBumperY, NewBumper.RightBumperY) &&
                yPosition < Math.Max(NewBumper.LeftBumperY, NewBumper.RightBumperY))
            {
                yBumper = yPosition;
            }

            if (yBumper.AlmostEqual(yPosition, (double)1))
            {
                if (!aBumperHasJustBeenHit)
                {
                    double velocityMagnitude = Math.Sqrt(Math.Pow(xVelocity, 2) + Math.Pow(yVelocity, 2));
                    double theta             = Math.Atan2(yVelocity, xVelocity);
                    double newTheta          = 2 * (IsMirrored * NewBumper.CalculateAlpha()) - theta;
                    newRow[2]             = velocityMagnitude * Math.Cos(newTheta);
                    newRow[3]             = velocityMagnitude * Math.Sin(newTheta);
                    aBumperHasJustBeenHit = true;
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
            aBumperHasJustBeenHit = false;
            return(false);
        }
        public static void AlmostEqual(double expected, double actual, int decimalPlaces)
        {
            if (double.IsNaN(expected) && double.IsNaN(actual))
            {
                return;
            }

            if (!expected.AlmostEqual(actual, decimalPlaces))
            {
                Assert.Fail("Not equal within {0} places. Expected:{1}; Actual:{2}", decimalPlaces, expected, actual);
            }
        }
Example #9
0
        public static Prediction GetSymmetricPrediction(double spotPrice, double volatility, double interestRate, double daysInFuture, int?numberOfPointsArg = null)
        {
            int numberOfPoints = numberOfPointsArg ?? DefaultNumberOfPredictionResults;

            volatility = 0.2;
            double t             = daysInFuture / (365 * numberOfPoints);
            double tmp           = interestRate / 100 - volatility * volatility / 2;
            double x             = Math.Sqrt(tmp * tmp * t * t + volatility * volatility * t);
            double probabilityUp = x.AlmostEqual(0)
                                                                                ? 0.5 + tmp / 2
                                                                                : 0.5 + (tmp * t) / (2 * x);
            double probabilityDown = 1 - probabilityUp;

            double[] stockPrice     = new double[numberOfPoints];
            double[] cumulativeProb = new double[numberOfPoints];

            double prevStockPrice = stockPrice[0] = Math.Log(spotPrice) - (numberOfPoints) * x;

            for (int i = 0; i < numberOfPoints; i++)
            {
                prevStockPrice = prevStockPrice + 2 * x;
                stockPrice[i]  = Math.Exp(prevStockPrice);
            }
            stockPrice[0] = Math.Exp(stockPrice[0]);

            double prevCumulativeProb = 0.0;

            for (int i = 0; i < numberOfPoints; i++)
            {
                double probability = SpecialFunctions.Binomial(numberOfPoints, i) *
                                     Math.Pow(probabilityDown, numberOfPoints - i) *
                                     Math.Pow(probabilityUp, i);

                probability      += prevCumulativeProb;
                cumulativeProb[i] = probability.CoerceZero(SignificantDoubleValue);

                prevCumulativeProb = probability;
            }

            for (int i = numberOfPoints / 2; i < numberOfPoints; i++)
            {
                cumulativeProb[i] = 1.0 - cumulativeProb[i];
                if (cumulativeProb[i] < 0)
                {
                    cumulativeProb[i] = 0;
                }
            }

            Prediction prediction = new Prediction(cumulativeProb, stockPrice, daysInFuture);

            return(prediction);
        }
        /// <summary>
        /// Tries to find what value of volatility x fulfill the following condition: GetEuroPrice(x) == (ask + bid) / 2
        /// </summary>
        private double SigmaImp()
        {
            // double ave = (_ask + _bid) / 2;
            double ave = _lastPrice;

            double sigma1 = SigmaLow;
            double sigma2 = SigmaHigh;

            if (ave.AlmostEqual(0))
            {
                return((sigma1 + sigma2) / 2);
            }

            int i = 0;

            if (GetEuroPrice(0) > ave)
            {
                return(0.0001);
            }

            while (!sigma1.AlmostEqualRelative(sigma2, 1e-6))
            {
                double sigma3 = (sigma1 + sigma2) / 2;
                double x1     = GetEuroPrice(sigma1);
                double x3     = GetEuroPrice(sigma3);

                double decisionVar = (x1 - ave) * (x3 - ave);
                if (decisionVar > 0)
                {
                    sigma1 = sigma3;
                }
                else if (decisionVar < 0)
                {
                    sigma2 = sigma3;
                }

                if (i++ > MaxLoopsNumber)
                {
                    break;
                }
            }

            double impliedVolatility = (sigma1 + sigma2) / 2;

            if (impliedVolatility < 0)
            {
                impliedVolatility = 0;
            }

            return(impliedVolatility.CoerceZero(SignificantDoubleValue));
        }
Example #11
0
        /// <summary>
        /// Checks if two complex numbers are equal. Two complex numbers are equal if their
        /// corresponding real and imaginary components are equal.
        /// </summary>
        /// <returns>
        /// Returns <c>true</c> if the two objects are the same object, or if their corresponding
        /// real and imaginary components are equal, <c>false</c> otherwise.
        /// </returns>
        /// <param name="other">
        /// The complex number to compare to with.
        /// </param>
        public bool Equals(Complex other)
        {
            if (this.IsNaN() || other.IsNaN())
            {
                return(false);
            }

            if (this.IsInfinity() && other.IsInfinity())
            {
                return(true);
            }

            return(_real.AlmostEqual(other._real) && _imag.AlmostEqual(other._imag));
        }
Example #12
0
        /// <summary>
        /// Gets all the t values where the derivative is 0
        /// see: https://mathworld.wolfram.com/StationaryPoint.html
        /// </summary>
        /// <returns>An array of t values (in the domain of the function) where the derivative of the spline is 0</returns>
        public double[] StationaryPoints()
        {
            List <double> points = new List <double>();

            for (int index = 0; index < _x.Length - 1; index++)
            {
                double a = 6 * _c3[index]; //derive ax^3 and multiply by 2
                double b = 2 * _c2[index]; //derive bx^2
                double c = _c1[index];     //derive cx
                double d = b * b - 2 * a * c;
                //first check if a is 0, if so its a linear function, this happens with quadratic condition
                if (a.AlmostEqual(0))
                {
                    double x = _x[index] - c / b;
                    //check if the result is in the domain
                    if (_x[index] <= x && x <= _x[index + 1])
                    {
                        points.Add(x);
                    }
                }
                else if (d.AlmostEqual(0))//its a quadratic with a single solution
                {
                    double x = _x[index] - b / a;
                    if (_x[index] <= x && x <= _x[index + 1])
                    {
                        points.Add(x);
                    }
                }
                else if (d > 0)//only has a solution if d is greater than 0
                {
                    d = (double)System.Math.Sqrt(d);
                    //apply quadratic equation
                    double x1 = _x[index] + (-b + d) / a;
                    double x2 = _x[index] + (-b - d) / a;
                    //Add any solution points that fall within the domain to the list
                    if ((_x[index] <= x1) && (x1 <= _x[index + 1]))
                    {
                        points.Add(x1);
                    }
                    if ((_x[index] <= x2) && (x2 <= _x[index + 1]))
                    {
                        points.Add(x2);
                    }
                }
            }
            return(points.ToArray());
        }
Example #13
0
        private IEnumerable <Issue> GetIssue(HitObject hitObject, double time, float volume, bool isActive = false)
        {
            volume = GetActualVolume(volume);
            if (volume > 20)
            {
                // Volumes greater than 20% are usually audible.
                yield break;
            }

            bool   isHead    = time.AlmostEqual(hitObject.time);
            string timestamp = isHead ? Timestamp.Get(hitObject) : Timestamp.Get(time);
            string partName  = hitObject.GetPartName(time).ToLower().Replace("body", "tick");

            if (isActive)
            {
                if (isHead)
                {
                    if (volume <= 10)
                    {
                        yield return(new Issue(GetTemplate("Warning Volume"), hitObject.beatmap,
                                               timestamp, volume, partName));
                    }
                    else
                    {
                        yield return(new Issue(GetTemplate("Minor Volume"), hitObject.beatmap,
                                               timestamp, volume, partName));
                    }
                }
                else
                {
                    // Must be a slider reverse, mappers rarely map these to nothing.
                    if (volume <= 10)
                    {
                        yield return(new Issue(GetTemplate("Passive Reverse"), hitObject.beatmap,
                                               timestamp, volume, partName));
                    }
                }
            }
            else if (volume <= 10)
            {
                // Must be a slider tail or similar, these are often silenced intentionally.
                yield return(new Issue(GetTemplate("Passive"), hitObject.beatmap,
                                       timestamp, volume, partName));
            }
        }
        public Dictionary <DateAndNumberOfDaysUntil, Prediction> MakePredictionsForDates(IBasicPredictionCalculationData data, IEnumerable <DateAndNumberOfDaysUntil> dates)
        {
            Dictionary <DateAndNumberOfDaysUntil, Prediction> predictions = new Dictionary <DateAndNumberOfDaysUntil, Prediction>();

            foreach (DateAndNumberOfDaysUntil date in dates)
            {
                double daysInFuture = date.TotalNumberOfDaysUntilExpiry;
                if (daysInFuture.AlmostEqual(0) || daysInFuture < 0)
                {
                    continue;
                }

                double     volatility = data.GetVolatility(daysInFuture);
                Prediction prediction = MarketMath.GetSymmetricPrediction(data.LastPrice, volatility, data.InterestRate, daysInFuture);
                predictions.Add(date, prediction);
            }

            return(predictions);
        }
Example #15
0
        private List <OptionPair> FindAtTheMoneyOptions(IReadOnlyList <OptionPair> pairs)
        {
            List <OptionPair> atTheMoneyOptionChains = new List <OptionPair>();

            if (pairs.Count == 0)
            {
                return(atTheMoneyOptionChains);
            }

            double minDiff = pairs.Min(chain => Math.Abs(chain.StrikePrice - UnderlyingCurrentPrice));

            foreach (OptionPair optionChain in pairs)
            {
                double diff = Math.Abs(optionChain.StrikePrice - UnderlyingCurrentPrice);
                if (diff.AlmostEqual(minDiff))
                {
                    atTheMoneyOptionChains.Add(optionChain);
                }
            }
            return(atTheMoneyOptionChains);
        }
Example #16
0
        public static Prediction GetPrediction(double spotPrice, double putSigma, double callSigma, double interestRate, double daysInFuture, int?numberOfPointsArg = null)
        {
            int numberOfPoints = numberOfPointsArg ?? DefaultNumberOfPredictionResults;

            if (putSigma.AlmostEqual(callSigma))
            {
                Prediction sp = GetSymmetricPrediction(spotPrice, putSigma, interestRate, daysInFuture, numberOfPoints);
                return(sp);
            }

            Prediction pr1 = GetSymmetricPrediction(spotPrice, putSigma, interestRate, daysInFuture, numberOfPoints);
            Prediction pr2 = GetSymmetricPrediction(spotPrice, callSigma, interestRate, daysInFuture, numberOfPoints);

            int           pointsToTake  = numberOfPoints / 2 + 1;
            List <double> prices        = new List <double>(pr1.Prices.Take(pointsToTake).Concat(pr2.Prices.Skip(pointsToTake)));
            List <double> probabilities = new List <double>(pr1.Probabilities.Take(pointsToTake).Concat(pr2.Probabilities.Skip(pointsToTake)));

            prices[pointsToTake]        = (pr1.Prices[pointsToTake] + pr2.Prices[pointsToTake]) / 2;
            probabilities[pointsToTake] = (pr1.Probabilities[pointsToTake] + pr2.Probabilities[pointsToTake]) / 2;
            Prediction combined = new Prediction(probabilities, prices, daysInFuture);

            return(combined);
        }
Example #17
0
        public void CanGetRS()
        {
            double rs = RSICalculator.GetRS(37.77);

            Assert.IsTrue(rs.AlmostEqual(0.61));
        }
Example #18
0
        public void NotEqualDTest()
        {
            double test = 0;

            Assert.IsTrue(test.AlmostEqual(0.1, 0.11));
        }
Example #19
0
        public void AlmostEqualDOnNegativeNumbersTest()
        {
            double test = -10;

            Assert.IsTrue(test.AlmostEqual(-11.1, 1.1));
        }
Example #20
0
        /// <summary>
        /// Returns the lower incomplete regularized gamma function
        /// P(a,x) = 1/Gamma(a) * int(exp(-t)t^(a-1),t=0..x) for real a &gt; 0, x &gt; 0.
        /// </summary>
        /// <param name="a">The argument for the gamma function.</param>
        /// <param name="x">The upper integral limit.</param>
        /// <returns>The lower incomplete gamma function.</returns>
        public static double GammaLowerRegularized(double a, double x)
        {
            const double Epsilon          = 0.000000000000001;
            const double BigNumber        = 4503599627370496.0;
            const double BigNumberInverse = 2.22044604925031308085e-16;

            if (a < 0d || x < 0d)
            {
                throw new ArgumentOutOfRangeException("a,x", Properties.Resources.ArgumentNotNegative);
            }

            if (a.AlmostEqual(0.0))
            {
                if (x.AlmostEqual(0.0))
                {
                    // either 0 or 1, depending on the limit direction
                    return(Double.NaN);
                }

                return(1d);
            }

            if (x.AlmostEqual(0.0))
            {
                return(0d);
            }

            double ax = (a * Math.Log(x)) - x - SpecialFunctions.GammaLn(a);

            if (ax < -709.78271289338399)
            {
                return(1d);
            }

            if (x <= 1 || x <= a)
            {
                double r2   = a;
                double c2   = 1;
                double ans2 = 1;

                do
                {
                    r2    = r2 + 1;
                    c2    = c2 * x / r2;
                    ans2 += c2;
                }while ((c2 / ans2) > Epsilon);

                return(Math.Exp(ax) * ans2 / a);
            }

            int    c = 0;
            double y = 1 - a;
            double z = x + y + 1;

            double p3  = 1;
            double q3  = x;
            double p2  = x + 1;
            double q2  = z * x;
            double ans = p2 / q2;

            double error = 0;

            do
            {
                c++;
                y += 1;
                z += 2;
                double yc = y * c;

                double p = (p2 * z) - (p3 * yc);
                double q = (q2 * z) - (q3 * yc);

                if (q != 0)
                {
                    double nextans = p / q;
                    error = Math.Abs((ans - nextans) / nextans);
                    ans   = nextans;
                }
                else
                {
                    // zero div, skip
                    error = 1;
                }

                // shift
                p3 = p2;
                p2 = p;
                q3 = q2;
                q2 = q;

                // normalize fraction when the numerator becomes large
                if (Math.Abs(p) > BigNumber)
                {
                    p3 *= BigNumberInverse;
                    p2 *= BigNumberInverse;
                    q3 *= BigNumberInverse;
                    q2 *= BigNumberInverse;
                }
            }while (error > Epsilon);

            return(1d - (Math.Exp(ax) * ans));
        }
        private static List <CoveredCall> GetCoveredCallsByLegType(OptionChain data, Dictionary <DateAndNumberOfDaysUntil, Prediction> predictions,       /*EarningsCalendar calendar,*/
                                                                   LegType legType, /*Signal volOfVol,*/ double?minimumPremiumParam, double?minimumReturnParam)
        {
            double minimumPremium = minimumPremiumParam ?? DefaultMinimumPremium;
            double minimumReturn  = minimumReturnParam ?? DefaultMinimumReturn;

            HashSet <DateTime> optimalIsFound = new HashSet <DateTime>();
            List <CoveredCall> coveredCalls   = new List <CoveredCall>();

            foreach (OptionPair optionChain in data)
            {
                Option option = legType == LegType.Call
                                        ? optionChain.CallOption
                                        : optionChain.PutOption;

                double bid                      = option.Bid;
                double currentPremium           = bid;
                DateAndNumberOfDaysUntil expiry = optionChain.Expiry;
                double lastPrice                = data.UnderlyingCurrentPrice;
                double strkePrice               = optionChain.StrikePrice;

                List <OptionPair> chainsWithTheSameExpiry = data.Where(x => x.Expiry == expiry).ToList();

                // todo: optionChain.OptionType
                //bool typeisSuitable = optionChain.OptionType == OptionType.Standard;

                double daysQuantity = expiry.TotalNumberOfDaysUntilExpiry;

                // Ignore expired options
                if (daysQuantity < 0 || daysQuantity.AlmostEqual(0) /*|| !typeisSuitable*/)
                {
                    continue;
                }

                bool strikePriceIsSuitable = legType == LegType.Call
                                        ? optionChain.StrikePrice > lastPrice
                                        : optionChain.StrikePrice < lastPrice;

                if (!strikePriceIsSuitable)
                {
                    // Check if fifth strike is suitable
                    strikePriceIsSuitable = legType == LegType.Call
                                                ? chainsWithTheSameExpiry.Where(x => x.StrikePrice < lastPrice)
                                            .OrderBy(x => lastPrice - x.StrikePrice)
                                            .Take(5).Last().StrikePrice <optionChain.StrikePrice
                                                                         : chainsWithTheSameExpiry.Where(x => x.StrikePrice > lastPrice)
                                                                         .OrderBy(x => x.StrikePrice - lastPrice)
                                                                         .Take(5).Last().StrikePrice> optionChain.StrikePrice;
                }

                if (!strikePriceIsSuitable)
                {
                    continue;
                }

                double intrinsicValue = legType == LegType.Call
                                        ? lastPrice > optionChain.StrikePrice ? lastPrice - optionChain.StrikePrice : 0
                                        : lastPrice < optionChain.StrikePrice ? optionChain.StrikePrice - lastPrice : 0;

                double currentReturn = (Math.Pow(1 + (currentPremium - intrinsicValue) / lastPrice, 365.0 / daysQuantity) - 1) * 100;

                bool firstAboveBelowStdDev = false;

                Prediction   prediction = predictions[optionChain.Expiry];
                StdDevPrices stdDev     = prediction.GetStdDevPrices(1);

                bool deviationIsSuitable = legType == LegType.Call
                                        ? strkePrice > stdDev.UpPrice
                                        : strkePrice < stdDev.DownPrice;
                if (deviationIsSuitable)
                {
                    firstAboveBelowStdDev = legType == LegType.Call
                                                ? chainsWithTheSameExpiry
                                            .Where(x => x.StrikePrice >= stdDev.UpPrice)
                                            .Select(y => y.StrikePrice - stdDev.UpPrice)
                                            .Min()
                                            .AlmostEqual(strkePrice - stdDev.UpPrice)
                                                : chainsWithTheSameExpiry
                                            .Where(x => x.StrikePrice <= stdDev.DownPrice)
                                            .Select(y => stdDev.DownPrice - y.StrikePrice)
                                            .Min()
                                            .AlmostEqual(stdDev.DownPrice - optionChain.StrikePrice);
                }

                double      probability         = prediction.GetProbabilityByPrice(optionChain.StrikePrice) * 100;
                double      probabilityInSigmas = MarketMath.GetSigmaProbabilityByDeviation(probability / 100);
                CoveredCall coveredCall         = new CoveredCall();

                coveredCall.Premium = currentPremium;
                coveredCall.Return  = currentReturn;

                coveredCall.OptionNumber        = option.OptionNumber;
                coveredCall.Probability         = probability;
                coveredCall.ProbabilityInSigmas = probabilityInSigmas;

//				if (volOfVol != null)
//				{
//					coveredCall.VolOfVol = volOfVol.Value;
//				}
                coveredCall.PercentAboveBelowCurrentPrice = Math.Abs((optionChain.StrikePrice - lastPrice)) / lastPrice * 100;

                int numberOfStrikes = legType == LegType.Call
                                        ? chainsWithTheSameExpiry.Where(x => x.StrikePrice >= lastPrice)
                                      .OrderBy(x => x.StrikePrice)
                                      .ToList()
                                      .FindIndex(x => x.StrikePrice.AlmostEqual(optionChain.StrikePrice)) + 1
                                        : chainsWithTheSameExpiry.Where(x => x.StrikePrice <= lastPrice)
                                      .OrderByDescending(x => x.StrikePrice)
                                      .ToList()
                                      .FindIndex(x => x.StrikePrice.AlmostEqual(optionChain.StrikePrice)) + 1;

                coveredCall.NumberOfStrikesBelowAboveCurrentPrice = numberOfStrikes;
                coveredCall.NumberOfSdBelowAboveCurrentPrice      = probabilityInSigmas;

//				coveredCall.HasEarnings = calendar != null && calendar.Date >= DateTime.Now && calendar.Date <= optionChain.Expiry;
//				if (calendar != null)
//				{
//					coveredCall.DaysQuantityBeforeEarnings = (calendar.Date - DateTime.UtcNow).TotalDays;
//				}

                coveredCalls.Add(coveredCall);

                if (bid.AlmostEqual(0.0))
                {
                    coveredCall.RiskTolerance = RiskTolerance.NoBid;
                    continue;
                }

                if (!deviationIsSuitable)
                {
                    if (currentPremium < minimumPremium)
                    {
                        coveredCall.RiskTolerance = RiskTolerance.LowPremium;
                        continue;
                    }

                    coveredCall.RiskTolerance = currentReturn >= minimumReturn
                                                ? RiskTolerance.Aggressive
                                                : RiskTolerance.LowReturn;
                    continue;
                }

                if (currentPremium < minimumPremium)
                {
                    coveredCall.RiskTolerance = RiskTolerance.LowPremium;
                    continue;
                }

                if (currentReturn < minimumReturn)
                {
                    coveredCall.RiskTolerance = RiskTolerance.LowReturn;
                    continue;
                }

                if (!optimalIsFound.Contains(optionChain.Expiry.FutureDate) &&
                    daysQuantity >= 3 &&
                    daysQuantity <= 60
                    //&& (!coveredCall.HasEarnings || daysQuantity < coveredCall.DaysQuantityBeforeEarnings)
                    && firstAboveBelowStdDev)
                {
                    coveredCall.RiskTolerance = RiskTolerance.Optimal;
                    optimalIsFound.Add(optionChain.Expiry.FutureDate);
                }
                else
                {
                    coveredCall.RiskTolerance = RiskTolerance.Conservative;
                }
            }
            return(coveredCalls);
        }
Example #22
0
        /// <summary>
        /// Returns the inverse P^(-1) of the regularized lower incomplete gamma function
        /// P(a,x) = 1/Gamma(a) * int(exp(-t)t^(a-1),t=0..x) for real a &gt; 0, x &gt; 0,
        /// such that P^(-1)(a,P(a,x)) == x.
        /// </summary>
        public static double GammaLowerRegularizedInv(double a, double y0)
        {
            const double epsilon   = 0.000000000000001;
            const double big       = 4503599627370496.0;
            const double threshold = 5 * epsilon;

            if (double.IsNaN(a) || double.IsNaN(y0))
            {
                return(double.NaN);
            }

            if (a < 0 || a.AlmostEqual(0.0))
            {
                throw new ArgumentOutOfRangeException(nameof(a));
            }

            if (y0 < 0 || y0 > 1)
            {
                throw new ArgumentOutOfRangeException(nameof(y0));
            }

            if (y0.AlmostEqual(0.0))
            {
                return(0d);
            }

            if (y0.AlmostEqual(1.0))
            {
                return(double.PositiveInfinity);
            }

            y0 = 1 - y0;

            double xUpper = big;
            double xLower = 0;
            double yUpper = 1;
            double yLower = 0;

            // Initial Guess
            double d   = 1 / (9 * a);
            double y   = 1 - d - (0.98 * Constants.Sqrt2 * ErfInv((2.0 * y0) - 1.0) * Math.Sqrt(d));
            double x   = a * y * y * y;
            double lgm = GammaLn(a);

            for (int i = 0; i < 20; i++)
            {
                if (x < xLower || x > xUpper)
                {
                    d = 0.0625;
                    break;
                }

                y = 1 - GammaLowerRegularized(a, x);
                if (y < yLower || y > yUpper)
                {
                    d = 0.0625;
                    break;
                }

                if (y < y0)
                {
                    xUpper = x;
                    yLower = y;
                }
                else
                {
                    xLower = x;
                    yUpper = y;
                }

                d = ((a - 1) * Math.Log(x)) - x - lgm;
                if (d < -709.78271289338399)
                {
                    d = 0.0625;
                    break;
                }

                d = -Math.Exp(d);
                d = (y - y0) / d;
                if (Math.Abs(d / x) < epsilon)
                {
                    return(x);
                }

                if ((d > (x / 4)) && (y0 < 0.05))
                {
                    // Naive heuristics for cases near the singularity
                    d = x / 10;
                }

                x -= d;
            }

            if (xUpper == big)
            {
                if (x <= 0)
                {
                    x = 1;
                }

                while (xUpper == big)
                {
                    x = (1 + d) * x;
                    y = 1 - GammaLowerRegularized(a, x);
                    if (y < y0)
                    {
                        xUpper = x;
                        yLower = y;
                        break;
                    }

                    d = d + d;
                }
            }

            int dir = 0;

            d = 0.5;
            for (int i = 0; i < 400; i++)
            {
                x   = xLower + (d * (xUpper - xLower));
                y   = 1 - GammaLowerRegularized(a, x);
                lgm = (xUpper - xLower) / (xLower + xUpper);
                if (Math.Abs(lgm) < threshold)
                {
                    return(x);
                }

                lgm = (y - y0) / y0;
                if (Math.Abs(lgm) < threshold)
                {
                    return(x);
                }

                if (x <= 0d)
                {
                    return(0d);
                }

                if (y >= y0)
                {
                    xLower = x;
                    yUpper = y;
                    if (dir < 0)
                    {
                        dir = 0;
                        d   = 0.5;
                    }
                    else
                    {
                        if (dir > 1)
                        {
                            d = (0.5 * d) + 0.5;
                        }
                        else
                        {
                            d = (y0 - yLower) / (yUpper - yLower);
                        }
                    }

                    dir = dir + 1;
                }
                else
                {
                    xUpper = x;
                    yLower = y;
                    if (dir > 0)
                    {
                        dir = 0;
                        d   = 0.5;
                    }
                    else
                    {
                        if (dir < -1)
                        {
                            d = 0.5 * d;
                        }
                        else
                        {
                            d = (y0 - yLower) / (yUpper - yLower);
                        }
                    }

                    dir = dir - 1;
                }
            }

            return(x);
        }
Example #23
0
        /// <summary>
        /// Returns the lower incomplete regularized gamma function
        /// P(a,x) = 1/Gamma(a) * int(exp(-t)t^(a-1),t=0..x) for real a &gt; 0, x &gt; 0.
        /// </summary>
        /// <param name="a">The argument for the gamma function.</param>
        /// <param name="x">The upper integral limit.</param>
        /// <returns>The lower incomplete gamma function.</returns>
        public static double GammaLowerRegularized(double a, double x)
        {
            const double epsilon = 0.000000000000001;
            const double big     = 4503599627370496.0;
            const double bigInv  = 2.22044604925031308085e-16;

            if (a < 0d)
            {
                throw new ArgumentOutOfRangeException(nameof(a), Properties.Resources.ArgumentNotNegative);
            }

            if (x < 0d)
            {
                throw new ArgumentOutOfRangeException(nameof(x), Properties.Resources.ArgumentNotNegative);
            }

            if (a.AlmostEqual(0.0))
            {
                if (x.AlmostEqual(0.0))
                {
                    //use right hand limit value because so that regularized upper/lower gamma definition holds.
                    return(1d);
                }

                return(1d);
            }

            if (x.AlmostEqual(0.0))
            {
                return(0d);
            }

            double ax = (a * Math.Log(x)) - x - GammaLn(a);

            if (ax < -709.78271289338399)
            {
                return(a < x ? 1d : 0d);
            }

            if (x <= 1 || x <= a)
            {
                double r2   = a;
                double c2   = 1;
                double ans2 = 1;

                do
                {
                    r2    = r2 + 1;
                    c2    = c2 * x / r2;
                    ans2 += c2;
                }while ((c2 / ans2) > epsilon);

                return(Math.Exp(ax) * ans2 / a);
            }

            int    c = 0;
            double y = 1 - a;
            double z = x + y + 1;

            double p3  = 1;
            double q3  = x;
            double p2  = x + 1;
            double q2  = z * x;
            double ans = p2 / q2;

            double error;

            do
            {
                c++;
                y += 1;
                z += 2;
                double yc = y * c;

                double p = (p2 * z) - (p3 * yc);
                double q = (q2 * z) - (q3 * yc);

                if (q != 0)
                {
                    double nextans = p / q;
                    error = Math.Abs((ans - nextans) / nextans);
                    ans   = nextans;
                }
                else
                {
                    // zero div, skip
                    error = 1;
                }

                // shift
                p3 = p2;
                p2 = p;
                q3 = q2;
                q2 = q;

                // normalize fraction when the numerator becomes large
                if (Math.Abs(p) > big)
                {
                    p3 *= bigInv;
                    p2 *= bigInv;
                    q3 *= bigInv;
                    q2 *= bigInv;
                }
            }while (error > epsilon);

            return(1d - (Math.Exp(ax) * ans));
        }
Example #24
0
 public WavEditor FreezeRegion(double fromSecond, double time = -1)
 {
     return(FreezeRegion((int)(fromSecond * wav.SampleRate), (int)(time.AlmostEqual(-1) ? -1 : (fromSecond + time) * wav.SampleRate)));
 }
Example #25
0
        /// <summary>
        /// Normalized Sinc function. sinc(x) = sin(pi*x)/(pi*x).
        /// </summary>
        public static double Sinc(double x)
        {
            double z = Math.PI * x;

            return(z.AlmostEqual(0.0, 15) ? 1.0 : Math.Sin(z) / z);
        }
 public static bool IsLessOrEqual(this double left, double right)
 {
     return(left.IsSmaller(right, double.Epsilon) || left.AlmostEqual(right, double.Epsilon));
 }
 public static bool IsEqual(this double left, double right)
 {
     return(left.AlmostEqual(right, double.Epsilon));
 }
Example #28
0
        public ConvexMonoticInterpolator(
            IEnumerable <Tuple <double, double> > points,
            double quadraticity     = 0.3,
            double monotonicity     = 0.7,
            bool forcePositive      = true,
            bool constFinalPeriod   = false,
            bool allowExtrapolation = true)
        {
            _keyPoints          = points.ToArray();
            _xArr               = _keyPoints.Select(x => x.Item1).ToArray();
            _yArr               = _keyPoints.Select(x => x.Item2).ToArray();
            _quadraticity       = quadraticity;
            _monotonicity       = monotonicity;
            _forcePositive      = forcePositive;
            _constFinalPeriod   = constFinalPeriod;
            _allowExtrapolation = allowExtrapolation;

            var length = _keyPoints.Length;

            _helpers = new ISectionHelper[length];
            if (length < 2)
            {
                throw new PricingLibraryException("Convex monotonic interpolator must have at least 2 points");
            }
            if (_keyPoints.Length == 2)
            {
                var helper = new EverywhereConstantHelper(_keyPoints.Last().Item2, 0.0, _keyPoints.First().Item1);
                _helpers[1]          = helper;
                _extrapolationHelper = helper;
            }

            var f = new double[length];

            for (var i = 1; i < length - 1; ++i)
            {
                var dxPrev = _xArr[i] - _xArr[i - 1];
                var dx     = _xArr[i + 1] - _xArr[i];
                f[i] = dxPrev / (dx + dxPrev) * _yArr[i] + dx / (dx + dxPrev) * _yArr[i + 1];
            }

            f[0]          = 1.5 * _yArr[1] - 0.5 * f[1];
            f[length - 1] = 1.5 * _yArr.Last() - 0.5 * f[length - 2];
            if (_forcePositive)
            {
                if (f[0] < 0.0)
                {
                    f[0] = 0;
                }
                if (f[length - 1] < 0.0)
                {
                    f[length - 1] = 0.0;
                }
            }

            var integral = 0.0;
            var end      = constFinalPeriod ? length - 1 : length;

            for (var i = 1; i < end; ++i)
            {
                var gPrev = f[i - 1] - _yArr[i];
                var gNext = f[i] - _yArr[i];
                if (gPrev.IsAlmostZero() && gNext.IsAlmostZero())
                {
                    _helpers[i] = new ConstantGradHelper(f[i - 1], integral, _xArr[i - 1], _xArr[i], f[i]);
                }
                else
                {
                    quadraticity = _quadraticity;
                    ISectionHelper quadraticHelper    = null;
                    ISectionHelper convMonotoneHelper = null;
                    if (_quadraticity > 0.0)
                    {
                        if (gPrev >= -2.0 * gNext && gPrev > -0.5 * gNext && _forcePositive)
                        {
                            quadraticHelper = new QuadraticMinHelper(_xArr[i - 1], _xArr[i], f[i - 1], f[i], _yArr[i], integral);
                        }
                        else
                        {
                            quadraticHelper = new QuadraticHelper(_xArr[i - 1], _xArr[i], f[i - 1], f[i], _yArr[i], integral);
                        }
                    }
                    if (_quadraticity < 1.0)
                    {
                        if ((gPrev > 0.0 && -0.5 * gPrev >= gNext && gNext >= -2.0 * gPrev) ||
                            (gPrev < 0.0 && -0.5 * gPrev <= gNext && gNext <= -2.0 * gPrev))
                        {
                            quadraticity = 1.0;
                            if (_quadraticity.IsAlmostZero())
                            {
                                quadraticHelper = _forcePositive
                                                                        ? (ISectionHelper) new QuadraticMinHelper(_xArr[i - 1], _xArr[i], f[i - 1], f[i], _yArr[i], integral)
                                                                        : new QuadraticHelper(_xArr[i - 1], _xArr[i], f[i - 1], f[i], _yArr[i], integral);
                            }
                        }
                        else if ((gPrev < 0.0 && gNext > -2.0 * gPrev) || (gPrev > 0.0 && gNext < -2.0 * gPrev))
                        {
                            var eta = (gNext + 2.0 * gPrev) / (gNext - gPrev);
                            var b2  = (1.0 + _monotonicity) / 2.0;
                            if (eta < b2)
                            {
                                convMonotoneHelper = new ConvexMonotone2Helper(_xArr[i - 1], _xArr[i], gPrev, gNext, _yArr[i], eta, integral);
                            }
                            else
                            {
                                convMonotoneHelper = _forcePositive
                                                                        ? new ConvexMonotone4MinHelper(_xArr[i - 1], _xArr[i], gPrev, gNext, _yArr[i], b2, integral)
                                                                        : new ConvexMonotone4Helper(_xArr[i - 1], _xArr[i], gPrev, gNext, _yArr[i], b2, integral);
                            }
                        }
                        else if ((gPrev > 0.0 && gNext < 0.0 && gNext > -0.5 * gPrev) || (gPrev < 0.0 && gNext > 0.0 && gNext < -0.5 * gPrev))
                        {
                            var eta = gNext / (gNext - gPrev) * 3.0;
                            var b3  = (1.0 - _monotonicity) / 2.0;
                            if (eta > b3)
                            {
                                convMonotoneHelper = new ConvexMonotone3Helper(_xArr[i - 1], _xArr[i], gPrev, gNext, _yArr[i], eta, integral);
                            }
                            else
                            {
                                convMonotoneHelper = _forcePositive ? new ConvexMonotone4MinHelper(_xArr[i - 1], _xArr[i], gPrev, gNext, _yArr[i], b3, integral) : new ConvexMonotone4Helper(_xArr[i - 1], _xArr[i], gPrev, gNext, _yArr[i], b3, integral);
                            }
                        }
                        else
                        {
                            var eta = gNext / (gPrev + gNext);
                            var b2  = (1.0 + _monotonicity) / 2.0;
                            var b3  = (1.0 - _monotonicity) / 2.0;
                            if (eta > b2)
                            {
                                eta = b2;
                            }
                            if (eta < b3)
                            {
                                eta = b3;
                            }
                            convMonotoneHelper = _forcePositive
                                                                ? new ConvexMonotone4MinHelper(_xArr[i - 1], _xArr[i], gPrev, gNext, _yArr[i], eta, integral)
                                                                : new ConvexMonotone4Helper(_xArr[i - 1], _xArr[i], gPrev, gNext, _yArr[i], eta, integral);
                        }
                    }

                    if (quadraticity.AlmostEqual(1.0))
                    {
                        _helpers[i] = quadraticHelper;
                    }
                    else if (quadraticity.IsAlmostZero())
                    {
                        _helpers[i] = convMonotoneHelper;
                    }
                    else
                    {
                        _helpers[i] = new ComboHelper(quadraticHelper, convMonotoneHelper, quadraticity);
                    }
                }
                integral += _yArr[i] * (_xArr[i] - _xArr[i - 1]);
            }

            if (_constFinalPeriod)
            {
                _helpers[length - 1] = new EverywhereConstantHelper(_yArr[length - 1], integral, _xArr[length - 2]);
                _extrapolationHelper = _helpers[length - 1];
            }
            else
            {
                _extrapolationHelper = new EverywhereConstantHelper(_helpers[length - 1].GetValue(_xArr.Last()), integral, _xArr.Last());
            }
        }
 public static bool IsGreaterOrEqual(this double left, double right)
 {
     return(left.IsLarger(right, double.Epsilon) || left.AlmostEqual(right, double.Epsilon));
 }
Example #30
0
        /// <summary>
        /// Solves the matrix equation Ax = b, where A is the coefficient matrix, b is the
        /// solution vector and x is the unknown vector.
        /// </summary>
        /// <param name="matrix">The coefficient <see cref="Matrix"/>, <c>A</c>.</param>
        /// <param name="input">The solution <see cref="Vector"/>, <c>b</c>.</param>
        /// <param name="result">The result <see cref="Vector"/>, <c>x</c>.</param>
        public void Solve(Matrix matrix, Vector input, Vector result)
        {
            // If we were stopped before, we are no longer
            // We're doing this at the start of the method to ensure
            // that we can use these fields immediately.
            _hasBeenStopped = false;

            // Parameters checks
            if (matrix == null)
            {
                throw new ArgumentNullException("matrix");
            }

            if (matrix.RowCount != matrix.ColumnCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixSquare, "matrix");
            }

            if (input == null)
            {
                throw new ArgumentNullException("input");
            }

            if (result == null)
            {
                throw new ArgumentNullException("result");
            }

            if (result.Count != input.Count)
            {
                throw new ArgumentException(Resources.ArgumentVectorsSameLength);
            }

            if (input.Count != matrix.RowCount)
            {
                throw Matrix.DimensionsDontMatch <ArgumentException>(input, matrix);
            }

            // Initialize the solver fields
            // Set the convergence monitor
            if (_iterator == null)
            {
                _iterator = Iterator.CreateDefault();
            }

            if (_preconditioner == null)
            {
                _preconditioner = new UnitPreconditioner();
            }

            _preconditioner.Initialize(matrix);

            // Compute r_0 = b - Ax_0 for some initial guess x_0
            // In this case we take x_0 = vector
            // This is basically a SAXPY so it could be made a lot faster
            Vector residuals = new DenseVector(matrix.RowCount);

            CalculateTrueResidual(matrix, residuals, result, input);

            // Choose r~ (for example, r~ = r_0)
            var tempResiduals = residuals.Clone();

            // create seven temporary vectors needed to hold temporary
            // coefficients. All vectors are mangled in each iteration.
            // These are defined here to prevent stressing the garbage collector
            Vector vecP     = new DenseVector(residuals.Count);
            Vector vecPdash = new DenseVector(residuals.Count);
            Vector nu       = new DenseVector(residuals.Count);
            Vector vecS     = new DenseVector(residuals.Count);
            Vector vecSdash = new DenseVector(residuals.Count);
            Vector temp     = new DenseVector(residuals.Count);
            Vector temp2    = new DenseVector(residuals.Count);

            // create some temporary double variables that are needed
            // to hold values in between iterations
            double currentRho = 0;
            double alpha      = 0;
            double omega      = 0;

            var iterationNumber = 0;

            while (ShouldContinue(iterationNumber, result, input, residuals))
            {
                // rho_(i-1) = r~^T r_(i-1) // dotproduct r~ and r_(i-1)
                var oldRho = currentRho;
                currentRho = tempResiduals.DotProduct(residuals);

                // if (rho_(i-1) == 0) // METHOD FAILS
                // If rho is only 1 ULP from zero then we fail.
                if (currentRho.AlmostEqual(0, 1))
                {
                    // Rho-type breakdown
                    throw new Exception("Iterative solver experience a numerical break down");
                }

                if (iterationNumber != 0)
                {
                    // beta_(i-1) = (rho_(i-1)/rho_(i-2))(alpha_(i-1)/omega(i-1))
                    var beta = (currentRho / oldRho) * (alpha / omega);

                    // p_i = r_(i-1) + beta_(i-1)(p_(i-1) - omega_(i-1) * nu_(i-1))
                    nu.Multiply(-omega, temp);
                    vecP.Add(temp, temp2);
                    temp2.CopyTo(vecP);

                    vecP.Multiply(beta, vecP);
                    vecP.Add(residuals, temp2);
                    temp2.CopyTo(vecP);
                }
                else
                {
                    // p_i = r_(i-1)
                    residuals.CopyTo(vecP);
                }

                // SOLVE Mp~ = p_i // M = preconditioner
                _preconditioner.Approximate(vecP, vecPdash);

                // nu_i = Ap~
                matrix.Multiply(vecPdash, nu);

                // alpha_i = rho_(i-1)/ (r~^T nu_i) = rho / dotproduct(r~ and nu_i)
                alpha = currentRho * 1 / tempResiduals.DotProduct(nu);

                // s = r_(i-1) - alpha_i nu_i
                nu.Multiply(-alpha, temp);
                residuals.Add(temp, vecS);

                // Check if we're converged. If so then stop. Otherwise continue;
                // Calculate the temporary result.
                // Be careful not to change any of the temp vectors, except for
                // temp. Others will be used in the calculation later on.
                // x_i = x_(i-1) + alpha_i * p^_i + s^_i
                vecPdash.Multiply(alpha, temp);
                temp.Add(vecSdash, temp2);
                temp2.CopyTo(temp);
                temp.Add(result, temp2);
                temp2.CopyTo(temp);

                // Check convergence and stop if we are converged.
                if (!ShouldContinue(iterationNumber, temp, input, vecS))
                {
                    temp.CopyTo(result);

                    // Calculate the true residual
                    CalculateTrueResidual(matrix, residuals, result, input);

                    // Now recheck the convergence
                    if (!ShouldContinue(iterationNumber, result, input, residuals))
                    {
                        // We're all good now.
                        return;
                    }

                    // Continue the calculation
                    iterationNumber++;
                    continue;
                }

                // SOLVE Ms~ = s
                _preconditioner.Approximate(vecS, vecSdash);

                // temp = As~
                matrix.Multiply(vecSdash, temp);

                // omega_i = temp^T s / temp^T temp
                omega = temp.DotProduct(vecS) / temp.DotProduct(temp);

                // x_i = x_(i-1) + alpha_i p^ + omega_i s^
                temp.Multiply(-omega, residuals);
                residuals.Add(vecS, temp2);
                temp2.CopyTo(residuals);

                vecSdash.Multiply(omega, temp);
                result.Add(temp, temp2);
                temp2.CopyTo(result);

                vecPdash.Multiply(alpha, temp);
                result.Add(temp, temp2);
                temp2.CopyTo(result);

                // for continuation it is necessary that omega_i != 0.0
                // If omega is only 1 ULP from zero then we fail.
                if (omega.AlmostEqual(0, 1))
                {
                    // Omega-type breakdown
                    throw new Exception("Iterative solver experience a numerical break down");
                }

                if (!ShouldContinue(iterationNumber, result, input, residuals))
                {
                    // Recalculate the residuals and go round again. This is done to ensure that
                    // we have the proper residuals.
                    // The residual calculation based on omega_i * s can be off by a factor 10. So here
                    // we calculate the real residual (which can be expensive) but we only do it if we're
                    // sufficiently close to the finish.
                    CalculateTrueResidual(matrix, residuals, result, input);
                }

                iterationNumber++;
            }
        }