1. Introduction

The data set consists of weekly stock data from 2018 to 2025 march for Tesla Inc., sourced from Investing.com. Each row represents a week’s trading summary, and key variables include Date (the week-ending date), Price or Close or High or low (the adjusted closing price for that week), and Return (the percentage change in price from the previous week). I have derived variables used for technical analysis include moving averages such as SMA_50, SMA_200, and EMA_50, which help identify long-term and short-term trends. The data set also includes Bollinger Bands components—up, dn, and mavg—used to assess market volatility, as well as MACD indicators (MACD, Signal, Histogram) to measure momentum. These variables together provide a comprehensive view of Tesla’s stock behavior over time, enabling both performance evaluation and trend forecasting.

Liberary function for the coding.

I have loaded all the required library function usisng the following function.

library(TTR)
library(ggplot2)
library(plotly)
library(tidyverse)
library(gapminder)
library(gganimate)
library(dplyr)
library(readr)
library(lubridate)
library(tidyr)
library(quantmod)
library(PerformanceAnalytics)
  1. Data accumulation

After that, I Loaded the data sets to do the required calculation. Here, I have assure the name of each column and also fix the data that has been uploaded in the csv file usig gsub function.

tesla_data <- read.delim("~/R/Tesla.csv")
      View(tesla_data)
      
colnames(tesla_data) <- c("Date", "Price","Open", "High","low")

tesla_data$Date <- as.Date(tesla_data$Date, format="%m/%d/%Y")

tesla_data$Price <- as.numeric(gsub(",", "", tesla_data$Price))

tesla_data$Open <- as.numeric(gsub(",", "", tesla_data$Open))

tesla_data$High <- as.numeric(gsub(",", "", tesla_data$High))

tesla_data$low <- as.numeric(gsub(",", "", tesla_data$low))
  1. Summary and Return calculation

After I uploaded the data, using the sum and summery function I have check the data status and Weekly Return calculation of Tesla for last eight years has been conducted using mutate function.

str(tesla_data)
## 'data.frame':    378 obs. of  5 variables:
##  $ Date : Date, format: "2018-01-07" "2018-01-14" ...
##  $ Price: num  22.4 23.3 22.9 22.9 20.7 ...
##  $ Open : num  21.1 22.5 23.3 22.7 22.5 ...
##  $ High : num  23 23.5 24 24 23.2 ...
##  $ low  : num  21 22.3 22.4 22.6 19.6 ...
sum(is.na(tesla_data))  
## [1] 0
summary(tesla_data)
##       Date                Price             Open             High       
##  Min.   :2018-01-07   Min.   : 12.34   Min.   : 12.37   Min.   : 13.00  
##  1st Qu.:2019-10-28   1st Qu.: 23.52   1st Qu.: 23.71   1st Qu.: 24.36  
##  Median :2021-08-18   Median :191.19   Median :188.93   Median :199.51  
##  Mean   :2021-08-18   Mean   :164.55   Mean   :164.17   Mean   :174.30  
##  3rd Qu.:2023-06-09   3rd Qu.:248.91   3rd Qu.:247.88   3rd Qu.:258.20  
##  Max.   :2025-03-30   Max.   :436.23   Max.   :441.09   Max.   :488.54  
##       low        
##  Min.   : 11.80  
##  1st Qu.: 22.35  
##  Median :177.67  
##  Mean   :154.70  
##  3rd Qu.:234.82  
##  Max.   :417.64
tesla_data <- tesla_data %>%
  arrange(Date) %>%
  mutate(Return = (Price - lag(Price)) / lag(Price))

tesla_data$Return[is.na(tesla_data$Return)] <- 0
  1. Candlestick visualization

This code includes several functions for cleaning, summarizing, and visualizing Tesla’s weekly stock data. The gsub function removes commas from the Price column to ensure numeric formatting, while as.numeric converts the cleaned data from character to numeric format. The summary function is then applied to the Price, Open, High, and Low columns to produce basic descriptive statistics like minimum, maximum, mean, and median values. For visualization, the plot_ly function generates an interactive candlestick chart with the Open, High, Low, and Price columns, allowing users to investigate Tesla’s stock movement over time. The layout function modifies the chart by adding titles to the axes and the chart itself. Finally, ggplotly is used to make the plot interactive, allowing it to be easily embedded in R Markdown documents or Shiny applications.

 tesla_data$Price <- as.numeric(gsub(",", "", tesla_data$Price))

