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
2 Answers
Reset to default 0TradingView 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;
}