Zomato
(ETERNAL.NS)
Price and
Returns
getSymbols("ETERNAL.NS", src = "yahoo", from = "2023-01-01", to = "2026-03-30")
## [1] "ETERNAL.NS"
zomato_price <- Ad(ETERNAL.NS)
colnames(zomato_price) <- "Price"
plot(zomato_price,
main = "Zomato - Adjusted Closing Price",
col = "steelblue", lwd = 1.5,
ylab = "Price (INR)", xlab = "Date")

zomato_returns <- diff(log(zomato_price))
zomato_returns <- na.omit(zomato_returns)
plot(zomato_returns,
main = "Zomato - Daily Log Returns",
col = "darkred", lwd = 1,
ylab = "Log Return", xlab = "Date")

Stationarity Test
(ADF)
adf.test(zomato_returns)
##
## Augmented Dickey-Fuller Test
##
## data: zomato_returns
## Dickey-Fuller = -9.6216, Lag order = 9, p-value = 0.01
## alternative hypothesis: stationary
ACF and PACF
par(mfrow = c(1, 2))
acf(zomato_returns, main = "ACF - Zomato", lag.max = 30)
pacf(zomato_returns, main = "PACF - Zomato", lag.max = 30)

par(mfrow = c(1, 1))
ARIMA Model
zomato_arima <- auto.arima(zomato_returns,
seasonal = FALSE,
stepwise = FALSE,
approximation = FALSE)
summary(zomato_arima)
## Series: zomato_returns
## ARIMA(1,0,1) with non-zero mean
##
## Coefficients:
## ar1 ma1 mean
## -0.9131 0.9525 0.0016
## s.e. 0.0674 0.0521 0.0009
##
## sigma^2 = 0.0005955: log likelihood = 1756.45
## AIC=-3504.9 AICc=-3504.85 BIC=-3486.35
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE ACF1
## Training set 1.421569e-05 0.02435502 0.01850837 NaN Inf 0.703212 0.001583951
Residual
Diagnostics
checkresiduals(zomato_arima)