summary(tesla_data$Price)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   12.34   23.52  191.19  164.55  248.91  436.23
summary(tesla_data$Open)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   12.37   23.71  188.93  164.17  247.88  441.09
summary(tesla_data$High)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   13.00   24.36  199.51  174.30  258.20  488.54
summary(tesla_data$Low)
## Length  Class   Mode 
##      0   NULL   NULL
CH <- fig <- tesla_data %>%
  plot_ly(x = ~Date, type = "candlestick",
          open = ~Open, high = ~High, low = ~low, close = ~Price) %>%
  layout(title = "Tesla Candlestick Chart 2018 to 2025",
         xaxis = list(title = "Date"),
         yaxis = list(title = "Price"))

plotly_chart <- ggplotly(CH)
plotly_chart
  1. Static Visualization: Tesla Stock Closing Price Over Time

I have used ggplot2 to create a line chart of Tesla’s stock price over the last eight years, and plotly to make it interactive. The plot is initialized with Date on the x-axis and Price on the y-axis by the ggplot function. While geom_smooth adds a red linear regression line without a confidence interval (se = FALSE) to emphasize the overall trend, geom_line depicts the stock price trend as a smooth blue line. The theme_minimal gives the plot a tidy appearance, and the labs function adds axis labels and clear titles. Lastly, ggplotly turns the static ggplot chart into an interactive plot, allowing for tooltip display, zooming, and hovering. .

gg <- ggplot(tesla_data, aes(x = Date, y = Price)) +
  geom_line(color = "blue", size = 1, alpha = 0.9) +
  geom_smooth(method = "lm", color = "red", se = FALSE) +
  labs(title = "Tesla Stock Price Over 8 Years", x = "Date", y = "Closing Price ($)") +
  theme_minimal()

plotly_chart <- ggplotly(gg)
plotly_chart

The Figure above shows the trend of tesla price from 2018 to 2025. We can see from the visuals that the price till 2020 was smooth and low but once it starts recovering form the Covid, the price has increasing dramatically. T rend also shows that the price is in increasing trend for Tesla.

  1. Create an Animated Visualization

This visuals shows how the price has been since 2018 to 2025 throught the animated bubble.

gg_anim <- ggplot(tesla_data, aes(x = Date, y = Price)) +
  geom_line(color = "blue", size = 1, alpha = 0.8) +
  geom_point(aes(color = High), size = 3) +
  labs(title = "Tesla Stock Price Movement: {frame_time}", x = "Date", y = "Closing Price ($)") +
  transition_time(Date) +
  ease_aes("linear")

animate(gg_anim, nframes = 100, fps = 10)
gganimate::anim_save("tesla_stock_animation.gif", gg_anim)

gg_anim

7. Regression

Using the regression formula i have calculate the Beta value.The beta value for the tesla for last 8 years is 0.51, which means its not very risky stok and if market goes up by 10%, the stock will go up by 5%.

reg_model <- lm(Price ~ Open + High + low, data = tesla_data)
summary(reg_model)
## 
## Call:
## lm(formula = Price ~ Open + High + low, data = tesla_data)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -40.178  -1.826  -0.209   2.609  25.408 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  0.51313    0.61581   0.833    0.405    
## Open        -0.63841    0.04100 -15.570   <2e-16 ***
## High         0.91857    0.03923  23.415   <2e-16 ***
## low          0.70291    0.04259  16.505   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 6.875 on 374 degrees of freedom
## Multiple R-squared:  0.9965, Adjusted R-squared:  0.9965 
## F-statistic: 3.537e+04 on 3 and 374 DF,  p-value: < 2.2e-16
  1. Price vs return

In this code, a scatter plot is created to visualize the relationship between Tesla’s stock returns and prices. Using ggplot, the plot maps Return on the x-axis and Price on the y-axis. geom_point adds semi-transparent blue dots to represent individual data points. Two trend lines are added using geom_smooth: the first is a red linear regression line without a confidence interval, and the second is a firebrick-colored line with a green shaded confidence band (se = TRUE, fill = “green”, alpha = 0.3). coord_cartesian ensures the plot stays within the actual range of the data, and theme_minimal keeps the design clean and simple. Finally, ggplotly makes the plot interactive, allowing dynamic data exploration.

