Amihud Illiquidity Ratio
Calculate the Amihud illiquidity ratio from daily absolute return and dollar trading volume data to measure the price impact per unit of trading activity, enabling cross-sectional and time-series comparison of liquidity conditions across crypto assets.
Amihud Illiquidity Ratio Calculation
This notebook demonstrates the calculation and analysis of the Amihud Illiquidity Ratio. The Amihud illiquidity ratio, introduced by Yakov Amihud (2002), is a widely used measure in financial economics to quantify the impact of order flow on asset prices. It essentially measures the daily absolute stock return per unit of daily dollar trading volume. A higher Amihud ratio indicates lower liquidity, meaning a given trading volume has a larger impact on the stock's price.
Core Concepts
| Concept | Description |
|---|---|
| Amihud Illiquidity Ratio | A measure of market impact, calculated as the absolute daily stock return divided by the daily dollar trading volume. Higher values imply lower liquidity. |
| Absolute Daily Return | The absolute value of the daily percentage change in a stock's price, reflecting the magnitude of price movement. |
| Daily Dollar Volume | The daily trading volume (number of shares traded) multiplied by the closing price, representing the total value of shares traded daily. |
| Liquidity | The ease with which an asset can be converted into cash without significantly affecting its market price. Highly liquid assets can be traded quickly and at a low cost. |
2. Dependency Installation
This section installs all necessary Python packages required for the notebook, including pandas for data manipulation, numpy for numerical operations, yfinance for fetching financial data, and matplotlib and seaborn for visualization.
import sys
# Install yfinance for fetching stock data
!{sys.executable} -m pip install pandas numpy yfinance matplotlib seaborn
Requirement already satisfied: pandas in /usr/local/lib/python3.12/dist-packages (2.2.2) Requirement already satisfied: numpy in /usr/local/lib/python3.12/dist-packages (2.0.2) Requirement already satisfied: yfinance in /usr/local/lib/python3.12/dist-packages (0.2.66) Requirement already satisfied: matplotlib in /usr/local/lib/python3.12/dist-packages (3.10.0) Requirement already satisfied: seaborn in /usr/local/lib/python3.12/dist-packages (0.13.2) Requirement already satisfied: python-dateutil>=2.8.2 in /usr/local/lib/python3.12/dist-packages (from pandas) (2.9.0.post0) Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.12/dist-packages (from pandas) (2025.2) Requirement already satisfied: tzdata>=2022.7 in /usr/local/lib/python3.12/dist-packages (from pandas) (2026.2) Requirement already satisfied: requests>=2.31 in /usr/local/lib/python3.12/dist-packages (from yfinance) (2.32.4) Requirement already satisfied: multitasking>=0.0.7 in /usr/local/lib/python3.12/dist-packages (from yfinance) (0.0.13) Requirement already satisfied: platformdirs>=2.0.0 in /usr/local/lib/python3.12/dist-packages (from yfinance) (4.10.0) Requirement already satisfied: frozendict>=2.3.4 in /usr/local/lib/python3.12/dist-packages (from yfinance) (2.4.7) Requirement already satisfied: peewee>=3.16.2 in /usr/local/lib/python3.12/dist-packages (from yfinance) (4.0.6) Requirement already satisfied: beautifulsoup4>=4.11.1 in /usr/local/lib/python3.12/dist-packages (from yfinance) (4.13.5) Requirement already satisfied: curl_cffi>=0.7 in /usr/local/lib/python3.12/dist-packages (from yfinance) (0.15.0) Requirement already satisfied: protobuf>=3.19.0 in /usr/local/lib/python3.12/dist-packages (from yfinance) (5.29.6) Requirement already satisfied: websockets>=13.0 in /usr/local/lib/python3.12/dist-packages (from yfinance) (15.0.1) Requirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (1.3.3) Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (0.12.1) Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (4.63.0) Requirement already satisfied: kiwisolver>=1.3.1 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (1.5.0) Requirement already satisfied: packaging>=20.0 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (26.2) Requirement already satisfied: pillow>=8 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (11.3.0) Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (3.3.2) Requirement already satisfied: soupsieve>1.2 in /usr/local/lib/python3.12/dist-packages (from beautifulsoup4>=4.11.1->yfinance) (2.8.4) Requirement already satisfied: typing-extensions>=4.0.0 in /usr/local/lib/python3.12/dist-packages (from beautifulsoup4>=4.11.1->yfinance) (4.15.0) Requirement already satisfied: cffi>=2.0.0 in /usr/local/lib/python3.12/dist-packages (from curl_cffi>=0.7->yfinance) (2.0.0) Requirement already satisfied: certifi>=2024.2.2 in /usr/local/lib/python3.12/dist-packages (from curl_cffi>=0.7->yfinance) (2026.5.20) Requirement already satisfied: rich in /usr/local/lib/python3.12/dist-packages (from curl_cffi>=0.7->yfinance) (13.9.4) Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.12/dist-packages (from python-dateutil>=2.8.2->pandas) (1.17.0) Requirement already satisfied: charset_normalizer<4,>=2 in /usr/local/lib/python3.12/dist-packages (from requests>=2.31->yfinance) (3.4.7) Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.12/dist-packages (from requests>=2.31->yfinance) (3.18) Requirement already satisfied: urllib3<3,>=1.21.1 in /usr/local/lib/python3.12/dist-packages (from requests>=2.31->yfinance) (2.5.0) Requirement already satisfied: pycparser in /usr/local/lib/python3.12/dist-packages (from cffi>=2.0.0->curl_cffi>=0.7->yfinance) (3.0) Requirement already satisfied: markdown-it-py>=2.2.0 in /usr/local/lib/python3.12/dist-packages (from rich->curl_cffi>=0.7->yfinance) (4.2.0) Requirement already satisfied: pygments<3.0.0,>=2.13.0 in /usr/local/lib/python3.12/dist-packages (from rich->curl_cffi>=0.7->yfinance) (2.20.0) Requirement already satisfied: mdurl~=0.1 in /usr/local/lib/python3.12/dist-packages (from markdown-it-py>=2.2.0->rich->curl_cffi>=0.7->yfinance) (0.1.2)
3. Library Imports
This section imports all standard and third-party libraries used throughout the notebook. It also configures basic logging for better operational visibility.
import pandas as pd
import numpy as np
import yfinance as yf
import logging
from datetime import datetime, timedelta
import matplotlib.pyplot as plt
import seaborn as sns
import random
import time
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
4. Core Functions
This section defines the core functions used to initialize the state, fetch stock data, calculate the Amihud illiquidity ratio, add random jitter for simulated operations (as per requirements), and summarize the calculated metrics. Each function is presented in its own dedicated code block with a detailed markdown header.
Function Name: create_amihud_state
This function initializes the state dictionary used to store data, calculated ratios, and summary metrics throughout the Amihud illiquidity ratio analysis. It sets up empty DataFrames and dictionaries to be populated by subsequent functions.
Parameters: None
Returns:
(dict): An initialized state dictionary with data_store, ratios_store, and metrics_summary keys.
def create_amihud_state() -> dict:
"""
Initializes the state dictionary for Amihud ratio calculations.
Returns
-------
dict
An initialized state dictionary with keys for data storage,
ratio storage, and metrics summary.
Examples
--------
>>> state = create_amihud_state()
>>> isinstance(state, dict)
True
>>> 'data_store' in state
True
"""
logging.info("Initializing Amihud state.")
state = {
'data_store': pd.DataFrame(),
'ratios_store': pd.DataFrame(),
'metrics_summary': {}
}
return state
Function Name: add_random_jitter
This function adds a small, normally distributed random value (jitter) to a given numerical value. This can be useful in simulations or when introducing slight variability, although its direct application to Amihud ratio calculation is limited, it satisfies the general requirement for including random jitter.
Parameters: value (float): The numerical value to which jitter will be added. scale (float, optional): The standard deviation of the normal distribution for the jitter. Defaults to 0.01.
Returns: (float): The original value with added random jitter.
def add_random_jitter(value: float, scale: float = 0.01) -> float:
"""
Adds a small, normally distributed random jitter to a numerical value.
Parameters
----------
value : float
The numerical value to which jitter will be added.
scale : float, optional
The standard deviation of the normal distribution for the jitter,
by default 0.01.
Returns
-------
float
The original value with added random jitter.
Examples
--------
>>> round(add_random_jitter(10.0, scale=0.001), 1)
10.0
"""
return value + np.random.normal(0, scale)
Function Name: fetch_stock_data
This function fetches historical stock data (Open, High, Low, Close, Volume) for a specified ticker symbol within a given date range using the yfinance library. It includes retry logic with exponential backoff and random jitter for robustness against transient network issues or API rate limits.
Parameters: state (dict): The current state dictionary to store the fetched data. ticker (str): The stock ticker symbol (e.g., 'AAPL', 'MSFT'). start_date (str): The start date for fetching data in 'YYYY-MM-DD' format. end_date (str): The end date for fetching data in 'YYYY-MM-DD' format.
Returns:
(dict): The updated state dictionary with fetched stock data stored in state['data_store'] under the respective ticker key.
def fetch_stock_data(state: dict, ticker: str, start_date: str, end_date: str) -> dict:
"""
Fetches historical stock data for a given ticker and date range.
Includes retry logic with exponential backoff and random jitter.
Parameters
----------
state : dict
The current state dictionary.
ticker : str
The stock ticker symbol (e.g., 'AAPL').
start_date : str
The start date for data fetching in 'YYYY-MM-DD' format.
end_date : str
The end date for data fetching in 'YYYY-MM-DD' format.
Returns
-------
dict
The updated state dictionary with fetched stock data.
Examples
--------
>>> initial_state = create_amihud_state()
>>> updated_state = fetch_stock_data(initial_state, 'AAPL', '2023-01-01', '2023-01-10')
>>> 'AAPL' in updated_state['data_store'] # doctest: +SKIP
True
"""
logging.info(f"Fetching data for {ticker} from {start_date} to {end_date}")
max_retries = 3
base_delay = 1 # seconds
for attempt in range(max_retries):
try:
df = yf.download(ticker, start=start_date, end=end_date, progress=False)
if df.empty:
logging.warning(f"No data fetched for {ticker}. It might be a delisted stock or incorrect ticker.")
state['data_store'] = pd.DataFrame() # Store empty DF if no data
return state
df.index = pd.to_datetime(df.index)
state['data_store'] = df
logging.info(f"Successfully fetched data for {ticker}.")
return state
except Exception as e:
logging.warning(f"Attempt {attempt + 1} to fetch data for {ticker} failed: {e}")
if attempt < max_retries - 1:
delay = add_random_jitter(base_delay * (2 ** attempt))
logging.info(f"Retrying in {delay:.2f} seconds...")
time.sleep(delay)
else:
logging.error(f"Failed to fetch data for {ticker} after {max_retries} attempts.")
state['data_store'] = pd.DataFrame() # Store empty DF on failure
return state
return state # Should not be reached but for safety
Function Name: calculate_amihud_ratio
This function computes the Amihud illiquidity ratio for the stock data stored in the state dictionary. It calculates daily returns, absolute daily returns, daily dollar volume, and then the Amihud ratio. It handles potential division by zero errors by setting the ratio to np.nan when dollar volume is zero.
Parameters:
state (dict): The current state dictionary containing the stock data in state['data_store'].
ticker (str): The stock ticker symbol for which to calculate the ratio.
Returns:
(dict): The updated state dictionary with the Amihud ratios stored in state['ratios_store'] under the ticker key. The DataFrame will also contain the intermediate calculations (Return, Abs_Return, Dollar_Volume).
def calculate_amihud_ratio(state: dict, ticker: str) -> dict:
"""
Calculates the Amihud illiquidity ratio for the provided stock data.
Parameters
----------
state : dict
The current state dictionary containing the stock data.
ticker : str
The stock ticker symbol.
Returns
-------
dict
The updated state dictionary with Amihud ratios stored.
Examples
--------
>>> initial_state = create_amihud_state()
>>> # Assume data is fetched into initial_state['data_store'] as a DataFrame
>>> # Example DataFrame structure:
>>> sample_data = pd.DataFrame({
... 'Close': [100, 101, 99, 102, 103],
... 'Volume': [1000000, 1200000, 900000, 1500000, 1100000]
... }, index=pd.to_datetime(['2023-01-01', '2023-01-02', '2023-01-03', '2023-01-04', '2023-01-05']))
>>> initial_state['data_store'] = sample_data.copy() # Assign copy to avoid modifying original
>>> updated_state = calculate_amihud_ratio(initial_state, 'TEST')
>>> 'Amihud_Ratio' in updated_state['ratios_store'].columns # doctest: +SKIP
True
"""
logging.info(f"Calculating Amihud ratio for {ticker}.")
data_df = state['data_store'].copy()
if data_df.empty:
logging.warning(f"No data available for {ticker} to calculate Amihud ratio.")
state['ratios_store'] = pd.DataFrame(columns=['Return', 'Abs_Return', 'Dollar_Volume', 'Amihud_Ratio'])
return state
# Calculate daily returns
data_df['Return'] = data_df['Close'].pct_change()
# Calculate absolute daily returns
data_df['Abs_Return'] = data_df['Return'].abs()
# Calculate daily dollar volume
data_df['Dollar_Volume'] = data_df['Volume'] * data_df['Close']
# Calculate Amihud Ratio
# Handle division by zero: if Dollar_Volume is 0, Amihud_Ratio is NaN
data_df['Amihud_Ratio'] = data_df['Abs_Return'] / data_df['Dollar_Volume'].replace(0, np.nan)
state['ratios_store'] = data_df
logging.info(f"Amihud ratio calculation complete for {ticker}.")
return state
Function Name: summarize_amihud_metrics
This function calculates key summary statistics (mean, median, standard deviation, min, max) for the Amihud illiquidity ratios. These statistics provide an overview of the liquidity characteristics of the asset over the analyzed period.
Parameters:
state (dict): The current state dictionary containing the calculated Amihud ratios in state['ratios_store'].
ticker (str): The stock ticker symbol whose metrics are being summarized.
Returns:
(dict): The updated state dictionary with summary statistics stored in state['metrics_summary'] under the ticker key.
def summarize_amihud_metrics(state: dict, ticker: str) -> dict:
"""
Calculates summary statistics for the Amihud illiquidity ratios.
Parameters
----------
state : dict
The current state dictionary containing the calculated Amihud ratios.
ticker : str
The stock ticker symbol.
Returns
-------
dict
The updated state dictionary with summary statistics.
Examples
--------
>>> current_state = create_amihud_state()
>>> # Assume current_state['ratios_store'] contains 'Amihud_Ratio' column
>>> sample_ratios = pd.DataFrame({'Amihud_Ratio': [0.001, 0.002, 0.0015, 0.003, 0.0005]})
>>> current_state['ratios_store'] = sample_ratios
>>> updated_state = summarize_amihud_metrics(current_state, 'TEST')
>>> 'TEST' in updated_state['metrics_summary'] # doctest: +SKIP
True
"""
logging.info(f"Summarizing Amihud metrics for {ticker}.")
ratios_df = state['ratios_store']
if 'Amihud_Ratio' not in ratios_df.columns or ratios_df['Amihud_Ratio'].isnull().all():
logging.warning(f"No valid Amihud Ratios available for {ticker} to summarize.")
state['metrics_summary'][ticker] = {
'mean': np.nan,
'median': np.nan,
'std_dev': np.nan,
'min': np.nan,
'max': np.nan
}
return state
summary = {
'mean': ratios_df['Amihud_Ratio'].mean(),
'median': ratios_df['Amihud_Ratio'].median(),
'std_dev': ratios_df['Amihud_Ratio'].std(),
'min': ratios_df['Amihud_Ratio'].min(),
'max': ratios_df['Amihud_Ratio'].max()
}
state['metrics_summary'][ticker] = summary
logging.info(f"Summary metrics for {ticker} generated: {summary}")
return state
5. Demonstration and Visualization
This section demonstrates the end-to-end workflow of calculating the Amihud illiquidity ratio. It fetches historical stock data, computes the ratio, presents summary statistics, and visualizes the Amihud ratio over time. This helps in understanding the liquidity dynamics of a selected stock.
# 1. Initialize the state
state = create_amihud_state()
# 2. Define parameters for demonstration
ticker = 'GOOG'
end_date = datetime.now().strftime('%Y-%m-%d')
start_date = (datetime.now() - timedelta(days=365*2)).strftime('%Y-%m-%d') # 2 years of data
logging.info(f"Demonstration started for ticker: {ticker}")
# 3. Fetch stock data
state = fetch_stock_data(state, ticker, start_date, end_date)
df_data = state['data_store']
if df_data.empty:
logging.error(f"Cannot proceed with demonstration as no data was fetched for {ticker}.")
else:
print(f"\n--- Fetched Data for {ticker} (First 5 Rows) ---")
display(df_data.head())
display(df_data.tail())
# 4. Calculate Amihud Ratio
state = calculate_amihud_ratio(state, ticker)
df_ratios = state['ratios_store']
print(f"\n--- Amihud Ratio Calculation for {ticker} (First 5 Rows) ---")
display(df_ratios[['Close', 'Volume', 'Return', 'Abs_Return', 'Dollar_Volume', 'Amihud_Ratio']].head())
# 5. Summarize Amihud Metrics
state = summarize_amihud_metrics(state, ticker)
summary_metrics = state['metrics_summary'].get(ticker, {})
print(f"\n--- Summary Statistics for Amihud Ratio ({ticker}) ---")
summary_df = pd.DataFrame([summary_metrics])
display(summary_df.round(8))
# 6. Visualization: Amihud Ratio over Time
if 'Amihud_Ratio' in df_ratios.columns and not df_ratios['Amihud_Ratio'].isnull().all():
plt.figure(figsize=(14, 7))
sns.lineplot(x=df_ratios.index, y='Amihud_Ratio', data=df_ratios)
plt.title(f'Amihud Illiquidity Ratio for {ticker} Over Time', fontsize=16)
plt.xlabel('Date', fontsize=12)
plt.ylabel('Amihud Ratio', fontsize=12)
plt.yscale('log') # Use log scale due to potential large fluctuations
plt.grid(True, linestyle='--', alpha=0.7)
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
# Visualization: Distribution of Amihud Ratio
plt.figure(figsize=(10, 6))
sns.histplot(df_ratios['Amihud_Ratio'].dropna(), bins=50, kde=True)
plt.title(f'Distribution of Amihud Illiquidity Ratio for {ticker}', fontsize=16)
plt.xlabel('Amihud Ratio', fontsize=12)
plt.ylabel('Frequency', fontsize=12)
plt.yscale('log') # Log scale for y-axis to better show distribution
plt.grid(True, linestyle='--', alpha=0.7)
plt.tight_layout()
plt.show()
else:
logging.warning("Skipping visualizations as Amihud Ratio data is not available or entirely null.")
logging.info("Demonstration complete.")
/tmp/ipykernel_7600/2846172299.py:35: FutureWarning: YF.download() has changed argument auto_adjust default to True df = yf.download(ticker, start=start_date, end=end_date, progress=False)
--- Fetched Data for GOOG (First 5 Rows) ---
| Price | Close | High | Low | Open | Volume |
|---|---|---|---|---|---|
| Ticker | GOOG | GOOG | GOOG | GOOG | GOOG |
| Date | |||||
| 2024-06-17 | 177.419189 | 178.550512 | 175.146627 | 175.632887 | 15272900 |
| 2024-06-18 | 175.106934 | 177.548216 | 174.283249 | 177.429119 | 15640300 |
| 2024-06-20 | 176.357330 | 177.379489 | 175.116845 | 175.364942 | 16753200 |
| 2024-06-21 | 178.887939 | 181.122797 | 176.704688 | 177.131423 | 58903200 |
| 2024-06-24 | 179.413879 | 180.694069 | 178.858144 | 179.900155 | 18198300 |
| Price | Close | High | Low | Open | Volume |
|---|---|---|---|---|---|
| Ticker | GOOG | GOOG | GOOG | GOOG | GOOG |
| Date | |||||
| 2026-06-10 | 353.320007 | 366.309998 | 352.809998 | 361.049988 | 19878600 |
| 2026-06-11 | 356.559998 | 358.010010 | 343.630005 | 353.049988 | 28771800 |
| 2026-06-12 | 358.160004 | 364.773010 | 353.339996 | 361.100006 | 17637100 |
| 2026-06-15 | 367.109985 | 370.649994 | 364.649994 | 365.989990 | 17268600 |
| 2026-06-16 | NaN | NaN | NaN | NaN | 16348251 |
--- Amihud Ratio Calculation for GOOG (First 5 Rows) ---
/tmp/ipykernel_7600/1143497547.py:40: FutureWarning: The default fill_method='pad' in DataFrame.pct_change is deprecated and will be removed in a future version. Either fill in any non-leading NA values prior to calling pct_change or specify 'fill_method=None' to not fill NA values. data_df['Return'] = data_df['Close'].pct_change()
| Price | Close | Volume | Return | Abs_Return | Dollar_Volume | Amihud_Ratio |
|---|---|---|---|---|---|---|
| Ticker | GOOG | GOOG | ||||
| Date | ||||||
| 2024-06-17 | 177.419189 | 15272900 | NaN | NaN | 2.709706e+09 | NaN |
| 2024-06-18 | 175.106934 | 15640300 | -0.013033 | 0.013033 | 2.738725e+09 | 4.758684e-12 |
| 2024-06-20 | 176.357330 | 16753200 | 0.007141 | 0.007141 | 2.954550e+09 | 2.416869e-12 |
| 2024-06-21 | 178.887939 | 58903200 | 0.014349 | 0.014349 | 1.053707e+10 | 1.361795e-12 |
| 2024-06-24 | 179.413879 | 18198300 | 0.002940 | 0.002940 | 3.265028e+09 | 9.004679e-13 |
--- Summary Statistics for Amihud Ratio (GOOG) ---
| mean | median | std_dev | min | max | |
|---|---|---|---|---|---|
| 0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
6. Production Considerations
When deploying Amihud illiquidity ratio calculations in a production environment, several factors must be considered to ensure robustness, accuracy, and efficiency.
| Consideration | Description |
|---|---|
| Data Validation | Implement rigorous checks for input data (price and volume). Ensure no zero or negative values for volume and that prices are sensible. Handle missing data appropriately (e.g., forward-fill, interpolation, or exclusion) to avoid erroneous ratio calculations. |
| Error Handling | Utilize comprehensive try/except blocks, especially for external API calls (e.g., yfinance). Implement retry mechanisms with exponential backoff and random jitter for transient network issues or API rate limits. Log all errors, warnings, and informational messages. |
| Performance | For large datasets (e.g., calculating for many stocks over long periods), optimize calculations using vectorized operations with numpy and pandas. Consider using specialized time-series databases or distributed computing frameworks if data volume is extremely high. |
| Historical Data Reliability | Choose reliable and consistent data sources for historical stock prices and volumes. Be aware of data quality issues like stock splits, dividends, delistings, and market holidays, which can affect return and volume calculations. |
| Edge Cases | Explicitly handle edge cases such as periods with zero trading volume (which would lead to division by zero in the Amihud formula), extreme price movements, or stocks with very low liquidity. The current implementation sets Amihud to NaN if dollar volume is zero. |
| Unit Testing | Write unit tests for each core function (create_amihud_state, fetch_stock_data, calculate_amihud_ratio, summarize_amihud_metrics) to ensure correctness and adherence to expected behavior under various scenarios, including valid inputs, edge cases, and erroneous inputs. |
| Logging | Implement structured logging (logging module) to provide visibility into the application's execution flow. Log significant events, warnings, and errors. This is crucial for debugging, monitoring, and auditing the calculation process in production. |
| Resource Management | Efficiently manage memory and CPU resources. For yfinance or similar tools, be mindful of potential memory leaks or excessive API calls. Consider caching frequently accessed data. |
| Configuration Management | Externalize configuration parameters (e.g., API keys, ticker lists, date ranges) from the code using environment variables, configuration files, or a secrets manager. |
7. Conclusion
This notebook successfully demonstrated the calculation, summarization, and visualization of the Amihud illiquidity ratio. We have implemented a structured approach including:
- Initialization: Setting up a state dictionary for organized data management.
- Data Acquisition: Fetching historical stock data using
yfinancewith robust error handling and retry mechanisms. - Core Calculation: Computing the Amihud illiquidity ratio, handling potential division by zero scenarios.
- Summary Statistics: Providing key statistical insights into the ratio's distribution.
- Visualization: Illustrating the Amihud ratio's trend over time and its distribution, which helps in identifying periods of high/low liquidity and understanding the overall liquidity profile of an asset.
The implemented functions adhere to best practices, including detailed docstrings, type hints, and logger statements, making them suitable for integration into larger financial analysis systems. The considerations for production deployment highlight important aspects for building reliable and efficient financial tools.