##
## Ljung-Box test
##
## data: Residuals from ARIMA(1,0,1) with non-zero mean
## Q* = 5.1901, df = 8, p-value = 0.7371
##
## Model df: 2. Total lags used: 10
Box.test(residuals(zomato_arima), lag = 10, type = "Ljung-Box")
##
## Box-Ljung test
##
## data: residuals(zomato_arima)
## X-squared = 5.1901, df = 10, p-value = 0.8781
ARCH Test
ArchTest(residuals(zomato_arima), lags = 10)
##
## ARCH LM-test; Null hypothesis: no ARCH effects
##
## data: residuals(zomato_arima)
## Chi-squared = 24.119, df = 10, p-value = 0.007292
GARCH(1,1) Model
garch_spec <- ugarchspec(
variance.model = list(model = "sGARCH", garchOrder = c(1, 1)),
mean.model = list(armaOrder = c(0, 0), include.mean = TRUE),
distribution.model = "norm"
)
zomato_garch <- ugarchfit(spec = garch_spec, data = zomato_returns)
show(zomato_garch)
##
## *---------------------------------*
## * GARCH Model Fit *
## *---------------------------------*
##
## Conditional Variance Dynamics
## -----------------------------------
## GARCH Model : sGARCH(1,1)
## Mean Model : ARFIMA(0,0,0)
## Distribution : norm
##
## Optimal Parameters
## ------------------------------------
## Estimate Std. Error t value Pr(>|t|)
## mu 0.001542 0.000870 1.7731 0.076216
## omega 0.000102 0.000045 2.2662 0.023436
## alpha1 0.090322 0.037959 2.3794 0.017339
## beta1 0.742401 0.093777 7.9167 0.000000
##
## Robust Standard Errors:
## Estimate Std. Error t value Pr(>|t|)
## mu 0.001542 0.000849 1.8171 0.069208
## omega 0.000102 0.000065 1.5651 0.117552
## alpha1 0.090322 0.050098 1.8029 0.071406
## beta1 0.742401 0.128150 5.7932 0.000000
##
## LogLikelihood : 1759.825
##
## Information Criteria
## ------------------------------------
##
## Akaike -4.5904
## Bayes -4.5661
## Shibata -4.5904
## Hannan-Quinn -4.5811
##
## Weighted Ljung-Box Test on Standardized Residuals
## ------------------------------------
## statistic p-value
## Lag[1] 0.9782 0.3226
## Lag[2*(p+q)+(p+q)-1][2] 1.7146 0.3149
## Lag[4*(p+q)+(p+q)-1][5] 2.2306 0.5650
## d.o.f=0
## H0 : No serial correlation
##
## Weighted Ljung-Box Test on Standardized Squared Residuals
## ------------------------------------
## statistic p-value
## Lag[1] 0.03128 0.8596
## Lag[2*(p+q)+(p+q)-1][5] 0.34279 0.9790
## Lag[4*(p+q)+(p+q)-1][9] 3.71201 0.6380
## d.o.f=2
##
## Weighted ARCH LM Tests
## ------------------------------------
## Statistic Shape Scale P-Value
## ARCH Lag[3] 0.02311 0.500 2.000 0.8792
## ARCH Lag[5] 0.32152 1.440 1.667 0.9345
## ARCH Lag[7] 3.91296 2.315 1.543 0.3593
##
## Nyblom stability test
## ------------------------------------
## Joint Statistic: 1.5836
## Individual Statistics:
## mu 0.36528
## omega 0.29991
## alpha1 0.03869
## beta1 0.20019
##
## Asymptotic Critical Values (10% 5% 1%)
## Joint Statistic: 1.07 1.24 1.6
## Individual Statistic: 0.35 0.47 0.75
##
## Sign Bias Test
## ------------------------------------
## t-value prob sig
## Sign Bias 0.5990 0.5494
## Negative Sign Bias 0.1018 0.9190
## Positive Sign Bias 0.6730 0.5012
## Joint Effect 2.8861 0.4095
##
##
## Adjusted Pearson Goodness-of-Fit Test:
## ------------------------------------
## group statistic p-value(g-1)
## 1 20 32.20 0.02965
## 2 30 41.63 0.06064
## 3 40 49.27 0.12537
## 4 50 52.97 0.32347
##
##
## Elapsed time : 0.06669593
Volatility Decay
alpha1 <- coef(zomato_garch)["alpha1"]
beta1 <- coef(zomato_garch)["beta1"]
persistence <- alpha1 + beta1
decay <- 1 - persistence
half_life <- log(0.5) / log(persistence)
cat("Alpha1 :", round(alpha1, 4), "\n")
## Alpha1 : 0.0903
cat("Beta1 :", round(beta1, 4), "\n")
## Beta1 : 0.7424
cat("Persistence :", round(persistence, 4), "\n")
## Persistence : 0.8327
cat("Decay Rate :", round(decay, 4), "\n")
## Decay Rate : 0.1673
cat("Half-Life :", round(half_life, 2), "days\n")
## Half-Life : 3.79 days
decay_df <- data.frame(Day = 1:60, Persistence = persistence^(1:60))
ggplot(decay_df, aes(x = Day, y = Persistence)) +
geom_line(color = "red", linewidth = 1.2) +
geom_hline(yintercept = 0.5, linetype = "dashed", color = "gray40") +
geom_vline(xintercept = half_life, linetype = "dotted", color = "steelblue") +
labs(title = "Zomato - GARCH Volatility Decay Curve",
subtitle = paste("Half-life =", round(half_life, 2), "trading days"),
x = "Days After Shock", y = "Proportion of Volatility Remaining") +
theme_minimal()

30-Day Forecast
zomato_fc <- forecast(zomato_arima, h = 30)
zomato_last <- as.numeric(tail(zomato_price, 1))
zomato_prices <- zomato_last * exp(cumsum(as.numeric(zomato_fc$mean)))
zomato_dates <- seq(as.Date("2026-03-31"), by = "day", length.out = 45)
zomato_dates <- zomato_dates[!weekdays(zomato_dates) %in% c("Saturday", "Sunday")][1:30]
zomato_df <- data.frame(Date = zomato_dates, Price = zomato_prices)
ggplot(zomato_df, aes(x = Date, y = Price)) +
geom_line(color = "steelblue", linewidth = 1.2) +
geom_hline(yintercept = zomato_last, linetype = "dashed", color = "red") +
labs(title = "Zomato - 30 Day Price Forecast",
subtitle = paste("Last Known Price: Rs.", round(zomato_last, 2)),
x = "Date", y = "Forecasted Price (INR)") +
theme_minimal()

