Spaces:
Sleeping
Sleeping
app file
Browse files
app.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
| 0 |
# Max Rows and Columns
|
| 1 |
pd.set_option('display.max_columns', 500)
|
| 2 |
pd.set_option('display.max_rows', None)
|
| 3 |
|
| 4 |
# Two Decimals
|
| 5 |
pd.options.display.float_format = '{:.2f}'.format
|
| 6 |
|
| 7 |
# The stock symbol
|
| 8 |
symbol = ticker
|
| 9 |
ticker = yf.Ticker(symbol)
|
| 10 |
company_name = ticker.info.get("longName", "N/A")
|
| 11 |
|
| 12 |
# Get historical share prices
|
| 13 |
price_history = ticker.history(period='5y')
|
| 14 |
|
| 15 |
# Extract the closing prices at the end of each fiscal year
|
| 16 |
# We will reindex to have end-of-year dates that match the years of the income statements
|
| 17 |
year_end_prices = price_history.resample('A').last()['Close']
|
| 18 |
year_end_prices.index = year_end_prices.index.year
|
| 19 |
|
| 20 |
# Get the number of shares from the info or financials
|
| 21 |
shares_outstanding = ticker.info.get('sharesOutstanding')
|
| 22 |
|
| 23 |
# Get the annual income statement data
|
| 24 |
income_statement = ticker.financials
|
| 25 |
|
| 26 |
# Transpose the income statement to have years as rows
|
| 27 |
income_statement = income_statement.T
|
| 28 |
|
| 29 |
# Extract net income and calculate EPS
|
| 30 |
income_statement['EPS'] = income_statement['Net Income'] / shares_outstanding
|
| 31 |
|
| 32 |
# Convert the 'Date' index to a year
|
| 33 |
income_statement.index = income_statement.index.year
|
| 34 |
|
| 35 |
# Combine EPS and closing prices into one DataFrame
|
| 36 |
pe_ratios_df = pd.DataFrame({
|
| 37 |
'Year': income_statement.index,
|
| 38 |
'EPS': income_statement['EPS'],
|
| 39 |
'Revenue': income_statement['Total Revenue'],
|
| 40 |
'Closing Price': year_end_prices.reindex(income_statement.index).values
|
| 41 |
})
|
| 42 |
|
| 43 |
# Calculate the P/E ratio
|
| 44 |
pe_ratios_df['P/E Ratio'] = pe_ratios_df['Closing Price'] / pe_ratios_df['EPS']
|
| 45 |
|
| 46 |
# Calculate Market Capitalization for each year (Closing Price * Shares Outstanding)
|
| 47 |
pe_ratios_df['Market Cap'] = pe_ratios_df['Closing Price'] * shares_outstanding
|
| 48 |
|
| 49 |
# Calculate the P/S ratio
|
| 50 |
pe_ratios_df['P/S Ratio'] = pe_ratios_df['Market Cap'] / pe_ratios_df['Revenue']
|
| 51 |
|
| 52 |
# Create DataFrame with last 10 years
|
| 53 |
current_year = datetime.now().year
|
| 54 |
|
| 55 |
# Create a list of the last 10 years
|
| 56 |
years = list(range(current_year - 9, current_year + 1))
|
| 57 |
|
| 58 |
# Create a DataFrame
|
| 59 |
df_years = pd.DataFrame({'Year': years})
|
| 60 |
|
| 61 |
# Get the historical dividend data
|
| 62 |
dividend_data = ticker.dividends
|
| 63 |
|
| 64 |
# Convert the Series to a DataFrame
|
| 65 |
dividend_df = dividend_data.reset_index()
|
| 66 |
|
| 67 |
# Rename the columns for clarity
|
| 68 |
dividend_df.columns = ['Date', 'Dividend']
|
| 69 |
|
| 70 |
# Extract the year from the Date column
|
| 71 |
dividend_df['Year'] = dividend_df['Date'].dt.year
|
| 72 |
|
| 73 |
# Group by Year and get the last dividend of each year
|
| 74 |
dividend_df = dividend_df.groupby('Year').last().reset_index()
|
| 75 |
|
| 76 |
# Merge DataFrames
|
| 77 |
dividend_df = pd.merge(df_years, dividend_df, on='Year', how='left')
|
| 78 |
|
| 79 |
# Replace NaN with last years value
|
| 80 |
dividend_df['Dividend'] = dividend_df['Dividend'].ffill()
|
| 81 |
|
| 82 |
# Sort the DataFrame by Year
|
| 83 |
dividend_df = dividend_df.sort_values(by='Year')
|
| 84 |
|
| 85 |
# Calculate the 3-year percentage change
|
| 86 |
dividend_df['Dividend Growth (3y)'] = dividend_df['Dividend'].pct_change(periods=3) * 100
|
| 87 |
|
| 88 |
# Calculate the 5-year percentage change
|
| 89 |
dividend_df['Dividend Growth (5y)'] = dividend_df['Dividend'].pct_change(periods=5) * 100
|
| 90 |
|
| 91 |
# Calculate the 10-year percentage change
|
| 92 |
dividend_df['Dividend Growth (10y)'] = dividend_df['Dividend'].pct_change(periods=10) * 100
|
| 93 |
|
| 94 |
# Drop Columns
|
| 95 |
dividend_df = dividend_df.drop(columns=['Dividend'])
|
| 96 |
|
| 97 |
print(dividend_df)
|
| 98 |
|
| 99 |
# Get the historical stock price data for the last 10 years
|
| 100 |
price_history = ticker.history(period='10y')
|
| 101 |
|
| 102 |
# Initialize a list to accumulate the annual data
|
| 103 |
value_data = []
|
| 104 |
|
| 105 |
# Start with an initial investment value of 1 share
|
| 106 |
initial_value = price_history['Close'].iloc[0]
|
| 107 |
cumulative_value = initial_value
|
| 108 |
|
| 109 |
# Track the last year processed to ensure we only capture the final value for each year
|
| 110 |
last_year = price_history.index[0].year
|
| 111 |
|
| 112 |
# Iterate over each date in the price history to calculate the value including dividends
|
| 113 |
for i in range(len(price_history)):
|
| 114 |
current_date = price_history.index[i]
|
| 115 |
current_price = price_history['Close'].iloc[i]
|
| 116 |
current_year = current_date.year
|
| 117 |
|
| 118 |
# Check if any dividends were paid out on the current date
|
| 119 |
if current_date in dividend_df['Date'].values:
|
| 120 |
dividend = dividend_df[dividend_df['Date'] == current_date]['Dividend'].values[0]
|
| 121 |
# Calculate the value increase due to dividends
|
| 122 |
cumulative_value += (dividend / current_price) * cumulative_value
|
| 123 |
|
| 124 |
# Update the cumulative value with the price change
|
| 125 |
if i < len(price_history) - 1:
|
| 126 |
next_price = price_history['Close'].iloc[i + 1]
|
| 127 |
cumulative_value *= (next_price / current_price)
|
| 128 |
|
| 129 |
# At the end of each year, record the value including dividends
|
| 130 |
if current_year != last_year:
|
| 131 |
# Append the cumulative value at the end of the previous year
|
| 132 |
value_data.append({'Year': last_year, 'Value Including Dividends': cumulative_value})
|
| 133 |
last_year = current_year
|
| 134 |
|
| 135 |
# Append the final value at the end of the last year in the dataset
|
| 136 |
value_data.append({'Year': last_year, 'Value Including Dividends': cumulative_value})
|
| 137 |
|
| 138 |
# Convert the accumulated list to a DataFrame
|
| 139 |
value_including_dividends_df = pd.DataFrame(value_data)
|
| 140 |
|
| 141 |
# Calculate the percentage increase in value including dividends
|
| 142 |
value_including_dividends_df['Value Increase'] = value_including_dividends_df['Value Including Dividends'].pct_change() * 100
|
| 143 |
|
| 144 |
# Get the historical dividend data
|
| 145 |
dividend_data = ticker.dividends
|
| 146 |
|
| 147 |
# Convert the Series to a DataFrame
|
| 148 |
dividend_df2 = dividend_data.reset_index()
|
| 149 |
|
| 150 |
# Rename the columns for clarity
|
| 151 |
dividend_df2.columns = ['Date', 'Dividend']
|
| 152 |
|
| 153 |
# Extract the year from the Date column
|
| 154 |
dividend_df2['Year'] = dividend_df2['Date'].dt.year
|
| 155 |
|
| 156 |
# Aggregate the annual dividends by summing them up
|
| 157 |
annual_dividends = dividend_df2.groupby('Year')['Dividend'].sum().reset_index()
|
| 158 |
|
| 159 |
# Calculate the year-over-year dividend increase
|
| 160 |
annual_dividends['Dividend Increase'] = annual_dividends['Dividend'].diff() > 0
|
| 161 |
|
| 162 |
# Calculate the cumulative number of increases
|
| 163 |
annual_dividends['No of Increases'] = annual_dividends['Dividend Increase'].cumsum()
|
| 164 |
|
| 165 |
# Drop the 'Dividend Increase' column if not needed in the final output
|
| 166 |
annual_dividends = annual_dividends.drop(columns=['Dividend Increase'])
|
| 167 |
|
| 168 |
# Get the annual income statement data to find EPS
|
| 169 |
income_statement = ticker.financials.T
|
| 170 |
|
| 171 |
# Extract the EPS (Earnings Per Share)
|
| 172 |
annual_eps = (income_statement['Net Income'] / ticker.info['sharesOutstanding']).reset_index()
|
| 173 |
annual_eps.columns = ['Year', 'EPS']
|
| 174 |
|
| 175 |
# Convert the index to years for the EPS DataFrame
|
| 176 |
annual_eps['Year'] = annual_eps['Year'].dt.year
|
| 177 |
|
| 178 |
# Align the DataFrames on the 'Year' column
|
| 179 |
aligned_dividends_eps = pd.merge(annual_dividends, annual_eps, on='Year', how='outer')
|
| 180 |
|
| 181 |
# Calculate the Payout Ratio
|
| 182 |
aligned_dividends_eps['Payout Ratio (%)'] = (aligned_dividends_eps['Dividend'] / aligned_dividends_eps['EPS']) * 100
|
| 183 |
|
| 184 |
aligned_dividends_eps.sort_values('Year', axis=0, ascending=True, inplace=True)
|
| 185 |
|
| 186 |
# Get the income statement data
|
| 187 |
income_statement = ticker.financials
|
| 188 |
|
| 189 |
# Transpose the data to make it easier to read
|
| 190 |
income_statement = income_statement.T
|
| 191 |
|
| 192 |
# Rename the columns for clarity
|
| 193 |
income_statement = income_statement.rename(columns={'Total Revenue': 'Revenue'})
|
| 194 |
income_statement = income_statement.rename(columns={'Gross Profit': 'Earnings'})
|
| 195 |
|
| 196 |
# Convert Index to Year and rename it to Year and sort by it
|
| 197 |
income_statement['Year'] = income_statement.index.year
|
| 198 |
income_statement = income_statement.sort_values(by='Year')
|
| 199 |
|
| 200 |
# Calculate Growth Columns
|
| 201 |
income_statement['Revenue Growth'] = income_statement['Revenue'].pct_change() * 100
|
| 202 |
income_statement['EBITDA Growth'] = income_statement['EBITDA'].pct_change() * 100
|
| 203 |
|
| 204 |
# Calculate Margin Columns
|
| 205 |
income_statement['EBITDA Margin'] = (income_statement['EBITDA']/income_statement['Revenue']).pct_change() * 100
|
| 206 |
|
| 207 |
# Calculate Gross Profit and Gross Profit Margin and Gross Profit Growth
|
| 208 |
income_statement['GP'] = income_statement['Revenue'] - income_statement['Cost Of Revenue']
|
| 209 |
income_statement['GP Margin'] = (income_statement['GP'] / income_statement['Revenue']) * 100
|
| 210 |
|
| 211 |
# Calculate Gross Profit Growth
|
| 212 |
income_statement['GP Growth'] = income_statement['GP'].pct_change() * 100
|
| 213 |
|
| 214 |
# Format EBITDA
|
| 215 |
income_statement['EBITDA MEUR'] = income_statement['EBITDA'] / 1000000
|
| 216 |
|
| 217 |
income_df = income_statement[['Year','EBITDA MEUR', 'Revenue Growth', 'GP Margin', 'GP Growth', 'EBITDA Margin', 'EBITDA Growth']]
|
| 218 |
|
| 219 |
# Get the cashflow data
|
| 220 |
cashflow_data = ticker.cashflow
|
| 221 |
|
| 222 |
# Transpose the data to have years as rows
|
| 223 |
cashflow_statement = cashflow_data.T
|
| 224 |
|
| 225 |
# Get the number of shares outstanding from the info
|
| 226 |
shares_outstanding = ticker.info.get('sharesOutstanding')
|
| 227 |
|
| 228 |
# Extract Cash Flow from Operations and CapEx
|
| 229 |
cashflow_operations = cashflow_statement['Operating Cash Flow']
|
| 230 |
capex = cashflow_statement['Capital Expenditure']
|
| 231 |
cashflow = cashflow_statement['Free Cash Flow']
|
| 232 |
|
| 233 |
# Calculate Cash Flow per Share
|
| 234 |
cashflow_per_share = cashflow_operations / shares_outstanding
|
| 235 |
|
| 236 |
# Calculate Free Cash Flow (FCF)
|
| 237 |
cashflow = cashflow_operations + capex # CapEx is typically a negative number in the cash flow statement
|
| 238 |
|
| 239 |
# Convert the 'Date' index to a year
|
| 240 |
cashflow.index = cashflow.index.year
|
| 241 |
|
| 242 |
# Create a DataFrame for display
|
| 243 |
cashflow_df = pd.DataFrame({
|
| 244 |
'Year': cashflow.index,
|
| 245 |
'Cashflow Operations': cashflow_operations.values,
|
| 246 |
'Cashflow per Share': cashflow_per_share,
|
| 247 |
#'Capital Expenditures': capex.values,
|
| 248 |
'Free Cashflow': cashflow.values
|
| 249 |
})
|
| 250 |
|
| 251 |
# Get the annual balance sheet data
|
| 252 |
balance_sheet = ticker.balance_sheet
|
| 253 |
|
| 254 |
# Transpose the data to have years as rows
|
| 255 |
balance_sheet = balance_sheet.T
|
| 256 |
|
| 257 |
# Extract Total Stockholder Equity
|
| 258 |
total_equity = balance_sheet['Stockholders Equity']
|
| 259 |
|
| 260 |
# Get the number of shares outstanding from the info
|
| 261 |
shares_outstanding = ticker.info.get('sharesOutstanding')
|
| 262 |
|
| 263 |
# Calculate Book Value per Share
|
| 264 |
book_value_per_share = total_equity / shares_outstanding
|
| 265 |
|
| 266 |
# Extract Total Debt and Cash Equivalents
|
| 267 |
total_debt = balance_sheet['Total Debt']
|
| 268 |
cash_and_equivalents = balance_sheet['Cash And Cash Equivalents']
|
| 269 |
|
| 270 |
# Calculate Net Financial Liabilities
|
| 271 |
net_financial_liabilities = total_debt - cash_and_equivalents
|
| 272 |
|
| 273 |
# Convert the index to years
|
| 274 |
net_financial_liabilities.index = net_financial_liabilities.index.year
|
| 275 |
|
| 276 |
# Create a DataFrame for display
|
| 277 |
net_financial_liabilities_df = pd.DataFrame({
|
| 278 |
'Year': net_financial_liabilities.index,
|
| 279 |
'Bookvalue per Share': book_value_per_share,
|
| 280 |
'Total Debt': total_debt.values,
|
| 281 |
'Cash': cash_and_equivalents.values,
|
| 282 |
'Net Financial Liabilities': net_financial_liabilities.values
|
| 283 |
})
|
| 284 |
|
| 285 |
# Merge DataFrames
|
| 286 |
df = pd.merge(pe_ratios_df, annual_dividends, on='Year', how='left')
|
| 287 |
df = pd.merge(df, value_including_dividends_df, on='Year', how='inner')
|
| 288 |
df = pd.merge(df, income_df, on='Year', how='inner')
|
| 289 |
df = pd.merge(df, dividend_df, on='Year', how='left')
|
| 290 |
df = pd.merge(df, cashflow_df, on='Year', how='inner')
|
| 291 |
df = pd.merge(df, net_financial_liabilities_df, on='Year', how='inner')
|
| 292 |
|
| 293 |
return company_name, df
|
| 294 |
gr.Markdown("# Stock Data Viewer\nEnter a stock ticker symbol to view the historical data.")
|
| 295 |
|
| 296 |
with gr.Row():
|
| 297 |
ticker_input = gr.Textbox(label="Enter Ticker Symbol")
|
| 298 |
with gr.Row():
|
| 299 |
submit_btn = gr.Button("Submit")
|
| 300 |
|
| 301 |
ticker_headline = gr.Markdown("")
|
| 302 |
|
| 303 |
with gr.Row():
|
| 304 |
data_output = gr.Dataframe()
|
| 305 |
def show_dataframe(ticker):
|
| 306 |
company_name, df = get_stock_data(ticker)
|
| 307 |
headline = f"### Data for {company_name} ({ticker})"
|
| 308 |
return headline, df
|
| 309 |
submit_btn.click(show_dataframe, inputs=ticker_input, outputs=[ticker_headline, data_output])
|
|
|
|
| 1 |
+
import yfinance as yf
|
| 2 |
# Max Rows and Columns
|
| 3 |
pd.set_option('display.max_columns', 500)
|
| 4 |
pd.set_option('display.max_rows', None)
|
| 5 |
|
| 6 |
# Two Decimals
|
| 7 |
pd.options.display.float_format = '{:.2f}'.format
|
| 8 |
|
| 9 |
# The stock symbol
|
| 10 |
symbol = ticker
|
| 11 |
ticker = yf.Ticker(symbol)
|
| 12 |
company_name = ticker.info.get("longName", "N/A")
|
| 13 |
|
| 14 |
# Get historical share prices
|
| 15 |
price_history = ticker.history(period='5y')
|
| 16 |
|
| 17 |
# Extract the closing prices at the end of each fiscal year
|
| 18 |
# We will reindex to have end-of-year dates that match the years of the income statements
|
| 19 |
year_end_prices = price_history.resample('A').last()['Close']
|
| 20 |
year_end_prices.index = year_end_prices.index.year
|
| 21 |
|
| 22 |
# Get the number of shares from the info or financials
|
| 23 |
shares_outstanding = ticker.info.get('sharesOutstanding')
|
| 24 |
|
| 25 |
# Get the annual income statement data
|
| 26 |
income_statement = ticker.financials
|
| 27 |
|
| 28 |
# Transpose the income statement to have years as rows
|
| 29 |
income_statement = income_statement.T
|
| 30 |
|
| 31 |
# Extract net income and calculate EPS
|
| 32 |
income_statement['EPS'] = income_statement['Net Income'] / shares_outstanding
|
| 33 |
|
| 34 |
# Convert the 'Date' index to a year
|
| 35 |
income_statement.index = income_statement.index.year
|
| 36 |
|
| 37 |
# Combine EPS and closing prices into one DataFrame
|
| 38 |
pe_ratios_df = pd.DataFrame({
|
| 39 |
'Year': income_statement.index,
|
| 40 |
'EPS': income_statement['EPS'],
|
| 41 |
'Revenue': income_statement['Total Revenue'],
|
| 42 |
'Closing Price': year_end_prices.reindex(income_statement.index).values
|
| 43 |
})
|
| 44 |
|
| 45 |
# Calculate the P/E ratio
|
| 46 |
pe_ratios_df['P/E Ratio'] = pe_ratios_df['Closing Price'] / pe_ratios_df['EPS']
|
| 47 |
|
| 48 |
# Calculate Market Capitalization for each year (Closing Price * Shares Outstanding)
|
| 49 |
pe_ratios_df['Market Cap'] = pe_ratios_df['Closing Price'] * shares_outstanding
|
| 50 |
|
| 51 |
# Calculate the P/S ratio
|
| 52 |
pe_ratios_df['P/S Ratio'] = pe_ratios_df['Market Cap'] / pe_ratios_df['Revenue']
|
| 53 |
|
| 54 |
# Create DataFrame with last 10 years
|
| 55 |
current_year = datetime.now().year
|
| 56 |
|
| 57 |
# Create a list of the last 10 years
|
| 58 |
years = list(range(current_year - 9, current_year + 1))
|
| 59 |
|
| 60 |
# Create a DataFrame
|
| 61 |
df_years = pd.DataFrame({'Year': years})
|
| 62 |
|
| 63 |
# Get the historical dividend data
|
| 64 |
dividend_data = ticker.dividends
|
| 65 |
|
| 66 |
# Convert the Series to a DataFrame
|
| 67 |
dividend_df = dividend_data.reset_index()
|
| 68 |
|
| 69 |
# Rename the columns for clarity
|
| 70 |
dividend_df.columns = ['Date', 'Dividend']
|
| 71 |
|
| 72 |
# Extract the year from the Date column
|
| 73 |
dividend_df['Year'] = dividend_df['Date'].dt.year
|
| 74 |
|
| 75 |
# Group by Year and get the last dividend of each year
|
| 76 |
dividend_df = dividend_df.groupby('Year').last().reset_index()
|
| 77 |
|
| 78 |
# Merge DataFrames
|
| 79 |
dividend_df = pd.merge(df_years, dividend_df, on='Year', how='left')
|
| 80 |
|
| 81 |
# Replace NaN with last years value
|
| 82 |
dividend_df['Dividend'] = dividend_df['Dividend'].ffill()
|
| 83 |
|
| 84 |
# Sort the DataFrame by Year
|
| 85 |
dividend_df = dividend_df.sort_values(by='Year')
|
| 86 |
|
| 87 |
# Calculate the 3-year percentage change
|
| 88 |
dividend_df['Dividend Growth (3y)'] = dividend_df['Dividend'].pct_change(periods=3) * 100
|
| 89 |
|
| 90 |
# Calculate the 5-year percentage change
|
| 91 |
dividend_df['Dividend Growth (5y)'] = dividend_df['Dividend'].pct_change(periods=5) * 100
|
| 92 |
|
| 93 |
# Calculate the 10-year percentage change
|
| 94 |
dividend_df['Dividend Growth (10y)'] = dividend_df['Dividend'].pct_change(periods=10) * 100
|
| 95 |
|
| 96 |
# Drop Columns
|
| 97 |
dividend_df = dividend_df.drop(columns=['Dividend'])
|
| 98 |
|
| 99 |
print(dividend_df)
|
| 100 |
|
| 101 |
# Get the historical stock price data for the last 10 years
|
| 102 |
price_history = ticker.history(period='10y')
|
| 103 |
|
| 104 |
# Initialize a list to accumulate the annual data
|
| 105 |
value_data = []
|
| 106 |
|
| 107 |
# Start with an initial investment value of 1 share
|
| 108 |
initial_value = price_history['Close'].iloc[0]
|
| 109 |
cumulative_value = initial_value
|
| 110 |
|
| 111 |
# Track the last year processed to ensure we only capture the final value for each year
|
| 112 |
last_year = price_history.index[0].year
|
| 113 |
|
| 114 |
# Iterate over each date in the price history to calculate the value including dividends
|
| 115 |
for i in range(len(price_history)):
|
| 116 |
current_date = price_history.index[i]
|
| 117 |
current_price = price_history['Close'].iloc[i]
|
| 118 |
current_year = current_date.year
|
| 119 |
|
| 120 |
# Check if any dividends were paid out on the current date
|
| 121 |
if current_date in dividend_df['Date'].values:
|
| 122 |
dividend = dividend_df[dividend_df['Date'] == current_date]['Dividend'].values[0]
|
| 123 |
# Calculate the value increase due to dividends
|
| 124 |
cumulative_value += (dividend / current_price) * cumulative_value
|
| 125 |
|
| 126 |
# Update the cumulative value with the price change
|
| 127 |
if i < len(price_history) - 1:
|
| 128 |
next_price = price_history['Close'].iloc[i + 1]
|
| 129 |
cumulative_value *= (next_price / current_price)
|
| 130 |
|
| 131 |
# At the end of each year, record the value including dividends
|
| 132 |
if current_year != last_year:
|
| 133 |
# Append the cumulative value at the end of the previous year
|
| 134 |
value_data.append({'Year': last_year, 'Value Including Dividends': cumulative_value})
|
| 135 |
last_year = current_year
|
| 136 |
|
| 137 |
# Append the final value at the end of the last year in the dataset
|
| 138 |
value_data.append({'Year': last_year, 'Value Including Dividends': cumulative_value})
|
| 139 |
|
| 140 |
# Convert the accumulated list to a DataFrame
|
| 141 |
value_including_dividends_df = pd.DataFrame(value_data)
|
| 142 |
|
| 143 |
# Calculate the percentage increase in value including dividends
|
| 144 |
value_including_dividends_df['Value Increase'] = value_including_dividends_df['Value Including Dividends'].pct_change() * 100
|
| 145 |
|
| 146 |
# Get the historical dividend data
|
| 147 |
dividend_data = ticker.dividends
|
| 148 |
|
| 149 |
# Convert the Series to a DataFrame
|
| 150 |
dividend_df2 = dividend_data.reset_index()
|
| 151 |
|
| 152 |
# Rename the columns for clarity
|
| 153 |
dividend_df2.columns = ['Date', 'Dividend']
|
| 154 |
|
| 155 |
# Extract the year from the Date column
|
| 156 |
dividend_df2['Year'] = dividend_df2['Date'].dt.year
|
| 157 |
|
| 158 |
# Aggregate the annual dividends by summing them up
|
| 159 |
annual_dividends = dividend_df2.groupby('Year')['Dividend'].sum().reset_index()
|
| 160 |
|
| 161 |
# Calculate the year-over-year dividend increase
|
| 162 |
annual_dividends['Dividend Increase'] = annual_dividends['Dividend'].diff() > 0
|
| 163 |
|
| 164 |
# Calculate the cumulative number of increases
|
| 165 |
annual_dividends['No of Increases'] = annual_dividends['Dividend Increase'].cumsum()
|
| 166 |
|
| 167 |
# Drop the 'Dividend Increase' column if not needed in the final output
|
| 168 |
annual_dividends = annual_dividends.drop(columns=['Dividend Increase'])
|
| 169 |
|
| 170 |
# Get the annual income statement data to find EPS
|
| 171 |
income_statement = ticker.financials.T
|
| 172 |
|
| 173 |
# Extract the EPS (Earnings Per Share)
|
| 174 |
annual_eps = (income_statement['Net Income'] / ticker.info['sharesOutstanding']).reset_index()
|
| 175 |
annual_eps.columns = ['Year', 'EPS']
|
| 176 |
|
| 177 |
# Convert the index to years for the EPS DataFrame
|
| 178 |
annual_eps['Year'] = annual_eps['Year'].dt.year
|
| 179 |
|
| 180 |
# Align the DataFrames on the 'Year' column
|
| 181 |
aligned_dividends_eps = pd.merge(annual_dividends, annual_eps, on='Year', how='outer')
|
| 182 |
|
| 183 |
# Calculate the Payout Ratio
|
| 184 |
aligned_dividends_eps['Payout Ratio (%)'] = (aligned_dividends_eps['Dividend'] / aligned_dividends_eps['EPS']) * 100
|
| 185 |
|
| 186 |
aligned_dividends_eps.sort_values('Year', axis=0, ascending=True, inplace=True)
|
| 187 |
|
| 188 |
# Get the income statement data
|
| 189 |
income_statement = ticker.financials
|
| 190 |
|
| 191 |
# Transpose the data to make it easier to read
|
| 192 |
income_statement = income_statement.T
|
| 193 |
|
| 194 |
# Rename the columns for clarity
|
| 195 |
income_statement = income_statement.rename(columns={'Total Revenue': 'Revenue'})
|
| 196 |
income_statement = income_statement.rename(columns={'Gross Profit': 'Earnings'})
|
| 197 |
|
| 198 |
# Convert Index to Year and rename it to Year and sort by it
|
| 199 |
income_statement['Year'] = income_statement.index.year
|
| 200 |
income_statement = income_statement.sort_values(by='Year')
|
| 201 |
|
| 202 |
# Calculate Growth Columns
|
| 203 |
income_statement['Revenue Growth'] = income_statement['Revenue'].pct_change() * 100
|
| 204 |
income_statement['EBITDA Growth'] = income_statement['EBITDA'].pct_change() * 100
|
| 205 |
|
| 206 |
# Calculate Margin Columns
|
| 207 |
income_statement['EBITDA Margin'] = (income_statement['EBITDA']/income_statement['Revenue']).pct_change() * 100
|
| 208 |
|
| 209 |
# Calculate Gross Profit and Gross Profit Margin and Gross Profit Growth
|
| 210 |
income_statement['GP'] = income_statement['Revenue'] - income_statement['Cost Of Revenue']
|
| 211 |
income_statement['GP Margin'] = (income_statement['GP'] / income_statement['Revenue']) * 100
|
| 212 |
|
| 213 |
# Calculate Gross Profit Growth
|
| 214 |
income_statement['GP Growth'] = income_statement['GP'].pct_change() * 100
|
| 215 |
|
| 216 |
# Format EBITDA
|
| 217 |
income_statement['EBITDA MEUR'] = income_statement['EBITDA'] / 1000000
|
| 218 |
|
| 219 |
income_df = income_statement[['Year','EBITDA MEUR', 'Revenue Growth', 'GP Margin', 'GP Growth', 'EBITDA Margin', 'EBITDA Growth']]
|
| 220 |
|
| 221 |
# Get the cashflow data
|
| 222 |
cashflow_data = ticker.cashflow
|
| 223 |
|
| 224 |
# Transpose the data to have years as rows
|
| 225 |
cashflow_statement = cashflow_data.T
|
| 226 |
|
| 227 |
# Get the number of shares outstanding from the info
|
| 228 |
shares_outstanding = ticker.info.get('sharesOutstanding')
|
| 229 |
|
| 230 |
# Extract Cash Flow from Operations and CapEx
|
| 231 |
cashflow_operations = cashflow_statement['Operating Cash Flow']
|
| 232 |
capex = cashflow_statement['Capital Expenditure']
|
| 233 |
cashflow = cashflow_statement['Free Cash Flow']
|
| 234 |
|
| 235 |
# Calculate Cash Flow per Share
|
| 236 |
cashflow_per_share = cashflow_operations / shares_outstanding
|
| 237 |
|
| 238 |
# Calculate Free Cash Flow (FCF)
|
| 239 |
cashflow = cashflow_operations + capex # CapEx is typically a negative number in the cash flow statement
|
| 240 |
|
| 241 |
# Convert the 'Date' index to a year
|
| 242 |
cashflow.index = cashflow.index.year
|
| 243 |
|
| 244 |
# Create a DataFrame for display
|
| 245 |
cashflow_df = pd.DataFrame({
|
| 246 |
'Year': cashflow.index,
|
| 247 |
'Cashflow Operations': cashflow_operations.values,
|
| 248 |
'Cashflow per Share': cashflow_per_share,
|
| 249 |
#'Capital Expenditures': capex.values,
|
| 250 |
'Free Cashflow': cashflow.values
|
| 251 |
})
|
| 252 |
|
| 253 |
# Get the annual balance sheet data
|
| 254 |
balance_sheet = ticker.balance_sheet
|
| 255 |
|
| 256 |
# Transpose the data to have years as rows
|
| 257 |
balance_sheet = balance_sheet.T
|
| 258 |
|
| 259 |
# Extract Total Stockholder Equity
|
| 260 |
total_equity = balance_sheet['Stockholders Equity']
|
| 261 |
|
| 262 |
# Get the number of shares outstanding from the info
|
| 263 |
shares_outstanding = ticker.info.get('sharesOutstanding')
|
| 264 |
|
| 265 |
# Calculate Book Value per Share
|
| 266 |
book_value_per_share = total_equity / shares_outstanding
|
| 267 |
|
| 268 |
# Extract Total Debt and Cash Equivalents
|
| 269 |
total_debt = balance_sheet['Total Debt']
|
| 270 |
cash_and_equivalents = balance_sheet['Cash And Cash Equivalents']
|
| 271 |
|
| 272 |
# Calculate Net Financial Liabilities
|
| 273 |
net_financial_liabilities = total_debt - cash_and_equivalents
|
| 274 |
|
| 275 |
# Convert the index to years
|
| 276 |
net_financial_liabilities.index = net_financial_liabilities.index.year
|
| 277 |
|
| 278 |
# Create a DataFrame for display
|
| 279 |
net_financial_liabilities_df = pd.DataFrame({
|
| 280 |
'Year': net_financial_liabilities.index,
|
| 281 |
'Bookvalue per Share': book_value_per_share,
|
| 282 |
'Total Debt': total_debt.values,
|
| 283 |
'Cash': cash_and_equivalents.values,
|
| 284 |
'Net Financial Liabilities': net_financial_liabilities.values
|
| 285 |
})
|
| 286 |
|
| 287 |
# Merge DataFrames
|
| 288 |
df = pd.merge(pe_ratios_df, annual_dividends, on='Year', how='left')
|
| 289 |
df = pd.merge(df, value_including_dividends_df, on='Year', how='inner')
|
| 290 |
df = pd.merge(df, income_df, on='Year', how='inner')
|
| 291 |
df = pd.merge(df, dividend_df, on='Year', how='left')
|
| 292 |
df = pd.merge(df, cashflow_df, on='Year', how='inner')
|
| 293 |
df = pd.merge(df, net_financial_liabilities_df, on='Year', how='inner')
|
| 294 |
|
| 295 |
return company_name, df
|
| 296 |
gr.Markdown("# Stock Data Viewer\nEnter a stock ticker symbol to view the historical data.")
|
| 297 |
|
| 298 |
with gr.Row():
|
| 299 |
ticker_input = gr.Textbox(label="Enter Ticker Symbol")
|
| 300 |
with gr.Row():
|
| 301 |
submit_btn = gr.Button("Submit")
|
| 302 |
|
| 303 |
ticker_headline = gr.Markdown("")
|
| 304 |
|
| 305 |
with gr.Row():
|
| 306 |
data_output = gr.Dataframe()
|
| 307 |
def show_dataframe(ticker):
|
| 308 |
company_name, df = get_stock_data(ticker)
|
| 309 |
headline = f"### Data for {company_name} ({ticker})"
|
| 310 |
return headline, df
|
| 311 |
submit_btn.click(show_dataframe, inputs=ticker_input, outputs=[ticker_headline, data_output])
|