ga <- ggplot(tesla_data, aes(x = Return, y = Price)) +
  geom_point(color = "blue", size = 2, alpha = 0.6) +
  geom_smooth(method = "lm", color = "red", linetype = "solid", se = FALSE) + 
  labs(title = "Scatter Plot of Price vs Return with Trend Line", x = "Return (%)", y = "Price") +  geom_smooth(method = "lm", color = "firebrick", se = TRUE, fill = "green", alpha = 0.3) +
  
  coord_cartesian(xlim = c(min(tesla_data$Return), max(tesla_data$Return)),
                  ylim = c(min(tesla_data$Price), max(tesla_data$Price))) +
   theme_minimal()

 plotly_chart <- ggplotly(ga)
plotly_chart
  1. Volatility Analysis of Tesla

I have used histogram to depict the return distribution of Tesla and find out that the return distribution for Tesla looks more or less a normal distribution.

tesla_data$Return <- na.omit(tesla_data$Return)
chart.Histogram(tesla_data$Return, main = "Tesla Stock Return Distribution", methods = c("add.normal"))

  1. Moving Averages Calculation

I have used function like SMA and EMA to depict the moving average for Tesla inc. Differemt colours and function like geom_line and other are used to get the clear figure of it.

tesla_data$SMA_50 <- SMA(tesla_data$Price, n = 50)
tesla_data$SMA_200 <- SMA(tesla_data$Price, n = 200)

tesla_data$EMA_50 <- EMA(tesla_data$Price, n = 50)

Raut <- ggplot(tesla_data, aes(x = Date)) +
  geom_line(aes(y = Price, color = "Price"), size = 1) +
  geom_line(aes(y = SMA_50, color = "50-day SMA"), size = 1, linetype = "dashed") +
  geom_line(aes(y = SMA_200, color = "200-day SMA"), size = 1, linetype = "dashed") +
  geom_line(aes(y = EMA_50, color = "50-day EMA"), size = 1) +
  labs(title = "Tesla Stock Price with 50-day and 200-day SMA, and EMA",
       x = "Date", y = "Price ($)") +
  scale_color_manual(values = c("Price" = "black", 
                                "50-day SMA" = "blue", 
                                "200-day SMA" = "red", 
                                "50-day EMA" = "green")) +
  theme_minimal() +
  theme(legend.title = element_blank())


plotly_chart <- ggplotly(Raut)
plotly_chart

The graph above has shows all the combination of price and some relative moving average for Tesla. From the figure we can say that the trend are in increasing rate and we can see positive market trend.

  1. Relative Strength Index (RSI)

Relative Strength Index (RSI) has been defined as the momentum oscillator that measures the speed and change of price movements. It is commonly used in technical analysis to identify overbought or oversold conditions in a market. I have used RSI to see the Tesla status and depict a grpah.

tesla_data$RSI <- RSI(tesla_data$Price, n = 14)

gg_rsi <- ggplot(tesla_data, aes(x = Date, y = RSI)) +
  geom_line(color = "purple", size = 1) +
  geom_hline(yintercept = c(30, 70), linetype = "dashed", color = "red") +
  labs(title = "Tesla Stock RSI Indicator", x = "Date", y = "RSI") +
  theme_minimal()

plotly_chart <- ggplotly(gg_rsi)
plotly_chart

RSI above 70 generally indicates that the asset is overbought, meaning the price has risen too quickly and could be due for a pullback or correction which incur in 2020 and 2024 in case of Tesla. Similarly, RSI below 30 typically suggests that the asset is oversold, meaning the price has fallen too quickly and could be due for a bounce or reversal and it occurs in 2023. Other then that, the price of Tessa’s values is between 30 and 70 indicate a neutral condition, where the price is neither overbought nor oversold.

  1. Monte Carlo Simulation

I have done an monte carlo simulation for Tesla which define as computational technique used to understand the impact of uncertainty and variability in models and processes. I have generated 20 possible paths which can occur for Tesla. Following formula has been used: simulated_prices[t] <- simulated_prices[t - 1] * exp((mean_return - 0.5 * volatility^2) * dt + volatility * sqrt(dt) * random_shock)

