Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixing ALMA calculation per Issue 455 #456

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 18 additions & 20 deletions pandas_ta/overlap/alma.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# -*- coding: utf-8 -*-
from numpy import exp as npExp
from numpy import nan as npNaN
from numpy import power as npPow
from numpy import dot as npDot
from numpy import empty as npEmpty
from numpy import array as npArray
from pandas import Series
from pandas_ta.utils import get_offset, verify_series

Expand All @@ -14,31 +18,25 @@ def alma(close, length=None, sigma=None, distribution_offset=None, offset=None,
close = verify_series(close, length)
offset = get_offset(offset)

if close is None: return
if close is None:
return

# Pre-Calculations
# Compute filter weights
m = distribution_offset * (length - 1)
s = length / sigma
wtd = list(range(length))
for i in range(0, length):
wtd[i] = npExp(-1 * ((i - m) * (i - m)) / (2 * s * s))

# Calculate Result
result = [npNaN for _ in range(0, length - 1)] + [0]
for i in range(length, close.size):
window_sum = 0
cum_sum = 0
for j in range(0, length):
# wtd = math.exp(-1 * ((j - m) * (j - m)) / (2 * s * s)) # moved to pre-calc for efficiency
window_sum = window_sum + wtd[j] * close.iloc[i - j]
cum_sum = cum_sum + wtd[j]

almean = window_sum / cum_sum
result.append(npNaN) if i == length else result.append(almean)

filter_index = npArray(range(length))
weights = npExp(-npPow(filter_index - m, 2) / (2 * npPow(s, 2)))
norm = weights.sum()

result = npEmpty(close.shape)
result[:] = npNaN
valid_rng = range(length - 1, close.size)
for j in valid_rng:
subset = close[j - length + 1:j + 1]
result[j] = npDot(subset, weights) / norm
alma = Series(result, index=close.index)

# Offset
# Apply offset
if offset != 0:
alma = alma.shift(offset)

Expand Down