import numpy as np
import pytest
import scirs2
class TestTimeSeries:
def test_create_timeseries(self):
data = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
ts = scirs2.PyTimeSeries(data, None)
assert len(ts) == 5
def test_describe(self):
data = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
ts = scirs2.PyTimeSeries(data, None)
stats = ts.describe()
assert "mean" in stats
assert "std" in stats
assert abs(stats["mean"] - 3.0) < 1e-10
class TestDifferencing:
def test_first_difference(self):
data = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
ts = scirs2.PyTimeSeries(data, None)
diff = scirs2.apply_differencing(ts, 1)
assert len(diff) == 4
assert np.allclose(diff, [1.0, 1.0, 1.0, 1.0], atol=1e-10)
def test_second_difference(self):
data = np.array([1.0, 4.0, 9.0, 16.0, 25.0])
ts = scirs2.PyTimeSeries(data, None)
diff = scirs2.apply_differencing(ts, 2)
assert len(diff) == 3
assert np.allclose(diff, [8.0, 12.0, 16.0], atol=1e-10)
def test_seasonal_difference(self):
data = np.array([1.0, 2.0, 3.0, 1.0, 2.0, 3.0, 1.0, 2.0, 3.0])
ts = scirs2.PyTimeSeries(data, None)
diff = scirs2.apply_seasonal_differencing(ts, 3)
assert len(diff) == 6
assert np.allclose(diff, [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], atol=1e-10)
class TestARIMA:
def test_arima_fit(self):
np.random.seed(42)
n = 100
data = np.zeros(n)
data[0] = np.random.randn()
for i in range(1, n):
data[i] = 0.5 * data[i-1] + np.random.randn()
ts = scirs2.PyTimeSeries(data, None)
arima = scirs2.PyARIMA(1, 0, 0)
arima.fit(ts)
params = arima.get_params()
assert "p" in params or len(params) > 0
def test_arima_forecast(self):
np.random.seed(123)
n = 50
data = np.zeros(n)
data[0] = np.random.randn()
for i in range(1, n):
data[i] = 0.7 * data[i-1] + np.random.randn()
ts = scirs2.PyTimeSeries(data, None)
arima = scirs2.PyARIMA(1, 0, 0)
arima.fit(ts)
forecast = arima.forecast(3)
assert len(forecast) == 3
class TestTransformations:
def test_boxcox_transform(self):
data = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0])
ts = scirs2.PyTimeSeries(data, None)
result = scirs2.boxcox_transform(ts, None)
assert "transformed" in result
assert "lambda" in result
transformed = result["transformed"]
assert len(transformed) == len(data)
def test_boxcox_inverse(self):
data = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0])
ts = scirs2.PyTimeSeries(data, None)
result = scirs2.boxcox_transform(ts, None)
transformed = result["transformed"]
lambda_val = result["lambda"]
recovered = scirs2.boxcox_inverse(np.array(transformed), lambda_val)
assert np.allclose(data, recovered, atol=1e-6)
class TestStatisticalTests:
def test_adf_stationary(self):
np.random.seed(42)
data = np.random.randn(100)
ts = scirs2.PyTimeSeries(data, None)
result = scirs2.adf_test(ts, None)
assert "statistic" in result
assert "p_value" in result
assert result["p_value"] < 0.1
def test_adf_nonstationary(self):
t = np.arange(100, dtype=np.float64)
data = t * 0.5 + np.random.randn(100) * 0.1
ts = scirs2.PyTimeSeries(data, None)
result = scirs2.adf_test(ts, None)
assert "p_value" in result
assert 0.0 <= result["p_value"] <= 1.0
class TestDecomposition:
def test_stl_decomposition(self):
n = 100
t = np.arange(n)
seasonal = 5 * np.sin(2 * np.pi * t / 12)
trend = 0.1 * t
noise = 0.5 * np.random.randn(n)
data = seasonal + trend + noise
ts = scirs2.PyTimeSeries(data, None)
result = scirs2.stl_decomposition(ts, 12)
assert "trend" in result
assert "seasonal" in result
assert "residual" in result
if __name__ == "__main__":
pytest.main([__file__, "-v"])