Fix issue in exponential moving average generator. Although I found where the generator was being used....the context

of the usage has no impact on the issue with the generator because the usage was only using the first index in the
exponential moving average which always amounts to just the value of the simple moving average.  (i.e.) smoothing does
not occur on the first index, only subsequent indices are smoothed.
This commit is contained in:
2025-01-29 11:12:37 -05:00
parent 8143730c38
commit a1b15682ce

View File

@@ -114,20 +114,30 @@ namespace MarketData.Generator
return null;
}
}
/// <summary>
/// The EMA coverage shoudld be the same as the simple moving average. If you have 10 elements in the SMA then you should have 10 elements in the EMA
/// The EMA smooths the line by applying a smoothing (Beta) where Beta=1/(dayCount+1). Foe example if you are wanting to calculate the
/// 20 day exponential moving average over a series then Beta=2/(20+1)=.095
/// The formula: EMA=prevEMA.AVGPrice+beta*(smaPrice.CurrentPrice - prevEMA.AVGPrice)
/// Tom Basso uses a 9 day(Fast) and 41 day(Slow) exponential moving average crossover to determine change in trend direction.
/// </summary>
/// <param name="prices"></param>
/// <param name="dayCount"></param>
/// <returns></returns>
public static DMAPrices GenerateExponentialMovingAverage(Prices prices,int dayCount)
{
try
{
if(null==prices||prices.Count<dayCount+1)return null; // (i.e.) a 20 day ExponentialMovingAverage requires 21 days of data
double smoothing=2.00/((double)dayCount+1.00);
double beta=2.00/((double)dayCount+1.00);
DMAPrices emaPrices=new DMAPrices();
DMAPrices smaPrices=GenerateMovingAverage(prices,dayCount);
if(null==smaPrices||smaPrices.Count<dayCount)return null;
smaPrices=new DMAPrices(smaPrices.Top(dayCount));
for(int index=0;index<smaPrices.Count;index++)
{
DMAPrice smaPrice=smaPrices[index]; // where yesterday is at index+1
DMAPrice smaPrice=smaPrices[index];
DMAPrice emaPrice=new DMAPrice();
if(0==index)
{
@@ -141,7 +151,7 @@ namespace MarketData.Generator
DMAPrice prevEMA=emaPrices[emaPrices.Count-1];
emaPrice.Symbol=smaPrice.Symbol;
emaPrice.Date=smaPrice.Date;
emaPrice.AVGPrice=(smaPrice.AVGPrice*(smoothing/(1.00+dayCount)))+(prevEMA.AVGPrice*(1.00-(smoothing/(1.00+dayCount))));
emaPrice.AVGPrice = prevEMA.AVGPrice+beta*(smaPrice.CurrentPrice - prevEMA.AVGPrice);
emaPrices.Add(emaPrice);
}
}
@@ -153,6 +163,7 @@ namespace MarketData.Generator
return null;
}
}
/// <summary>Generates a dayCount moving average given prices.</summary>
public static DMAPrices GenerateMovingAverage(Prices prices, int dayCount)
{