-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathewma.py
101 lines (74 loc) · 2.81 KB
/
ewma.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
"""Computing of exponentially weighted values."""
# ----------------------------------------------------------------------------------------------------------------------------
# LOGGING
# ----------------------------------------------------------------------------------------------------------------------------
import logging
logger = logging.getLogger(__name__)
# ----------------------------------------------------------------------------------------------------------------------------
# Packages
# ----------------------------------------------------------------------------------------------------------------------------
from pyutilz.pythonlib import ensure_installed
# ensure_installed("numpy")
# ----------------------------------------------------------------------------------------------------------------------------
# Normal Imports
# ----------------------------------------------------------------------------------------------------------------------------
from typing import *
import numpy as np
from numba import njit
def ewma(x, alpha) -> np.ndarray:
"""
Returns the exponentially weighted moving average of x.
>>>alpha = 0.55
>>>x = np.random.randint(0,30,15)
>>>df = pd.DataFrame(x, columns=['A'])
>>>np.allclose(df.ewm(alpha=alpha).mean().values.flatten(),ewma(x=x, alpha=alpha))
True
Parameters:
-----------
x : array-like
alpha : float {0 <= alpha <= 1}
Returns:
--------
ewma: numpy array
the exponentially weighted moving average
"""
# Coerce x to an array
# x = np.array(x)
n = x.size
# Create an initial weight matrix of (1-alpha), and a matrix of powers
# to raise the weights by
w0 = np.ones(shape=(n, n)) * (1 - alpha)
p = np.vstack([np.arange(i, i - n, -1) for i in range(n)])
# Create the weight matrix
w = np.tril(w0**p, 0)
# Calculate the ewma
return np.dot(w, x[:: np.newaxis]) / w.sum(axis=1)
@njit
def compute_p(n: int) -> np.ndarray:
p = np.empty((n, n), dtype=np.int64) # Preallocate the output array
for i in range(n):
for j in range(n):
p[i, j] = i - j
return p
@njit()
def ewma_numba(x: np.ndarray, alpha: float) -> np.ndarray:
"""
Returns the exponentially weighted moving average of x.
Parameters:
-----------
x : array-like
alpha : float {0 <= alpha <= 1}
Returns:
--------
ewma: numpy array
the exponentially weighted moving average
"""
n = x.size
# Create an initial weight matrix of (1-alpha), and a matrix of powers
# to raise the weights by
w0 = np.ones(shape=(n, n)) * (1 - alpha)
p = compute_p(n)
# Create the weight matrix
w = np.tril(w0**p, 0).astype(x.dtype)
# Calculate the ewma
return np.dot(w, np.ascontiguousarray(x[:: np.newaxis])) / w.sum(axis=1)