|
import streamlit as st |
|
import pandas as pd |
|
from utils import * |
|
|
|
st.title("Stock Portfolio and Tax Analysis") |
|
|
|
|
|
if 'stock_sales' not in st.session_state: |
|
st.session_state.stock_sales = pd.DataFrame(columns=['Name', 'Sale Price', 'Purchase Price', 'Quantity', 'Holding Period (Months)']) |
|
if 'portfolio_stocks' not in st.session_state: |
|
st.session_state.portfolio_stocks = pd.DataFrame(columns=['Name', 'Purchase Price', 'Current Price', 'Quantity']) |
|
|
|
|
|
def add_stock_sale(): |
|
with st.form(key="stock_sale_form"): |
|
col1, col2, col3, col4, col5 = st.columns(5) |
|
with col1: |
|
name = st.text_input("Stock Name", key="stock_sale_name") |
|
with col2: |
|
sale_price = st.number_input("Sale Price", min_value=1.0, key="stock_sale_price") |
|
with col3: |
|
purchase_price = st.number_input("Purchase Price", min_value=1.0, key="stock_sale_purchase_price") |
|
with col4: |
|
sell_quantity = st.number_input("Quantity", min_value=10, key="stock_sale_qty") |
|
with col5: |
|
holding_period_months = st.number_input("Holding Period (Months)", min_value=1, key="stock_sale_holding_period") |
|
|
|
submit_button = st.form_submit_button("Add Sold Stock") |
|
if submit_button: |
|
new_stock = pd.DataFrame([{'Name': name, 'Sale Price': sale_price, 'Purchase Price': purchase_price, 'Quantity': sell_quantity, 'Holding Period (Months)': holding_period_months}]) |
|
st.session_state.stock_sales = pd.concat([st.session_state.stock_sales, new_stock], ignore_index=True) |
|
st.success("Sold Stock Added!") |
|
|
|
|
|
def add_portfolio_stock(): |
|
with st.form(key="portfolio_stock_form"): |
|
col1, col2, col3, col4 = st.columns(4) |
|
with col1: |
|
name = st.text_input("Stock Name", key="portfolio_stock_name") |
|
with col2: |
|
purchase_price = st.number_input("Purchase Price", min_value=0.0, key="portfolio_stock_purchase_price") |
|
with col3: |
|
current_price = st.number_input("Current Price", min_value=0.0, key="portfolio_stock_current_price") |
|
with col4: |
|
quantity = st.number_input("Quantity", min_value=0, key="portfolio_stock_quantity") |
|
|
|
submit_button = st.form_submit_button("Add Portfolio Stock") |
|
if submit_button: |
|
new_stock = pd.DataFrame([{'Name': name, 'Purchase Price': purchase_price, 'Current Price': current_price, 'Quantity': quantity}]) |
|
st.session_state.portfolio_stocks = pd.concat([st.session_state.portfolio_stocks, new_stock], ignore_index=True) |
|
st.success("Stock Added to Portfolio!") |
|
|
|
|
|
def delete_stock_sale(index): |
|
st.session_state.stock_sales = st.session_state.stock_sales.drop(index).reset_index(drop=True) |
|
st.success("Sold Stock Deleted!") |
|
|
|
def delete_portfolio_stock(index): |
|
st.session_state.portfolio_stocks = st.session_state.portfolio_stocks.drop(index).reset_index(drop=True) |
|
st.success("Stock Deleted from Portfolio!") |
|
|
|
def edit_stock_sale(index, name, sale_price, purchase_price, holding_period_months): |
|
st.session_state.stock_sales.at[index, 'Name'] = name |
|
st.session_state.stock_sales.at[index, 'Sale Price'] = sale_price |
|
st.session_state.stock_sales.at[index, 'Purchase Price'] = purchase_price |
|
st.session_state.stock_sales.at[index, 'Quantity'] = sell_quantity |
|
st.session_state.stock_sales.at[index, 'Holding Period (Months)'] = holding_period_months |
|
st.success("Sold Stock Updated!") |
|
|
|
def edit_portfolio_stock(index, name, purchase_price, current_price, quantity): |
|
st.session_state.portfolio_stocks.at[index, 'Name'] = name |
|
st.session_state.portfolio_stocks.at[index, 'Purchase Price'] = purchase_price |
|
st.session_state.portfolio_stocks.at[index, 'Current Price'] = current_price |
|
st.session_state.portfolio_stocks.at[index, 'Quantity'] = quantity |
|
st.success("Portfolio Stock Updated!") |
|
|
|
|
|
tabs = st.tabs(["Add Stocks", "Manage Stocks", "Tax Analysis"]) |
|
|
|
with tabs[0]: |
|
st.header("Add New Stock Sale and Portfolio Stock") |
|
st.subheader("Sold Stock") |
|
add_stock_sale() |
|
st.subheader("Portfolio Stock") |
|
add_portfolio_stock() |
|
|
|
with tabs[1]: |
|
st.header("Manage Stocks") |
|
|
|
st.subheader("Sold Stock") |
|
st.dataframe(st.session_state.stock_sales) |
|
|
|
if st.session_state.stock_sales.shape[0] > 0: |
|
selected_sale_index = st.selectbox("Select Sale to Edit", range(st.session_state.stock_sales.shape[0]), key="select_sale_to_edit") |
|
selected_sale = st.session_state.stock_sales.iloc[selected_sale_index] |
|
with st.form(key="edit_stock_sale_form"): |
|
col1, col2, col3, col4, col5 = st.columns(5) |
|
with col1: |
|
name = st.text_input("Edit Stock Sale Name", selected_sale['Name'], key="edit_stock_sale_name") |
|
with col2: |
|
sale_price = st.number_input("Edit Sale Price", min_value=0.0, value=selected_sale['Sale Price'], key="edit_stock_sale_price") |
|
with col3: |
|
purchase_price = st.number_input("Edit Purchase Price", min_value=0.0, value=selected_sale['Purchase Price'], key="edit_stock_sale_purchase_price") |
|
with col4: |
|
sell_quantity = st.number_input("Quantity", min_value=0, value=selected_sale['Quantity'], key="edit_stock_sale_qty") |
|
with col5: |
|
holding_period_months = st.number_input("Edit Holding Period (Months)", min_value=0, value=selected_sale['Holding Period (Months)'], key="edit_stock_sale_holding_period") |
|
|
|
update_button = st.form_submit_button("Update Stock Sale") |
|
if update_button: |
|
edit_stock_sale(selected_sale_index, name, sale_price, purchase_price, holding_period_months) |
|
|
|
delete_button = st.button("Delete Stock Sale", key="delete_stock_sale_button") |
|
if delete_button: |
|
delete_stock_sale(selected_sale_index) |
|
|
|
st.subheader("Portfolio Stocks") |
|
st.dataframe(st.session_state.portfolio_stocks) |
|
|
|
if st.session_state.portfolio_stocks.shape[0] > 0: |
|
selected_stock_index = st.selectbox("Select Portfolio Stock to Edit", range(st.session_state.portfolio_stocks.shape[0]), key="select_stock_to_edit_portfolio") |
|
selected_stock = st.session_state.portfolio_stocks.iloc[selected_stock_index] |
|
with st.form(key="edit_portfolio_stock_form"): |
|
col1, col2, col3, col4 = st.columns(4) |
|
with col1: |
|
name = st.text_input("Edit Portfolio Stock Name", selected_stock['Name'], key="edit_portfolio_stock_name") |
|
with col2: |
|
purchase_price = st.number_input("Edit Purchase Price", min_value=0.0, value=selected_stock['Purchase Price'], key="edit_portfolio_stock_purchase_price") |
|
with col3: |
|
current_price = st.number_input("Edit Current Price", min_value=0.0, value=selected_stock['Current Price'], key="edit_portfolio_stock_current_price") |
|
with col4: |
|
quantity = st.number_input("Edit Quantity", min_value=0, value=selected_stock['Quantity'], key="edit_portfolio_stock_quantity") |
|
|
|
update_button = st.form_submit_button("Update Portfolio Stock") |
|
if update_button: |
|
edit_portfolio_stock(selected_stock_index, name, purchase_price, current_price, quantity) |
|
|
|
delete_button = st.button("Delete Portfolio Stock", key="delete_portfolio_stock_button") |
|
if delete_button: |
|
delete_portfolio_stock(selected_stock_index) |
|
|
|
with tabs[2]: |
|
st.header("Tax Analysis") |
|
|
|
if st.session_state.stock_sales.shape[0] > 0: |
|
portfolio = Portfolio() |
|
for _, row in st.session_state.stock_sales.iterrows(): |
|
portfolio.add_stock(StockSale(row['Name'], row['Sale Price'], row['Purchase Price'], row['Quantity'], row['Holding Period (Months)'])) |
|
|
|
total_stcg, total_ltcg = portfolio.analyze_portfolio() |
|
stcg_tax, ltcg_tax, total_tax = portfolio.apply_tax(total_stcg, total_ltcg) |
|
|
|
stocks = [] |
|
for _, row in st.session_state.portfolio_stocks.iterrows(): |
|
stocks.append(Stock(row['Name'], row['Purchase Price'], row['Current Price'], row['Quantity'])) |
|
|
|
suggested_stocks = optimize_taxes_selling_stocks(stocks) |
|
total_loss = calculate_total_loss(suggested_stocks) |
|
recalculated_tax = max(0, total_tax - total_loss) |
|
|
|
st.subheader("Analysis Results") |
|
if total_tax > total_loss: |
|
|
|
st.write(f"Total Short-Term Capital Gains: ₹{total_stcg:.2f}") |
|
st.write(f"Total Long-Term Capital Gains: ₹{total_ltcg:.2f}") |
|
st.write(f"Short-Term Capital Gains Tax: ₹{stcg_tax:.2f}") |
|
st.write(f"Long-Term Capital Gains Tax: ₹{ltcg_tax:.2f}") |
|
st.write(f"Total Tax Liability: ₹{total_tax:.2f}") |
|
st.write(f"Total Loss of loss making stockes: ₹{total_loss:.2f}") |
|
|
|
|
|
st.write("\n") |
|
st.subheader("Suggested Stocks to Sell to Offset Gains:") |
|
|
|
suggested_stocks_data = { |
|
'Name': [stock.name for stock in suggested_stocks], |
|
'Current Price': [stock.current_price for stock in suggested_stocks], |
|
'Purchase Price': [stock.purchase_price for stock in suggested_stocks] |
|
} |
|
|
|
st.dataframe(suggested_stocks_data) |
|
|
|
st.write(f"Total Tax Liability before selling loss making stocks: ₹{total_tax:.2f}") |
|
st.write(f"Adjusted Tax Liability after Selling Loss-Making Stocks and buy again: ₹{recalculated_tax:.2f}") |
|
|
|
elif total_loss >= 0: |
|
st.write(f"Total Short-Term Capital Gains: ₹{total_stcg:.2f}") |
|
st.write(f"Total Long-Term Capital Gains: ₹{total_ltcg:.2f}") |
|
st.write(f"Short-Term Capital Gains Tax: ₹{stcg_tax:.2f}") |
|
st.write(f"Long-Term Capital Gains Tax: ₹{ltcg_tax:.2f}") |
|
st.write(f"Total Tax Liability: ₹{total_tax:.2f}") |
|
|
|
else: |
|
st.write("No suggested stocks for selling to offset gains.") |
|
|
|
|
|
|
|
def calculate_total_loss(suggested_stocks): |
|
total_loss = 0.0 |
|
for stock in suggested_stocks: |
|
total_loss += (stock.purchase_price - stock.current_price) * stock.quantity |
|
return total_loss |
|
|