diff --git a/README.md b/README.md
index 18ba0b2..b0c964b 100644
--- a/README.md
+++ b/README.md
@@ -20,6 +20,8 @@ Java library and command-line application for converting [StatsModels](https://w
* [Poisson](https://www.statsmodels.org/dev/generated/statsmodels.discrete.discrete_model.Poisson.html)
* [OrderedModel](https://www.statsmodels.org/dev/generated/statsmodels.miscmodels.ordinal_model.OrderedModel.html):
* Distributions: `logit`, `probit`
+ * Univariate Time-Series Analysis:
+ * [ARIMA](https://www.statsmodels.org/dev/generated/statsmodels.tsa.arima.model.ARIMA.html)
* Production quality:
* Complete test coverage.
* Fully compliant with the [JPMML-Evaluator](https://github.com/jpmml/jpmml-evaluator) library.
diff --git a/pmml-statsmodels/src/main/java/statsmodels/tools/Bunch.java b/pmml-statsmodels/src/main/java/statsmodels/tools/Bunch.java
new file mode 100644
index 0000000..ff11a8e
--- /dev/null
+++ b/pmml-statsmodels/src/main/java/statsmodels/tools/Bunch.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 Villu Ruusmann
+ *
+ * This file is part of JPMML-StatsModels
+ *
+ * JPMML-StatsModels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * JPMML-StatsModels is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with JPMML-StatsModels. If not, see .
+ */
+package statsmodels.tools;
+
+import org.jpmml.python.PythonObject;
+
+public class Bunch extends PythonObject {
+
+ public Bunch(String module, String name){
+ super(module, name);
+ }
+
+ public void __setstate__(Bunch bunch){
+ super.__setstate__(bunch);
+ }
+}
\ No newline at end of file
diff --git a/pmml-statsmodels/src/main/java/statsmodels/tsa/arima/ARIMA.java b/pmml-statsmodels/src/main/java/statsmodels/tsa/arima/ARIMA.java
new file mode 100644
index 0000000..335a821
--- /dev/null
+++ b/pmml-statsmodels/src/main/java/statsmodels/tsa/arima/ARIMA.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2024 Villu Ruusmann
+ *
+ * This file is part of JPMML-StatsModels
+ *
+ * JPMML-StatsModels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * JPMML-StatsModels is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with JPMML-StatsModels. If not, see .
+ */
+package statsmodels.tsa.arima;
+
+import java.util.List;
+
+import org.dmg.pmml.Array;
+import org.dmg.pmml.DataField;
+import org.dmg.pmml.DataType;
+import org.dmg.pmml.MiningField.UsageType;
+import org.dmg.pmml.MiningFunction;
+import org.dmg.pmml.MiningSchema;
+import org.dmg.pmml.OpType;
+import org.dmg.pmml.time_series.InterceptVector;
+import org.dmg.pmml.time_series.MeasurementMatrix;
+import org.dmg.pmml.time_series.StateSpaceModel;
+import org.dmg.pmml.time_series.StateVector;
+import org.dmg.pmml.time_series.TransitionMatrix;
+import org.jpmml.converter.CMatrix;
+import org.jpmml.converter.Matrix;
+import org.jpmml.converter.ModelUtil;
+import org.jpmml.converter.PMMLUtil;
+import org.jpmml.converter.Schema;
+import org.jpmml.python.HasArray;
+import org.jpmml.statsmodels.StatsModelsEncoder;
+import statsmodels.Results;
+import statsmodels.tsa.TimeSeriesModel;
+import statsmodels.tsa.statespace.SmootherResults;
+
+public class ARIMA extends TimeSeriesModel {
+
+ public ARIMA(String module, String name){
+ super(module, name);
+ }
+
+ @Override
+ public Schema encodeSchema(StatsModelsEncoder encoder){
+ Schema schema = super.encodeSchema(encoder);
+
+ @SuppressWarnings("unused")
+ DataField dataField = encoder.createDataField("horizon", OpType.CONTINUOUS, DataType.INTEGER);
+
+ return schema;
+ }
+
+ @Override
+ public org.dmg.pmml.time_series.TimeSeriesModel encodeModel(Results results, Schema schema){
+ HasArray predictedState = results.getArray("predicted_state");
+ SmootherResults smootherResults = results.get("smoother_results", SmootherResults.class);
+
+ HasArray design = smootherResults.getDesign();
+ HasArray obsIntercept = smootherResults.getObsIntercept();
+ HasArray transition = smootherResults.getTransition();
+
+ MiningSchema miningSchema = ModelUtil.createMiningSchema(schema.getLabel())
+ .addMiningFields(ModelUtil.createMiningField("horizon", UsageType.SUPPLEMENTARY));
+
+ StateVector stateVector = new StateVector(createRealArray(predictedState, -1));
+
+ MeasurementMatrix measurementMatrix = new MeasurementMatrix(createMatrix(design));
+
+ TransitionMatrix transitionMatrix = new TransitionMatrix(createMatrix(transition));
+
+ InterceptVector interceptVector = new InterceptVector(createRealArray(obsIntercept, -1))
+ .setType(InterceptVector.Type.OBSERVATION);
+
+ StateSpaceModel stateSpaceModel = new StateSpaceModel()
+ .setStateVector(stateVector)
+ .setMeasurementMatrix(measurementMatrix)
+ .setTransitionMatrix(transitionMatrix)
+ .setInterceptVector(interceptVector);
+
+ org.dmg.pmml.time_series.TimeSeriesModel timeSeriesModel = new org.dmg.pmml.time_series.TimeSeriesModel(MiningFunction.TIME_SERIES, org.dmg.pmml.time_series.TimeSeriesModel.Algorithm.STATE_SPACE_MODEL, miningSchema)
+ .setStateSpaceModel(stateSpaceModel);
+
+ return timeSeriesModel;
+ }
+
+ static
+ private Array createRealArray(HasArray hasArray, int column){
+ Matrix> matrix = toMatrix(hasArray);
+
+ List extends Number> columnValues;
+
+ if(column >= 0){
+ columnValues = (List)matrix.getColumnValues(column);
+ } else
+
+ {
+ columnValues = (List)matrix.getColumnValues(matrix.getColumns() + column);
+ }
+
+ return PMMLUtil.createRealArray(columnValues);
+ }
+
+ static
+ private org.dmg.pmml.Matrix createMatrix(HasArray hasArray){
+ Matrix> matrix = toMatrix(hasArray);
+
+ org.dmg.pmml.Matrix result = new org.dmg.pmml.Matrix()
+ .setNbRows(matrix.getRows())
+ .setNbCols(matrix.getColumns());
+
+ for(int row = 0; row < matrix.getRows(); row++){
+ List extends Number> rowValues = (List)matrix.getRowValues(row);
+
+ result.addArrays(PMMLUtil.createRealArray(rowValues));
+ }
+
+ return result;
+ }
+
+ static
+ private Matrix> toMatrix(HasArray hasArray){
+ int[] shape = hasArray.getArrayShape();
+ List> values = hasArray.getArrayContent();
+
+ if(shape.length == 3){
+
+ if(shape[2] != 1){
+ throw new IllegalArgumentException();
+ }
+ }
+
+ return new CMatrix(values, shape[0], shape[1]);
+ }
+
+ private static final String NAME_INDEX = "index";
+}
\ No newline at end of file
diff --git a/pmml-statsmodels/src/main/java/statsmodels/tsa/statespace/Initialization.java b/pmml-statsmodels/src/main/java/statsmodels/tsa/statespace/Initialization.java
new file mode 100644
index 0000000..f0eff4b
--- /dev/null
+++ b/pmml-statsmodels/src/main/java/statsmodels/tsa/statespace/Initialization.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2024 Villu Ruusmann
+ *
+ * This file is part of JPMML-StatsModels
+ *
+ * JPMML-StatsModels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * JPMML-StatsModels is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with JPMML-StatsModels. If not, see .
+ */
+package statsmodels.tsa.statespace;
+
+import org.jpmml.python.CythonObject;
+
+public class Initialization extends CythonObject {
+
+ public Initialization(String module, String name){
+ super(module, name);
+ }
+
+ @Override
+ public void __init__(Object[] args){
+ super.__setstate__(INIT_ATTRIBUTES, args);
+ }
+
+ private static final String[] INIT_ATTRIBUTES = {
+ "k_states",
+ "constant",
+ "stationary_cov",
+ "approximate_diffuse_variance"
+ };
+}
\ No newline at end of file
diff --git a/pmml-statsmodels/src/main/java/statsmodels/tsa/statespace/KalmanFilter.java b/pmml-statsmodels/src/main/java/statsmodels/tsa/statespace/KalmanFilter.java
new file mode 100644
index 0000000..3c4d138
--- /dev/null
+++ b/pmml-statsmodels/src/main/java/statsmodels/tsa/statespace/KalmanFilter.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2024 Villu Ruusmann
+ *
+ * This file is part of JPMML-StatsModels
+ *
+ * JPMML-StatsModels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * JPMML-StatsModels is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with JPMML-StatsModels. If not, see .
+ */
+package statsmodels.tsa.statespace;
+
+import org.jpmml.python.CythonObject;
+
+public class KalmanFilter extends CythonObject {
+
+ public KalmanFilter(String module, String name){
+ super(module, name);
+ }
+
+ @Override
+ public void __init__(Object[] args){
+ super.__setstate__(INIT_ATTRIBUTES, args);
+ }
+
+ private static final String[] INIT_ATTRIBUTES = {
+ "model",
+ "filter_method",
+ "inversion_method",
+ "stability_method",
+ "conserve_memory",
+ "filter_timing",
+ "tolerance",
+ "loglikelihood_burn"
+ };
+}
\ No newline at end of file
diff --git a/pmml-statsmodels/src/main/java/statsmodels/tsa/statespace/KalmanSmoother.java b/pmml-statsmodels/src/main/java/statsmodels/tsa/statespace/KalmanSmoother.java
new file mode 100644
index 0000000..9e4b744
--- /dev/null
+++ b/pmml-statsmodels/src/main/java/statsmodels/tsa/statespace/KalmanSmoother.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2024 Villu Ruusmann
+ *
+ * This file is part of JPMML-StatsModels
+ *
+ * JPMML-StatsModels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * JPMML-StatsModels is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with JPMML-StatsModels. If not, see .
+ */
+package statsmodels.tsa.statespace;
+
+import org.jpmml.python.CythonObject;
+
+public class KalmanSmoother extends CythonObject {
+
+ public KalmanSmoother(String module, String name){
+ super(module, name);
+ }
+
+ @Override
+ public void __init__(Object[] args){
+ super.__setstate__(INIT_ATTRIBUTES, args);
+ }
+
+ private static final String[] INIT_ATTRIBUTES = {
+ "model",
+ "kfilter",
+ "smoother_output",
+ "smooth_method"
+ };
+}
\ No newline at end of file
diff --git a/pmml-statsmodels/src/main/java/statsmodels/tsa/statespace/SmootherResults.java b/pmml-statsmodels/src/main/java/statsmodels/tsa/statespace/SmootherResults.java
new file mode 100644
index 0000000..cce6597
--- /dev/null
+++ b/pmml-statsmodels/src/main/java/statsmodels/tsa/statespace/SmootherResults.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2024 Villu Ruusmann
+ *
+ * This file is part of JPMML-StatsModels
+ *
+ * JPMML-StatsModels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * JPMML-StatsModels is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with JPMML-StatsModels. If not, see .
+ */
+package statsmodels.tsa.statespace;
+
+import org.jpmml.python.HasArray;
+import org.jpmml.python.PythonObject;
+
+public class SmootherResults extends PythonObject {
+
+ public SmootherResults(String module, String name){
+ super(module, name);
+ }
+
+ public HasArray getDesign(){
+ return getArray("design");
+ }
+
+ public HasArray getObsIntercept(){
+ return getArray("obs_intercept");
+ }
+
+ public HasArray getTransition(){
+ return getArray("transition");
+ }
+}
\ No newline at end of file
diff --git a/pmml-statsmodels/src/main/java/statsmodels/tsa/statespace/Statespace.java b/pmml-statsmodels/src/main/java/statsmodels/tsa/statespace/Statespace.java
new file mode 100644
index 0000000..84e8dff
--- /dev/null
+++ b/pmml-statsmodels/src/main/java/statsmodels/tsa/statespace/Statespace.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2024 Villu Ruusmann
+ *
+ * This file is part of JPMML-StatsModels
+ *
+ * JPMML-StatsModels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * JPMML-StatsModels is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with JPMML-StatsModels. If not, see .
+ */
+package statsmodels.tsa.statespace;
+
+import org.jpmml.python.CythonObject;
+
+public class Statespace extends CythonObject {
+
+ public Statespace(String module, String name){
+ super(module, name);
+ }
+
+ @Override
+ public void __init__(Object[] args){
+ super.__setstate__(INIT_ATTRBUTES, args);
+ }
+
+ private static final String[] INIT_ATTRBUTES = {
+ "obs",
+ "design",
+ "obs_intercept",
+ "obs_cov",
+ "transition",
+ "state_intercept",
+ "selection",
+ "state_cov",
+ "diagonal_obs_cov"
+ };
+}
\ No newline at end of file
diff --git a/pmml-statsmodels/src/main/resources/META-INF/statsmodels2pmml.properties b/pmml-statsmodels/src/main/resources/META-INF/statsmodels2pmml.properties
index 3d957b3..be8a42f 100644
--- a/pmml-statsmodels/src/main/resources/META-INF/statsmodels2pmml.properties
+++ b/pmml-statsmodels/src/main/resources/META-INF/statsmodels2pmml.properties
@@ -28,4 +28,13 @@ statsmodels.regression.linear_model.WLS = statsmodels.regression.LinearRegressio
statsmodels.regression.linear_model.RegressionResults = statsmodels.Results
statsmodels.regression.linear_model.RegressionResultsWrapper = statsmodels.ResultsWrapper
statsmodels.regression.quantile_regression.QuantReg = statsmodels.regression.LinearRegression
-statsmodels.regression.quantile_regression.QuantRegResults = statsmodels.Results
\ No newline at end of file
+statsmodels.regression.quantile_regression.QuantRegResults = statsmodels.Results
+statsmodels.tsa.arima.model.ARIMA = statsmodels.tsa.arima.ARIMA
+statsmodels.tsa.arima.model.ARIMAResults = statsmodels.Results
+statsmodels.tsa.arima.model.ARIMAResultsWrapper = statsmodels.ResultsWrapper
+statsmodels.tsa.statespace._initialization.(dInitialization|zInitialization) = statsmodels.tsa.statespace.Initialization
+statsmodels.tsa.statespace._kalman_filter.(dKalmanFilter|zKalmanFilter) = statsmodels.tsa.statespace.KalmanFilter
+statsmodels.tsa.statespace._kalman_smoother.dKalmanSmoother = statsmodels.tsa.statespace.KalmanSmoother
+statsmodels.tsa.statespace._representation.(dStatespace|zStatespace) = statsmodels.tsa.statespace.Statespace
+statsmodels.tsa.statespace.kalman_smoother.SmootherResults = statsmodels.tsa.statespace.SmootherResults
+statsmodels.tools.tools.Bunch = statsmodels.tools.Bunch
diff --git a/pmml-statsmodels/src/test/java/org/jpmml/statsmodels/testing/TimeSeriesTest.java b/pmml-statsmodels/src/test/java/org/jpmml/statsmodels/testing/TimeSeriesTest.java
new file mode 100644
index 0000000..3316cfe
--- /dev/null
+++ b/pmml-statsmodels/src/test/java/org/jpmml/statsmodels/testing/TimeSeriesTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2024 Villu Ruusmann
+ *
+ * This file is part of JPMML-StatsModels
+ *
+ * JPMML-StatsModels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * JPMML-StatsModels is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with JPMML-StatsModels. If not, see .
+ */
+package org.jpmml.statsmodels.testing;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import com.google.common.base.Equivalence;
+import com.google.common.collect.Iterables;
+import org.jpmml.evaluator.ResultField;
+import org.jpmml.evaluator.testing.Batch;
+import org.jpmml.evaluator.testing.BatchUtil;
+import org.jpmml.evaluator.testing.Conflict;
+import org.jpmml.evaluator.time_series.SeriesForecast;
+import org.junit.Test;
+
+public class TimeSeriesTest extends StatsModelsEncoderBatchTest {
+
+ @Override
+ public void evaluate(Batch batch) throws Exception {
+ Function