Calculating Exponential Moving Average in one cell (Scan Function?)

aryan1997

New Member
Joined
Jun 14, 2022
Messages
8
Office Version
  1. 365
Platform
  1. Windows
Hi all,

I am trying to figure out how to calculate the Exponential moving average of a stock. The sheet shows the steps involved. I tried using the scan function but I couldn't figure it out. I hope someone smarter than me can help with the formula or point me in the right direction. I know I can do it by adding helper columns but this will be much more efficient and help me learn something new. Thanks.



Book1
ABCDEFGH
1APPLE INC. (XNAS:AAPL)
2DateClosing PriceEMA CalculationMultiplier0.3
308-22-2022$ 167.57
408-23-2022$ 167.23
508-24-2022$ 167.53
608-25-2022$ 170.03
708-26-2022$ 163.62
808-29-2022$ 161.38
908-30-2022$ 158.91
1008-31-2022$ 157.22
1109-01-2022$ 157.96
1209-02-2022$ 155.81
1309-06-2022$ 154.53
1409-07-2022$ 155.96
1509-08-2022$ 154.46
1609-09-2022$ 157.37
1709-12-2022$ 163.43160.68#Starting no. is the last 14 day average
1809-13-2022$ 153.84159.69# After that its (Close - Previous Day EMA)*Multiplier + Previous Day EMA
1909-14-2022$ 155.31160.81
2009-15-2022$ 152.37158.72
2109-16-2022$ 150.70157.70
2209-19-2022$ 154.48156.10
2309-20-2022$ 156.90154.48
2409-21-2022$ 153.72154.48
2509-22-2022$ 152.74155.21
2609-23-2022$ 150.43154.76
2709-26-2022$ 150.77154.15
2809-27-2022$ 151.76153.04
2909-28-2022$ 149.84152.36
3009-29-2022$ 142.48152.18# Value I am looking for
Sheet1
Cell Formulas
RangeFormula
B3:C30B3=STOCKHISTORY(A1,WORKDAY(TODAY(),-29),TODAY(),0,0,0,1)
D17D17=AVERAGE(C3:C16)
D18:D30D18=((C16-D17)*$G$2)+D17
Dynamic array formulas.
 

Excel Facts

Lock one reference in a formula
Need 1 part of a formula to always point to the same range? use $ signs: $V$2:$Z$99 will always point to V2:Z99, even after copying
I have written my own EMA function that I use for exactly this purpose and I keep it in an addin so I can use it anywhere, you could put itin your personal.xlb file:
put 14 id D1 this is the time period, then put this in D18:
Excel Formula:
=ema(D$1,D17,C18)
and copy down:
this is the code for hte ema fucntion;
VBA Code:
Function EMA(Period, Lasttime, Drive)
If Not (IsNumeric(Period)) Then
  EMA = "This functions calculates the Expontial Moving average, it has three parameters: Period (days), The last time Value of the EMA, the latest value of variable"
Else
    TC = 2 / (Period + 1)
    EMA = Lasttime + TC * (Drive - Lasttime)
End If
End Function
 
Upvote 0
I have written my own EMA function that I use for exactly this purpose and I keep it in an addin so I can use it anywhere, you could put itin your personal.xlb file:
put 14 id D1 this is the time period, then put this in D18:
Excel Formula:
=ema(D$1,D17,C18)
and copy down:
this is the code for hte ema fucntion;
VBA Code:
Function EMA(Period, Lasttime, Drive)
If Not (IsNumeric(Period)) Then
  EMA = "This functions calculates the Expontial Moving average, it has three parameters: Period (days), The last time Value of the EMA, the latest value of variable"
Else
    TC = 2 / (Period + 1)
    EMA = Lasttime + TC * (Drive - Lasttime)
End If
End Function
Thanks for the reply but this doesn't give me the solution to the problem. This would still require me to have separate columns for closing price and multiple cells to calculate separately. I am looking to create a formula that would output the final value (152.18) in the same cell as the formula.

On a side note, with lambda you can create the custom function you mentioned without vba.
 
Upvote 0
Thanks for the reply but this doesn't give me the solution to the problem. This would still require me to have separate columns for closing price and multiple cells to calculate separately. I am looking to create a formula that would output the final value (152.18) in the same cell as the formula.

On a side note, with lambda you can create the custom function you mentioned without vba.
Just realized that you are a well-known member, so you probably know about lambda already 😬
 
Upvote 0
You can use my ema function and wrap in another function like this:
VBA Code:
Sub test()
Dim first As Range
Dim second As Range
Set first = Range("C3:c16")
Set second = Range("c17:c30")
result = totema(first, second, 14)
MsgBox result
End Sub
Function totema(Avrange As Range, emarange As Range, Period)
startav = WorksheetFunction.Average(Avrange)
emaarray = emarange
For i = 1 To UBound(emaarray, 1)
 startav = EMA(Period, startav, emaarray(i, 1))
Next i
totema = startav
End Function

Function EMA(Period, Lasttime, Drive)
If Not (IsNumeric(Period)) Then
  EMA = "This functions calculates the Expontial Moving average, it has three parameters: Period (days), The last time Value of the EMA, the latest value of variable"
Else
    TC = 2 / (Period + 1)
    EMA = Lasttime + TC * (Drive - Lasttime)
End If
End Function

You can then put this in a singel cell:
Excel Formula:
=totema(C3:C16,C17:C30,14)
 
Upvote 0
Solution
You can use my ema function and wrap in another function like this:
VBA Code:
Sub test()
Dim first As Range
Dim second As Range
Set first = Range("C3:c16")
Set second = Range("c17:c30")
result = totema(first, second, 14)
MsgBox result
End Sub
Function totema(Avrange As Range, emarange As Range, Period)
startav = WorksheetFunction.Average(Avrange)
emaarray = emarange
For i = 1 To UBound(emaarray, 1)
 startav = EMA(Period, startav, emaarray(i, 1))
Next i
totema = startav
End Function

Function EMA(Period, Lasttime, Drive)
If Not (IsNumeric(Period)) Then
  EMA = "This functions calculates the Expontial Moving average, it has three parameters: Period (days), The last time Value of the EMA, the latest value of variable"
Else
    TC = 2 / (Period + 1)
    EMA = Lasttime + TC * (Drive - Lasttime)
End If
End Function

You can then put this in a singel cell:
Excel Formula:
=totema(C3:C16,C17:C30,14)
Ah got it, this is a good solution as well. I was eventually able to figure it out by using the scan function.
 
Upvote 0
My solution: Here is the custom function I was able to create. I can already see some improvements I could make but for now this gets the job done. One example is that instead of using SCAN we can use REDUCE to get the final value instead of me using Index and Count to get it.

LAMBDA(stock, periodindays,
LET(
stocksymbol, stock,
period, periodindays,
smoothingfactor, 2 / (period + 1),
startingaverage, AVERAGE(
STOCKHISTORY(
stocksymbol,
WORKDAY(TODAY(), -period * 2),
WORKDAY(TODAY(), -period),
0,
0,
1
)
),
emadata, STOCKHISTORY(
stocksymbol,
WORKDAY(TODAY(), -(period - 1)),
TODAY(),
0,
0,
1
),
currentemadata, SCAN(
startingaverage,
emadata,
LAMBDA(a, b, ((b - a) * smoothingfactor) + a)
),
currentema, INDEX(currentemadata, COUNTA(currentemadata)),
currentema
)
)
 
Upvote 0

Forum statistics

Threads
1,223,884
Messages
6,175,173
Members
452,615
Latest member
bogeys2birdies

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top