import pandas as pd
import numpy as np
import MetaTrader5 as mt5
from datetime import datetime
import pytz
from scipy.stats import poisson
from scipy.special import logsumexp
import matplotlib.pyplot as plt

# Initializing MT5 
if not mt5.initialize():
    print("initialize() failed")
    quit()

timezone = pytz.timezone("Etc/UTC")
target_date = (2026, 4, 23) 

utc_from = datetime(*target_date, 12, 0, 0, tzinfo=timezone)
utc_to = datetime(*target_date, 12, 10, 0, tzinfo=timezone)

# Loading ticks
ticks = mt5.copy_ticks_range("EURUSD", utc_from, utc_to, mt5.COPY_TICKS_ALL)
mt5.shutdown()

# Create a DataFrame and count ticks per minute
df = pd.DataFrame(ticks)
df['time'] = pd.to_datetime(df['time'], unit='s')
df.set_index('time', inplace=True)
# Group by minute
minute_counts = df.resample('1min').count()['ask'].values

print(f"Data (number of ticks per minute): {minute_counts}")

sum_x = np.sum(minute_counts)
n = len(minute_counts)

# 1. Hypothesis grid
theta_grid = np.arange(1, 301)

# 2. Prior 
prior = poisson.pmf(theta_grid, mu=150)
prior /= prior.sum()

# 3. Likelihood
log_likelihood = sum_x * np.log(theta_grid) - n * theta_grid

# 4. Calculate the logarithm of the numerator (Likelihood + Prior)
log_numerator = log_likelihood + np.log(prior + 1e-12) # a vector with 300 elements

# 5. Find the logarithm of the marginal likelihood P(D) using LogSumExp
log_evidence = logsumexp(log_numerator)

# 6. Obtain the log of the normalized posterior
log_posterior = log_numerator - log_evidence

# 7. Final result as probabilities
posterior = np.exp(log_posterior)

print(f"Sum of probabilities: {np.sum(posterior)}")
print(f"Log evidence: {log_evidence:.4f}")

# Likelihood normalization for visualization
log_evidence_likelihood = logsumexp(log_likelihood)
likelihood_norm = np.exp(log_likelihood - log_evidence_likelihood)

# --- Visualization ---
plt.figure(figsize=(10, 5))

# Prior 
plt.plot(theta_grid, prior, label='Prior',color='blue', linestyle='--', alpha=0.6)

# Likelihood 
plt.plot(theta_grid, likelihood_norm, label='Likelihood (Normalized Data)', 
         color='green', linewidth=1, alpha=0.8)

# Posterior 
plt.plot(theta_grid, posterior, label='Posterior', color='red', linewidth=2)

plt.fill_between(theta_grid, posterior, color='red', alpha=0.1)

# MLE estimate
plt.axvline(sum_x/n, color='green', linestyle=':', alpha=0.8,label=f'Data Mean: {sum_x/n:.2f}')

plt.title(f"Discrete Bayesian Inference (EURUSD)\nMinutes: {n}, Total Ticks: {sum_x}", fontsize=12)
plt.xlabel("Ticks per Minute (θ)")
plt.ylabel("Probability")
plt.legend()
plt.grid(True, alpha=0.2)
plt.show()

print(f"Sample mean (MLE): {sum_x/n:.2f}")
print(f"Most probable value (MAP): {theta_grid[np.argmax(posterior)]}")