我正在使用 google 表格和 GoogleFinance 函数来获取股票数据。我可以用下面的公式计算一个简单的移动平均线。我试图为每只股票获得长度为 8、13、21、55 的指数移动平均线。关于指数移动平均线公式的任何建议
=AVERAGE(INDEX(GoogleFinance("MSFT","all",WORKDAY(TODAY(),-8),TODAY()),,3))
我正在使用 google 表格和 GoogleFinance 函数来获取股票数据。我可以用下面的公式计算一个简单的移动平均线。我试图为每只股票获得长度为 8、13、21、55 的指数移动平均线。关于指数移动平均线公式的任何建议
=AVERAGE(INDEX(GoogleFinance("MSFT","all",WORKDAY(TODAY(),-8),TODAY()),,3))
我发现这个归功于这个用户“Jonathan K 2806”。
试试这个,更简单,可能就足够了:
/**
* Calculates the EMA of the range.
*
* @param {range} range The range of cells to calculate.
* @param {number} n The number of trailing samples to give higer weight to, e.g. 30.
* @return The EMA of the range.
* @customfunction
*/
function EMA(range, n) {
if (!range.reduce) {
return range;
}
n = Math.min(n, range.length);
var a = 2 / (n + 1);
return range.reduce(function(accumulator, currentValue, index, array) {
return currentValue != "" ? (currentValue * a + accumulator * (1-a)) : accumulator;
}, 0);
}
转到工具 -> 脚本编辑器,将其粘贴到那里并点击保存,然后返回到您的电子表格并在单元格中输入 =EMA($A2:$A100, 10),或者您想使用它。
以下公式用于计算当前指数移动平均线 (EMA):
EMA = 收盘价 x decay_multiplayer + EMA(前一天) x (1-decay_multiplayer)
EMA 赋予近期价格更高的权重,而常规移动平均线赋予所有值同等权重。
decay_multiplayer应该选择大于 0 且小于 1。
如果您选择较大的数字,如短期移动平均线(更快衰减),如果您选择较小的数字,如长期移动平均线。
要在 google sheet 中实现这一点,您必须创建一个代表每天 EMV 值的新列。您必须填写第一个 EMV 值(第一个收盘价),然后使用上面的函数根据当前收盘价和之前的 EMV 值计算每个新的 EMV。
我在这里创建了一个谷歌表作为示例: https ://docs.google.com/spreadsheets/d/1ITfRfwQCBV-0amWpZzae2PbKBPAL_8YluUEmU_vbsCI/edit?usp=sharing
上述公式在技术上与指数移动平均线不同。指数衰减函数如下。 https://en.wikipedia.org/wiki/Exponential_decay
它通常用于模拟随时间衰减的影响,更重的权重更接近的条目(如上)。话虽如此,上面的公式并不相同。
EWMA/EMA 的实际形式有些不同,可以在这里找到:https ://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average
以上可能被认为是指数平滑的变体,但实际上并非如此:https ://en.wikipedia.org/wiki/Exponential_smoothing
就个人而言,我更喜欢使用 e^-ax 函数对我的平均值进行加权。我可以控制“a”参数来控制前后项目的权重,以便更好地调整权重。
currentValueComponent_i=currentValue * e^-time_i/Tau 为您想要的许多项目添加尽可能多的 currentValueComponents。Tau 是将添加到每次迭代中的元素衰减 63% 的时间常数,具体取决于加权平均值中包含的项目数。
资料来源:我是一名工程师。我定期这样做。
回馈对 Jonathan K 工作的一些改进。
提高短输入的准确性(range.length = 1 或 2)
边界检查 n
指定输入数组的预期顺序
给出 a 的 1 个替代定义
添加测试功能
/**
* Calculates the EMA of the range.
*
* @param {range} range The range of cells to calculate. New values (higher weight) should be on the left.
* @param {number} n The number of trailing samples to give higher weight to, e.g. 30.
* Values below 1 are treated as 1, which will just return the most recent value.
* @return The EMA of the range.
* @customfunction
*/
function EMA(range, n) {
if (!range.reduce) {
// can't run ema - bail
return range;
} else if (range.flat && range.reverse) {
// flatten the array if possible & reorganize w/ new values on right (last)
// NOTE: remove .reverse if the rightmost elements of input range are most recent / need higher weight
range = range.flat().reverse();
}
n = Math.max(n,1); // n has lower bound of 1
var a = 1-(2/(n+1));
// with the existing a setup, 86% of the total EMA weight will belong to the first n values.
// an alternate definition for a where n would be the desired number of intervals to keep ()
// ex: n = 4 -> quarterly values would get a "mean lifetime" of 1 year.
// var a = 1-Math.exp(-1 / n);
return range.reduce(function(accumulator, currentValue, index, array) {
if (currentValue != "") {
if (accumulator == null) {
return currentValue;
} else {
return currentValue * a + accumulator * (1-a);
}
} else {
return accumulator;
}
}, null);
}
function test() {
var emaValue = EMA([[13,14],[15,16]], 4);
Logger.log(emaValue);
}
最简单的方法是,给定一列X2:X...
和单元格中的权重系数 a,Z1
可以递归地计算行中的指数移动平均值Y2:Y...
,如下所示:
EMA
=X2
=$Z$1*X3+(1-$Z$1)*(Y2)
=$Z$1*X4+(1-$Z$1)*(Y3)
=$Z$1*X5+(1-$Z$1)*(Y4)
=... # the pattern will repeat itself properly using the drag function
此处描述了递归公式: https ://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average
当然,这仅适用于数据点之间的间隔始终相同的情况。