@property
    def kalman_gain(self):
        if self._kalman_gain is None:
            # k x n
            self._kalman_gain = np.zeros(
                (self.k_states, self.k_endog, self.nobs), dtype=self.dtype)
            for t in range(self.nobs):
                # In the case of entirely missing observations, let the Kalman
                # gain be zeros.
                if self.nmissing[t] == self.k_endog:
                    continue

                design_t = 0 if self.design.shape[2] == 1 else t
                transition_t = 0 if self.transition.shape[2] == 1 else t
                if self.nmissing[t] == 0:
                    self._kalman_gain[:, :, t] = np.dot(
                        np.dot(
                            self.transition[:, :, transition_t],
                            self.predicted_state_cov[:, :, t]
                        ),
                        np.dot(
                            np.transpose(self.design[:, :, design_t]),
                            np.linalg.inv(self.forecasts_error_cov[:, :, t])
                        )
                    )
                else:
                    mask = ~self.missing[:, t].astype(bool)
                    n = self.k_endog - self.nmissing[t]
                    F = self.forecasts_error_cov[np.ix_(mask, mask, [t])]
                    self._kalman_gain[:, mask, t] = np.dot(
                        np.dot(
                            self.transition[:, :, transition_t],
                            self.predicted_state_cov[:, :, t]
                        ),
                        np.dot(
                            np.transpose(self.design[mask, :, design_t]),
                            np.linalg.inv(F[:, :, 0])
                        )
                    )
        return self._kalman_gain
Kalman gain matrices
dataset/ETHPy150Open statsmodels/statsmodels/statsmodels/tsa/statespace/kalman_filter.py/FilterResults.kalman_gain