Skip to content

Commit f672bec

Browse files
committed
Add test file for memory.py and add remaining docstrings in task_plot_ar.py.
1 parent 663f520 commit f672bec

File tree

4 files changed

+158
-8
lines changed

4 files changed

+158
-8
lines changed

pytest.ini

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[pytest]
2+
filterwarnings =
3+
ignore::DeprecationWarning
4+
ignore:pkg_resources is deprecated:DeprecationWarning
5+
ignore::DeprecationWarning:nolds.datasets

src/lennart_epp/analysis/task_forecast_ar.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,3 @@ def task_forecast_ar(
5757

5858
produces.parent.mkdir(parents=True, exist_ok=True)
5959
pd.to_pickle(forecast, produces)
60-
61-
html_output = produces.with_suffix(".html")
62-
forecast.to_frame(name="Forecasted Close Price").to_html(html_output, index=True)

src/lennart_epp/final/task_plot_ar.py

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,28 @@
44
from lennart_epp.final.plot_ar import plot_top_ar_models
55
from lennart_epp.final.plot_forecast_ar import plot_forecast_ar
66

7-
no_top_models_msg = "Keine Top-Modelle in der Auswertung gefunden."
8-
file_creation_msg = "Datei konnte nicht erstellt werden."
7+
no_top_models_msg = "Top-models not found."
8+
file_creation_msg = "File could not be created."
99

1010

1111
def task_plot_top_ar_models(
1212
script=SRC / "final" / "plot_ar.py",
1313
evaluation_data=BLD / "models" / "ar_model_evaluation.pkl",
1414
produces=BLD / "plots" / "top_ar_models_plot.html",
1515
):
16+
"""Generate and save a plot of the top-performing AR models.
17+
18+
Args:
19+
script (Path): Path to the script responsible for plotting.
20+
evaluation_data (Path): Path to the AR model evaluation data.
21+
produces (Path): Path where the output plot (HTML) will be stored.
22+
23+
Returns:
24+
None: Ensures the top AR models are visualized and stored.
25+
26+
Raises:
27+
ValueError: If no top models are available in the evaluation results.
28+
"""
1629
evaluation = pd.read_pickle(evaluation_data)
1730

1831
top_models = pd.DataFrame(evaluation.get("top_models", []))
@@ -24,7 +37,7 @@ def task_plot_top_ar_models(
2437
top_models=top_models,
2538
df=pd.read_pickle(BLD / "data" / "cleaned_apple_data.pkl"),
2639
plot_path=str(produces),
27-
export_as_pdf=True, # Änderung: jetzt wird auch ein PDF erzeugt
40+
export_as_pdf=True,
2841
)
2942

3043
produces.parent.mkdir(parents=True, exist_ok=True)
@@ -33,9 +46,22 @@ def task_plot_top_ar_models(
3346

3447
def task_plot_forecast_ar(
3548
data=BLD / "data" / "cleaned_apple_data.pkl",
36-
forecast=BLD / "forecasts" / "apple_2023_forecast.pkl",
37-
produces=BLD / "plots" / "apple_forecast_2023.html",
49+
forecast=BLD / "forecasts" / "multistep_forecast.pkl",
50+
produces=BLD / "plots" / "multistep_forecast.html",
3851
):
52+
"""Generate and save a visualization of the AR model multi-step forecast.
53+
54+
Args:
55+
data (Path): Path to the cleaned stock price data.
56+
forecast (Path): Path to the multi-step forecast data.
57+
produces (Path): Path to store the generated forecast plot.
58+
59+
Returns:
60+
None: Ensures the forecast visualization is generated and saved.
61+
62+
Raises:
63+
AssertionError: If the output plot file is not created successfully.
64+
"""
3965
plot_forecast_ar(
4066
data_path=data,
4167
forecast_path=forecast,

tests/analysis/test_memory.py

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import numpy as np
2+
import pandas as pd
3+
import pytest
4+
5+
from lennart_epp.analysis.memory import (
6+
_compute_autocovariance,
7+
_compute_mean,
8+
_compute_variance,
9+
check_stat_diff_close,
10+
compute_acf,
11+
compute_hurst_exponent,
12+
)
13+
14+
15+
@pytest.fixture
16+
def test_series():
17+
"""Generate a random time series for testing."""
18+
rng = np.random.default_rng(2837)
19+
return rng.standard_normal(100)
20+
21+
22+
@pytest.fixture
23+
def test_df(test_series):
24+
"""Generate a DataFrame containing the test series."""
25+
return pd.DataFrame({"close_price": test_series})
26+
27+
28+
@pytest.fixture
29+
def precomputed_values(test_series):
30+
"""Precompute mean and variance tests."""
31+
mean_series = np.mean(test_series)
32+
variance_series = np.sum((test_series - mean_series) ** 2)
33+
return mean_series, variance_series
34+
35+
36+
def test_compute_mean(test_series):
37+
"""Test whether _compute_mean returns the correct mean."""
38+
assert _compute_mean(test_series) == pytest.approx(np.mean(test_series), rel=1e-6)
39+
40+
41+
def test_compute_variance(test_series, precomputed_values):
42+
"""Test whether _compute_variance returns the correct variance."""
43+
mean_series, expected_variance = precomputed_values
44+
assert _compute_variance(test_series, mean_series) == pytest.approx(
45+
expected_variance, rel=1e-6
46+
)
47+
48+
49+
def test_compute_autocovariance_lag_1(test_series, precomputed_values):
50+
"""Test whether _compute_autocovariance returns the correct value for lag=1."""
51+
mean_series, _ = precomputed_values
52+
lag = 1
53+
expected_autocov = np.sum(
54+
(test_series[lag:] - mean_series)
55+
* (test_series[: len(test_series) - lag] - mean_series)
56+
)
57+
assert _compute_autocovariance(test_series, mean_series, lag) == pytest.approx(
58+
expected_autocov, rel=1e-6
59+
)
60+
61+
62+
def test_compute_autocovariance_lag_5(test_series, precomputed_values):
63+
"""Test whether _compute_autocovariance returns the correct value for lag=10."""
64+
mean_series, _ = precomputed_values
65+
lag = 10
66+
expected_autocov = np.sum(
67+
(test_series[lag:] - mean_series)
68+
* (test_series[: len(test_series) - lag] - mean_series)
69+
)
70+
assert _compute_autocovariance(test_series, mean_series, lag) == pytest.approx(
71+
expected_autocov, rel=1e-6
72+
)
73+
74+
75+
def test_compute_acf_output_structure(test_df):
76+
"""Test whether compute_acf returns a dictionary with 'acf' and 'lags' keys."""
77+
result = compute_acf(test_df, column="close_price", lags=10)
78+
assert all(key in result for key in ("acf", "lags"))
79+
80+
81+
expected_length = 11
82+
83+
84+
def test_compute_acf_length(test_df):
85+
"""Test whether compute_acf returns arrays of correct length."""
86+
result = compute_acf(test_df, column="close_price", lags=10)
87+
assert len(result["acf"]) == expected_length
88+
assert len(result["lags"]) == expected_length
89+
90+
91+
def test_compute_hurst_exponent_output(test_df):
92+
"""Test if compute_hurst_exponent returns dictionary with 'Hurst Exponent' key."""
93+
result = compute_hurst_exponent(test_df, column="close_price")
94+
assert isinstance(result, dict)
95+
assert "Hurst Exponent" in result
96+
97+
98+
def test_compute_hurst_exponent_range(test_df):
99+
"""Test whether the computed Hurst Exponent is within the expected range [0,1]."""
100+
hurst_value = compute_hurst_exponent(test_df, column="close_price")[
101+
"Hurst Exponent"
102+
]
103+
assert 0 <= hurst_value <= 1
104+
105+
106+
def test_check_stat_diff_close_returns_dict(test_df):
107+
"""Ensure check_stat_diff_close returns a dictionary."""
108+
result = check_stat_diff_close(test_df, column="close_price")
109+
assert isinstance(result, dict)
110+
111+
112+
def test_check_stat_diff_close_has_expected_keys(test_df):
113+
"""Ensure the returned dictionary has the correct keys."""
114+
result = check_stat_diff_close(test_df, column="close_price")
115+
expected_keys = {"ADF Test Statistic", "P-Value", "Is Stationary"}
116+
assert set(result.keys()) == expected_keys
117+
118+
119+
def test_check_stat_diff_close_raises_error_for_missing_column(test_df):
120+
"""Ensure a ValueError is raised if the column does not exist."""
121+
with pytest.raises(ValueError, match="Column .* not found in dataframe."):
122+
check_stat_diff_close(test_df, column="non_existent_column")

0 commit comments

Comments
 (0)