Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
Sammindinventory authored Jan 15, 2024
0 parents commit 00c44d0
Show file tree
Hide file tree
Showing 21 changed files with 1,139 additions and 0 deletions.
9 changes: 9 additions & 0 deletions MIRMT.code-workspace
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"folders": [
{
"uri": "vscode-remote://codespaces+cuddly-space-doodle-rxrj99x7p6vf5v5w/workspaces/FinRisk"
}
],
"remoteAuthority": "codespaces+cuddly-space-doodle-rxrj99x7p6vf5v5w",
"settings": {}
}
21 changes: 21 additions & 0 deletions MindInventory-Financial-Risk-Analysis/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2024 Samar Patel

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
![cover_photo](./readmefile/Cover.png)

# MindInventory - Portfolio & Risk Management System
*FinRisk allows you to build a custom portfolio and assess its risk within
few clicks!*

*Portfolio Risk management is like wearing a helmet while riding a bike—it
shields your money during investments. For average investors, it's hard to
understand the risk of their portfolio, FinRisk is here to help.*

## Core Features
### Real Time Market Condition Previewer
Quick Glimpse of the Financial Frenzy! The market preview includes current
market status of Dow Jones, S&P 500, Nasdaq, and Russell 2000 index. Hold onto
your seat as we zoom into the exciting world of the top 8 tech and meme stocks!
🚀🎢 Get the scoop on current prices, price changes, and the percentage shake-ups.
![market_preview](./readmefile/market_preview.png)
### Portfolio Builder
Dream big and curate a portfolio that reflects your financial aspirations. You
have the power to choose up to 10 stocks!For each stock in your portfolio, some
fundamental information required: stock tickers, the specific quantity of shares,
and the record of purchase dates.
![portfolio_builder](./readmefile/portfolio_builder.png)