This Monte Carlo simulation is a versatile and robust tool for understanding and quantifying risk, enabling more informed decision-making in scenarios involving uncertainty about the stock of Tesla.

mean_return <- mean(tesla_data$Return)
volatility <- sd(tesla_data$Return)

num_simulations <- 20   
num_days <- 252        
initial_price <- tail(tesla_data$Price, 1) 


tesla_data$Return <- (tesla_data$Price - lag(tesla_data$Price)) / lag(tesla_data$Price)
mean_return <- mean(tesla_data$Return, na.rm = TRUE)
volatility <- sd(tesla_data$Return, na.rm = TRUE)


dt <- 1 / 252

simulated_paths <- data.frame(Date = rep(seq(from = Sys.Date(), by = "day", length.out = num_days), num_simulations),
                              Path = rep(1:num_simulations, each = num_days),
                              Price = NA)

set.seed(123)  
for (i in 1:num_simulations) {
  simulated_prices <- numeric(num_days)
  simulated_prices[1] <- initial_price
  
  for (t in 2:num_days) {
    random_shock <- rnorm(1, mean = 0, sd = 1)  
    simulated_prices[t] <- simulated_prices[t - 1] * exp((mean_return - 0.5 * volatility^2) * dt + volatility * sqrt(dt) * random_shock)
  }
  
  simulated_paths$Price[simulated_paths$Path == i] <- simulated_prices
}


MC <- ggplot(simulated_paths, aes(x = Date, y = Price, group = Path, color = as.factor(Path))) +
  geom_line() +
  labs(title = "Monte Carlo Simulation: 20 Paths of Tesla Stock Price",
       x = "Date", y = "Stock Price ($)", color = "Simulation Path") +
  theme_minimal() +
  theme(legend.position = "none") + 
  scale_color_viridis_d()


plotly_chart <- ggplotly(MC)
plotly_chart
  1. Bollinger Bands Calculation

I have used bollinger to see the price status of Tesla in last 8 years. Sometime the price has gone with upper band and sometimes with the lower band. These trends for instance shows that weather the stock is overbought or oversold. These can cause the uncertaining of bolling and breaing of the stock.

bollinger <- BBands(tesla_data$Price, n = 20, sd = 2)
tesla_data <- cbind(tesla_data, bollinger)

gg_bb <- ggplot(tesla_data, aes(x = Date, y = Price)) +
  geom_line(color = "black", size = 1, aes(color = "Price")) +  # Line for stock price
  geom_line(aes(y = up, color = "Upper Band"), linetype = "dashed", size = 1) +  # Upper Bollinger Band
  geom_line(aes(y = dn, color = "Lower Band"), linetype = "dashed", size = 1) +  # Lower Bollinger Band
  geom_line(aes(y = mavg, color = "Moving Average"), linetype = "dashed", size = 1) +  # Moving Average
  labs(title = "Tesla Stock Bollinger Bands", x = "Date", y = "Price ($)") +
  scale_color_manual(values = c("Price" = "black", "Upper Band" = "blue", "Lower Band" = "red", "Moving Average" = "green")) +  
  theme_minimal() +
  theme(legend.title = element_blank())

gg_bb

  1. sharpe_ratio
## 6.2 Risk-Return Profile
sharpe_ratio <- mean(tesla_data$Return, na.rm = TRUE) / 
                sd(tesla_data$Return, na.rm = TRUE)

cat("\nSharpe Ratio:", round(sharpe_ratio, 3))
## 
## Sharpe Ratio: 0.119

This value indicates that for every unit of risk, your investment or portfolio is only generating 0.118 units of excess return over the risk-free rate

  1. Weekly average return

This code groups Tesla stock data by Date, calculates the average return for each date, and then plots it as a bar chart using ggplot2. The bars (in steel blue) show how the average return varies over time. The x-axis shows the date by year, and the y-axis shows the average return.

tesla_data %>%
  group_by(Date) %>%
  summarize(Avg_Return = mean(Return, na.rm = TRUE)) %>%
  ggplot(aes(x = Date, y = Avg_Return)) +
  geom_col(fill = "steelblue") +
  labs(title = "Seasonality: Average Returns by Week of Year",
       y = "Average Return",
       x = "Week Number") + scale_x_date(date_breaks = "1 year", date_labels = "%Y")+
  theme_minimal()