portfolio / app.py
pvanand's picture
Update app.py
91e7fe7
raw
history blame
6.58 kB
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()