File size: 6,584 Bytes
4ce9f7c
e1354e7
 
 
 
 
 
4ce9f7c
8637176
 
 
 
e1354e7
 
 
 
 
 
 
4ce9f7c
e1354e7
 
 
 
 
a213323
e1354e7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2a24197
 
e1354e7
 
 
 
2a24197
e1354e7
2a24197
 
 
 
 
 
 
e1354e7
2a24197
 
 
 
 
e1354e7
2a24197
e1354e7
 
2a24197
e1354e7
2a24197
 
 
 
 
e1354e7
2a24197
 
 
 
e1354e7
2a24197
 
 
 
e1354e7
2a24197
 
 
 
 
e1354e7
2a24197
e1354e7
a98102e
 
 
 
e1354e7
2a24197
 
e1354e7
e1e51b3
 
 
2a24197
91e7fe7
e1e51b3
 
a25f51b
2a24197
e1354e7
 
 
 
12b3a61
e1354e7
e1e51b3
952bb21
 
e1354e7
24feab2
b310efb
82d9e6e
 
a25f51b
 
91e7fe7
2576813
a18e666
4ce9f7c
a18e666
 
d02b8b8
 
64fe45f
a18e666
 
5444e32
24feab2
a18e666
82d9e6e
 
4ce9f7c
 
b310efb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
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()