最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c# - EMA Calculation not matching - Stack Overflow

programmeradmin0浏览0评论

Im trying to replicate TradingView EMA calculation for a custom software, but get different results than on tradingview. According to TradingView Ema calculation documentation is should be the exact same method. What am i missing?

Sample Code: (Expected value for 01-09 is 84.99), following values are also off

var closePrices = new List<(string, decimal)>
{
  ("2024-01-03 00:00:00.0000000" , 84.0600000000m),
  ("2024-01-04 00:00:00.0000000" , 96.8900000000m),
  ("2024-01-05 00:00:00.0000000" , 89.6400000000m),
  ("2024-01-06 00:00:00.0000000" , 80.4300000000m),
  ("2024-01-07 00:00:00.0000000" , 73.1800000000m),
  ("2024-01-08 00:00:00.0000000" , 85.3900000000m),
  ("2024-01-09 00:00:00.0000000" , 85.3400000000m),
  ("2024-01-10 00:00:00.0000000" , 97.9800000000m),
  ("2024-01-11 00:00:00.0000000" , 108.0600000000m)
};

var emas = CalculateEMA(closePrices, 7);
foreach(var ema in emas)
{
    Console.WriteLine(ema);
}
static List<(string, decimal)> CalculateEMA(List<(string,decimal)> prices, int period)
{
    List<(string, decimal)> ema = new List<(string, decimal)>();
    decimal alpha = 2m / (period + 1);
    ema.Add(prices[0]);
    for (int i = 1; i < prices.Count; i++)
    {
        decimal value = alpha * prices[i].Item2 + (1 - alpha) * ema[i - 1].Item2;
        ema.Add((prices[i].Item1, value));
    }

    return ema;
}

Output:

(2024-01-03 00:00:00.0000000, 84,0600000000)
(2024-01-04 00:00:00.0000000, 87,267500000000)
(2024-01-05 00:00:00.0000000, 87,86062500000000)
(2024-01-06 00:00:00.0000000, 86,0029687500000000)
(2024-01-07 00:00:00.0000000, 82,797226562500000000)
(2024-01-08 00:00:00.0000000, 83,44541992187500000000)
(2024-01-09 00:00:00.0000000, 83,9190649414062500000000) <- should be 84,99
(2024-01-10 00:00:00.0000000, 87,434298706054687500000000)
(2024-01-11 00:00:00.0000000, 92,59072402954101562500000000)

Im trying to replicate TradingView EMA calculation for a custom software, but get different results than on tradingview. According to TradingView Ema calculation documentation is should be the exact same method. What am i missing?

Sample Code: (Expected value for 01-09 is 84.99), following values are also off

var closePrices = new List<(string, decimal)>
{
  ("2024-01-03 00:00:00.0000000" , 84.0600000000m),
  ("2024-01-04 00:00:00.0000000" , 96.8900000000m),
  ("2024-01-05 00:00:00.0000000" , 89.6400000000m),
  ("2024-01-06 00:00:00.0000000" , 80.4300000000m),
  ("2024-01-07 00:00:00.0000000" , 73.1800000000m),
  ("2024-01-08 00:00:00.0000000" , 85.3900000000m),
  ("2024-01-09 00:00:00.0000000" , 85.3400000000m),
  ("2024-01-10 00:00:00.0000000" , 97.9800000000m),
  ("2024-01-11 00:00:00.0000000" , 108.0600000000m)
};

var emas = CalculateEMA(closePrices, 7);
foreach(var ema in emas)
{
    Console.WriteLine(ema);
}
static List<(string, decimal)> CalculateEMA(List<(string,decimal)> prices, int period)
{
    List<(string, decimal)> ema = new List<(string, decimal)>();
    decimal alpha = 2m / (period + 1);
    ema.Add(prices[0]);
    for (int i = 1; i < prices.Count; i++)
    {
        decimal value = alpha * prices[i].Item2 + (1 - alpha) * ema[i - 1].Item2;
        ema.Add((prices[i].Item1, value));
    }

    return ema;
}

Output:

(2024-01-03 00:00:00.0000000, 84,0600000000)
(2024-01-04 00:00:00.0000000, 87,267500000000)
(2024-01-05 00:00:00.0000000, 87,86062500000000)
(2024-01-06 00:00:00.0000000, 86,0029687500000000)
(2024-01-07 00:00:00.0000000, 82,797226562500000000)
(2024-01-08 00:00:00.0000000, 83,44541992187500000000)
(2024-01-09 00:00:00.0000000, 83,9190649414062500000000) <- should be 84,99
(2024-01-10 00:00:00.0000000, 87,434298706054687500000000)
(2024-01-11 00:00:00.0000000, 92,59072402954101562500000000)
Share Improve this question edited Feb 2 at 15:46 Steffx115 asked Feb 2 at 14:07 Steffx115Steffx115 327 bronze badges 9
  • You are probably doing an integer division. Change to following : decimal alpha = 2m / (decimal)(period + 1); – jdweng Commented Feb 2 at 14:11
  • doesnt affect my values, VS greys out the cast – Steffx115 Commented Feb 2 at 14:15
  • 2 Can you describe what your input is, what the result is and what the expected result would be instead? – Lajos Arpad Commented Feb 2 at 14:50
  • 2 What is the definition of type EmaResult? – jdweng Commented Feb 2 at 14:58
  • I will build a sample application including static test values, will update the question when im done – Steffx115 Commented Feb 2 at 15:25
 |  Show 4 more comments

2 Answers 2

Reset to default 0

TradingView calculates the initial EMA value by averaging the prices over the first period data points. Try this

using System;
using System.Collections.Generic;
using System.Linq;

public class EMA
{
    public static List<(string, decimal)> CalculateEMA(List<(string, decimal)> prices, int period)
    {
        List<(string, decimal)> ema = new List<(string, decimal)>();
        decimal alpha = 2m / (period + 1);

        decimal initialEMA = prices.Take(period).Average(p => p.Item2);
        ema.Add((prices[period - 1].Item1, initialEMA));

        decimal currentEMA = initialEMA;

        for (int i = period; i < prices.Count; i++)
        {
            currentEMA = alpha * prices[i].Item2 + (1 - alpha) * currentEMA;
            currentEMA = Math.Round(currentEMA, 2);
            ema.Add((prices[i].Item1, currentEMA));
        }

        return ema;
    }

    public static void Main(string[] args)
    {
        List<(string, decimal)> closePrices = new List<(string, decimal)>()
        {
            ("2024-01-03 00:00:00.0000000", 84.06m),
            ("2024-01-04 00:00:00.0000000", 96.89m),
            ("2024-01-05 00:00:00.0000000", 89.64m),
            ("2024-01-06 00:00:00.0000000", 80.43m),
            ("2024-01-07 00:00:00.0000000", 73.18m),
            ("2024-01-08 00:00:00.0000000", 85.39m),
            ("2024-01-09 00:00:00.0000000", 85.34m),
            ("2024-01-10 00:00:00.0000000", 97.98m),
            ("2024-01-11 00:00:00.0000000", 108.06m),
        };

        List<(string, decimal)> emas = CalculateEMA(closePrices, 7);

        foreach (var item in emas)
        {
            Console.WriteLine($"({item.Item1}, {item.Item2})");
        }
    }
}

Using your prices I got

(2024-01-09 00:00:00.0000000, 84.99)
(2024-01-10 00:00:00.0000000, 88.24)
(2024-01-11 00:00:00.0000000, 93.20)

Nuff said:

static decimal CalculateBiasCorrectedStartingValue(decimal[] closes, int period)
{
    if (closes == null || closes.Length < period)
        throw new ArgumentException("The closes array must contain at least 'period' number of elements.");

    // Calculate the simple moving average (SMA) of the first 'period' closes.
    decimal sum = 0.0m;
    for (int i = 0; i < period; i++)
    {
        sum += closes[i];
    }
    decimal sma = sum / period;

    // Calculate the smoothing constant alpha.
    decimal alpha = 2.0m / (period + 1.0m);
    decimal oneMinusAlpha = 1 - alpha;

    // Calculate the weighted sum for closes C_period, C_{period-1}, ..., C_2.
    // Note: The array is assumed to be zero-indexed with:
    // closes[0] = C1, closes[1] = C2, ..., closes[period-1] = C_period.
    decimal weightedSum = 0.0m;
    // j goes from 0 to period-2
    for (int j = 0; j <= period - 2; j++)
    {
        // For j = 0, weight = (1-alpha)^0 and we use closes[period-1] (i.e. C_period).
        // For j = 1, weight = (1-alpha)^1 and we use closes[period-2] (i.e. C_{period-1}), etc.
        weightedSum += (decimal)Math.Pow((double)oneMinusAlpha, j) * closes[period - 1 - j];
    }

    // Denom is (1-alpha)^(period-1)
    decimal denominator = (decimal)Math.Pow((double)oneMinusAlpha, period - 1);

    // Solve for y.
    decimal y = (sma - alpha * weightedSum) / denominator;

    return y;
}
发布评论

评论列表(0)

  1. 暂无评论