Analyzing the Top 5 Companies in Nasdaq: Insights and Strategies for Optimizing Your Portfolio
Investing in the stock market requires thorough analysis and a strategic approach. In this article, I’ll walk you through an in-depth analysis of the top 5 companies in the Nasdaq, using historical performance data to make informed decisions and optimize your portfolio.
The Questions
To guide our analysis, we’ll focus on the following questions:
- How have the stock prices fluctuated over time? Are there any noticeable trends or patterns?
- How do the short-term and long-term trends compare? Are there any crossover points indicating potential buy/sell signals?
- When were the periods of high trading activity? Do volume spikes correlate with price changes?
- What are the average returns and risks associated with each stock? How volatile are these stocks?
- What is the ideal mix of these stocks to achieve the best risk-adjusted returns?
- What are the expected returns and associated risks for different portfolio combinations? Which portfolios lie on the efficient frontier?
Tools I Used
For this analysis, I harnessed the power of several key tools:
- Python: The backbone of my analysis, allowing me to analyze the data and find critical insights. Libraries used include Pandas, Matplotlib, Seaborn, and NumPy.
- Jupyter Notebooks: For running my Python scripts and including notes and analysis.
- Visual Studio Code: For executing Python scripts.
- Git & GitHub: Essential for version control and sharing code.
Data Preparation and Cleanup
I began by importing the necessary libraries and loading the dataset. Initial data cleaning ensured the quality of the data before saving it to CSV for further analysis.
import pandas as pd
import yfinance as yf
from datetime import date, timedelta
# Time period for the data
end_date = date.today().strftime("%Y-%m-%d")
start_date = (date.today() - timedelta(days=365)).strftime("%Y-%m-%d")
tickers = ['MSFT', 'AAPL', 'NVDA', 'GOOG', 'AMZN'] # Top 5 Nasdaq stocks
# Data Cleanup
import warnings
warnings.filterwarnings("ignore", category=FutureWarning)
data = yf.download(tickers, start=start_date, end=end_date, progress=False)
data.columns = ['_'.join(col).strip() for col in data.columns.values]
data = data.reset_index()
data_melted = data.melt(id_vars=['Date'], var_name='Attribute_Ticker', value_name='Value')
data_melted[['Attribute', 'Ticker']] = data_melted['Attribute_Ticker'].str.rsplit('_', n=1, expand=True)
data_pivoted = data_melted.pivot_table(index=['Date', 'Ticker'], columns='Attribute', values='Value', aggfunc='first')
stock_data = data_pivoted.reset_index()
# Save to CSV
stock_data.to_csv('stock_data.csv', index=False)
The Analysis
- How Have the Stock Prices Fluctuated Over Time?
By plotting the average closing prices over time, we can visualize the price movements of each stock.
import matplotlib.pyplot as plt
import seaborn as sns
# Reading the data
stock_data = pd.read_csv('stock_data.csv')
stock_data['Date'] = pd.to_datetime(stock_data['Date'])
stock_data.set_index('Date', inplace=True)
stock_data.reset_index(inplace=True)
# Plotting
plt.figure(figsize=(14, 7))
sns.set_theme(style='ticks')
sns.lineplot(data=stock_data, x='Date', y='Adj Close', hue='Ticker', marker='o')
plt.title('Adjusted Closing Price Over Time', fontsize=16)
plt.xlabel('Date', fontsize=14)
plt.ylabel('Adjusted Closing Price', fontsize=14)
plt.legend(title='Ticker', title_fontsize='13', fontsize='11')
plt.grid(True)
plt.xticks(rotation=25)
plt.show()
Insights:
- Microsoft (MSFT) consistently had the highest adjusted closing price, staying above $300 throughout the period.
- Apple (AAPL) and Amazon (AMZN) showed stable trends, clustering around the $100 to $200 range.
- Google (GOOG) had a similar trend to AAPL and AMZN but slightly higher.
- NVIDIA (NVDA) showed a strong upward trend starting around March 2024.
2. Short-Term vs. Long-Term Trends and Buy/Sell Signals
By comparing short-term (50-day) and long-term (200-day) moving averages, we can identify potential buy/sell signals.
short_window = 50
long_window = 200
stock_data.set_index('Date', inplace=True)
unique_tickers = stock_data['Ticker'].unique()
for ticker in unique_tickers:
ticker_data = stock_data[stock_data['Ticker'] == ticker].copy()
ticker_data['50_MA'] = ticker_data['Adj Close'].rolling(window=short_window).mean()
ticker_data['200_MA'] = ticker_data['Adj Close'].rolling(window=long_window).mean()
# Plotting
plt.figure(figsize=(14, 7))
plt.plot(ticker_data.index, ticker_data['Adj Close'], label='Adj Close')
plt.plot(ticker_data.index, ticker_data['50_MA'], label='50-Day MA')
plt.plot(ticker_data.index, ticker_data['200_MA'], label='200-Day MA')
plt.title(f'{ticker} - Adjusted Close and Moving Averages')
plt.xlabel('Date')
plt.ylabel('Price')
plt.legend()
plt.grid(True)
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
plt.figure(figsize=(14, 7))
plt.bar(ticker_data.index, ticker_data['Volume'], label='Volume', color='orange')
plt.title(f'{ticker} - Volume Traded')
plt.xlabel('Date')
plt.ylabel('Volume')
plt.legend()
plt.grid(True)
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
Insights:
- Apple (AAPL) showed a golden crossover in June 2024, indicating a potential bullish trend.
- Other stocks (MSFT, AMZN, GOOG, NVDA) showed similar trends, with occasional reversals.
3. Periods of High Trading Activity
Analyzing trading volumes revealed periods of high activity that often correlated with significant price movements.
Insights:
- Microsoft (MSFT) had consistent trading volume with occasional spikes.
- Apple (AAPL) and Amazon (AMZN) showed volume increases during earnings announcements and product releases.
- NVIDIA (NVDA) saw a significant volume increase around March 2024.
4. Average Returns and Risks
By examining the distribution of daily returns, we can assess the volatility and risk associated with each stock.
stock_data['Daily Return'] = stock_data.groupby('Ticker')['Adj Close'].pct_change()
plt.figure(figsize=(14, 7))
sns.set_style(style='whitegrid')
for ticker in unique_tickers:
ticker_data = stock_data[stock_data['Ticker'] == ticker]
sns.histplot(ticker_data['Daily Return'].dropna(), bins=50, kde=True, label=ticker, alpha=0.5)
plt.title('Distribution of Daily Returns', fontsize=16)
plt.xlabel('Daily Return', fontsize=14)
plt.ylabel('Frequency', fontsize=14)
plt.legend(title='Ticker', title_fontsize='13', fontsize='11')
plt.grid(True)
plt.tight_layout()
plt.show()
Insights:
Apple (AAPL) and Google (GOOG) showed wider distributions, suggesting higher volatility.
5. Ideal Mix for Best Risk-Adjusted Returns
A correlation matrix of daily returns helps identify effective combinations for a diversified portfolio.
daily_returns = stock_data.pivot_table(index='Date', columns='Ticker', values='Daily Return')
correlation_matrix = daily_returns.corr()
plt.figure(figsize=(12, 10))
sns.set_style(style='whitegrid')
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', linewidths=.5, fmt='.2f', annot_kws={"size": 10})
plt.title('Correlation Matrix of Daily Returns', fontsize=16)
plt.xticks(rotation=90)
plt.yticks(rotation=0)
plt.tight_layout()
plt.show()
Insights:
- Amazon (AMZN) and Microsoft (MSFT) had the highest correlation (0.58).
- A diversified portfolio with low correlation stocks reduces potential risk.
6. Expected Returns and Risks for Different Portfolios
Simulating 10,000 portfolios, we plot the efficient frontier to identify the best risk-adjusted returns.
import numpy as np
expected_returns = daily_returns.mean() * 252 # Annualize returns
volatility = daily_returns.std() * np.sqrt(252) # Annualize volatility
stock_stats = pd.DataFrame({
'Expected Return': expected_returns,
'Volatility': volatility
})
# Function to calculate portfolio performance
def portfolio_performance(weights, returns, cov_matrix):
portfolio_return = np.dot(weights, returns)
portfolio_volatility = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))
return portfolio_return, portfolio_volatility
# Simulate portfolios
num_portfolios = 10000
results = np.zeros((3, num_portfolios))
cov_matrix = daily_returns.cov() * 252
np.random.seed(42)
for i in range(num_portfolios):
weights = np.random.random(len(expected_returns))
weights /= np.sum(weights)
portfolio_return, portfolio_volatility = portfolio_performance(weights, expected_returns, cov_matrix)
results[0,i] = portfolio_return
results[1,i] = portfolio_volatility
results[2,i] = results[0,i] / results[1,i] # Sharpe ratio
# Efficient Frontier
max_sharpe_idx = np.argmax(results[2])
min_vol_idx = np.argmin(results[1])
plt.figure(figsize=(12, 8))
plt.scatter(results[1,:], results[0,:], c=results[2,:], cmap='viridis', marker='o', alpha=0.3)
plt.colorbar(label='Sharpe Ratio')
plt.scatter(results[1, max_sharpe_idx], results[0, max_sharpe_idx], marker='*', color='r', s=500, label='Max Sharpe Ratio')
plt.scatter(results[1, min_vol_idx], results[0, min_vol_idx], marker='*', color='b', s=500, label='Min Volatility')
plt.title('Efficient Frontier', fontsize=16)
plt.xlabel('Volatility (Std. Deviation)', fontsize=14)
plt.ylabel('Expected Return', fontsize=14)
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
Insights:
- The portfolio with the highest Sharpe Ratio includes NVIDIA (NVDA) and Apple (AAPL).
Conclusion
This comprehensive analysis demonstrates how we can leverage historical stock data to make informed investment decisions. By understanding stock price trends, trading volumes, returns, risks, and correlations, we can create a diversified portfolio optimized for risk-adjusted returns. Happy investing!
By focusing on these questions and utilizing powerful tools like Python and Jupyter Notebooks, you can gain valuable insights into the stock market, helping you make informed decisions to optimize your investment portfolio.