Example #1
0
        /// <summary>
        /// Returns the max of the feerates calculated with a 60%
        /// threshold required at target / 2, an 85% threshold required at target and a
        /// 95% threshold required at 2 * target.Each calculation is performed at the
        /// shortest time horizon which tracks the required target.Conservative
        /// estimates, however, required the 95% threshold at 2 * target be met for any
        /// longer time horizons also.
        /// </summary>
        public FeeRate EstimateSmartFee(int confTarget, FeeCalculation feeCalc, bool conservative)
        {
            lock (this.lockObject)
            {
                if (feeCalc != null)
                {
                    feeCalc.DesiredTarget  = confTarget;
                    feeCalc.ReturnedTarget = confTarget;
                }

                double           median     = -1;
                EstimationResult tempResult = new EstimationResult();

                // Return failure if trying to analyze a target we're not tracking
                if (confTarget <= 0 || confTarget > this.longStats.GetMaxConfirms())
                {
                    return(new FeeRate(0));  // error condition
                }

                // It's not possible to get reasonable estimates for confTarget of 1
                if (confTarget == 1)
                {
                    confTarget = 2;
                }

                int maxUsableEstimate = MaxUsableEstimate();
                if (confTarget > maxUsableEstimate && maxUsableEstimate > 1)
                {
                    confTarget = maxUsableEstimate;
                }
                if (feeCalc != null)
                {
                    feeCalc.ReturnedTarget = confTarget;
                }

                if (confTarget <= 1)
                {
                    return(new FeeRate(0)); // error condition
                }

                Guard.Assert(confTarget > 0); //estimateCombinedFee and estimateConservativeFee take unsigned ints

                // true is passed to estimateCombined fee for target/2 and target so
                // that we check the max confirms for shorter time horizons as well.
                // This is necessary to preserve monotonically increasing estimates.
                // For non-conservative estimates we do the same thing for 2*target, but
                // for conservative estimates we want to skip these shorter horizons
                // checks for 2*target because we are taking the max over all time
                // horizons so we already have monotonically increasing estimates and
                // the purpose of conservative estimates is not to let short term
                // fluctuations lower our estimates by too much.
                double halfEst = EstimateCombinedFee(confTarget / 2, HalfSuccessPct, true, tempResult);
                if (feeCalc != null)
                {
                    feeCalc.Estimation = tempResult;
                    feeCalc.Reason     = FeeReason.HalfEstimate;
                }
                median = halfEst;
                double actualEst = EstimateCombinedFee(confTarget, SuccessPct, true, tempResult);
                if (actualEst > median)
                {
                    median = actualEst;
                    if (feeCalc != null)
                    {
                        feeCalc.Estimation = tempResult;
                        feeCalc.Reason     = FeeReason.FullEstimate;
                    }
                }
                double doubleEst = EstimateCombinedFee(2 * confTarget, DoubleSuccessPct, !conservative, tempResult);
                if (doubleEst > median)
                {
                    median = doubleEst;
                    if (feeCalc != null)
                    {
                        feeCalc.Estimation = tempResult;
                        feeCalc.Reason     = FeeReason.DoubleEstimate;
                    }
                }

                if (conservative || median == -1)
                {
                    double consEst = EstimateConservativeFee(2 * confTarget, tempResult);
                    if (consEst > median)
                    {
                        median = consEst;
                        if (feeCalc != null)
                        {
                            feeCalc.Estimation = tempResult;
                            feeCalc.Reason     = FeeReason.Coservative;
                        }
                    }
                }

                if (median < 0)
                {
                    return(new FeeRate(0));            // error condition
                }
                return(new FeeRate(Convert.ToInt64(median)));
            }
        }