garch_vf <- ugarchforecast(zomato_garch, n.ahead = 30)
vol_df <- data.frame(Day = 1:30, Volatility = as.numeric(sigma(garch_vf)))
ggplot(vol_df, aes(x = Day, y = Volatility)) +
geom_line(color = "darkred", linewidth = 1.2) +
labs(title = "Zomato - 30 Day Volatility Forecast (GARCH)",
x = "Days Ahead", y = "Expected Daily Volatility (Sigma)") +
theme_minimal()

Nykaa (NYKAA.NS)
Price and
Returns
getSymbols("NYKAA.NS", src = "yahoo", from = "2023-01-01", to = "2026-03-30")
## [1] "NYKAA.NS"
nykaa_price <- Ad(NYKAA.NS)
colnames(nykaa_price) <- "Price"
plot(nykaa_price,
main = "Nykaa - Adjusted Closing Price",
col = "purple", lwd = 1.5,
ylab = "Price (INR)", xlab = "Date")

nykaa_returns <- diff(log(nykaa_price))
nykaa_returns <- na.omit(nykaa_returns)
plot(nykaa_returns,
main = "Nykaa - Daily Log Returns",
col = "darkorchid", lwd = 1,
ylab = "Log Return", xlab = "Date")

Stationarity Test
(ADF)
adf.test(nykaa_returns)
##
## Augmented Dickey-Fuller Test
##
## data: nykaa_returns
## Dickey-Fuller = -9.8727, Lag order = 9, p-value = 0.01
## alternative hypothesis: stationary
ACF and PACF
par(mfrow = c(1, 2))
acf(nykaa_returns, main = "ACF - Nykaa", lag.max = 30)
pacf(nykaa_returns, main = "PACF - Nykaa", lag.max = 30)

par(mfrow = c(1, 1))
ARIMA Model
nykaa_arima <- auto.arima(nykaa_returns,
seasonal = FALSE,
stepwise = FALSE,
approximation = FALSE)
summary(nykaa_arima)
## Series: nykaa_returns
## ARIMA(0,0,5) with zero mean
##
## Coefficients:
## ma1 ma2 ma3 ma4 ma5
## 0.0367 -0.0111 0.0380 -0.0342 -0.1324
## s.e. 0.0351 0.0351 0.0353 0.0353 0.0357
##
## sigma^2 = 0.0004126: log likelihood = 1979.53
## AIC=-3947.07 AICc=-3946.96 BIC=-3918.97
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE ACF1
## Training set 0.0006083864 0.02024964 0.0148479 NaN Inf 0.6991005 0.0004389825
Residual
Diagnostics
checkresiduals(nykaa_arima)

##
## Ljung-Box test
##
## data: Residuals from ARIMA(0,0,5) with zero mean
## Q* = 0.60782, df = 5, p-value = 0.9876
##
## Model df: 5. Total lags used: 10
Box.test(residuals(nykaa_arima), lag = 10, type = "Ljung-Box")
##
## Box-Ljung test
##
## data: residuals(nykaa_arima)
## X-squared = 0.60782, df = 10, p-value = 1
ARCH Test
ArchTest(residuals(nykaa_arima), lags = 10)
##
## ARCH LM-test; Null hypothesis: no ARCH effects
##
## data: residuals(nykaa_arima)
## Chi-squared = 10.197, df = 10, p-value = 0.4234
30-Day Forecast
nykaa_fc <- forecast(nykaa_arima, h = 30)
nykaa_last <- as.numeric(tail(nykaa_price, 1))
nykaa_prices <- nykaa_last * exp(cumsum(as.numeric(nykaa_fc$mean)))
nykaa_dates <- seq(as.Date("2026-03-31"), by = "day", length.out = 45)
nykaa_dates <- nykaa_dates[!weekdays(nykaa_dates) %in% c("Saturday", "Sunday")][1:30]
nykaa_df <- data.frame(Date = nykaa_dates, Price = nykaa_prices)
ggplot(nykaa_df, aes(x = Date, y = Price)) +
geom_line(color = "purple", linewidth = 1.2) +
geom_hline(yintercept = nykaa_last, linetype = "dashed", color = "red") +
labs(title = "Nykaa - 30 Day Price Forecast",
subtitle = paste("Last Known Price: Rs.", round(nykaa_last, 2)),
x = "Date", y = "Forecasted Price (INR)") +
theme_minimal()