### Portfolio Risk Simulator
The portfolio risk simulator is a powerful tool that allows you to assess your portfolio's risk using
Monte Carlo Simulation. The simulation unravels crucial metrics: Value at Risk (VaR) and Conditional Value
at Risk (CVaR). VaR adn CVaR are two of the most popular risk metrics used by financial institutions to
measure the risk of their portfolios. Simulation can be tailored to your needs by adjusting the number
of simulations, historical data of your selected stocks, the confidence levels (alpha). The simulation
will also generate a line chart for your portfolio's daily returns. All data can be downloaded as a CSV file for
further analysis.
![portfolio_risk_simulator](./readmefile/risk_model.png)
## How to Use
👉 click [MRMST](https://mrmst.streamlit.app/) to launch the app!
53 changes: 53 additions & 0 deletions assets/Collector.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import yfinance
import pandas as pd


class InfoCollector:

@staticmethod
def get_ticker(stock_name: str) -> yfinance.Ticker:
return yfinance.Ticker(stock_name)

@staticmethod
def get_history(ticker: yfinance.Ticker,
period="1mo", interval="1d",
start=None, end=None):
"""
period : str
Valid periods: 1d,5d,1mo,3mo,6mo,1y,2y,5y,10y,ytd,max
Either Use period parameter or use start and end
interval : str
Valid intervals: 1m,2m,5m,15m,30m,60m,90m,1h,1d,5d,1wk,1mo,3mo
Intraday data cannot extend last 60 days
start: str
Download start date string (YYYY-MM-DD) or _datetime, inclusive.
Default is 99 years ago
E.g. for start="2020-01-01", the first data point will be on "2020-01-01"
end: str
Download end date string (YYYY-MM-DD) or _datetime, exclusive.
Default is now
E.g. for end="2023-01-01", the last data point will be on "2022-12-31"
"""
return ticker.history(period=period, interval=interval,
start=start, end=end)

@staticmethod
def get_demo_daily_history(interval: str):
return InfoCollector.get_history(
ticker=yfinance.Ticker("AAPL"),
period="1d",
interval=interval,
start="2023-11-15",
end="2023-11-16")

@staticmethod
def get_prev_date(stock_info: pd.DataFrame):
return stock_info.index[0]

@staticmethod
def get_daily_info(stock_info: pd.DataFrame, key_info: str):
return stock_info.loc[stock_info.index[0], key_info]

@staticmethod
def download_batch_history(stocks: list, start_time, end_time):
return yfinance.download(stocks, start=start_time, end=end_time)
27 changes: 27 additions & 0 deletions assets/Portfolio.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from assets.Stock import Stock


class Portfolio:

def __init__(self) -> None:
self.stocks = {}
self.book_amount = 0
self.market_value = 0

def add_stock(self, stock: Stock) -> None:
if stock.stock_name in self.stocks.keys():
raise Exception("Stock included in portfolio. Please remove stock to add again")

self.stocks[stock.stock_name] = stock
self.book_amount += stock.get_book_cost()

def remove_stock(self, stock_name: str) -> None:
if stock_name not in self.stocks.keys():
raise Exception("Stock not in portfolio")
self.book_amount -= self.stocks[stock_name].get_book_cost()
self.stocks.pop(stock_name)

def update_market_value(self) -> None:
for stock in self.stocks.values():
stock_market_value = stock.get_market_value()
self.market_value += stock_market_value
105 changes: 105 additions & 0 deletions assets/Stock.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import datetime
from assets.Collector import InfoCollector


class Stock:

def __init__(self, stock_name: str):
self.stock_name = stock_name
self.ticker = InfoCollector.get_ticker(stock_name)
self.owned_quantity = 0
self.average_price = 0
self.previous_close = None
self.previous_open = None
self.previous_volume = None
self.previous_date = None

self._update_stock()

def __eq__(self, other):
if self.stock_name == other.stock_name:
return True
return False

def _update_stock(self) -> None:
"""
Updates the stock information, used as a check function to check if
stock exist
"""
stock_info = InfoCollector.get_history(self.ticker, period="1d")
if len(stock_info) == 0:
raise Exception("Invalid stock, enter a valid stock")
else:
self.previous_date = InfoCollector.get_prev_date(stock_info)
self.previous_open = InfoCollector.get_daily_info(stock_info, "Open")
self.previous_close = InfoCollector.get_daily_info(stock_info, "Close")
self.previous_volume = InfoCollector.get_daily_info(stock_info, "Volume")

def _get_purchase_price(self, purchase_date: datetime.datetime) -> float:
"""
Gets the purchase price (assumed be closed price) of the stock based
on given date if price at given date not found, track back for 5 days,
thought: smart implementation might be required for caching
"""
time_delta = datetime.timedelta(days=1)
start_date = purchase_date
end_date = purchase_date + time_delta

for _ in range(5):
info = InfoCollector.get_history(self.ticker,
start=start_date,
end=end_date)
if len(info) > 0:
purchased_price = InfoCollector.get_daily_info(info, "Close")
return purchased_price
start_date = start_date - time_delta
end_date = end_date - time_delta

raise Exception("Purchase price not found, please check the date or stock sticker")

def add_buy_action(self, quantity: int,
purchase_date: datetime.datetime) -> None:
"""
Add a purchase to the stock. Currently, do not support to add another
purchase to the stock
"""

# update own quantity

self.owned_quantity += quantity

if self.average_price == 0:

self.average_price = self._get_purchase_price(purchase_date=purchase_date)
else:
cur_purchase_price = self._get_purchase_price(purchase_date=purchase_date)
purchase_cost = quantity * cur_purchase_price

# update average price and owned_quantity
total_cost = purchase_cost + cur_purchase_price
self.average_price = total_cost / self.owned_quantity

def get_book_cost(self) -> float:
if self.owned_quantity == 0:
raise Exception("Stock not owned, please purchase first")

if self.average_price is None:
raise Exception("Purchase price not found, please check the date or stock sticker")

return self.average_price * self.owned_quantity

def get_market_value(self) -> float:
self._update_stock()
if self.owned_quantity == 0:
raise Exception("Stock not owned, please purchase first")

if self.previous_close is None:
raise Exception("Stock price not found, please check the date or stock sticker")

return self.previous_close * self.owned_quantity

def get_gain_loss(self) -> float:
return self.get_market_value() - self.get_book_cost()

def get_pct_change(self) -> float:
return (self.get_gain_loss() / self.get_book_cost()) * 100
61 changes: 61 additions & 0 deletions default_page.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import streamlit as st
import stTools as tools


def load_page():
st.markdown(
"""
Welcome to :green[MRMST]! Explore this app to assess and simulate
your investment portfolio's risk effortlessly! :green[Risk management] is like
:blue[wearing a helmet while riding a bike]—it shields your money during investments.
It's a strategy set to understand uncertainties in stocks or bonds.
Imagine your investment journey as a game; knowing rules and setbacks gives you a competitive edge.
:green[Value at Risk (VaR)] and :green[Conditional Value at Risk (CVaR)] aid in smart risk navigation,
keeping your game plan robust. Don't worry, I'll explain these concepts in a bit.
Build your :green[portfolio] on the sidebar; guidance is provided! Contact me at
[LinkedIn](https://www.linkedin.com/in/samarpatel/)
"""
)

st.subheader(f"Market Preview")

col_stock1, col_stock_2, col_stock_3, col_stock_4 = st.columns(4)

with col_stock1:
tools.create_candle_stick_plot(stock_ticker_name="^DJI",
stock_name="Dow Jones Industrial")

with col_stock_2:
tools.create_candle_stick_plot(stock_ticker_name="^IXIC",
stock_name="Nasdaq Composite")

with col_stock_3:
tools.create_candle_stick_plot(stock_ticker_name="^GSPC",
stock_name="S&P 500")

with col_stock_4:
tools.create_candle_stick_plot(stock_ticker_name="^RUT",
stock_name="Russell 2000")

# make 2 columns for sectors
col_sector1, col_sector2 = st.columns(2)

with col_sector1:
st.subheader(f"Tech Stocks")
stock_list = ["AAPL", "MSFT", "AMZN", "GOOG", "META", "TSLA", "NVDA", "AVGO"]
stock_name = ["Apple", "Microsoft", "Amazon", "Google", "Meta", "Tesla", "Nvidia", "Broadcom"]

df_stocks = tools.create_stocks_dataframe(stock_list, stock_name)
tools.create_dateframe_view(df_stocks)

with col_sector2:
st.subheader(f"Meme Stocks")
# give me a list of 8 meme stocks
stock_list = ["GME", "AMC", "BB", "NOK", "RIVN", "SPCE", "F", "T"]
stock_name = ["GameStop", "AMC Entertainment", "BlackBerry", "Nokia", "Rivian",
"Virgin Galactic", "Ford", "AT&T"]

df_stocks = tools.create_stocks_dataframe(stock_list, stock_name)
tools.create_dateframe_view(df_stocks)
33 changes: 33 additions & 0 deletions main_page.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import streamlit as st
import side_bar as comp
import stTools as tools
import default_page
import portfolio_page
import model_page

st.set_page_config(
page_title="MindInventory Financial Risk Tool",
page_icon="🦈",
layout="wide"
)

tools.remove_white_space()

st.title("MindInventory Risk Management Simulation Tool")

comp.load_sidebar()

if "load_portfolio_check" not in st.session_state:
st.session_state["load_portfolio_check"] = False

if "run_simulation_check" not in st.session_state:
st.session_state["run_simulation_check"] = False

if not st.session_state.load_portfolio_check:
default_page.load_page()

elif not st.session_state.run_simulation_check and st.session_state.load_portfolio_check:
portfolio_page.load_page()

elif st.session_state.run_simulation_check:
model_page.load_page()
Loading

0 comments on commit 00c44d0

Please sign in to comment.