Portfolio Optimization & Risk Analysis

This project built a comprehensive portfolio management system that simulates random asset allocation across major stocks and calculates key financial metrics including returns, volatility, and risk-adjusted performance. I developed a complete portfolio analytics framework using Python to evaluate investment strategies and portfolio performance over time.

๐Ÿ’ป Tech Stack:

๐Ÿงช Data Pipeline:

๐Ÿ“Š Code Snippets & Visualisations:

np.random.seed()

# Create random weights for the stocks
weights = np.array(np.random.random(9))

# Random Asset Allocation & Calculate Portfolio Daily Return
weights = weights / np.sum(weights)
print(weights)

# Define Normalization function
def normalize(df):
    x = df.copy()
    for i in x.columns[1:]:
        x[i] = x[i] / x[i][0]
    return x

# Enumerate returns the value and a counter as well
for counter, stock in enumerate(df_portfolio.columns[1:]):
    df_portfolio[stock] = df_portfolio[stock] * weights[counter]
    df_portfolio[stock] = df_portfolio[stock] * 1000000

# Calculate the portfolio daily return
df_portfolio['portfolio daily % return'] = 0.0000

for i in range(1, len(stocks_df)):
    # Calculate the percentage of change from the previous day
    df_portfolio['portfolio daily % return'][i] = (
        (df_portfolio['portfolio daily worth/$'][i] - df_portfolio['portfolio daily worth/$'][i - 1])
        / df_portfolio['portfolio daily worth/$'][i - 1]
    ) * 100

# Create a function for stock portfolio allocation
# Assume $1000000 is total amount for portfolio
def portfolio_allocation(df, weights):
    df_portfolio = df.copy()

    # Normalize the stock values
    df_portfolio = normalize(df_portfolio)

    for counter, stock in enumerate(df_portfolio.columns[1:]):
        df_portfolio[stock] = df_portfolio[stock] * weights[counter]
        df_portfolio[stock] = df_portfolio[stock] * 1000000

    df_portfolio['portfolio daily worth in $'] = df_portfolio[df_portfolio.columns[1:]].sum(axis=1)

    df_portfolio['portfolio daily % return'] = 0.0000

    for i in range(1, len(stocks_df)):
        # Calculate the percentage of change from the previous day
        df_portfolio['portfolio daily % return'][i] = (
            (df_portfolio['portfolio daily worth in $'][i] - df_portfolio['portfolio daily worth in $'][i - 1])
            / df_portfolio['portfolio daily worth in $'][i - 1]
        ) * 100

    # Set the value of first row to zero, as previous value is not available
    df_portfolio['portfolio daily % return'][0] = 0
    return df_portfolio

# Plot the portfolio daily return (Figure 1)
fig = px.line(
    x=df_portfolio.Date,
    y=df_portfolio['portfolio daily % return'],
    title='Portfolio Daily % Return',
    labels={"x": "Date", "y": "Daily Percentage Return"}
)
fig.show()

# Cumulative return of the portfolio
cumulative_return = (
    (df_portfolio['portfolio daily worth/$'][-1:] - df_portfolio['portfolio daily worth/$'][0])
    / df_portfolio['portfolio daily worth/$'][0]
) * 100
print('Cumulative return of the portfolio is {} %'.format(cumulative_return.values[0]))

# Calculate the average daily return
print('Average daily return of the portfolio is {} %'.format(df_portfolio['portfolio daily % return'].mean()))

# Portfolio Sharpe ratio
sharpe_ratio = (
    df_portfolio['portfolio daily % return'].mean()
    / df_portfolio['portfolio daily % return'].std()
    * np.sqrt(252)
)
print('Sharpe ratio of the portfolio is {}'.format(sharpe_ratio))
						

๐ŸŒŸ Key Insights:

๐Ÿง—๐Ÿพ Challenge Faced:

I initially encountered an indexing error when calculating portfolio daily returns because I was trying to access the previous day's value for the first row, which doesn't exist. The calculation df_portfolio['portfolio daily % return'][i-1] failed on the first iteration. I solved this by explicitly setting the first day's return to 0 using df_portfolio['portfolio daily % return'][0] = 0 after the loop, and ensuring the loop started from index 1 rather than 0. This approach properly handled the edge case while maintaining accurate percentage calculations for all subsequent trading days.

View on GitHub

โ† Back to Projects