Files
strategy-lab/to_explore/pyquantnews/11_InformationRatio.ipynb
David Brazda e3da60c647 daily update
2024-10-21 20:57:56 +02:00

6.9 KiB

No description has been provided for this image

This code downloads historical price data for specific stocks and calculates a portfolio's performance. It uses Yahoo Finance data to get adjusted close prices for QQQ, AAPL, and AMZN. The code constructs a simple portfolio of equal shares in AAPL and AMZN, computes the portfolio's value, daily returns, and cumulative returns over time. It then compares the portfolio's cumulative returns to a benchmark (QQQ). Finally, it calculates the information ratio to evaluate the portfolio's performance relative to the benchmark.

In [ ]:
import pandas as pd
import yfinance as yf

Download historical price data for QQQ, AAPL, and AMZN from Yahoo Finance

In [ ]:
data = yf.download(["QQQ", "AAPL", "AMZN"], start="2020-01-01", end="2022-07-31")

Extract adjusted close prices for the downloaded data

In [ ]:
closes = data['Adj Close']
benchmark_returns = closes.QQQ.pct_change()

Construct a simple portfolio with equal shares of AAPL and AMZN

In [ ]:
aapl_position = closes.AAPL * 50
amzn_position = closes.AMZN * 50

Compute the portfolio value over time by summing the positions

In [ ]:
portfolio_value = aapl_position + amzn_position

Calculate the portfolio's daily profit and loss (PnL)

In [ ]:
portfolio_pnl = (
    (aapl_position - aapl_position.shift()) 
    + (amzn_position - amzn_position.shift())
)

Compute the portfolio's daily return by dividing PnL by the portfolio value

In [ ]:
portfolio_returns = (portfolio_pnl / portfolio_value)
portfolio_returns.name = "Port"

Create cumulative returns for both the portfolio and the benchmark

In [ ]:
portfolio_cumulative_returns = (portfolio_returns.fillna(0.0) + 1).cumprod()
benchmark_cumulative_returns = (benchmark_returns.fillna(0.0) + 1).cumprod()

Plot the cumulative returns of the portfolio against the benchmark

In [ ]:
portfolio_cumulative_returns = (portfolio_returns.fillna(0.0) + 1).cumprod()
benchmark_cumulative_returns = (benchmark_returns.fillna(0.0) + 1).cumprod()
In [ ]:
pd.concat([portfolio_cumulative_returns, benchmark_cumulative_returns], axis=1).plot()
In [ ]:
def information_ratio(portfolio_returns, benchmark_returns):
    """
    Determines the information ratio of a strategy.
    
    Parameters
    ----------
    portfolio_returns : pd.Series or np.ndarray
        Daily returns of the strategy, noncumulative.
    benchmark_returns : int, float
        Daily returns of the benchmark or factor, noncumulative.

    Returns
    -------
    information_ratio : float

    Note
    -----
    See https://en.wikipedia.org/wiki/Information_ratio for more details.
    """
    
    # Calculate active return by subtracting benchmark returns from portfolio returns
    active_return = portfolio_returns - benchmark_returns

    # Calculate tracking error as the standard deviation of active returns
    tracking_error = active_return.std()

    # Return the information ratio, which is the mean active return divided by the tracking error
    return active_return.mean() / tracking_error

Calculate the information ratio of the portfolio relative to the benchmark

In [ ]:
information_ratio(portfolio_returns, benchmark_returns)

PyQuant News is where finance practitioners level up with Python for quant finance, algorithmic trading, and market data analysis. Looking to get started? Check out the fastest growing, top-selling course to get started with Python for quant finance. For educational purposes. Not investment advise. Use at your own risk.