portfolio / app.py
pvanand's picture
Update app.py
91e7fe7
import gradio as gr
import matplotlib.pyplot as plt
import pandas as pd
import sqlite3
from datetime import datetime
import sqlite3
from datetime import datetime
# Initialize variables
db_path = 'nifty50_stock_data.db' # Database path
nifty_50_symbols = pd.read_csv("nifty50-stock-tickers.csv").Symbol.to_list() # NIFTY 50 stock symbols
class Stock:
def __init__(self, symbol, db_path, start_date, end_date):
self.symbol = symbol
self.db_path = db_path
self.start_date = start_date
self.end_date = end_date
self.prices = self._download_prices()
def _download_prices(self):
conn = sqlite3.connect(self.db_path)
query = f"SELECT Date, Close FROM `{self.symbol}` WHERE Date BETWEEN '{self.start_date}' AND '{self.end_date}'"
prices = pd.read_sql_query(query, conn, parse_dates=['Date'])
prices.set_index('Date', inplace=True)
prices.ffill(inplace=True)
return prices
def CurPrice(self, curDate):
return self.prices.loc[curDate, 'Close'] if curDate in self.prices.index else None
def NDayRet(self, N, curDate):
if curDate not in self.prices.index:
return None
start_date = self.prices.index[self.prices.index.get_loc(curDate) - N]
start_price = self.prices.loc[start_date, 'Close']
end_price = self.prices.loc[curDate, 'Close']
return (end_price - start_price) / start_price
def DailyRet(self, curDate):
if curDate not in self.prices.index:
return None
previous_date = self.prices.index[self.prices.index.get_loc(curDate) - 1]
previous_price = self.prices.loc[previous_date, 'Close']
current_price = self.prices.loc[curDate, 'Close']
return (current_price - previous_price) / previous_price
def Last30daysPrice(self, curDate):
end_loc = self.prices.index.get_loc(curDate) + 1
start_loc = max(0, end_loc - 30)
return self.prices.iloc[start_loc:end_loc]['Close'].values
# Function to calculate monthly and daily percentage change
def calculate_percentage_changes(stocks):
monthly_pct_change = pd.DataFrame()
for symbol, stock_obj in stocks.items():
monthly_pct_change[symbol] = stock_obj.prices['Close'].resample('M').last().pct_change()
monthly_pct_change.fillna(0, inplace=True)
return monthly_pct_change
# Function to update stock investments
def update_stock_investments(monthly_pct_change, month_index, stock_investments):
month = monthly_pct_change.index[month_index]
month_performance = monthly_pct_change.loc[month]
positive_stocks = [stock for stock, pct_change in month_performance.items() if pct_change > 0]
portfolio_value = sum(stock_investments.iloc[month_index - 1][symbol] * (1 + monthly_pct_change.at[month, symbol])
for symbol in nifty_50_symbols if pd.notna(monthly_pct_change.at[month, symbol]))
if positive_stocks:
investment_per_positive_stock = portfolio_value / len(positive_stocks)
stock_investments.loc[month] = {stock: investment_per_positive_stock if stock in positive_stocks else 0 for stock in nifty_50_symbols}
else:
stock_investments.loc[month] = 0
return portfolio_value
def calculate_portfolio(start_date, end_date, investment_amount):
# Initialize stock dataframes and stocks object
stocks = {symbol: Stock(symbol, db_path, start_date, end_date) for symbol in nifty_50_symbols}
monthly_pct_change = calculate_percentage_changes(stocks)
stock_investments = pd.DataFrame(index=monthly_pct_change.index, columns=nifty_50_symbols)
portfolio_returns = pd.DataFrame(index=monthly_pct_change.index, columns=["portfolio_returns"])
# Initialize stock investments
num_stocks = len(nifty_50_symbols)
investment_per_stock = investment_amount / num_stocks
stock_investments.iloc[0] = investment_per_stock
# Calculate portfolio returns
for month_index in range(1, len(monthly_pct_change.index)):
portfolio_value = update_stock_investments(monthly_pct_change, month_index, stock_investments)
portfolio_returns.at[monthly_pct_change.index[month_index], 'portfolio_returns'] = portfolio_value
# Create Stock object and Calculate monthly returns for NIFTY50
nifty_50_stock = Stock('NIFTY50', db_path, start_date, end_date)
nifty_50_monthly_return = nifty_50_stock.prices['Close'].resample('M').last().pct_change()
nifty_50_portfolio_change = nifty_50_monthly_return*(investment_amount)
nifty_50_portfolio_value =nifty_50_portfolio_change.cumsum()+investment_amount
return portfolio_returns, nifty_50_portfolio_value
def calculate_cagr(final_value, initial_value, start_date, end_date):
num_years = (pd.to_datetime(end_date) - pd.to_datetime(start_date)).days / 365.25
return (final_value / initial_value) ** (1 / num_years) - 1
def plot_chart(start_date, end_date, investment_amount):
portfolio_returns, nifty_50_portfolio_value = calculate_portfolio(start_date, end_date, investment_amount)
portfolio_cagr = calculate_cagr(portfolio_returns.iloc[-1], investment_amount, start_date, end_date)[0]
nifty50_cagr = calculate_cagr(nifty_50_portfolio_value.iloc[-1], investment_amount, start_date, end_date)
# Visualization
plt.figure(figsize=(14, 10))
plt.plot(portfolio_returns.index, portfolio_returns, label=f'Portfolio (CAGR: {portfolio_cagr*100:.2f}%)')
plt.plot(nifty_50_portfolio_value.index, nifty_50_portfolio_value, label=f'NIFTY 50 (CAGR: {nifty50_cagr*100:.2f}%)')
plt.title('Portfolio Returns Vs NIFTY 50 Returns Over Time')
plt.xlabel('Date')
plt.ylabel('Portfolio Value (in Rupees)')
plt.legend()
plt.grid(True)
plt.savefig('portfolio_chart.png')
plt.show()
print(portfolio_cagr)
print(nifty50_cagr)
return 'portfolio_chart.png'
# Markdown text to be displayed
markdown_text = """
This interface allows you to test a stock selection strategy on nifty50 stocks and compare it with the return of nifty50 index.
Please pick a date range from **2009-01-01 to 2024-01-06**
Please reload the page if you are facing connection timeout / connection errored out """
# Gradio interface
iface = gr.Interface(
fn=plot_chart,
inputs=[
gr.Textbox(label="Start Date (YYYY-MM-DD)"),
gr.Textbox(label="End Date (YYYY-MM-DD)"),
gr.Number(label="Investment Amount (in Rupees)")
],
outputs=[
gr.Image(type="filepath"),
],
title="Stock Portfolio Performance",
description=markdown_text # Adding markdown text to the description
)
iface.launch()