我正在尝试用 Python 编写 smma(平滑移动平均线)。我从 tradeview 中的 pine 脚本中获取公式。
smma = 0.0
smma := na(smma[1]) ? ta.sma(src, length) : (smma[1] * (length - 1) + src) / length
因此,当没有先前的 smma 值时,我们应该采用 (src,length) 的简单移动平均值。接下来的计算是根据 (smma[1] * (length - 1) + src) / length 进行的。 smmma[1] 是之前的 smma 值。
这是我的代码:
def smma(src, length):
smma = 0.0
dataLength = len(src)
lookbackPeriod = dataLength - length
#first value of smma is the sma of src and length
#Convert list to dataframe
df = pd.DataFrame(src, columns = ['hl2'])
smma = df.rolling(window=length).mean()
smma = float(smma.iloc[-1])
log.info(f"First smma value = {smma}")
lookbackPeriod = dataLength - length + 1 #calculate smma for the other values
while (lookbackPeriod < dataLength):
smma = (smma * (length - 1) + float(src[lookbackPeriod])) / length
log.info(f"lookback = {lookbackPeriod} src[lookbackPeriod] = {src[lookbackPeriod]} smma = {smma}")
lookbackPeriod = lookbackPeriod + 1
return smma
周期长度为 5 的输出如下所示:
[2021-11-07 12:26:21,701] First smma value = 61842.0
[2021-11-07 12:26:21,701] lookback = 196 src[lookbackPeriod] = 61817.25 smma = 61837.05
[2021-11-07 12:26:21,701] lookback = 197 src[lookbackPeriod] = 61883.5 smma = 61846.340000000004
[2021-11-07 12:26:21,701] lookback = 198 src[lookbackPeriod] = 61867.75 smma = 61850.621999999996
[2021-11-07 12:26:21,702] lookback = 199 src[lookbackPeriod] = 61838.0 smma = 61848.0976
在我的例子中,src 是一个包含 200 个值的列表。
当我将第一个 smma 的值与 sma 进行比较时,与 Tradingview 上的值相比,它是正确的。与我在 Tradingview 上看到的相比,smma 的最终值不正确。 (在这种情况下,我将其作为源(高+低)/2,而不是收盘价,但当我将其作为 Tradingview 中的源时,它仍然无法正确显示)有人能发现我在这里做错了什么吗?
非常感谢!
https://technical-analysis-library-in-python.readthedocs.io/en/latest/ta .html)并获取 EMA。 SMMA本质上是EMA,只是长度不同。您可以在交易视图中尝试插入 SMMA 和 EMA,并按照此处的 screennip 中所述更改长度。您会发现 SMMA 和 EMA 在这里重叠。
理想情况下,SMMA长度为x,将EMA长度设置为x*2-1(当然长度1除外),你会得到准确的结果。希望这有帮助。
问题是你可以找到各种计算 SMMA 的公式,例如: 老实说,到目前为止我无法获得准确的 TradingView 结果,但我发现
chartmill 结果最接近 TradingView。
我尝试在 Java 中实现 SMMA 作为ta4j 库的扩展。请在下面找到我最近的结果。希望您发现它有帮助,我们将共同找到正确的实现:
public class SMMAIndicator extends RecursiveCachedIndicator<Num> {
/**
* N - Number of periods, over which the indicator is calculated.
*/
private final int barCount;
private final Num n;
/**
* Usually ClosePriceIndicator
*/
private final Indicator<Num> indicator;
/**
* SMA to calculate 1st SMMA period per index
*/
private final SMAIndicator smaIndicator;
public SMMAIndicator(Indicator<Num> indicator, int barCount) {
super(indicator.getBarSeries());
this.barCount = barCount;
this.n = numOf(barCount);
this.indicator = indicator;
this.smaIndicator = new SMAIndicator(indicator, barCount);
}
@Override
public Num calculate(int index) {
var i = max(0, index - barCount + 1);
if (i == 0) {
return smaIndicator.getValue(index);
}
if (i == 1) {
var nMinus1 = n.minus(numOf(1));
var smma0 = getValue(index - 1);
var input = indicator.getValue(index);
return smma0.multipliedBy(nMinus1).plus(input).dividedBy(n);
}
var prevSmma = getValue(index - 1);
var prevSum = prevSmma.multipliedBy(n);
return prevSum.minus(prevSmma).plus(indicator.getValue(index)).dividedBy(n);
}
}
def calculate_smma(src, length):
smma = pd.Series(index=src.index, dtype=float)
for i in range(len(src)):
if pd.isna(smma.iloc[i - 1]):
smma.iloc[i] = src.iloc[:i + 1].mean()
else:
smma.iloc[i] = (smma.iloc[i - 1] * (length - 1) + src.iloc[i]) / length
return smma