Say I have a time series X from Bernoulli Trials with outcomes 0 or 1 where X(n) is the $n$th outcome in the time series. The process is driven by some probability of success $\pi$ but this probability may change over time, meaning that we have $\pi(n)$ being the probability of success of the $n$th trial. What I would like to do is to from X estimate $\pi$ at every point in some maximum likelihood sense so we could see it's evolution over time.
I would of course like $\pi$ to behave nicely as well. $\pi$ may change gradually over time but shouldn't jump erratically, the naive solution to the above I guess would have $\pi$ jumping from 0 to 1 constantly without taking the history into account which is not what we want. Would we need to prescribe some dynamics to $\pi$ itself to accomplish this?
My best guess is I should be using some Bayesian inference to accomplish this and having the prior distribution of $\pi(n)$ be centered around $\pi(n-1)$ (normally distributed probably) and updating our belief about the current value from the $n$th outcome, but I'm not sure exactly how to go about it or if this is the right approach. Would appreciate any ideas.
EDIT: I've tried to do this with Bayesian inference where I start with a prior distribution of $\pi$ and update it with one data point at a time but I'm not convinced this is exactly what I want. One issue is that it's not quite as responsive to changes in the underlying probability as I would like (from simulated data with known probability) and the credible region (width indicated by red line) is always decreasing with additional data, ideally I would like that to be able to widen in the case that the underlying probability looks like it has changed to represent that we are again in unknown territory.
import pandas as pd
import numpy as np
from scipy.stats import beta
##Bayesian with equal weights.
# Load data
p_true = np.concatenate((0.1 * np.ones(2000), 0.2 * np.ones(2000), 0.3 * np.ones(2000)))
data = np.random.binomial(n=1, p=p_true)
# Set prior parameters
mean = 0.2
alpha_prior, beta_prior = Beta_Dist_shapeparam_from_mean(mean)
# Create empty list to store posterior parameters
alpha_posterior = []
beta_posterior = []
# Iterate over each trial in the data
for i in range(len(data)):
# Get outcome of current trial (0 or 1)
outcome = data[i]
# Compute posterior parameters using current outcome and prior parameters
alpha_post = alpha_prior + outcome
beta_post = beta_prior + 1 - outcome
# Store posterior parameters for future use
alpha_posterior.append(alpha_post)
beta_posterior.append(beta_post)
# Update prior parameters with posterior parameters
alpha_prior = alpha_post
beta_prior = beta_post
# Compute mean and standard deviation of posterior distribution for each trial
posterior_mean = np.array(alpha_posterior) / (np.array(alpha_posterior) + np.array(beta_posterior))
posterior_std = np.sqrt(np.array(alpha_posterior) * np.array(beta_posterior) / ((np.array(alpha_posterior) + np.array(beta_posterior)) ** 2 * (np.array(alpha_posterior) + np.array(beta_posterior) + 1)))
#Plot the posterior parameters
brms
something like:brmfit1 <- brm(data = mydata, family = bernoulli(link="logit"), flip_result ~ 1 + gp(try_number))
. $\endgroup$