Untitled
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...