First of all, I am new to both Python and the forum so please be kind if I misunderstand something. :)
I would like to incorporate first-order autocorrelation in a brownian motion monte carlo simulation since I found a conceptual mechanism as well as a negative correlation between two consecutive values, which if I understand the concept correctly, will result in less wide confidence intervals over time. I used the code below for non-autocorrelated simulations and found an article of Boeing making a similar adjusted simulation approach if I understand it right: https://www.imse.iastate.edu/files/2014/03/ZhangMinxiang-thesis.pdf. Code for BMMC:
# Data
data = pd.DataFrame([3.1, 4.2, 3.7, 5.1, 4.3, 6.6, 8.4, 8.1, 7.5, 11.6, 10.2, 13.2])
# Calculate the logarithmic, differenciated y of our data.
df = np.log(data).diff().dropna()
# Extract the last available value
S0 = data.iloc[len(df)]
mu = df.mean()
var = df.var()
desvest = df.std()
n_simulations = 2000
time_units = np.arange(9)
conf_level = 0.8
z_score = NormalDist().inv_cdf((1 + conf_level) / 2.)
# Determine the drift (slope)
drift = mu - (0.5*var)
# Determine the epsilon
epsilon = norm.ppf(np.random.rand(len(time_units), n_simulations))
# Determine y
y = drift.values + desvest.values * epsilon
# Prepare the series
y_interval_1 = np.zeros(len(time_units))
y_interval_2 = np.zeros(len(time_units))
expected_y = np.zeros(len(time_units))
# Compute the confidence interval logic
for t in range(1, len(time_units)):
y_interval_1[t] = drift*(t-time_units[0]) + desvest *z_score*np.sqrt(t - time_units[0])
y_interval_2[t] = drift*(t-time_units[0]) + desvest *(-1*z_score)*np.sqrt(t - time_units[0])
# Prepare the outcome series
S = np.zeros_like(y)
S_interval_1 = np.zeros_like(y_interval_1)
S_interval_2 = np.zeros_like(y_interval_2)
# Set initial value(s) - last available value of inserted series, named S0
S_interval_1[0] = S0
S_interval_2[0] = S0
S[0] = S0
expected_y[0] = S0
# Simulate the individials trails by using a for loop
for t in range(1, len(time_units)):
S[t] = S[t-1]*np.exp(y[t])
S_interval_1[t] = S0*np.exp(y_interval_1[t])
S_interval_2[t] = S0*np.exp(y_interval_2[t])
expected_y[t] = expected_y[t-1]*np.exp(mu.values)
Now, my questions are:
- are my understandings right and is this method appropriate to use given the situation? If not, which alternatives are there to incorporate (negative) first-order autocorrelation into the simulation trails?
- How to properly implement the best approach into the code correctly? I messed around but was not able to reproduce similar results to the article.
Thanks in advance!