/// <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.AlmostEqualRelative(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); }
/// <summary> /// Adaptive approximation of the definite integral in the provided interval by the trapezium rule. /// </summary> /// <param name="f">The analytic smooth function to integrate.</param> /// <param name="intervalBegin">Where the interval starts, inclusive and finite.</param> /// <param name="intervalEnd">Where the interval stops, inclusive and finite.</param> /// <param name="targetError">The expected accuracy of the approximation.</param> /// <returns>Approximation of the finite integral in the given interval.</returns> public static double IntegrateAdaptive(Func <double, double> f, double intervalBegin, double intervalEnd, double targetError) { if (f == null) { throw new ArgumentNullException(nameof(f)); } int numberOfPartitions = 1; double step = intervalEnd - intervalBegin; double sum = 0.5 * step * (f(intervalBegin) + f(intervalEnd)); for (int k = 0; k < 20; k++) { double midpointsum = 0; for (int i = 0; i < numberOfPartitions; i++) { midpointsum += f(intervalBegin + ((i + 0.5) * step)); } midpointsum *= step; sum = 0.5 * (sum + midpointsum); step *= 0.5; numberOfPartitions *= 2; if (sum.AlmostEqualRelative(midpointsum, targetError)) { break; } } return(sum); }
public static void AlmostEqualRelative(double expected, double actual, int decimalPlaces) { if (double.IsNaN(expected) && double.IsNaN(actual)) { return; } if (!expected.AlmostEqualRelative(actual, decimalPlaces)) { Assert.Fail("Not equal within {0} places. Expected:{1}; Actual:{2}", decimalPlaces, expected, actual); } }
/// <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> /// Asserts that the expected value and the actual value are equal up to a certain number of decimal places. If both /// <paramref name="expected"/> and <paramref name="actual"/> are NaN then no assert is thrown. /// </summary> /// <param name="expected">The expected value.</param> /// <param name="actual">The actual value.</param> /// <param name="decimalPlaces">The number of decimal places to agree on.</param> public static void AlmostEqual(double expected, double actual, int decimalPlaces) { if (double.IsNaN(expected) && double.IsNaN(actual)) { return; } var pass = expected.AlmostEqualRelative(actual, decimalPlaces); if (!pass) { // signals Gallio that the test failed. Assert.Fail("Not equal within {0} places. Expected:{1}; Actual:{2}", decimalPlaces, expected, actual); } }
private static List <double> IdenticalVolumeFilter(ref List <double> price, ref List <double> volume) { List <double> idenSR = new List <double>(); bool haveIncidentIdentical = true; while (haveIncidentIdentical) { haveIncidentIdentical = false; int lowIndicator = 0; for (; lowIndicator < volume.Count - 1; lowIndicator++) { double currentVolume = volume[lowIndicator]; double nextVolume = volume[lowIndicator + 1]; if (currentVolume.AlmostEqualRelative(nextVolume, AbsoluteError)) { haveIncidentIdentical = true; break; } } if (haveIncidentIdentical) { int highIndicator = lowIndicator + 1; for (; highIndicator < volume.Count; highIndicator++) { double currentVolume = volume[highIndicator]; double prevVolume = volume[highIndicator - 1]; if (!currentVolume.AlmostEqualRelative(prevVolume, AbsoluteError)) { break; } } idenSR.Add(price[lowIndicator]); idenSR.Add(price[highIndicator - 1]); price.RemoveRange(lowIndicator, highIndicator - lowIndicator); volume.RemoveRange(lowIndicator, highIndicator - lowIndicator); } } return(idenSR); }
public static bool GreaterOrEqual(this double var1, double var2, double error = 1e-5) { return(var1 >= var2 || var1.AlmostEqualRelative(var2, error)); }