/// <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); }
/// <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); } }
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!"); } }
/// <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); }
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); } }
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)); }
/// <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)); }
/// <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()); }
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); }
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); }
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); }
public void CanGetRS() { double rs = RSICalculator.GetRS(37.77); Assert.IsTrue(rs.AlmostEqual(0.61)); }
public void NotEqualDTest() { double test = 0; Assert.IsTrue(test.AlmostEqual(0.1, 0.11)); }
public void AlmostEqualDOnNegativeNumbersTest() { double test = -10; Assert.IsTrue(test.AlmostEqual(-11.1, 1.1)); }
/// <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 > 0, x > 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); }
/// <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 > 0, x > 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); }
/// <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 > 0, x > 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)); }
public WavEditor FreezeRegion(double fromSecond, double time = -1) { return(FreezeRegion((int)(fromSecond * wav.SampleRate), (int)(time.AlmostEqual(-1) ? -1 : (fromSecond + time) * wav.SampleRate))); }
/// <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)); }
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)); }
/// <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++; } }