Delhivery
(DELHIVERY.NS)
Price and
Returns
getSymbols("DELHIVERY.NS", src = "yahoo", from = "2023-01-01", to = "2026-03-30")
## [1] "DELHIVERY.NS"
delhivery_price <- Ad(DELHIVERY.NS)
colnames(delhivery_price) <- "Price"
plot(delhivery_price,
main = "Delhivery - Adjusted Closing Price",
col = "darkorange", lwd = 1.5,
ylab = "Price (INR)", xlab = "Date")

delhivery_returns <- diff(log(delhivery_price))
delhivery_returns <- na.omit(delhivery_returns)
plot(delhivery_returns,
main = "Delhivery - Daily Log Returns",
col = "orange3", lwd = 1,
ylab = "Log Return", xlab = "Date")

Stationarity Test
(ADF)
adf.test(delhivery_returns)
##
## Augmented Dickey-Fuller Test
##
## data: delhivery_returns
## Dickey-Fuller = -9.1249, Lag order = 9, p-value = 0.01
## alternative hypothesis: stationary
ACF and PACF
par(mfrow = c(1, 2))
acf(delhivery_returns, main = "ACF - Delhivery", lag.max = 30)
pacf(delhivery_returns, main = "PACF - Delhivery", lag.max = 30)

par(mfrow = c(1, 1))
ARIMA Model
delhivery_arima <- auto.arima(delhivery_returns,
seasonal = FALSE,
stepwise = FALSE,
approximation = FALSE)
summary(delhivery_arima)
## Series: delhivery_returns
## ARIMA(0,0,0) with zero mean
##
## sigma^2 = 0.0004472: log likelihood = 1945
## AIC=-3888 AICc=-3887.99 BIC=-3883.31
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE ACF1
## Training set 0.0003208525 0.02114652 0.01530683 100 100 0.6975244 -0.02960336
Residual
Diagnostics
checkresiduals(delhivery_arima)

##
## Ljung-Box test
##
## data: Residuals from ARIMA(0,0,0) with zero mean
## Q* = 11.603, df = 10, p-value = 0.3125
##
## Model df: 0. Total lags used: 10
Box.test(residuals(delhivery_arima), lag = 10, type = "Ljung-Box")
##
## Box-Ljung test
##
## data: residuals(delhivery_arima)
## X-squared = 11.603, df = 10, p-value = 0.3125
ARCH Test
ArchTest(residuals(delhivery_arima), lags = 10)
##
## ARCH LM-test; Null hypothesis: no ARCH effects
##
## data: residuals(delhivery_arima)
## Chi-squared = 14.357, df = 10, p-value = 0.1573
30-Day Forecast
delhivery_fc <- forecast(delhivery_arima, h = 30)
delhivery_last <- as.numeric(tail(delhivery_price, 1))
delhivery_prices <- delhivery_last * exp(cumsum(as.numeric(delhivery_fc$mean)))
delhivery_dates <- seq(as.Date("2026-03-31"), by = "day", length.out = 45)
delhivery_dates <- delhivery_dates[!weekdays(delhivery_dates) %in% c("Saturday", "Sunday")][1:30]
delhivery_df <- data.frame(Date = delhivery_dates, Price = delhivery_prices)
ggplot(delhivery_df, aes(x = Date, y = Price)) +
geom_line(color = "darkorange", linewidth = 1.2) +
geom_hline(yintercept = delhivery_last, linetype = "dashed", color = "red") +
labs(title = "Delhivery - 30 Day Price Forecast",
subtitle = paste("Last Known Price: Rs.", round(delhivery_last, 2)),
x = "Date", y = "Forecasted Price (INR)") +
theme_minimal()

Naukri / Info Edge
(NAUKRI.NS)
Price and
Returns
getSymbols("NAUKRI.NS", src = "yahoo", from = "2023-01-01", to = "2026-03-30")
## [1] "NAUKRI.NS"
naukri_price <- Ad(NAUKRI.NS)
colnames(naukri_price) <- "Price"
plot(naukri_price,
main = "Naukri - Adjusted Closing Price",
col = "darkgreen", lwd = 1.5,
ylab = "Price (INR)", xlab = "Date")

