import marimo __generated_with = "0.9.15" app = marimo.App(width="medium") @app.cell(hide_code=True) def __(mo): mo.md(r"""# Cryptocurrency Minuet Dashboard""") return @app.cell(hide_code=True) def __(): import marimo as mo import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns import yfinance as yf import mplfinance as mpf import altair as alt from datetime import date, timedelta, datetime from sklearn.preprocessing import MinMaxScaler return ( MinMaxScaler, alt, date, datetime, mo, mpf, np, pd, plt, sns, timedelta, yf, ) @app.cell(hide_code=True) def __(datetime, timedelta, yf): tickers = [f'{ticker}-USD' for ticker in [ 'BTC', 'ETH', 'AR', 'SOL', 'ADA', 'XMR', 'DOGE', 'SHIB', 'PEPE24478', 'BNB', 'AVAX', ]] yesterday = (datetime.now() - timedelta(days=1)).strftime('%Y-%m-%d') data = yf.download(tickers, start=yesterday, interval='5m') closes = data['Close'] return closes, data, tickers, yesterday @app.cell(hide_code=True) def __(closes): highest_percentage_change = {} for ticker in closes.columns: # Group by day and calculate min and max within the day daily_high = closes[ticker].resample('D').max() daily_low = closes[ticker].resample('D').min() # Calculate percentage change daily_percentage_change = ((daily_high - daily_low) / daily_low) * 100 # Get the highest percentage change within the day highest_percentage_change[ticker] = daily_percentage_change.max() return ( daily_high, daily_low, daily_percentage_change, highest_percentage_change, ticker, ) @app.cell(hide_code=True) def __(mo): mo.md("""## Highest Returns in the since Yesterday""") return @app.cell(hide_code=True) def __(highest_percentage_change, mo, tickers): def show_highest_percentage(ticker): percentage = highest_percentage_change[ticker] up = 'success' if percentage > 0 else 'danger' percentage_text = '%.2f%%' % percentage if percentage is not None else 'N/A' return mo.callout(value=f'{ticker} {percentage_text}', kind=up) # Calculate and sort percentage changes highest_percentage_sorted = sorted(highest_percentage_change.items(), key=lambda x: x[1], reverse=True) highest, second_highest = highest_percentage_sorted[0], highest_percentage_sorted[1] lowest, second_lowest = highest_percentage_sorted[-1], highest_percentage_sorted[-2] # Generate markdown explanations callouts_length = int(len(tickers) / 2) top_callout = mo.md(f""" ### Overview of Highest and Lowest Daily Percentage Changes The **highest daily percentage change** was recorded by `{highest[0]}` at {highest[1]:.2f}%. The **second highest** was `{second_highest[0]}` with a change of {second_highest[1]:.2f}%. The **lowest daily percentage change** occurred for `{lowest[0]}` at {lowest[1]:.2f}%. The **second lowest** was `{second_lowest[0]}` with a change of {second_lowest[1]:.2f}%. """) callouts_top = mo.hstack([show_highest_percentage(ticker) for ticker in tickers[:callouts_length]]) callouts_bottom = mo.hstack([show_highest_percentage(ticker) for ticker in tickers[callouts_length:]]) # mo.vstack([top_callout, callouts_top, callouts_bottom], align='start', heights='equal') return ( callouts_bottom, callouts_length, callouts_top, highest, highest_percentage_sorted, lowest, second_highest, second_lowest, show_highest_percentage, top_callout, ) @app.cell(hide_code=True) def __(top_callout): top_callout return @app.cell(hide_code=True) def __(callouts_top): callouts_top return @app.cell(hide_code=True) def __(callouts_bottom): callouts_bottom return @app.cell(hide_code=True) def __(mo): mo.md(r"""## Log Returns Correlation""") return @app.cell(hide_code=True) def __(closes, mo, np): # Calculate log returns and correlation matrix log_returns = np.log(closes / closes.shift(1)) correlation_matrix = log_returns.corr() # Identify the highest and lowest correlations highest_corr = correlation_matrix.unstack().sort_values(ascending=False).drop_duplicates().iloc[1] lowest_corr = correlation_matrix.unstack().sort_values().drop_duplicates().iloc[0] mo.md(f""" ### Highest Correlation\n\nThe highest correlation is between `{highest_corr}` and `{highest_corr}` with a value of **{highest_corr:.2f}**, indicating a strong positive relationship. This suggests that these two assets move similarly over the selected period.\n ### Lowest Correlation\n\nThe lowest correlation is between `{lowest_corr}` and `{lowest_corr}` with a value of **{lowest_corr:.2f}**, indicating a weak or almost no relationship. These assets may provide diversification benefits in a portfolio. ### Additional Insights - **High Positive Correlations**: Assets with high correlations tend to respond similarly to market events, which can be useful for **trend-following strategies**. - **Low or Negative Correlations**: Assets with low or negative correlations might help reduce overall portfolio risk, making them useful for **diversification**. - **Portfolio Strategy**: If you're seeking to **balance risk**, consider assets with lower correlations, while highly correlated assets can be beneficial for **momentum-based** portfolios. """) return correlation_matrix, highest_corr, log_returns, lowest_corr @app.cell def __(log_returns, plt, sns): plt.figure(figsize=(6, 5)) sns.heatmap(log_returns.corr(), cmap="YlGnBu", annot=True) plt.gca() return @app.cell def __(): return @app.cell def __(): return if __name__ == "__main__": app.run()