-
-
Notifications
You must be signed in to change notification settings - Fork 103
Expand file tree
/
Copy pathtest_algorithms.py
More file actions
80 lines (64 loc) · 2.38 KB
/
Copy pathtest_algorithms.py
File metadata and controls
80 lines (64 loc) · 2.38 KB
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
from datetime import timedelta
import pytest
from progressbar import algorithms
def test_ema_initialization() -> None:
ema = algorithms.ExponentialMovingAverage()
assert ema.alpha == 0.5
assert ema.value is None
@pytest.mark.parametrize(
'alpha, new_value, expected',
[
(0.5, 10, 5),
(0.1, 20, 2),
(0.9, 30, 27),
(0.3, 15, 4.5),
(0.7, 40, 28),
(0.5, 0, 0),
(0.2, 100, 20),
(0.8, 50, 40),
],
)
def test_ema_update(alpha, new_value: float, expected) -> None:
# The first update seeds the average, so blending starts from an
# explicit zero observation: alpha * new_value + (1 - alpha) * 0
ema = algorithms.ExponentialMovingAverage(alpha)
ema.update(0, timedelta(seconds=1))
result = ema.update(new_value, timedelta(seconds=1))
assert result == expected
def test_dema_initialization() -> None:
dema = algorithms.DoubleExponentialMovingAverage()
assert dema.alpha == 0.5
assert dema.ema1 is None
assert dema.ema2 is None
@pytest.mark.parametrize(
'alpha, new_value, expected',
[
(0.5, 10, 7.5),
(0.1, 20, 3.8),
(0.9, 30, 29.7),
(0.3, 15, 7.65),
(0.5, 0, 0),
(0.2, 100, 36.0),
(0.8, 50, 48.0),
],
)
def test_dema_update(alpha, new_value: float, expected) -> None:
# Seeded with an explicit zero observation, a single update yields
# ema1 = alpha * v, ema2 = alpha^2 * v, so the result is
# alpha * v * (2 - alpha) which matches the historical values
dema = algorithms.DoubleExponentialMovingAverage(alpha)
dema.update(0, timedelta(seconds=1))
result = dema.update(new_value, timedelta(seconds=1))
assert result == pytest.approx(expected)
# Additional test functions can be added here as needed.
def test_ema_seeds_from_first_value() -> None:
# Regression: B8 - the average started at 0, biasing early values
# toward zero instead of the first observation.
ema = algorithms.ExponentialMovingAverage(0.5)
assert ema.update(100, timedelta(seconds=1)) == 100
assert ema.update(50, timedelta(seconds=1)) == 75
def test_dema_seeds_from_first_value() -> None:
# Regression: B8 - same zero bias for the double EMA.
dema = algorithms.DoubleExponentialMovingAverage(0.5)
assert dema.update(100, timedelta(seconds=1)) == 100
assert dema.update(50, timedelta(seconds=1)) == 62.5