Untitled

 avatar
unknown
python
2 years ago
4.2 kB
4
Indexable
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Feb 22 17:01:07 2023

@author: noahakesson
"""

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime


df = pd.read_excel('price_combined_esg.xlsx')
df = df.rename(columns={'PX_LAST':'price'})

# Define the rolling window size
window_size = 365

# Calculate the momentum for each stock
df['Momentum'] = df.groupby('Symbol')['esg'].apply(lambda x: x.pct_change(window_size).shift(-window_size))

# Define the threshold for buying and selling
buy_threshold = 0.05
sell_threshold = -0.05

# Initialize the portfolio
portfolio = pd.DataFrame(columns=['Symbol', 'Shares', 'Price', 'Total'])

# Initialize the statistics
statistics = pd.DataFrame(columns=['Symbol', 'Total Return', 'Annualized Return', 'Volatility'])

# Loop through each stock in the data
for symbol in df['Symbol'].unique():

    # Filter the data for the current stock
    stock_data = df[df['Symbol'] == symbol].copy()

    # Apply the momentum strategy
    stock_data['Signal'] = np.where(stock_data['Momentum'] > buy_threshold, 1, np.where(stock_data['Momentum'] < sell_threshold, -1, 0))
    stock_data['Position'] = stock_data['Signal'].shift(1)
    stock_data['Position'].fillna(0, inplace=True)

    # Calculate the daily returns
    stock_data['Returns'] = stock_data['price'].pct_change() * stock_data['Position']
    stock_data['Cumulative Returns'] = (1 + stock_data['Returns']).cumprod()

    # Calculate the portfolio value
    shares = 10000 // stock_data['price'][0]
    portfolio_data = pd.DataFrame({'Symbol': [symbol], 'Shares': [shares], 'Price': [stock_data['price'][0]], 'Total': [shares * stock_data['price'][0]]})
    for i, row in stock_data.iterrows():
        if row['Position'] == 1:
            portfolio_data = portfolio_data.append({'Symbol': symbol, 'Shares': shares, 'Price': row['price'], 'Total': shares * row['price']}, ignore_index=True)
        elif row['Position'] == -1:
            portfolio_data = portfolio_data.append({'Symbol': symbol, 'Shares': -shares, 'Price': row['price'], 'Total': -shares * row['price']}, ignore_index=True)
    portfolio_data['Cumulative Total'] = portfolio_data['Total'].cumsum()
    portfolio = pd.concat([portfolio, portfolio_data])

    # Calculate the statistics
    total_return = None
    annualized_return = None
    volatility = None
    print(symbol + str(len(portfolio_data['Cumulative Total'])))
    
    if len(portfolio_data['Cumulative Total']) > 0:
        total_return = (portfolio_data.loc['Cumulative Total',-1] - portfolio_data['Cumulative Total'][0]) / portfolio_data['Cumulative Total'][0]
        annualized_return = (1 + total_return) ** (252 / len(stock_data)) - 1
        volatility = stock_data['Returns'].std() * np.sqrt(252)
        statistics = statistics.append({'Symbol': symbol, 'Total Return': total_return, 'Annualized Return': annualized_return, 'Volatility': volatility}, ignore_index=True)
    else:
        print(symbol)
        

# Calculate the overall portfolio value
portfolio['Cumulative Total'] = portfolio['Total'].cumsum()

# Plot the cumulative returns of each stock
sns.set(style='darkgrid')
g = sns.relplot(x='Date', y='Cumulative Returns', hue='Symbol', kind='line', data=df, height=6, aspect=2)
g.fig.suptitle('Cumulative Returns of Each Stock')
plt.show()

# Plot the portfolio value over time
sns.set(style='darkgrid')
plt.plot(portfolio.index, portfolio['Cumulative Total'])
plt.title('Portfolio Value Over Time')
plt.xlabel('Date')
plt.ylabel('Value')
plt.show()

# Plot the performance statistics of each stock
sns.set(style='darkgrid')
g = sns.catplot(x='Symbol', y='Annualized Return', kind='bar', data=statistics, height=6, aspect=2)
g.fig.suptitle('Annualized Return of Each Stock')
plt.show()

sns.set(style='darkgrid')
g = sns.catplot(x='Symbol', y='Volatility', kind='bar', data=statistics, height=6, aspect=2)
g.fig.suptitle('Volatility of Each Stock')
plt.show()

sns.set(style='darkgrid')
g = sns.catplot(x='Symbol', y='Total Return', kind='bar', data=statistics, height=6, aspect=2)
g.fig.suptitle('Total Return of Each Stock')
plt.show()
Editor is loading...