naukri_returns <- diff(log(naukri_price))
naukri_returns <- na.omit(naukri_returns)
plot(naukri_returns,
main = "Naukri - Daily Log Returns",
col = "forestgreen", lwd = 1,
ylab = "Log Return", xlab = "Date")

Stationarity Test
(ADF)
adf.test(naukri_returns)
##
## Augmented Dickey-Fuller Test
##
## data: naukri_returns
## Dickey-Fuller = -10.054, Lag order = 9, p-value = 0.01
## alternative hypothesis: stationary
ACF and PACF
par(mfrow = c(1, 2))
acf(naukri_returns, main = "ACF - Naukri", lag.max = 30)
pacf(naukri_returns, main = "PACF - Naukri", lag.max = 30)

par(mfrow = c(1, 1))
ARIMA Model
naukri_arima <- auto.arima(naukri_returns,
seasonal = FALSE,
stepwise = FALSE,
approximation = FALSE)
summary(naukri_arima)
## Series: naukri_returns
## ARIMA(3,0,0) with zero mean
##
## Coefficients:
## ar1 ar2 ar3
## 0.0077 -0.1020 0.0642
## s.e. 0.0353 0.0351 0.0354
##
## sigma^2 = 0.0003648: log likelihood = 2027.78
## AIC=-4047.55 AICc=-4047.5 BIC=-4028.82
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE ACF1
## Training set 0.0003244283 0.0190625 0.0142931 NaN Inf 0.6876491 0.000722082
Residual
Diagnostics
checkresiduals(naukri_arima)

##
## Ljung-Box test
##
## data: Residuals from ARIMA(3,0,0) with zero mean
## Q* = 5.4279, df = 7, p-value = 0.6079
##
## Model df: 3. Total lags used: 10
Box.test(residuals(naukri_arima), lag = 10, type = "Ljung-Box")
##
## Box-Ljung test
##
## data: residuals(naukri_arima)
## X-squared = 5.4279, df = 10, p-value = 0.8608
ARCH Test
ArchTest(residuals(naukri_arima), lags = 10)
##
## ARCH LM-test; Null hypothesis: no ARCH effects
##
## data: residuals(naukri_arima)
## Chi-squared = 8.6926, df = 10, p-value = 0.5615
30-Day Forecast
naukri_fc <- forecast(naukri_arima, h = 30)
naukri_last <- as.numeric(tail(naukri_price, 1))
naukri_prices <- naukri_last * exp(cumsum(as.numeric(naukri_fc$mean)))
naukri_dates <- seq(as.Date("2026-03-31"), by = "day", length.out = 45)
naukri_dates <- naukri_dates[!weekdays(naukri_dates) %in% c("Saturday", "Sunday")][1:30]
naukri_df <- data.frame(Date = naukri_dates, Price = naukri_prices)
ggplot(naukri_df, aes(x = Date, y = Price)) +
geom_line(color = "darkgreen", linewidth = 1.2) +
geom_hline(yintercept = naukri_last, linetype = "dashed", color = "red") +
labs(title = "Naukri - 30 Day Price Forecast",
subtitle = paste("Last Known Price: Rs.", round(naukri_last, 2)),
x = "Date", y = "Forecasted Price (INR)") +
theme_minimal()

IndiaMART
(INDIAMART.NS)
Price and
Returns
getSymbols("INDIAMART.NS", src = "yahoo", from = "2023-01-01", to = "2026-03-30")
## [1] "INDIAMART.NS"
indiamart_price <- Ad(INDIAMART.NS)
colnames(indiamart_price) <- "Price"
plot(indiamart_price,
main = "IndiaMART - Adjusted Closing Price",
col = "royalblue", lwd = 1.5,
ylab = "Price (INR)", xlab = "Date")

indiamart_returns <- diff(log(indiamart_price))
indiamart_returns <- na.omit(indiamart_returns)
plot(indiamart_returns,
main = "IndiaMART - Daily Log Returns",
col = "blue3", lwd = 1,
ylab = "Log Return", xlab = "Date")

