简体   繁体   中英

Convert Reverse Moving Average Formula to C#

I have been racking my brain trying to convert this formula to C# with no success.

REMA Formula . 在此输入图像描述
I am decent in doing proggies but not in Math.

Where 0 < λ ≤ 1 is a decay factor.
When λ < 1, the exponentially weighted moving average assigns greater weights to the prices.

Contrary to the regular exponential moving average that gives greater weights to the most recent prices, the reverse exponential moving average assigns greater weights to the oldest prices and decreases the importance of the most recent prices.

Efficient REMA() with error-checking & context-specific return values

Efficient? Yes, avoids repeating duplicate expensive ops ( or relying on compiler optimisation tricks )

With Error-checking? Yes, almost a must for Q/A procedures.

Context-specific? Yes, returns { -1. | REMA( k, lambda ) } { -1. | REMA( k, lambda ) } { -1. | REMA( k, lambda ) } which allows the caller to handle the corner case of input error(s).

double[] fTimeSeriesPRICE;     // a forward-stepping storage ( vs. a MT4 reversed-stepping model )

public double REMA( int k, double lambda )
{   
    if (  lambda <= 0.0        // lambda shall not fall on/under  0.0
       || lambda >  1.0        //        shall not grow beyond    1.0
       || k      <= 0          // depth  shall not be negative or 0
       )
       return -1.0;            // context-protecting RET value

    int aCurrentPricePTR  = fTimeSeriesPRICE.Length - 1;
    int aMaxIterableDEPTH = Math.Min( aCurrentPricePTR, k );

    double numerator   = 0.0;
    double denominator = 0.0;  // REMA formula-expansion contains +1 at the end, never less, never negative
    double lambdator   = 1.0;  // lambda ^ ( ( k - j ) == 0 ) == 1.0

    for ( int aReverseSteppingPTR  = 0;
              aReverseSteppingPTR <= aMaxIterableDEPTH;
              aReverseSteppingPTR++
              )
    {   numerator   += lambdator * fTimeSeriesPRICE[aCurrentPricePTR - aReverseSteppingPTR];
        denominator += lambdator;
        lambdator   *= lambda;
    }
    return numerator / denominator; // numerically fair, denominator never < +1.0
}

This appears to me to be one summation divided by another. Here is my attempt at a straight-forward answer. My results were definitely averages that were more heavily weighted toward the earlier entries in the list, but I don't claim to know if they were correct.

double[] m_prices;

public double Rema(int k, double lambda)
{
    // Simple parameter validation
    if(lambda == 0.0 || k == 0)
        return 0.0;

    // Ensure the iteration will not be larger than the number of entries
    int t = m_prices.Length - 1;
    k = Math.Min(t, k);

    double numerator = 0;
    double denominator = 0;
    for (int j = 0; j <= k; j++)
    {
        // Preform the 2 sigma operations from the formula
        numerator += Math.Pow(lambda, k-j) * m_prices[t - j];
        denominator += Math.Pow(lambda, k-j);
    }

    // Simple error check
    if (denominator == 0.0)
        return 0.0;
    return numerator / denominator;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM