Intro to stock analysis
Tags: python, tutorial, beginners, api
Published: 2024-03-02 22:16:50

In this exploration, we're diving into the stock market analysis using the [Finazon](https://finazon.io). Leveraging Python's Pandas library, we aim to dissect, visualize, and understand the intricacies of stock performance. Our dataset, courtesy of Finazon's comprehensive financial data packages, provides us with a robust foundation for analysis.

**Project Overview**

Our focus will revolve around answering pivotal questions that any investor or financial analyst might ponder:

- How has the price of a stock fluctuated over time?
- What's the average daily return of a stock?
- How do the moving averages of stocks compare?
- The significance of moving averages in stock analysis.
- Understanding and utilizing technical indicators.
- The correlation between daily returns of various stocks.
- Evaluating the returns of different stocks.
- Assessing the risk associated with investing in particular stocks.
- Predicting future stock behavior based on historical trends.

## Loading data

**Analyzing AI Tech Giants**

For our case study, we'll zoom in on the tech behemoths: Nvidia (NVDA), Google (GOOGL), Microsoft (MSFT), and ARM Holdings (ARM). The aim is to dissect their performance over the past year, leveraging the Finazon package to fetch real-time and historical data.

**Data Extraction and Initial Analysis**

Instead of relying on static CSV files from Yahoo Finance, we dynamically fetch data via Finazon, ensuring our analysis is up-to-date and reflective of the latest market conditions. 

We need to install Finazon gRPC Python [package](https://github.com/finazon-io/finazon-grpc-python) to fetch stocks historical data:

```shell
pip install finazon-grpc-python
```

And here's a snippet to fetch Nvidia's stock data:

```python
from finazon_grpc_python.time_series_service import TimeSeriesService, GetTimeSeriesRequest
from google.protobuf.json_format import MessageToDict
import pandas as pd

service = TimeSeriesService('YOUR_API_KEY')

request = GetTimeSeriesRequest(ticker='NVDA', interval='1d', dataset='us_stocks_essential', page_size=100)
response = service.get_time_series(request)

df = pd.DataFrame.from_dict(MessageToDict(response)['result'])
```

This code snippet showcases the conversion of the Finazon data format to a pandas data frame, enabling us to query detailed stock information easily.

**Deep Dive into the Data**

Upon retrieving the data, we delved into its structure, examining key statistics and ensuring there were all the values. Our analysis will cover the basic statistics of Nvidia's stock data, similar to how one would use Pandas' `df.head()`, `df.tail()`, `df.describe()` and `df.info()` methods.


![NVDA output of df.describe()](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4ew0bjt9bxj7y3x0caeb.png)


**Price Fluctuations Over Time**

Analyzing the price changes over the past year offers insights into market trends and stock performance. With Finazon data, we can easily plot the adjusted close price for Nvidia. 

Additionally, understanding the volume of stock traded is crucial for gauging market interest and liquidity. We'll visualize the trading volume for Nvidia, highlighting spikes and troughs throughout the period.

First, install the following visualization packages if you still need to.

```shell
pip install matplotlib mplfinance seaborn
```

And here is the code for the chart.

```python
import mplfinance as mpf

# reverse order of the rows
df = df.reindex(index=df.index[::-1])

# convert timestamp to date
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='s').apply(lambda x: x.date())

# set index (X-axis) to be in datetime format
df.index = pd.to_datetime(df.index)

# create an additional volume chart
apdict = mpf.make_addplot(df['volume'], type='line', panel=1, color='blue', ylabel='Volume')

mpf.plot(df,
         type='candle',
         addplot=apdict,
         volume=True,
         figratio=(12, 6),
         figscale=1.0,
         style='charles',
         title='NVidia (NVDA) chart',
         ylabel='Price')
```


![Nvidia OHLC chart with volume](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/35i94lzylh9bc325vme6.png)

## Technical Indicators

Finazon simplifies access to technical indicators, making them readily available without cumbersome calculations. This accessibility transforms how investors and hedge funds analyze stocks, saving precious time and computational resources.

To demonstrate, let's leverage Finazon's Python package to enrich our dataset with various technical indicators. Here's how to get started with a simple moving average:

```python
from finazon_grpc_python.time_series_service import TimeSeriesService, GetTimeSeriesRequest, GetTimeSeriesMaRequest
from google.protobuf.json_format import MessageToDict

service_ma = TimeSeriesService('YOUR_API_KEY')

ts = GetTimeSeriesRequest(ticker='NVDA', interval='1h', dataset='us_stocks_essential', page_size=100)
request_ma = GetTimeSeriesMaRequest(time_series=ts, time_period=10)
response_ma = service_ma.get_time_series_ma(request_ma)

df = pd.DataFrame.from_dict(MessageToDict(response_ma)['result'])
```

**Exploring Moving Averages**

Moving averages smooth out price data to identify trends over time, making them indispensable in stock analysis. Let's calculate and visualize moving averages for Nvidia based on the first chart:

```python
df['SMA20'] = df['close'].rolling(window=20).mean()
df['SMA50'] = df['close'].rolling(window=50).mean()

# Create a dictionary for the additional plots (moving averages)
add_plots = [
    pdf.make_addplot(df['SMA20'], color='blue', width=0.75),  # Simple Moving Average 20
    mpf.make_addplot(df['SMA50'], color='red', width=0.75),   # Simple Moving Average 50
]

# Plot the candlestick chart with moving averages
mpf.plot(df,
         type='candle',
         style='charles',
         volume=True,
         addplot=add_plots,
         figratio=(12, 6),
         title="Candlestick chart with SMA20 (blue), SMA50 (red)",
         ylabel='Price',
         ylabel_lower='Volume',
         volume_panel=1,
         panel_ratios=(3, 1)) 
```

This visualization provides a clear view of Nvidia's stock trend, with the smoothing effect of moving averages revealing underlying patterns.

**Why Technical Indicators**
Technical indicators encompass various statistical tools based on historical trading data to predict future stock price movements. These include moving averages, momentum oscillators, volatility bands, and trend indicators, among others. Each type provides insights into different aspects of market behavior, such as momentum, trend direction, volatility, and trading volumes.

For traders and investors, technical indicators are invaluable for crafting strategies. They help identify critical support and resistance levels - crucial markers for determining when to enter or exit a trade. Moreover, these indicators play a significant role in spotting trend reversals, enabling traders to capitalize on market shifts. By integrating these tools into their analysis, market participants can make more informed, data-backed trading and investment decisions, enhancing their potential for profitability.

## Advanced

**Assessing Daily Returns**

Examining a stock's daily returns is crucial to gauge its volatility and potential for profit (or loss). Here's how to compute and visualize them for Nvidia:

```python
import seaborn as sns
import matplotlib.pyplot as plt

# Calculate daily returns
df['return'] = df['close'].pct_change()

sns.displot(df['return'].dropna(), bins=60, color='green', kde=True)
plt.show()
```

![Nvidia's daily returns](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y7803lszwxuj4t6z6qf7.png)


This distribution plot reveals the frequency of positive versus negative daily returns, providing insights into the stock's risk and reward profile.

In our journey through stock market analysis, understanding the correlation between the daily returns of different stocks is crucial. This metric helps us discern how stocks move about one another. By aggregating our data into a single data frame, we unlock the ability to perform comprehensive correlation analyses.



```python
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from finazon_grpc_python.time_series_service import TimeSeriesService, GetTimeSeriesRequest
from google.protobuf.json_format import MessageToDict


def get_time_series(ticker):
    # Initialize the service with your API key
    service = TimeSeriesService('YOUR_API_KEY')

    request = GetTimeSeriesRequest(ticker=ticker, interval='1d', dataset='us_stocks_essential', page_size=100)
    response = service.get_time_series(request)
    df = pd.DataFrame.from_dict(MessageToDict(response)['result'])
    df['timestamp'] = pd.to_datetime(df['timestamp'], unit='s')
    df.set_index('timestamp', inplace=True)
    df = df[['close']].rename(columns={'close': ticker})
    return df


# Get the time series for each ticker
tickers = ['NVDA', 'MSFT', 'GOOGL', 'ARM']
dfs = [get_time_series(ticker) for ticker in tickers]

# Combine all dataframes into a single dataframe
combined_df = pd.concat(dfs, axis=1)

# Compute the Pearson correlation matrix
corr_matrix = combined_df.corr()

# Display the heatmap
sns.heatmap(corr_matrix, annot=True, cmap='RdYlGn')
plt.title('Pearson Correlation Matrix')
plt.show()
```

The heatmap vividly illustrates the correlations, revealing strong interconnections, particularly among tech giants like Nvidia, Google, and Microsoft, with Arm Holdings showing a slightly divergent path.


![AI companies heatmap](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ao18p3rnh2676z3ef4qk.png)

**Evaluating Stock Returns**

A pivotal aspect of our analysis is comparing the returns of various stocks. A direct approach involves plotting the price movements over time. However, to gauge the actual performance, normalizing these prices to the start of our observation period offers a clearer perspective.

```python
# Normalize the closing prices
normalized_dfs = [(df.iloc[:, 0].pct_change() * 100).dropna() for df in dfs]

# Combine the normalized dataframes into a single dataframe
combined_normalized_df = pd.concat(normalized_dfs, axis=1, join='inner')
combined_normalized_df.columns = tickers

# Plot the daily return percentage for each instrument
combined_normalized_df.plot(figsize=(15, 10))
plt.title('Daily Return Percentage')
plt.ylabel('Daily Return (%)')
plt.xlabel('Date')
plt.legend(title="Ticker")
plt.show()
```

This normalized view provides a more apples-to-apples comparison, highlighting each stock's relative performance and potential return from the initial investment point.


![Normalized daily returns of AI giants](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/84ujurrxpwmda85zgxsv.png)



**Quantifying Risk and Return**

Understanding the risk and potential return of investments is pivotal. A straightforward method is to contrast the average daily return with the standard deviation of these returns. This comparison delineates the risk-return profile of each stock, enabling investors to make informed decisions based on their risk tolerance.

**Value at Risk (VaR): A Measure of Investment Risk**

VaR offers a quantified estimate of a portfolio's potential loss in value. By applying the Bootstrap and Monte Carlo methods, we can ascertain this risk metric, offering a clearer view of what we stand to lose under adverse market conditions.

```python
# Reverse the order of the DataFrame and reset index
df = df.iloc[::-1].reset_index(drop=True)

# Convert timestamp to datetime and set as index
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='s')
df.set_index('timestamp', inplace=True)

# Calculate daily_returns
df['daily_return'] = df['close'].pct_change()

# Drop NaN values from the 'daily_return' column
df = df.dropna(subset=['daily_return'])

# Bootstrap Method for calculating VaR
var_bootstrap = df['daily_return'].quantile(0.05)

# Monte Carlo Simulation for VaR
num_simulations = 10000
mean_return = df['daily_return'].mean()
std_return = df['daily_return'].std()
simulated_returns = np.random.normal(mean_return, std_return, num_simulations)
var_monte_carlo = np.percentile(simulated_returns, 5)

print(f"Bootstrap VaR at 95% confidence level: {var_bootstrap*100:.2f}%")
print(f"Monte Carlo VaR at 95% confidence level: {var_monte_carlo*100:.2f}%")
```

This calculation suggests that, with 95% confidence, our worst expected daily loss won't exceed ~ -3%, providing investors with a tangible measure of risk.


![Output of Nvidia's value at risk metrics](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/92es0y05hc4qky3xckl1.png)



**Wrapping Up**

Our analysis, leveraging the rich dataset and tools provided by Finazon, not only demystifies stock market dynamics but also empowers investors with actionable insights. From understanding the correlation between stocks and assessing their return profiles to quantifying investment risk through VaR, these analyses form the bedrock of informed investment strategies. Whether for seasoned investors or those new to the market, the insights gleaned here pave the way for more nuanced and data-driven investment decisions, ensuring that risks are known and returns are maximized.

What do you think? Post your thoughts in the comments!