Stationarity Test
(ADF)
adf.test(indiamart_returns)
##
## Augmented Dickey-Fuller Test
##
## data: indiamart_returns
## Dickey-Fuller = -10.103, Lag order = 9, p-value = 0.01
## alternative hypothesis: stationary
ACF and PACF
par(mfrow = c(1, 2))
acf(indiamart_returns, main = "ACF - IndiaMART", lag.max = 30)
pacf(indiamart_returns, main = "PACF - IndiaMART", lag.max = 30)

par(mfrow = c(1, 1))
ARIMA Model
indiamart_arima <- auto.arima(indiamart_returns,
seasonal = FALSE,
stepwise = FALSE,
approximation = FALSE)
summary(indiamart_arima)
## Series: indiamart_returns
## ARIMA(0,0,0) with zero mean
##
## sigma^2 = 0.0003617: log likelihood = 2029.59
## AIC=-4057.18 AICc=-4057.18 BIC=-4052.5
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE ACF1
## Training set -7.698239e-05 0.01901958 0.01301462 100 100 0.6926321 -0.03157466
Residual
Diagnostics
checkresiduals(indiamart_arima)

##
## Ljung-Box test
##
## data: Residuals from ARIMA(0,0,0) with zero mean
## Q* = 11.735, df = 10, p-value = 0.3032
##
## Model df: 0. Total lags used: 10
Box.test(residuals(indiamart_arima), lag = 10, type = "Ljung-Box")
##
## Box-Ljung test
##
## data: residuals(indiamart_arima)
## X-squared = 11.735, df = 10, p-value = 0.3032
ARCH Test
ArchTest(residuals(indiamart_arima), lags = 10)
##
## ARCH LM-test; Null hypothesis: no ARCH effects
##
## data: residuals(indiamart_arima)
## Chi-squared = 6.22, df = 10, p-value = 0.7965
30-Day Forecast
indiamart_fc <- forecast(indiamart_arima, h = 30)
indiamart_last <- as.numeric(tail(indiamart_price, 1))
indiamart_prices <- indiamart_last * exp(cumsum(as.numeric(indiamart_fc$mean)))
indiamart_dates <- seq(as.Date("2026-03-31"), by = "day", length.out = 45)
indiamart_dates <- indiamart_dates[!weekdays(indiamart_dates) %in% c("Saturday", "Sunday")][1:30]
indiamart_df <- data.frame(Date = indiamart_dates, Price = indiamart_prices)
ggplot(indiamart_df, aes(x = Date, y = Price)) +
geom_line(color = "royalblue", linewidth = 1.2) +
geom_hline(yintercept = indiamart_last, linetype = "dashed", color = "red") +
labs(title = "IndiaMART - 30 Day Price Forecast",
subtitle = paste("Last Known Price: Rs.", round(indiamart_last, 2)),
x = "Date", y = "Forecasted Price (INR)") +
theme_minimal()

All 5 Stocks - Indexed
Comparison
all_forecasts <- data.frame(
Date = zomato_dates,
Zomato = zomato_prices,
Nykaa = nykaa_prices,
Delhivery = delhivery_prices,
Naukri = naukri_prices,
IndiaMART = indiamart_prices
)
all_norm <- all_forecasts
all_norm$Zomato <- 100 * all_norm$Zomato / all_norm$Zomato[1]
all_norm$Nykaa <- 100 * all_norm$Nykaa / all_norm$Nykaa[1]
all_norm$Delhivery <- 100 * all_norm$Delhivery / all_norm$Delhivery[1]
all_norm$Naukri <- 100 * all_norm$Naukri / all_norm$Naukri[1]
all_norm$IndiaMART <- 100 * all_norm$IndiaMART / all_norm$IndiaMART[1]
all_long <- pivot_longer(all_norm, cols = -Date,
names_to = "Stock",
values_to = "IndexedPrice")
ggplot(all_long, aes(x = Date, y = IndexedPrice, color = Stock)) +
geom_line(linewidth = 1.1) +
geom_hline(yintercept = 100, linetype = "dashed", color = "gray50") +
labs(title = "30-Day Forecast - All 5 Stocks (Indexed to 100)",
subtitle = "Base = First Forecast Day | April-May 2026",
x = "Date", y = "Indexed Price", color = "Stock") +
theme_minimal()
