Spaces:
Runtime error
Runtime error
Add application
Browse files- .gitignore +5 -0
- Dockerfile +59 -0
- README.md +1 -0
- finance-app-tutorial/README.md +3 -0
- finance-app-tutorial/charts.py +117 -0
- finance-app-tutorial/daily_APPLE.csv +101 -0
- finance-app-tutorial/daily_IBM.csv +101 -0
- finance-app-tutorial/earnings-data.json +0 -0
- finance-app-tutorial/main.py +183 -0
- finance-app-tutorial/prompts.py +134 -0
- finance-app-tutorial/static/README.md +8 -0
- finance-app-tutorial/static/custom.css +12 -0
- finance-app-tutorial/static/favicon.png +0 -0
- finance-app-tutorial/stock_data.py +91 -0
- finance-app-tutorial/ui.json +749 -0
- pyproject.toml +15 -0
.gitignore
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
venv
|
| 2 |
+
__pycache__
|
| 3 |
+
.env
|
| 4 |
+
tmp*.pdf
|
| 5 |
+
.DS_Store
|
Dockerfile
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Build stage
|
| 2 |
+
FROM python:3.11-slim-buster AS Build
|
| 3 |
+
|
| 4 |
+
# Set environment variables for Python and Poetry
|
| 5 |
+
ENV PYTHONUNBUFFERED=1 \
|
| 6 |
+
PIP_NO_CACHE_DIR=1 \
|
| 7 |
+
POETRY_NO_INTERACTION=1 \
|
| 8 |
+
POETRY_VIRTUALENVS_CREATE=false \
|
| 9 |
+
POETRY_VERSION=1.7.1
|
| 10 |
+
|
| 11 |
+
# Set the working directory in the container
|
| 12 |
+
WORKDIR /app
|
| 13 |
+
|
| 14 |
+
# Copy the dependencies file to the working directory
|
| 15 |
+
COPY ./pyproject.toml /app/
|
| 16 |
+
|
| 17 |
+
# Update, install dependencies, and prepare the Python environment
|
| 18 |
+
RUN apt-get update && \
|
| 19 |
+
apt-get install -y gcc g++ unixodbc-dev && \
|
| 20 |
+
pip install "poetry==$POETRY_VERSION" && \
|
| 21 |
+
poetry export --without-hashes --format requirements.txt --output requirements.txt && \
|
| 22 |
+
python3 -m pip wheel --no-cache-dir --no-deps -w /app/wheels -r requirements.txt
|
| 23 |
+
|
| 24 |
+
# Runtime stage
|
| 25 |
+
FROM python:3.11-slim-buster AS Run
|
| 26 |
+
|
| 27 |
+
# Set environment variables for Python and Poetry
|
| 28 |
+
ENV HOME=/home/user \
|
| 29 |
+
PATH=/home/user/.local/bin:$PATH
|
| 30 |
+
|
| 31 |
+
# Create a non-root user
|
| 32 |
+
RUN useradd -m -u 1000 user
|
| 33 |
+
|
| 34 |
+
# Switch to the non-root user
|
| 35 |
+
USER user
|
| 36 |
+
|
| 37 |
+
# Copy wheel files from the build stage
|
| 38 |
+
COPY --from=build /app/wheels $HOME/app/wheels
|
| 39 |
+
|
| 40 |
+
# Set the working directory to where the wheels are
|
| 41 |
+
WORKDIR $HOME/app/wheels
|
| 42 |
+
|
| 43 |
+
# Install the wheel files
|
| 44 |
+
RUN pip3 --no-cache-dir install *.whl
|
| 45 |
+
|
| 46 |
+
# Copy the application files to the working directory (change to your app name)
|
| 47 |
+
COPY --chown=user ./finance-app-tutorial $HOME/app
|
| 48 |
+
|
| 49 |
+
# Set the working directory to the application files
|
| 50 |
+
WORKDIR $HOME/app
|
| 51 |
+
|
| 52 |
+
# Specify the command to run the application
|
| 53 |
+
ENTRYPOINT [ "writer", "run" ]
|
| 54 |
+
|
| 55 |
+
# Expose the port the app runs on
|
| 56 |
+
EXPOSE 8080
|
| 57 |
+
|
| 58 |
+
# Set the default command to run the app
|
| 59 |
+
CMD [ ".", "--port", "8080", "--host", "0.0.0.0" ]
|
README.md
CHANGED
|
@@ -5,6 +5,7 @@ colorFrom: green
|
|
| 5 |
colorTo: red
|
| 6 |
sdk: docker
|
| 7 |
pinned: false
|
|
|
|
| 8 |
---
|
| 9 |
|
| 10 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
|
| 5 |
colorTo: red
|
| 6 |
sdk: docker
|
| 7 |
pinned: false
|
| 8 |
+
app_port: 8080
|
| 9 |
---
|
| 10 |
|
| 11 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
finance-app-tutorial/README.md
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
This app was created using Writer Framework.
|
| 2 |
+
|
| 3 |
+
To learn more about it, visit https://dev.writer.com/framework
|
finance-app-tutorial/charts.py
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
import plotly.express as px
|
| 3 |
+
import plotly.graph_objects as go
|
| 4 |
+
from plotly.subplots import make_subplots
|
| 5 |
+
|
| 6 |
+
def handle_click(state, context: dict, ui):
|
| 7 |
+
# Resetting the classes for active button
|
| 8 |
+
if state["active_button"]:
|
| 9 |
+
active_button = ui.find(state["active_button"])
|
| 10 |
+
active_button.content["cssClasses"] = ""
|
| 11 |
+
|
| 12 |
+
event_target = context["target"]
|
| 13 |
+
button = ui.find(event_target)
|
| 14 |
+
|
| 15 |
+
# Storing the clicked button ID in state
|
| 16 |
+
state["active_button"] = event_target
|
| 17 |
+
|
| 18 |
+
button_text = button.content["text"]
|
| 19 |
+
_handle_time_period(state, button_text)
|
| 20 |
+
button.content["cssClasses"] = "button-click"
|
| 21 |
+
|
| 22 |
+
button_max = ui.find("e13teponreio9yyz")
|
| 23 |
+
button_max.content["cssClasses"] = ""
|
| 24 |
+
|
| 25 |
+
ui.component_tree.updated = True
|
| 26 |
+
|
| 27 |
+
def _handle_time_period(state, period):
|
| 28 |
+
state["main_df_subset"] = state["main_df"]
|
| 29 |
+
if period == "5D":
|
| 30 |
+
state["main_df_subset"] = state["main_df_subset"][:5]
|
| 31 |
+
elif period == "1M":
|
| 32 |
+
state["main_df_subset"] = state["main_df_subset"][:30]
|
| 33 |
+
elif period == "3M":
|
| 34 |
+
state["main_df_subset"] = state["main_df_subset"][:90]
|
| 35 |
+
elif period == "1Y":
|
| 36 |
+
state["main_df_subset"] = state["main_df_subset"][:360]
|
| 37 |
+
elif period == "5Y":
|
| 38 |
+
state["main_df_subset"] = state["main_df_subset"][:1800]
|
| 39 |
+
elif period == "Max":
|
| 40 |
+
# No need to slice, already has the full data
|
| 41 |
+
pass
|
| 42 |
+
update_scatter_chart(state)
|
| 43 |
+
|
| 44 |
+
def update_scatter_chart(state):
|
| 45 |
+
fig = px.line(state["main_df_subset"], x="Date", y="Open", height=400)
|
| 46 |
+
|
| 47 |
+
df1 = state["main_df_subset"]
|
| 48 |
+
df2 = state["another_df"]
|
| 49 |
+
df2 = df2.head(len(df1))
|
| 50 |
+
|
| 51 |
+
# Add a new column to each dataframe to identify the source
|
| 52 |
+
df1["Source"] = "Main_DF"
|
| 53 |
+
df2["Source"] = "Another_DF"
|
| 54 |
+
|
| 55 |
+
# Concatenate the dataframes
|
| 56 |
+
combined_df = pd.concat([df1, df2])
|
| 57 |
+
state["main_df_subset"] = combined_df
|
| 58 |
+
|
| 59 |
+
# Plot the lines
|
| 60 |
+
fig = make_subplots(specs=[[{"secondary_y": True}]])
|
| 61 |
+
|
| 62 |
+
# Add traces for the primary y-axis (Main_DF)
|
| 63 |
+
fig.add_trace(
|
| 64 |
+
go.Scatter(x=df1["Date"], y=df1["Open"], name=state["symbol"], mode='lines'),
|
| 65 |
+
secondary_y=False,
|
| 66 |
+
)
|
| 67 |
+
|
| 68 |
+
# Add traces for the secondary y-axis (Another_DF)
|
| 69 |
+
fig.add_trace(
|
| 70 |
+
go.Scatter(x=df2["Date"], y=df2["Open"], name="S&P 500", mode='lines'),
|
| 71 |
+
secondary_y=True,
|
| 72 |
+
)
|
| 73 |
+
|
| 74 |
+
# Set axis titles
|
| 75 |
+
fig.update_yaxes(title_text=f"{state["symbol"]} Stock Price", secondary_y=False)
|
| 76 |
+
fig.update_yaxes(title_text="S&P 500", secondary_y=True)
|
| 77 |
+
|
| 78 |
+
# Update layout
|
| 79 |
+
fig.update_layout(height=550, title_text=f"{state["symbol"]} Stock vs the S&P 500", title_x = 0.5, title_y = 0.9, legend=dict(
|
| 80 |
+
orientation='h',
|
| 81 |
+
yanchor='top',
|
| 82 |
+
y=-0.2, # Adjust this value as needed
|
| 83 |
+
xanchor='center',
|
| 84 |
+
x=0.5
|
| 85 |
+
))
|
| 86 |
+
|
| 87 |
+
state["scatter_chart"] = fig
|
| 88 |
+
|
| 89 |
+
def update_bar_graph(state):
|
| 90 |
+
fig = px.line(state["main_df_subset"], x="Date", y="Open", height=400)
|
| 91 |
+
|
| 92 |
+
df = state["income_statement_df"]
|
| 93 |
+
selected_metrics = ["Total Revenue", "Net Income", "Operating Income"]
|
| 94 |
+
df_filtered = df.loc[selected_metrics]
|
| 95 |
+
|
| 96 |
+
# Transpose the DataFrame for easier plotting
|
| 97 |
+
df_transposed = df_filtered.transpose().reset_index()
|
| 98 |
+
df_transposed = df_transposed.melt(
|
| 99 |
+
id_vars=["index"], var_name="Metric", value_name="Value"
|
| 100 |
+
)
|
| 101 |
+
|
| 102 |
+
# Create the bar graph using Plotly Express
|
| 103 |
+
fig = px.bar(
|
| 104 |
+
df_transposed,
|
| 105 |
+
x="index",
|
| 106 |
+
y="Value",
|
| 107 |
+
color="Metric",
|
| 108 |
+
barmode="group",
|
| 109 |
+
labels={"index": "", "Value": ""},
|
| 110 |
+
title="Summary of Quarterly Income Statement",
|
| 111 |
+
)
|
| 112 |
+
|
| 113 |
+
fig.update_layout(
|
| 114 |
+
legend=dict(orientation="h", yanchor="top", y=-0.2, xanchor="center", x=0.5)
|
| 115 |
+
)
|
| 116 |
+
|
| 117 |
+
state["bar_graph"] = fig
|
finance-app-tutorial/daily_APPLE.csv
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
timestamp,open,high,low,close,volume
|
| 2 |
+
2024-06-17,213.3700,218.9500,212.7200,216.6700,93728300
|
| 3 |
+
2024-06-14,213.8500,215.1700,211.3000,212.4900,70122748
|
| 4 |
+
2024-06-13,214.7400,216.7500,211.6000,214.2400,97862729
|
| 5 |
+
2024-06-12,207.3700,220.2000,206.9000,213.0700,198134293
|
| 6 |
+
2024-06-11,193.6500,207.1600,193.6300,207.1500,172373296
|
| 7 |
+
2024-06-10,196.9000,197.3000,192.1500,193.1200,97262077
|
| 8 |
+
2024-06-07,194.6500,196.9400,194.1400,196.8900,53103912
|
| 9 |
+
2024-06-06,195.6850,196.5000,194.1700,194.4800,41181753
|
| 10 |
+
2024-06-05,195.4000,196.9000,194.8700,195.8700,54156785
|
| 11 |
+
2024-06-04,194.6350,195.3200,193.0342,194.3500,47471445
|
| 12 |
+
2024-06-03,192.9000,194.9900,192.5200,194.0300,50080539
|
| 13 |
+
2024-05-31,191.4400,192.5700,189.9100,192.2500,75158277
|
| 14 |
+
2024-05-30,190.7600,192.1800,190.6300,191.2900,49947941
|
| 15 |
+
2024-05-29,189.6100,192.2470,189.5100,190.2900,53068016
|
| 16 |
+
2024-05-28,191.5100,193.0000,189.1000,189.9900,52280051
|
| 17 |
+
2024-05-24,188.8200,190.5800,188.0404,189.9800,36326975
|
| 18 |
+
2024-05-23,190.9800,191.0000,186.6250,186.8800,51005924
|
| 19 |
+
2024-05-22,192.2650,192.8231,190.2700,190.9000,34648547
|
| 20 |
+
2024-05-21,191.0900,192.7300,190.9201,192.3500,42309401
|
| 21 |
+
2024-05-20,189.3250,191.9199,189.0100,191.0400,44361275
|
| 22 |
+
2024-05-17,189.5100,190.8100,189.1800,189.8700,41282925
|
| 23 |
+
2024-05-16,190.4700,191.0950,189.6601,189.8400,52845230
|
| 24 |
+
2024-05-15,187.9100,190.6500,187.3700,189.7200,70399988
|
| 25 |
+
2024-05-14,187.5100,188.3000,186.2900,187.4300,52393619
|
| 26 |
+
2024-05-13,185.4350,187.1000,184.6200,186.2800,72044809
|
| 27 |
+
2024-05-10,184.9000,185.0900,182.1300,183.0500,50759496
|
| 28 |
+
2024-05-09,182.5600,184.6600,182.1100,184.5700,48982972
|
| 29 |
+
2024-05-08,182.8500,183.0700,181.4500,182.7400,45057087
|
| 30 |
+
2024-05-07,183.4500,184.9000,181.3200,182.4000,77305771
|
| 31 |
+
2024-05-06,182.3540,184.2000,180.4200,181.7100,78569667
|
| 32 |
+
2024-05-03,186.6450,187.0000,182.6600,183.3800,163224109
|
| 33 |
+
2024-05-02,172.5100,173.4150,170.8900,173.0300,94214915
|
| 34 |
+
2024-05-01,169.5800,172.7050,169.1100,169.3000,50383147
|
| 35 |
+
2024-04-30,173.3300,174.9900,170.0000,170.3300,65934776
|
| 36 |
+
2024-04-29,173.3700,176.0300,173.1000,173.5000,68169419
|
| 37 |
+
2024-04-26,169.8800,171.3400,169.1800,169.3000,44838354
|
| 38 |
+
2024-04-25,169.5250,170.6100,168.1511,169.8900,50558329
|
| 39 |
+
2024-04-24,166.5400,169.3000,166.2100,169.0200,48251835
|
| 40 |
+
2024-04-23,165.3500,167.0500,164.9200,166.9000,49537761
|
| 41 |
+
2024-04-22,165.5150,167.2600,164.7700,165.8400,48116443
|
| 42 |
+
2024-04-19,166.2100,166.4000,164.0750,165.0000,68149377
|
| 43 |
+
2024-04-18,168.0300,168.6400,166.5500,167.0400,43122903
|
| 44 |
+
2024-04-17,169.6100,170.6500,168.0000,168.0000,50901210
|
| 45 |
+
2024-04-16,171.7500,173.7600,168.2700,169.3800,73711235
|
| 46 |
+
2024-04-15,175.3600,176.6300,172.5000,172.6900,73531773
|
| 47 |
+
2024-04-12,174.2600,178.3600,174.2100,176.5500,101670886
|
| 48 |
+
2024-04-11,168.3400,175.4600,168.1600,175.0400,91070275
|
| 49 |
+
2024-04-10,168.8000,169.0900,167.1100,167.7800,49709336
|
| 50 |
+
2024-04-09,168.7000,170.0800,168.3500,169.6700,42231444
|
| 51 |
+
2024-04-08,169.0300,169.2000,168.2400,168.4500,37216858
|
| 52 |
+
2024-04-05,169.5900,170.3900,168.9500,169.5800,41975776
|
| 53 |
+
2024-04-04,170.2900,171.9200,168.8200,168.8200,53355055
|
| 54 |
+
2024-04-03,168.7900,170.6800,168.5800,169.6500,45571129
|
| 55 |
+
2024-04-02,169.0800,169.3400,168.2302,168.8400,49013991
|
| 56 |
+
2024-04-01,171.1900,171.2500,169.4750,170.0300,43772506
|
| 57 |
+
2024-03-28,171.7500,172.2300,170.5100,171.4800,65672690
|
| 58 |
+
2024-03-27,170.4100,173.6000,170.1100,173.3100,60273265
|
| 59 |
+
2024-03-26,170.0000,171.4200,169.5800,169.7100,57388449
|
| 60 |
+
2024-03-25,170.5650,171.9400,169.4500,170.8500,54288328
|
| 61 |
+
2024-03-22,171.7600,173.0500,170.0600,172.2800,71160138
|
| 62 |
+
2024-03-21,177.0500,177.4900,170.8400,171.3700,106181270
|
| 63 |
+
2024-03-20,175.7200,178.6700,175.0900,178.6700,53423102
|
| 64 |
+
2024-03-19,174.3400,176.6050,173.0300,176.0800,55215244
|
| 65 |
+
2024-03-18,175.5700,177.7100,173.5200,173.7200,75604184
|
| 66 |
+
2024-03-15,171.1700,172.6200,170.2850,172.6200,121752699
|
| 67 |
+
2024-03-14,172.9100,174.3078,172.0500,173.0000,72571635
|
| 68 |
+
2024-03-13,172.7700,173.1850,170.7600,171.1300,51948951
|
| 69 |
+
2024-03-12,173.1500,174.0300,171.0100,173.2300,59544927
|
| 70 |
+
2024-03-11,172.9400,174.3800,172.0500,172.7500,58929918
|
| 71 |
+
2024-03-08,169.0000,173.7000,168.9400,170.7300,76267041
|
| 72 |
+
2024-03-07,169.1500,170.7300,168.4900,169.0000,71765061
|
| 73 |
+
2024-03-06,171.0600,171.2400,168.6800,169.1200,68587707
|
| 74 |
+
2024-03-05,170.7600,172.0400,169.6200,170.1200,95132355
|
| 75 |
+
2024-03-04,176.1500,176.9000,173.7900,175.1000,81510101
|
| 76 |
+
2024-03-01,179.5500,180.5300,177.3800,179.6600,73563082
|
| 77 |
+
2024-02-29,181.2700,182.5700,179.5300,180.7500,136682597
|
| 78 |
+
2024-02-28,182.5100,183.1200,180.1300,181.4200,48953939
|
| 79 |
+
2024-02-27,181.1000,183.9225,179.5600,182.6300,54318851
|
| 80 |
+
2024-02-26,182.2400,182.7600,180.6500,181.1600,40867421
|
| 81 |
+
2024-02-23,185.0100,185.0400,182.2300,182.5200,45119677
|
| 82 |
+
2024-02-22,183.4800,184.9550,182.4600,184.3700,52292208
|
| 83 |
+
2024-02-21,181.9400,182.8888,180.6600,182.3200,41529674
|
| 84 |
+
2024-02-20,181.7900,182.4300,180.0000,181.5600,53665553
|
| 85 |
+
2024-02-16,183.4200,184.8500,181.6650,182.3100,49752465
|
| 86 |
+
2024-02-15,183.5500,184.4900,181.3500,183.8600,65434496
|
| 87 |
+
2024-02-14,185.3200,185.5300,182.4400,184.1500,54630517
|
| 88 |
+
2024-02-13,185.7700,186.2100,183.5128,185.0400,56529529
|
| 89 |
+
2024-02-12,188.4150,188.6700,186.7900,187.1500,41781934
|
| 90 |
+
2024-02-09,188.6500,189.9900,188.0000,188.8500,45155216
|
| 91 |
+
2024-02-08,189.3850,189.5350,187.3500,188.3200,40962046
|
| 92 |
+
2024-02-07,190.6400,191.0500,188.6100,189.4100,53438955
|
| 93 |
+
2024-02-06,186.8600,189.3100,186.7695,189.3000,43490759
|
| 94 |
+
2024-02-05,188.1500,189.2500,185.8400,187.6800,69668820
|
| 95 |
+
2024-02-02,179.8600,187.3300,179.2500,185.8500,102551680
|
| 96 |
+
2024-02-01,183.9850,186.9500,183.8200,186.8600,64885408
|
| 97 |
+
2024-01-31,187.0400,187.0950,184.3500,184.4000,55467803
|
| 98 |
+
2024-01-30,190.9400,191.8000,187.4700,188.0400,55859370
|
| 99 |
+
2024-01-29,192.0100,192.2000,189.5800,191.7300,47145622
|
| 100 |
+
2024-01-26,194.2700,194.7600,191.9400,192.4200,44594011
|
| 101 |
+
2024-01-25,195.2200,196.2675,193.1125,194.1700,54822126
|
finance-app-tutorial/daily_IBM.csv
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
timestamp,open,high,low,close,volume
|
| 2 |
+
2024-06-17,168.7600,169.7200,167.5000,169.5000,3239815
|
| 3 |
+
2024-06-14,168.2900,169.4700,167.2300,169.2100,2777717
|
| 4 |
+
2024-06-13,169.0100,169.5900,168.3350,169.1200,3525717
|
| 5 |
+
2024-06-12,171.3500,172.4700,168.1010,169.0000,3522698
|
| 6 |
+
2024-06-11,169.9800,170.0000,166.8100,169.3200,2951251
|
| 7 |
+
2024-06-10,169.5500,170.7600,168.8800,170.3800,3444684
|
| 8 |
+
2024-06-07,168.1800,171.3050,168.0600,170.0100,3475495
|
| 9 |
+
2024-06-06,167.3800,168.4400,166.8000,168.2000,2207263
|
| 10 |
+
2024-06-05,166.4100,167.7900,165.7800,167.3800,3049377
|
| 11 |
+
2024-06-04,164.6000,166.4000,163.8800,165.8100,2594203
|
| 12 |
+
2024-06-03,166.5400,166.7800,163.5300,165.2800,2776058
|
| 13 |
+
2024-05-31,165.7000,166.9700,163.8400,166.8500,4905002
|
| 14 |
+
2024-05-30,165.5600,166.7300,164.2300,165.6300,3852963
|
| 15 |
+
2024-05-29,168.0000,168.6300,166.2100,167.0500,4206576
|
| 16 |
+
2024-05-28,170.4400,171.0850,168.6500,169.6600,2629645
|
| 17 |
+
2024-05-24,171.4800,172.0100,170.2100,170.8900,2587829
|
| 18 |
+
2024-05-23,175.3900,175.4600,170.4350,170.6700,3341335
|
| 19 |
+
2024-05-22,173.3900,174.9900,172.7600,173.6900,3294900
|
| 20 |
+
2024-05-21,169.9400,174.9700,169.9400,173.4700,6459800
|
| 21 |
+
2024-05-20,169.0000,170.1600,168.3800,169.9200,2726261
|
| 22 |
+
2024-05-17,168.9700,169.1100,167.3300,169.0300,2956387
|
| 23 |
+
2024-05-16,168.2600,169.6300,167.7900,168.9700,3492267
|
| 24 |
+
2024-05-15,167.9400,168.3500,167.3400,168.2600,4468823
|
| 25 |
+
2024-05-14,167.8600,168.1300,166.4800,167.3600,2600967
|
| 26 |
+
2024-05-13,167.5000,168.0600,166.7600,167.5600,2414859
|
| 27 |
+
2024-05-10,167.1300,168.0700,166.3200,167.1500,2255370
|
| 28 |
+
2024-05-09,167.5000,167.5500,165.8800,166.2700,4266616
|
| 29 |
+
2024-05-08,168.0100,170.2600,167.9000,169.9000,3522011
|
| 30 |
+
2024-05-07,169.0000,169.2900,167.9400,168.3800,3155260
|
| 31 |
+
2024-05-06,166.5000,168.6700,166.3800,168.6100,4222266
|
| 32 |
+
2024-05-03,165.0000,166.6100,164.9200,165.7100,3400405
|
| 33 |
+
2024-05-02,164.3500,164.8800,162.6200,164.6900,3829853
|
| 34 |
+
2024-05-01,165.6900,166.2700,164.3000,164.4300,4030960
|
| 35 |
+
2024-04-30,166.4900,166.7600,165.2605,166.2000,6011634
|
| 36 |
+
2024-04-29,167.4000,168.2200,166.2250,167.4300,5263342
|
| 37 |
+
2024-04-26,167.5000,167.8700,165.7300,167.1300,8983796
|
| 38 |
+
2024-04-25,168.2000,172.4500,165.6600,168.9100,16702150
|
| 39 |
+
2024-04-24,183.1700,184.2900,181.4000,184.1000,7616643
|
| 40 |
+
2024-04-23,182.7300,184.6800,179.0000,182.1900,5950229
|
| 41 |
+
2024-04-22,182.4500,183.3150,180.4500,181.9000,3076451
|
| 42 |
+
2024-04-19,182.4300,182.8000,180.5700,181.5800,3037990
|
| 43 |
+
2024-04-18,182.3500,183.4600,180.1700,181.4700,2886733
|
| 44 |
+
2024-04-17,184.1600,184.6700,181.7800,183.1000,3003033
|
| 45 |
+
2024-04-16,185.5900,185.7100,182.8600,183.7500,4473654
|
| 46 |
+
2024-04-15,185.5700,187.4800,180.8800,181.2500,3528140
|
| 47 |
+
2024-04-12,184.0000,185.1699,181.6850,182.2700,3547378
|
| 48 |
+
2024-04-11,186.0400,186.7950,184.5800,185.9000,2861736
|
| 49 |
+
2024-04-10,187.4200,187.9150,185.5200,186.0400,3081915
|
| 50 |
+
2024-04-09,190.5400,191.2500,186.6600,189.3100,2790673
|
| 51 |
+
2024-04-08,189.2400,190.2400,188.9118,189.8200,2673611
|
| 52 |
+
2024-04-05,188.5900,190.3200,188.0200,189.1400,2012428
|
| 53 |
+
2024-04-04,192.0000,193.2800,187.3400,187.9400,2924438
|
| 54 |
+
2024-04-03,188.6000,191.3500,188.4850,190.9000,2818910
|
| 55 |
+
2024-04-02,189.1400,189.8000,187.6000,188.8800,2689711
|
| 56 |
+
2024-04-01,190.0000,190.4600,188.5200,189.8300,2362586
|
| 57 |
+
2024-03-28,190.9400,191.9299,190.3400,190.9600,3742169
|
| 58 |
+
2024-03-27,189.6000,190.9600,188.6000,190.8000,3693305
|
| 59 |
+
2024-03-26,189.0200,190.0000,188.5000,188.5000,4229535
|
| 60 |
+
2024-03-25,190.2600,190.8200,188.7500,188.7900,3718289
|
| 61 |
+
2024-03-22,192.0000,192.9850,190.5100,190.8400,3988398
|
| 62 |
+
2024-03-21,193.0000,193.3700,190.0100,191.9000,6013561
|
| 63 |
+
2024-03-20,192.8700,193.9800,191.3100,193.9600,3238643
|
| 64 |
+
2024-03-19,191.4900,193.5800,190.2800,193.3400,5317341
|
| 65 |
+
2024-03-18,191.7000,193.2300,190.3200,191.6900,5410562
|
| 66 |
+
2024-03-15,191.9900,193.0573,190.7000,191.0700,8828184
|
| 67 |
+
2024-03-14,196.9500,197.7480,192.1200,193.4300,4102202
|
| 68 |
+
2024-03-13,197.5500,198.1000,195.3200,196.7000,3960737
|
| 69 |
+
2024-03-12,192.4600,199.1800,192.1500,197.7800,5862512
|
| 70 |
+
2024-03-11,195.0900,195.3800,190.8800,191.7300,4712688
|
| 71 |
+
2024-03-08,196.0600,197.7700,194.3800,195.9500,3943113
|
| 72 |
+
2024-03-07,197.5800,198.7300,196.1400,196.5400,4604458
|
| 73 |
+
2024-03-06,193.5000,198.1300,192.9600,196.1600,6945818
|
| 74 |
+
2024-03-05,192.0000,193.9400,190.5700,191.9500,5653641
|
| 75 |
+
2024-03-04,187.7600,193.8980,187.6000,193.0600,7938266
|
| 76 |
+
2024-03-01,185.4900,188.3800,185.1800,188.2000,4018354
|
| 77 |
+
2024-02-29,186.1500,186.8495,184.6900,185.0300,6458487
|
| 78 |
+
2024-02-28,184.6300,185.3700,183.5500,185.3000,3216345
|
| 79 |
+
2024-02-27,184.1600,185.1300,182.6200,184.8700,3641378
|
| 80 |
+
2024-02-26,185.6000,186.1250,184.0600,184.1300,4620815
|
| 81 |
+
2024-02-23,184.9000,186.4550,184.5700,185.7200,3433800
|
| 82 |
+
2024-02-22,182.4500,184.5500,181.9300,184.2100,5078398
|
| 83 |
+
2024-02-21,182.5600,183.0300,178.7500,179.7000,4728473
|
| 84 |
+
2024-02-20,187.6400,188.7700,183.0600,183.4400,4247181
|
| 85 |
+
2024-02-16,186.6300,188.9500,185.9452,187.6400,4842840
|
| 86 |
+
2024-02-15,183.6200,186.9800,183.6200,186.8700,4714301
|
| 87 |
+
2024-02-14,185.0000,185.0000,182.2600,183.5700,3173391
|
| 88 |
+
2024-02-13,184.2800,184.7700,182.3600,183.7000,4290453
|
| 89 |
+
2024-02-12,185.9000,186.4800,184.0300,186.1600,4724021
|
| 90 |
+
2024-02-09,184.4400,187.1800,183.8500,186.3400,5064641
|
| 91 |
+
2024-02-08,182.6300,184.5500,181.4900,184.3600,5161185
|
| 92 |
+
2024-02-07,183.3400,184.0200,182.6250,183.7400,4841188
|
| 93 |
+
2024-02-06,183.5500,184.6800,183.0400,183.4100,3338196
|
| 94 |
+
2024-02-05,185.5100,185.7800,183.2550,183.4200,4379602
|
| 95 |
+
2024-02-02,187.1000,187.3900,185.6150,185.7900,4055411
|
| 96 |
+
2024-02-01,183.6300,187.5100,182.7100,186.9000,4669444
|
| 97 |
+
2024-01-31,187.0500,187.6500,183.1400,183.6600,8876055
|
| 98 |
+
2024-01-30,187.7100,188.6500,186.7700,187.8700,4575058
|
| 99 |
+
2024-01-29,187.4600,189.4600,186.0500,187.1400,6107908
|
| 100 |
+
2024-01-26,191.3100,192.3896,186.1600,187.4200,9895941
|
| 101 |
+
2024-01-25,184.9600,196.9000,184.8300,190.4300,29596239
|
finance-app-tutorial/earnings-data.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
finance-app-tutorial/main.py
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import writer as wf
|
| 2 |
+
import writer.ai
|
| 3 |
+
import pandas as pd
|
| 4 |
+
from prompts import stock_prompts, income_prompts, earnings_prompt
|
| 5 |
+
from stock_data import download_data, download_sp500, stock_news, _one_day_data, income_statement, earnings_calls
|
| 6 |
+
from charts import update_scatter_chart
|
| 7 |
+
from dotenv import load_dotenv
|
| 8 |
+
import os
|
| 9 |
+
|
| 10 |
+
load_dotenv()
|
| 11 |
+
|
| 12 |
+
writer.ai.init(os.getenv("WRITER_API_KEY"))
|
| 13 |
+
|
| 14 |
+
# Update all data
|
| 15 |
+
def updates(state):
|
| 16 |
+
state["message"] = "% Refreshing stock data..."
|
| 17 |
+
earnings_calls(state)
|
| 18 |
+
download_sp500(state)
|
| 19 |
+
stock_news(state)
|
| 20 |
+
download_data(state)
|
| 21 |
+
income_statement(state)
|
| 22 |
+
update_scatter_chart(state)
|
| 23 |
+
_one_day_data(state)
|
| 24 |
+
_refresh_window(state)
|
| 25 |
+
|
| 26 |
+
# Refresh the window
|
| 27 |
+
def _refresh_window(state):
|
| 28 |
+
state["show_income_metrics"]["visible"] = False
|
| 29 |
+
state["show_bar_graph"]["visible"] = False
|
| 30 |
+
state["show_analysis_text"]["visible"] = False
|
| 31 |
+
state["show_analysis_text"]["language"] = False
|
| 32 |
+
state["message"] = "Writer AI insights will be generated here"
|
| 33 |
+
|
| 34 |
+
# Summarize earnings call using Palmyra-Fin model
|
| 35 |
+
def summarize_earnings(state):
|
| 36 |
+
_refresh_window(state)
|
| 37 |
+
state["message"] = f"% {state["symbol"]} earnings call will be summarized here"
|
| 38 |
+
|
| 39 |
+
earnings_transcript = state["earnings_transcript"]
|
| 40 |
+
prompt = earnings_prompt.format(earnings_transcript=earnings_transcript)
|
| 41 |
+
submission = writer.ai.complete(prompt, config={"model": "palmyra-fin-32k", "temperature": 0.7, "max_tokens": 8192})
|
| 42 |
+
state["message"] = f"+ {state["symbol"]} earnings call summary"
|
| 43 |
+
state["analysis"] = submission.strip()
|
| 44 |
+
state["show_analysis_text"]["visible"] = True
|
| 45 |
+
|
| 46 |
+
def prompt_parameters_words(state,payload):
|
| 47 |
+
state["prompt_parameters_words"] = payload
|
| 48 |
+
_refresh_window(state)
|
| 49 |
+
|
| 50 |
+
def prompt_parameters_lang(state,payload):
|
| 51 |
+
state["prompt_parameters_lang"] = payload
|
| 52 |
+
generate_stock_analysis(state)
|
| 53 |
+
|
| 54 |
+
def generate_stock_analysis(state):
|
| 55 |
+
_refresh_window(state)
|
| 56 |
+
if(state["prompt_parameters_lang"] == ""):
|
| 57 |
+
state["prompt_parameters_lang"] == "English"
|
| 58 |
+
|
| 59 |
+
state["message"] = f"% {state["symbol"]} trends will be analyzed here in {state['prompt_parameters_lang']}"
|
| 60 |
+
stock_name = state["symbol"]
|
| 61 |
+
stock_data = state["main_df"][:365]
|
| 62 |
+
|
| 63 |
+
rounded_value = round(state["prompt_parameters_words"], 0)
|
| 64 |
+
language = state["prompt_parameters_lang"]
|
| 65 |
+
# Convert the rounded value to an integer
|
| 66 |
+
integer_value = int(rounded_value)
|
| 67 |
+
|
| 68 |
+
prompt = stock_prompts.format(language=language, stock_name=stock_name,words=integer_value,stock_data=stock_data)
|
| 69 |
+
submission = writer.ai.complete(prompt, config={"model": "palmyra-fin-32k", "temperature": 0.7, "max_tokens": 8192})
|
| 70 |
+
state["analysis"] = submission.strip()
|
| 71 |
+
state["message"] = f"+ {state["symbol"]} trends analyzed"
|
| 72 |
+
state["show_analysis_text"]["visible"] = True
|
| 73 |
+
state["show_analysis_text"]["language"] = True
|
| 74 |
+
|
| 75 |
+
return submission
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
def generate_income_analysis(state):
|
| 79 |
+
_refresh_window(state)
|
| 80 |
+
state["message"] = f"% {state["symbol"]} income statement will be visualized here"
|
| 81 |
+
stock_name = state["symbol"]
|
| 82 |
+
stock_data = state["main_df"][:365]
|
| 83 |
+
income_statement_data = state["income_statement_df"][:365]
|
| 84 |
+
prompt = income_prompts.format(
|
| 85 |
+
income_statement_data=income_statement_data,
|
| 86 |
+
stock_data=stock_data,
|
| 87 |
+
stock_name=stock_name,
|
| 88 |
+
)
|
| 89 |
+
submission = writer.ai.complete(prompt, config={"model": "palmyra-fin-32k", "temperature": 0.7, "max_tokens": 8192})
|
| 90 |
+
state["analysis"] = submission.strip()
|
| 91 |
+
state["message"] = f"+ {state["symbol"]} income statement visualized"
|
| 92 |
+
state["show_income_metrics"]["visible"] = True
|
| 93 |
+
state["show_analysis_text"]["visible"] = True
|
| 94 |
+
state["show_bar_graph"]["visible"] = True
|
| 95 |
+
return submission
|
| 96 |
+
|
| 97 |
+
def stock_tags(state, payload):
|
| 98 |
+
state["symbol"] = payload
|
| 99 |
+
updates(state)
|
| 100 |
+
|
| 101 |
+
def _get_main_df(filename):
|
| 102 |
+
main_df = pd.read_csv(filename)
|
| 103 |
+
return main_df
|
| 104 |
+
|
| 105 |
+
initial_state = wf.init_state(
|
| 106 |
+
{
|
| 107 |
+
"last_24_hours_open": "168.76",
|
| 108 |
+
"last_24_hours_high": "169.72",
|
| 109 |
+
"last_24_hours_low": "167.50",
|
| 110 |
+
"message": None,
|
| 111 |
+
"main_df": _get_main_df("daily_IBM.csv"),
|
| 112 |
+
"main_df_subset": _get_main_df("daily_IBM.csv"),
|
| 113 |
+
"symbol": "AAPL",
|
| 114 |
+
"articles": {
|
| 115 |
+
"EU seeks views on Microsoft, OpenAI, Google and Samsung deals, EU's Vestager says": {
|
| 116 |
+
"source": "Reuters",
|
| 117 |
+
"published_at": "June 28, 2024 at 15:40",
|
| 118 |
+
"url": "https://finance.yahoo.com/news/eu-seeks-views-microsoft-openai-144044802.html",
|
| 119 |
+
},
|
| 120 |
+
"Forget the S&P 500 -- Buy This Magnificent ETF Instead": {
|
| 121 |
+
"source": "Motley Fool",
|
| 122 |
+
"published_at": "June 28, 2024 at 15:00",
|
| 123 |
+
"url": "https://finance.yahoo.com/m/662fcc10-7b6c-3bd1-8b7f-6cc25e8a1e61/forget-the-s%26p-500-buy.html",
|
| 124 |
+
},
|
| 125 |
+
"Microsoft Corporation (MSFT) is Attracting Investor Attention: Here is What You Should Know": {
|
| 126 |
+
"source": "Zacks",
|
| 127 |
+
"published_at": "June 28, 2024 at 14:00",
|
| 128 |
+
"url": "https://finance.yahoo.com/news/microsoft-corporation-msft-attracting-investor-130015018.html",
|
| 129 |
+
},
|
| 130 |
+
},
|
| 131 |
+
"show_analysis_text": {
|
| 132 |
+
"visible": False,
|
| 133 |
+
"language": False
|
| 134 |
+
},
|
| 135 |
+
"show_income_metrics": {
|
| 136 |
+
"visible": False,
|
| 137 |
+
},
|
| 138 |
+
"tab_message": "- **Performance** tab highlights stock trends using an interactive graph where time filters can be selected.<br><li>**Stock data** tab shows the stock data from Yahoo Finance. <br><li>**Income data** tab shows the income statement from Yahoo Finance. <br><li>**View 10-K** tab shows the selected stock 10-K in a PDF viewer shown via an _API integration_.",
|
| 139 |
+
"prompt_parameters_lang": "English",
|
| 140 |
+
"prompt_parameters_words": 100,
|
| 141 |
+
"message": "Writer AI insights will be generated here",
|
| 142 |
+
"show_bar_graph": {"visible": False},
|
| 143 |
+
"output_language": {
|
| 144 |
+
"English": "English",
|
| 145 |
+
"Arabic": "Arabic",
|
| 146 |
+
"Bengali": "Bengali",
|
| 147 |
+
"Bulgarian": "Bulgarian",
|
| 148 |
+
"Chinese simplified": "Chinese simplified",
|
| 149 |
+
"Chinese traditional": "Chinese traditional",
|
| 150 |
+
"Croatian": "Croatian",
|
| 151 |
+
"Czech": "Czech",
|
| 152 |
+
"Danish": "Danish",
|
| 153 |
+
"Dutch": "Dutch",
|
| 154 |
+
"Finnish": "Finnish",
|
| 155 |
+
"French": "French",
|
| 156 |
+
"German": "German",
|
| 157 |
+
"Greek": "Greek",
|
| 158 |
+
"Hebrew": "Hebrew",
|
| 159 |
+
"Hindi": "Hindi",
|
| 160 |
+
"Hungarian": "Hungarian",
|
| 161 |
+
"Indonesian": "Indonesian",
|
| 162 |
+
"Italian": "Italian",
|
| 163 |
+
"Japanese": "Japanese",
|
| 164 |
+
"Korean": "Korean",
|
| 165 |
+
"Lithuanian": "Lithuanian",
|
| 166 |
+
"Polish": "Polish",
|
| 167 |
+
"Portuguese": "Portuguese",
|
| 168 |
+
"Romanian": "Romanian",
|
| 169 |
+
"Russian": "Russian",
|
| 170 |
+
"Spanish": "Spanish",
|
| 171 |
+
"Swahili": "Swahili",
|
| 172 |
+
"Swedish": "Swedish",
|
| 173 |
+
"Thai": "Thai",
|
| 174 |
+
"Turkish": "Turkish",
|
| 175 |
+
"Ukrainian": "Ukrainian",
|
| 176 |
+
"Vietnamese": "Vietnamese",
|
| 177 |
+
},
|
| 178 |
+
}
|
| 179 |
+
)
|
| 180 |
+
|
| 181 |
+
updates(initial_state)
|
| 182 |
+
|
| 183 |
+
initial_state.import_stylesheet("theme", "/static/custom.css?18")
|
finance-app-tutorial/prompts.py
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# BASE PROMPTS (TAILORED TO EACH COMPANY)
|
| 2 |
+
|
| 3 |
+
# base_prompts = {}
|
| 4 |
+
|
| 5 |
+
stock_prompts = """
|
| 6 |
+
|
| 7 |
+
Variables:
|
| 8 |
+
|
| 9 |
+
{language}, {stock_name}, {words}, {stock_data}
|
| 10 |
+
|
| 11 |
+
************************
|
| 12 |
+
|
| 13 |
+
Prompt:
|
| 14 |
+
You will be acting as a stock market analyst. When I provide the stock data in the specified format between the <stock_data> tags, your task is to carefully review the data and provide insights, trends, and financial analysis for the stock specified in the {stock_name} variable.
|
| 15 |
+
|
| 16 |
+
<stock_data>
|
| 17 |
+
{stock_data}
|
| 18 |
+
</stock_data>
|
| 19 |
+
|
| 20 |
+
Please analyze the stock data concisely in {words} words using paragraphs, considering the following steps:
|
| 21 |
+
|
| 22 |
+
1. Identify any notable trends in the stock's price, volume, or other key metrics over the given time period. Discuss potential reasons behind these trends.
|
| 23 |
+
|
| 24 |
+
2. Compare the stock's performance and financial metrics to industry averages and key competitors. Discuss how the stock stacks up against its peers.
|
| 25 |
+
|
| 26 |
+
3. Based on your analysis, provide an overall assessment of the stock's current position and future prospects. Consider factors such as growth potential, risk level, and market sentiment.
|
| 27 |
+
|
| 28 |
+
Before giving your final recommendation, please provide detailed reasoning and analysis to support your conclusions inside <reasoning> tags.
|
| 29 |
+
|
| 30 |
+
Finally, offer a clear recommendation inside <recommendation> tags on whether to buy, hold, or sell {stock_name}, taking into account both the stock's current valuation and its long-term potential.
|
| 31 |
+
|
| 32 |
+
Remember to base your analysis and recommendation solely on the provided stock data for
|
| 33 |
+
{stock_name}. If there is insufficient information to draw a conclusion, state this limitation in your response.
|
| 34 |
+
|
| 35 |
+
Output the analysis in {language}.
|
| 36 |
+
|
| 37 |
+
"""
|
| 38 |
+
|
| 39 |
+
income_prompts = """
|
| 40 |
+
|
| 41 |
+
Variables:
|
| 42 |
+
|
| 43 |
+
{income_statement_data}, {stock_name}
|
| 44 |
+
|
| 45 |
+
************************
|
| 46 |
+
|
| 47 |
+
Prompt:
|
| 48 |
+
You are a financial analyst tasked with analyzing the income statement of a
|
| 49 |
+
company. To assist in your analysis, you have been provided with the following data:
|
| 50 |
+
|
| 51 |
+
<stock_name>
|
| 52 |
+
{stock_name}
|
| 53 |
+
</stock_name>
|
| 54 |
+
|
| 55 |
+
<income_statement_data>
|
| 56 |
+
{income_statement_data}
|
| 57 |
+
</income_statement_data>
|
| 58 |
+
|
| 59 |
+
Using the provided data, please conduct an executive summary analysis in 100 words, using paragraphs, of the company's financial health and
|
| 60 |
+
future prospects. Your analysis should include:
|
| 61 |
+
|
| 62 |
+
<scratchpad>
|
| 63 |
+
- Analyze key financial metrics from the income statement, such as revenue growth, profit margins,
|
| 64 |
+
and expenses
|
| 65 |
+
- Assess the company's profitability and efficiency based on the income statement data
|
| 66 |
+
- Identify any potential risks or opportunities for the company based on the financial data
|
| 67 |
+
- Consider industry trends and market conditions that may impact the company's performance
|
| 68 |
+
</scratchpad>
|
| 69 |
+
|
| 70 |
+
After conducting your analysis, please provide your findings and conclusions in the following
|
| 71 |
+
format:
|
| 72 |
+
|
| 73 |
+
<analysis>
|
| 74 |
+
Income Statement Analysis:
|
| 75 |
+
- [Discuss the company's revenue growth and profitability based on the income statement data]
|
| 76 |
+
- [Identify any significant changes or trends in expenses or profit margins]
|
| 77 |
+
- [Assess the company's overall financial health and efficiency based on the income statement
|
| 78 |
+
metrics]
|
| 79 |
+
|
| 80 |
+
Risks and Opportunities:
|
| 81 |
+
- [Identify any potential risks or challenges the company may face based on the financial data]
|
| 82 |
+
- [Discuss any opportunities for growth or improvement based on the analysis]
|
| 83 |
+
|
| 84 |
+
Conclusion:
|
| 85 |
+
- [Provide a summary of your overall assessment of the company's financial performance and future
|
| 86 |
+
prospects]
|
| 87 |
+
- [Include any recommendations or insights for investors or stakeholders]
|
| 88 |
+
</analysis>
|
| 89 |
+
|
| 90 |
+
Please ensure that your analysis is clear, concise, and well-supported by the provided financial
|
| 91 |
+
data. Use specific examples and figures from the stock data and income statement to support your
|
| 92 |
+
conclusions.
|
| 93 |
+
|
| 94 |
+
"""
|
| 95 |
+
|
| 96 |
+
earnings_prompt = """
|
| 97 |
+
|
| 98 |
+
Variables:
|
| 99 |
+
|
| 100 |
+
{earnings_transcript}
|
| 101 |
+
|
| 102 |
+
************************
|
| 103 |
+
|
| 104 |
+
Prompt:
|
| 105 |
+
You are an expert at analyzing quarterly earnings reports. Please carefully review the following earnings call transcript:
|
| 106 |
+
|
| 107 |
+
<transcript>
|
| 108 |
+
{earnings_transcript}
|
| 109 |
+
</transcript>
|
| 110 |
+
|
| 111 |
+
After reading through the transcript, take some time to think through the key insights and takeaways
|
| 112 |
+
in a <scratchpad>. Consider the following aspects:
|
| 113 |
+
- Financial performance: How did the company perform financially this quarter? Were revenue,
|
| 114 |
+
profits, margins, etc. up or down compared to prior periods? Did they meet, exceed or fall short of
|
| 115 |
+
expectations?
|
| 116 |
+
- Future outlook: What is the company's outlook for upcoming quarters? Are they optimistic or
|
| 117 |
+
cautious? What are their projections for key metrics?
|
| 118 |
+
- Strategic initiatives: Did the company discuss any major strategic initiatives, partnerships, new
|
| 119 |
+
products, expansion plans or other projects? What is the rationale and potential impact?
|
| 120 |
+
- Significant changes: Were there any notable leadership changes, restructurings, pivots in strategy
|
| 121 |
+
or other significant developments disclosed?
|
| 122 |
+
</scratchpad>
|
| 123 |
+
|
| 124 |
+
Once you've thought through the main points, please provide a summary of the key insights from the
|
| 125 |
+
earnings call. The summary should concisely hit on the major takeaways around
|
| 126 |
+
financial performance, outlook, strategy and changes while including specific details that support
|
| 127 |
+
the main points. Aim for around 4-6 paragraphs.
|
| 128 |
+
|
| 129 |
+
Remember, your goal is to extract and communicate the most important information from the earnings
|
| 130 |
+
call in a clear, insightful executive summary. Focus on the high-level story and don't get too in
|
| 131 |
+
the weeds with minor details. Put yourself in the shoes of an analyst or investor and highlight what
|
| 132 |
+
you think they would care about most.
|
| 133 |
+
|
| 134 |
+
"""
|
finance-app-tutorial/static/README.md
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Serving static files
|
| 2 |
+
|
| 3 |
+
You can use this folder to store files which will be served statically in the "/static" route.
|
| 4 |
+
|
| 5 |
+
This is useful to store images and other files which will be served directly to the user of your application.
|
| 6 |
+
|
| 7 |
+
For example, if you store an image named "myimage.jpg" in this folder, it'll be accessible as "static/myimage.jpg".
|
| 8 |
+
You can use this relative route as the source in an Image component.
|
finance-app-tutorial/static/custom.css
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.link {
|
| 2 |
+
text-align: right !important;
|
| 3 |
+
}
|
| 4 |
+
|
| 5 |
+
.button-click {
|
| 6 |
+
background-color: #5551ff !important;
|
| 7 |
+
color: white !important;
|
| 8 |
+
}
|
| 9 |
+
|
| 10 |
+
.custom-iframe {
|
| 11 |
+
height: 700px !important;
|
| 12 |
+
}
|
finance-app-tutorial/static/favicon.png
ADDED
|
|
finance-app-tutorial/stock_data.py
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
from datetime import datetime
|
| 3 |
+
import yfinance as yf
|
| 4 |
+
from charts import update_bar_graph
|
| 5 |
+
from dotenv import load_dotenv
|
| 6 |
+
import json
|
| 7 |
+
|
| 8 |
+
load_dotenv()
|
| 9 |
+
|
| 10 |
+
# Download stock data and format into a DataFrame
|
| 11 |
+
def download_data(state):
|
| 12 |
+
df = yf.download(state["symbol"], period="max", interval="1d")
|
| 13 |
+
df = df.reset_index()
|
| 14 |
+
df = df.sort_values(by="Date", ascending=False)
|
| 15 |
+
df = df.round({"Open": 2, "High": 2, "Low": 2, "Close": 2, "Adj Close": 2})
|
| 16 |
+
df["Date"] = pd.to_datetime(df["Date"])
|
| 17 |
+
state["main_df_subset"] = df
|
| 18 |
+
state["main_df"] = state["main_df_subset"]
|
| 19 |
+
|
| 20 |
+
# Download S&P 500 data and format into a DataFrame
|
| 21 |
+
def download_sp500(state):
|
| 22 |
+
df = yf.download(tickers="^GSPC", period="max", interval="1d")
|
| 23 |
+
df = df.reset_index()
|
| 24 |
+
df = df.sort_values(by="Date", ascending=False)
|
| 25 |
+
df = df.round({"Open": 2, "High": 2, "Low": 2, "Close": 2, "Adj Close": 2})
|
| 26 |
+
df["Date"] = pd.to_datetime(df["Date"])
|
| 27 |
+
state["another_df"] = df
|
| 28 |
+
|
| 29 |
+
# Retrieve latest stock news
|
| 30 |
+
def stock_news(state):
|
| 31 |
+
msft = yf.Ticker(state["symbol"])
|
| 32 |
+
articles = {}
|
| 33 |
+
data = msft.news
|
| 34 |
+
latest_articles = sorted(
|
| 35 |
+
data, key=lambda x: x["providerPublishTime"], reverse=True
|
| 36 |
+
)[:4]
|
| 37 |
+
|
| 38 |
+
for item in latest_articles:
|
| 39 |
+
provider_publish_time = item.get("providerPublishTime", "")
|
| 40 |
+
if provider_publish_time:
|
| 41 |
+
# Convert the timestamp to a readable date
|
| 42 |
+
formatted_date = datetime.fromtimestamp(provider_publish_time)
|
| 43 |
+
readable_date = formatted_date.strftime("%B %d, %Y at %H:%M")
|
| 44 |
+
else:
|
| 45 |
+
readable_date = "Date not available"
|
| 46 |
+
|
| 47 |
+
title = item.get("title", "No Title")
|
| 48 |
+
articles[title] = {
|
| 49 |
+
"source": item.get("publisher", ""),
|
| 50 |
+
"published_at": readable_date,
|
| 51 |
+
"url": item.get("link", ""),
|
| 52 |
+
}
|
| 53 |
+
state["articles"] = articles
|
| 54 |
+
|
| 55 |
+
# Retrieve income statement data
|
| 56 |
+
def income_statement(state):
|
| 57 |
+
quarterly_income_stmt = yf.Ticker(state["symbol"]).quarterly_income_stmt
|
| 58 |
+
df = pd.DataFrame(quarterly_income_stmt)
|
| 59 |
+
df.columns = pd.to_datetime(df.columns).strftime("%Y-%m-%d")
|
| 60 |
+
state["income_statement_df"] = df
|
| 61 |
+
update_bar_graph(state)
|
| 62 |
+
show_fin_metrics(state)
|
| 63 |
+
|
| 64 |
+
# Show financial metrics
|
| 65 |
+
def show_fin_metrics(state):
|
| 66 |
+
stock = yf.Ticker(state["symbol"])
|
| 67 |
+
operating_margins = stock.info['operatingMargins']
|
| 68 |
+
gross_margin = stock.info['grossMargins']
|
| 69 |
+
ebitda_margin = stock.info['ebitdaMargins']
|
| 70 |
+
|
| 71 |
+
state["operating_margin"] = f"{operating_margins * 100:.2f}%"
|
| 72 |
+
state["gross_margin"] = f"{gross_margin * 100:.2f}%"
|
| 73 |
+
state["ebitda_margin"] = f"{ebitda_margin * 100:.2f}%"
|
| 74 |
+
|
| 75 |
+
def _one_day_data(state):
|
| 76 |
+
state["last_24_hours_open"] = round(state["main_df"]["Open"].iloc[0], 2)
|
| 77 |
+
state["last_24_hours_high"] = round(state["main_df"]["High"].iloc[0], 2)
|
| 78 |
+
state["last_24_hours_low"] = round(state["main_df"]["Low"].iloc[0], 2)
|
| 79 |
+
|
| 80 |
+
# Retrieve earnings call transcript from JSON file
|
| 81 |
+
# You could replace this with a call to an API like Financial Modeling Prep
|
| 82 |
+
def earnings_calls(state):
|
| 83 |
+
ticker = state["symbol"]
|
| 84 |
+
with open('earnings-data.json', 'r') as file:
|
| 85 |
+
earnings_transcript = json.load(file)
|
| 86 |
+
if earnings_transcript:
|
| 87 |
+
for item in earnings_transcript:
|
| 88 |
+
if item['symbol'] == ticker:
|
| 89 |
+
state["earnings_transcript"] = item["content"]
|
| 90 |
+
else:
|
| 91 |
+
print("No earnings transcript found.")
|
finance-app-tutorial/ui.json
ADDED
|
@@ -0,0 +1,749 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"metadata": {
|
| 3 |
+
"writer_version": "0.7.0rc2"
|
| 4 |
+
},
|
| 5 |
+
"components": {
|
| 6 |
+
"root": {
|
| 7 |
+
"id": "root",
|
| 8 |
+
"type": "root",
|
| 9 |
+
"content": {
|
| 10 |
+
"appName": "Finance Dashboard"
|
| 11 |
+
},
|
| 12 |
+
"isCodeManaged": false,
|
| 13 |
+
"position": 0,
|
| 14 |
+
"handlers": {},
|
| 15 |
+
"visible": true
|
| 16 |
+
},
|
| 17 |
+
"c0f99a9e-5004-4e75-a6c6-36f17490b134": {
|
| 18 |
+
"id": "c0f99a9e-5004-4e75-a6c6-36f17490b134",
|
| 19 |
+
"type": "page",
|
| 20 |
+
"content": {
|
| 21 |
+
"pageMode": ""
|
| 22 |
+
},
|
| 23 |
+
"isCodeManaged": false,
|
| 24 |
+
"position": 0,
|
| 25 |
+
"parentId": "root",
|
| 26 |
+
"handlers": {},
|
| 27 |
+
"visible": true
|
| 28 |
+
},
|
| 29 |
+
"bebc5fe9-63a7-46a7-b0fa-62303555cfaf": {
|
| 30 |
+
"id": "bebc5fe9-63a7-46a7-b0fa-62303555cfaf",
|
| 31 |
+
"type": "header",
|
| 32 |
+
"content": {
|
| 33 |
+
"text": "Finance Research Dashboard"
|
| 34 |
+
},
|
| 35 |
+
"isCodeManaged": false,
|
| 36 |
+
"position": 0,
|
| 37 |
+
"parentId": "c0f99a9e-5004-4e75-a6c6-36f17490b134",
|
| 38 |
+
"handlers": {},
|
| 39 |
+
"visible": true
|
| 40 |
+
},
|
| 41 |
+
"ahwykl4cny005thy": {
|
| 42 |
+
"id": "ahwykl4cny005thy",
|
| 43 |
+
"type": "dataframe",
|
| 44 |
+
"content": {
|
| 45 |
+
"dataframe": "@{main_df_subset}",
|
| 46 |
+
"showIndex": "no",
|
| 47 |
+
"enableSearch": "no"
|
| 48 |
+
},
|
| 49 |
+
"isCodeManaged": false,
|
| 50 |
+
"position": 0,
|
| 51 |
+
"parentId": "vyij4ox2ad95xyr9",
|
| 52 |
+
"handlers": {},
|
| 53 |
+
"visible": true
|
| 54 |
+
},
|
| 55 |
+
"opn16nq04zq9xha8": {
|
| 56 |
+
"id": "opn16nq04zq9xha8",
|
| 57 |
+
"type": "plotlygraph",
|
| 58 |
+
"content": {
|
| 59 |
+
"spec": "@{scatter_chart}"
|
| 60 |
+
},
|
| 61 |
+
"isCodeManaged": false,
|
| 62 |
+
"position": 2,
|
| 63 |
+
"parentId": "1db76a00z7imlyz1",
|
| 64 |
+
"handlers": {
|
| 65 |
+
"plotly-click": "charts.update_scatter_chart"
|
| 66 |
+
}
|
| 67 |
+
},
|
| 68 |
+
"e13teponreio9yyz": {
|
| 69 |
+
"id": "e13teponreio9yyz",
|
| 70 |
+
"type": "button",
|
| 71 |
+
"content": {
|
| 72 |
+
"text": "Max",
|
| 73 |
+
"buttonColor": "#BFCBFF",
|
| 74 |
+
"cssClasses": "",
|
| 75 |
+
"buttonTextColor": "#000000"
|
| 76 |
+
},
|
| 77 |
+
"isCodeManaged": false,
|
| 78 |
+
"position": 0,
|
| 79 |
+
"parentId": "g5mgb80xt38atz4f",
|
| 80 |
+
"handlers": {
|
| 81 |
+
"wf-click": "charts.handle_click"
|
| 82 |
+
},
|
| 83 |
+
"visible": true
|
| 84 |
+
},
|
| 85 |
+
"g5mgb80xt38atz4f": {
|
| 86 |
+
"id": "g5mgb80xt38atz4f",
|
| 87 |
+
"type": "horizontalstack",
|
| 88 |
+
"content": {},
|
| 89 |
+
"isCodeManaged": false,
|
| 90 |
+
"position": 1,
|
| 91 |
+
"parentId": "1db76a00z7imlyz1",
|
| 92 |
+
"handlers": {},
|
| 93 |
+
"visible": true
|
| 94 |
+
},
|
| 95 |
+
"juip2rw7hywumv35": {
|
| 96 |
+
"id": "juip2rw7hywumv35",
|
| 97 |
+
"type": "button",
|
| 98 |
+
"content": {
|
| 99 |
+
"text": "5D",
|
| 100 |
+
"buttonColor": "#BFCBFF",
|
| 101 |
+
"cssClasses": "",
|
| 102 |
+
"buttonTextColor": "#000000"
|
| 103 |
+
},
|
| 104 |
+
"isCodeManaged": false,
|
| 105 |
+
"position": 1,
|
| 106 |
+
"parentId": "g5mgb80xt38atz4f",
|
| 107 |
+
"handlers": {
|
| 108 |
+
"wf-click": "charts.handle_click"
|
| 109 |
+
},
|
| 110 |
+
"visible": true
|
| 111 |
+
},
|
| 112 |
+
"afamuurw1lpjkkze": {
|
| 113 |
+
"id": "afamuurw1lpjkkze",
|
| 114 |
+
"type": "button",
|
| 115 |
+
"content": {
|
| 116 |
+
"text": "1M",
|
| 117 |
+
"buttonColor": "#BFCBFF",
|
| 118 |
+
"cssClasses": "",
|
| 119 |
+
"buttonTextColor": "#000000"
|
| 120 |
+
},
|
| 121 |
+
"isCodeManaged": false,
|
| 122 |
+
"position": 2,
|
| 123 |
+
"parentId": "g5mgb80xt38atz4f",
|
| 124 |
+
"handlers": {
|
| 125 |
+
"wf-click": "charts.handle_click"
|
| 126 |
+
},
|
| 127 |
+
"visible": true
|
| 128 |
+
},
|
| 129 |
+
"77u7x4pf0ximsf0j": {
|
| 130 |
+
"id": "77u7x4pf0ximsf0j",
|
| 131 |
+
"type": "button",
|
| 132 |
+
"content": {
|
| 133 |
+
"text": "3M",
|
| 134 |
+
"buttonColor": "#BFCBFF",
|
| 135 |
+
"cssClasses": "",
|
| 136 |
+
"buttonTextColor": "#000000"
|
| 137 |
+
},
|
| 138 |
+
"isCodeManaged": false,
|
| 139 |
+
"position": 3,
|
| 140 |
+
"parentId": "g5mgb80xt38atz4f",
|
| 141 |
+
"handlers": {
|
| 142 |
+
"wf-click": "charts.handle_click"
|
| 143 |
+
},
|
| 144 |
+
"visible": true
|
| 145 |
+
},
|
| 146 |
+
"oh2g51ixvuu8gdwa": {
|
| 147 |
+
"id": "oh2g51ixvuu8gdwa",
|
| 148 |
+
"type": "metric",
|
| 149 |
+
"content": {
|
| 150 |
+
"name": "Open",
|
| 151 |
+
"note": "L24",
|
| 152 |
+
"description": "",
|
| 153 |
+
"metricValue": "@{last_24_hours_open}"
|
| 154 |
+
},
|
| 155 |
+
"isCodeManaged": false,
|
| 156 |
+
"position": 0,
|
| 157 |
+
"parentId": "rgv1dgdrvgiosh42",
|
| 158 |
+
"handlers": {},
|
| 159 |
+
"visible": true
|
| 160 |
+
},
|
| 161 |
+
"rgv1dgdrvgiosh42": {
|
| 162 |
+
"id": "rgv1dgdrvgiosh42",
|
| 163 |
+
"type": "horizontalstack",
|
| 164 |
+
"content": {},
|
| 165 |
+
"isCodeManaged": false,
|
| 166 |
+
"position": 0,
|
| 167 |
+
"parentId": "1db76a00z7imlyz1",
|
| 168 |
+
"handlers": {},
|
| 169 |
+
"visible": true
|
| 170 |
+
},
|
| 171 |
+
"6646510g33an9r0g": {
|
| 172 |
+
"id": "6646510g33an9r0g",
|
| 173 |
+
"type": "metric",
|
| 174 |
+
"content": {
|
| 175 |
+
"note": "L24",
|
| 176 |
+
"name": "High",
|
| 177 |
+
"description": "",
|
| 178 |
+
"metricValue": "@{last_24_hours_high}"
|
| 179 |
+
},
|
| 180 |
+
"isCodeManaged": false,
|
| 181 |
+
"position": 2,
|
| 182 |
+
"parentId": "rgv1dgdrvgiosh42",
|
| 183 |
+
"handlers": {},
|
| 184 |
+
"visible": true
|
| 185 |
+
},
|
| 186 |
+
"df3mr8my8ivc8yrt": {
|
| 187 |
+
"id": "df3mr8my8ivc8yrt",
|
| 188 |
+
"type": "metric",
|
| 189 |
+
"content": {
|
| 190 |
+
"note": "L24",
|
| 191 |
+
"name": "Low",
|
| 192 |
+
"description": "",
|
| 193 |
+
"metricValue": "@{last_24_hours_low}"
|
| 194 |
+
},
|
| 195 |
+
"isCodeManaged": false,
|
| 196 |
+
"position": 4,
|
| 197 |
+
"parentId": "rgv1dgdrvgiosh42",
|
| 198 |
+
"handlers": {},
|
| 199 |
+
"visible": true
|
| 200 |
+
},
|
| 201 |
+
"9v92jyh672s5wjkg": {
|
| 202 |
+
"id": "9v92jyh672s5wjkg",
|
| 203 |
+
"type": "tab",
|
| 204 |
+
"content": {
|
| 205 |
+
"name": "Stock data"
|
| 206 |
+
},
|
| 207 |
+
"isCodeManaged": false,
|
| 208 |
+
"position": 1,
|
| 209 |
+
"parentId": "yzujnjalyh2s2x16",
|
| 210 |
+
"handlers": {},
|
| 211 |
+
"visible": true
|
| 212 |
+
},
|
| 213 |
+
"bha2uz0y2jr7eszp": {
|
| 214 |
+
"id": "bha2uz0y2jr7eszp",
|
| 215 |
+
"type": "separator",
|
| 216 |
+
"content": {},
|
| 217 |
+
"isCodeManaged": false,
|
| 218 |
+
"position": 1,
|
| 219 |
+
"parentId": "rgv1dgdrvgiosh42",
|
| 220 |
+
"handlers": {},
|
| 221 |
+
"visible": true
|
| 222 |
+
},
|
| 223 |
+
"nzp2whzndpknrk55": {
|
| 224 |
+
"id": "nzp2whzndpknrk55",
|
| 225 |
+
"type": "separator",
|
| 226 |
+
"content": {},
|
| 227 |
+
"isCodeManaged": false,
|
| 228 |
+
"position": 3,
|
| 229 |
+
"parentId": "rgv1dgdrvgiosh42",
|
| 230 |
+
"handlers": {},
|
| 231 |
+
"visible": true
|
| 232 |
+
},
|
| 233 |
+
"suu5ceib1bqj0si5": {
|
| 234 |
+
"id": "suu5ceib1bqj0si5",
|
| 235 |
+
"type": "columns",
|
| 236 |
+
"content": {},
|
| 237 |
+
"isCodeManaged": false,
|
| 238 |
+
"position": 0,
|
| 239 |
+
"parentId": "9v92jyh672s5wjkg",
|
| 240 |
+
"handlers": {},
|
| 241 |
+
"visible": true
|
| 242 |
+
},
|
| 243 |
+
"vyij4ox2ad95xyr9": {
|
| 244 |
+
"id": "vyij4ox2ad95xyr9",
|
| 245 |
+
"type": "column",
|
| 246 |
+
"content": {
|
| 247 |
+
"width": "1"
|
| 248 |
+
},
|
| 249 |
+
"isCodeManaged": false,
|
| 250 |
+
"position": 0,
|
| 251 |
+
"parentId": "suu5ceib1bqj0si5",
|
| 252 |
+
"handlers": {},
|
| 253 |
+
"visible": true
|
| 254 |
+
},
|
| 255 |
+
"chwivjdj78wyyi9x": {
|
| 256 |
+
"id": "chwivjdj78wyyi9x",
|
| 257 |
+
"type": "button",
|
| 258 |
+
"content": {
|
| 259 |
+
"text": "Analyze trends"
|
| 260 |
+
},
|
| 261 |
+
"isCodeManaged": false,
|
| 262 |
+
"position": 0,
|
| 263 |
+
"parentId": "1yuilwwrhm40gxtx",
|
| 264 |
+
"handlers": {
|
| 265 |
+
"wf-click": "generate_stock_analysis"
|
| 266 |
+
},
|
| 267 |
+
"visible": true
|
| 268 |
+
},
|
| 269 |
+
"km4vvfnq6bwlakmp": {
|
| 270 |
+
"id": "km4vvfnq6bwlakmp",
|
| 271 |
+
"type": "text",
|
| 272 |
+
"content": {
|
| 273 |
+
"text": "@{analysis}",
|
| 274 |
+
"useMarkdown": "yes"
|
| 275 |
+
},
|
| 276 |
+
"isCodeManaged": false,
|
| 277 |
+
"position": 4,
|
| 278 |
+
"parentId": "i23vdas64ziuiazm",
|
| 279 |
+
"handlers": {},
|
| 280 |
+
"visible": "show_analysis_text.visible"
|
| 281 |
+
},
|
| 282 |
+
"h72djsz1oqncb5ls": {
|
| 283 |
+
"id": "h72djsz1oqncb5ls",
|
| 284 |
+
"type": "section",
|
| 285 |
+
"content": {
|
| 286 |
+
"title": "Latest news"
|
| 287 |
+
},
|
| 288 |
+
"isCodeManaged": false,
|
| 289 |
+
"position": 1,
|
| 290 |
+
"parentId": "0p1levffmcf4xlpl",
|
| 291 |
+
"handlers": {},
|
| 292 |
+
"visible": true
|
| 293 |
+
},
|
| 294 |
+
"zinu9f9cyur23m66": {
|
| 295 |
+
"id": "zinu9f9cyur23m66",
|
| 296 |
+
"type": "repeater",
|
| 297 |
+
"content": {
|
| 298 |
+
"repeaterObject": "@{articles}",
|
| 299 |
+
"keyVariable": "itemId",
|
| 300 |
+
"valueVariable": "item"
|
| 301 |
+
},
|
| 302 |
+
"isCodeManaged": false,
|
| 303 |
+
"position": 0,
|
| 304 |
+
"parentId": "h72djsz1oqncb5ls",
|
| 305 |
+
"handlers": {},
|
| 306 |
+
"visible": true
|
| 307 |
+
},
|
| 308 |
+
"dbdmqg2z74k4frq4": {
|
| 309 |
+
"id": "dbdmqg2z74k4frq4",
|
| 310 |
+
"type": "columns",
|
| 311 |
+
"content": {
|
| 312 |
+
"cssClasses": ""
|
| 313 |
+
},
|
| 314 |
+
"isCodeManaged": false,
|
| 315 |
+
"position": 0,
|
| 316 |
+
"parentId": "zinu9f9cyur23m66",
|
| 317 |
+
"handlers": {},
|
| 318 |
+
"visible": true
|
| 319 |
+
},
|
| 320 |
+
"p13mw4f6rr4z8d47": {
|
| 321 |
+
"id": "p13mw4f6rr4z8d47",
|
| 322 |
+
"type": "column",
|
| 323 |
+
"content": {
|
| 324 |
+
"title": "",
|
| 325 |
+
"width": "1",
|
| 326 |
+
"isSticky": "yes",
|
| 327 |
+
"isCollapsible": "",
|
| 328 |
+
"startCollapsed": "",
|
| 329 |
+
"cssClasses": ""
|
| 330 |
+
},
|
| 331 |
+
"isCodeManaged": false,
|
| 332 |
+
"position": 0,
|
| 333 |
+
"parentId": "dbdmqg2z74k4frq4",
|
| 334 |
+
"handlers": {},
|
| 335 |
+
"visible": true
|
| 336 |
+
},
|
| 337 |
+
"tji08jpu1y52kzz1": {
|
| 338 |
+
"id": "tji08jpu1y52kzz1",
|
| 339 |
+
"type": "link",
|
| 340 |
+
"content": {
|
| 341 |
+
"url": "@{item.url}",
|
| 342 |
+
"text": "@{item.source}",
|
| 343 |
+
"primaryTextColor": "#1d53d3",
|
| 344 |
+
"cssClasses": "link"
|
| 345 |
+
},
|
| 346 |
+
"isCodeManaged": false,
|
| 347 |
+
"position": 1,
|
| 348 |
+
"parentId": "4avlmncllyffxniu",
|
| 349 |
+
"handlers": {},
|
| 350 |
+
"visible": true
|
| 351 |
+
},
|
| 352 |
+
"4avlmncllyffxniu": {
|
| 353 |
+
"id": "4avlmncllyffxniu",
|
| 354 |
+
"type": "section",
|
| 355 |
+
"content": {
|
| 356 |
+
"title": "@{itemId}",
|
| 357 |
+
"primaryTextColor": "#000000",
|
| 358 |
+
"containerBackgroundColor": "#f7f7f7",
|
| 359 |
+
"containerShadow": "5px 5px 5px 2px #f8f7f7"
|
| 360 |
+
},
|
| 361 |
+
"isCodeManaged": false,
|
| 362 |
+
"position": 0,
|
| 363 |
+
"parentId": "p13mw4f6rr4z8d47",
|
| 364 |
+
"handlers": {},
|
| 365 |
+
"visible": true
|
| 366 |
+
},
|
| 367 |
+
"w3wt3976ggvcuwrg": {
|
| 368 |
+
"id": "w3wt3976ggvcuwrg",
|
| 369 |
+
"type": "text",
|
| 370 |
+
"content": {
|
| 371 |
+
"text": "**@{item.published_at}**",
|
| 372 |
+
"alignment": "right",
|
| 373 |
+
"useMarkdown": "yes"
|
| 374 |
+
},
|
| 375 |
+
"isCodeManaged": false,
|
| 376 |
+
"position": 0,
|
| 377 |
+
"parentId": "4avlmncllyffxniu",
|
| 378 |
+
"handlers": {},
|
| 379 |
+
"visible": true
|
| 380 |
+
},
|
| 381 |
+
"1db76a00z7imlyz1": {
|
| 382 |
+
"id": "1db76a00z7imlyz1",
|
| 383 |
+
"type": "section",
|
| 384 |
+
"content": {
|
| 385 |
+
"title": "@{symbol} stock performance"
|
| 386 |
+
},
|
| 387 |
+
"isCodeManaged": false,
|
| 388 |
+
"position": 1,
|
| 389 |
+
"parentId": "18wepug77yr8m1iu",
|
| 390 |
+
"handlers": {},
|
| 391 |
+
"visible": true
|
| 392 |
+
},
|
| 393 |
+
"i23vdas64ziuiazm": {
|
| 394 |
+
"id": "i23vdas64ziuiazm",
|
| 395 |
+
"type": "section",
|
| 396 |
+
"content": {
|
| 397 |
+
"title": ""
|
| 398 |
+
},
|
| 399 |
+
"isCodeManaged": false,
|
| 400 |
+
"position": 0,
|
| 401 |
+
"parentId": "0p1levffmcf4xlpl",
|
| 402 |
+
"handlers": {},
|
| 403 |
+
"visible": true
|
| 404 |
+
},
|
| 405 |
+
"8dbcbgiukyg74dkb": {
|
| 406 |
+
"id": "8dbcbgiukyg74dkb",
|
| 407 |
+
"type": "columns",
|
| 408 |
+
"content": {},
|
| 409 |
+
"isCodeManaged": false,
|
| 410 |
+
"position": 3,
|
| 411 |
+
"parentId": "c0f99a9e-5004-4e75-a6c6-36f17490b134",
|
| 412 |
+
"handlers": {},
|
| 413 |
+
"visible": true
|
| 414 |
+
},
|
| 415 |
+
"0p1levffmcf4xlpl": {
|
| 416 |
+
"id": "0p1levffmcf4xlpl",
|
| 417 |
+
"type": "column",
|
| 418 |
+
"content": {
|
| 419 |
+
"width": "0.75"
|
| 420 |
+
},
|
| 421 |
+
"isCodeManaged": false,
|
| 422 |
+
"position": 0,
|
| 423 |
+
"parentId": "8dbcbgiukyg74dkb",
|
| 424 |
+
"handlers": {},
|
| 425 |
+
"visible": true
|
| 426 |
+
},
|
| 427 |
+
"334d69p14onyi9wq": {
|
| 428 |
+
"id": "334d69p14onyi9wq",
|
| 429 |
+
"type": "column",
|
| 430 |
+
"content": {
|
| 431 |
+
"width": "1"
|
| 432 |
+
},
|
| 433 |
+
"isCodeManaged": false,
|
| 434 |
+
"position": 1,
|
| 435 |
+
"parentId": "8dbcbgiukyg74dkb",
|
| 436 |
+
"handlers": {},
|
| 437 |
+
"visible": true
|
| 438 |
+
},
|
| 439 |
+
"yzujnjalyh2s2x16": {
|
| 440 |
+
"id": "yzujnjalyh2s2x16",
|
| 441 |
+
"type": "tabs",
|
| 442 |
+
"content": {},
|
| 443 |
+
"isCodeManaged": false,
|
| 444 |
+
"position": 0,
|
| 445 |
+
"parentId": "334d69p14onyi9wq",
|
| 446 |
+
"handlers": {},
|
| 447 |
+
"visible": true
|
| 448 |
+
},
|
| 449 |
+
"18wepug77yr8m1iu": {
|
| 450 |
+
"id": "18wepug77yr8m1iu",
|
| 451 |
+
"type": "tab",
|
| 452 |
+
"content": {
|
| 453 |
+
"name": "Performance"
|
| 454 |
+
},
|
| 455 |
+
"isCodeManaged": false,
|
| 456 |
+
"position": 0,
|
| 457 |
+
"parentId": "yzujnjalyh2s2x16",
|
| 458 |
+
"handlers": {}
|
| 459 |
+
},
|
| 460 |
+
"9eieaedqpr1ickbb": {
|
| 461 |
+
"id": "9eieaedqpr1ickbb",
|
| 462 |
+
"type": "section",
|
| 463 |
+
"content": {
|
| 464 |
+
"title": "Investment research options",
|
| 465 |
+
"cssClasses": "",
|
| 466 |
+
"containerBackgroundColor": "#e9d3fd"
|
| 467 |
+
},
|
| 468 |
+
"isCodeManaged": false,
|
| 469 |
+
"position": 2,
|
| 470 |
+
"parentId": "c0f99a9e-5004-4e75-a6c6-36f17490b134",
|
| 471 |
+
"handlers": {},
|
| 472 |
+
"visible": true
|
| 473 |
+
},
|
| 474 |
+
"1yuilwwrhm40gxtx": {
|
| 475 |
+
"id": "1yuilwwrhm40gxtx",
|
| 476 |
+
"type": "horizontalstack",
|
| 477 |
+
"content": {},
|
| 478 |
+
"isCodeManaged": false,
|
| 479 |
+
"position": 0,
|
| 480 |
+
"parentId": "9eieaedqpr1ickbb",
|
| 481 |
+
"handlers": {},
|
| 482 |
+
"visible": true
|
| 483 |
+
},
|
| 484 |
+
"1vyfwym5dfh07ihb": {
|
| 485 |
+
"id": "1vyfwym5dfh07ihb",
|
| 486 |
+
"type": "message",
|
| 487 |
+
"content": {
|
| 488 |
+
"message": "@{message}"
|
| 489 |
+
},
|
| 490 |
+
"isCodeManaged": false,
|
| 491 |
+
"position": 0,
|
| 492 |
+
"parentId": "i23vdas64ziuiazm",
|
| 493 |
+
"handlers": {},
|
| 494 |
+
"visible": true
|
| 495 |
+
},
|
| 496 |
+
"fwmg7b84wstpxs7m": {
|
| 497 |
+
"id": "fwmg7b84wstpxs7m",
|
| 498 |
+
"type": "button",
|
| 499 |
+
"content": {
|
| 500 |
+
"text": "1Y",
|
| 501 |
+
"buttonColor": "#BFCBFF",
|
| 502 |
+
"cssClasses": "",
|
| 503 |
+
"buttonTextColor": "#000000"
|
| 504 |
+
},
|
| 505 |
+
"isCodeManaged": false,
|
| 506 |
+
"position": 4,
|
| 507 |
+
"parentId": "g5mgb80xt38atz4f",
|
| 508 |
+
"handlers": {
|
| 509 |
+
"wf-click": "charts.handle_click"
|
| 510 |
+
},
|
| 511 |
+
"visible": true
|
| 512 |
+
},
|
| 513 |
+
"jcs5oslp27w5v52j": {
|
| 514 |
+
"id": "jcs5oslp27w5v52j",
|
| 515 |
+
"type": "button",
|
| 516 |
+
"content": {
|
| 517 |
+
"text": "5Y",
|
| 518 |
+
"buttonColor": "#BFCBFF",
|
| 519 |
+
"cssClasses": "",
|
| 520 |
+
"buttonTextColor": "#000000"
|
| 521 |
+
},
|
| 522 |
+
"isCodeManaged": false,
|
| 523 |
+
"position": 5,
|
| 524 |
+
"parentId": "g5mgb80xt38atz4f",
|
| 525 |
+
"handlers": {
|
| 526 |
+
"wf-click": "charts.handle_click"
|
| 527 |
+
},
|
| 528 |
+
"visible": true
|
| 529 |
+
},
|
| 530 |
+
"s2jsn9u5xb23hase": {
|
| 531 |
+
"id": "s2jsn9u5xb23hase",
|
| 532 |
+
"type": "tags",
|
| 533 |
+
"content": {
|
| 534 |
+
"tags": "{\n \"AAPL\": \"AAPL\",\n \"IBM\": \"IBM\",\n \"NVDA\": \"NVDA\",\n \"MSFT\": \"MSFT\",\n \"TSLA\": \"TSLA\"\n}"
|
| 535 |
+
},
|
| 536 |
+
"isCodeManaged": false,
|
| 537 |
+
"position": 0,
|
| 538 |
+
"parentId": "kr54hbg2r5fkhsct",
|
| 539 |
+
"handlers": {
|
| 540 |
+
"wf-tag-click": "stock_tags"
|
| 541 |
+
},
|
| 542 |
+
"visible": true
|
| 543 |
+
},
|
| 544 |
+
"kr54hbg2r5fkhsct": {
|
| 545 |
+
"id": "kr54hbg2r5fkhsct",
|
| 546 |
+
"type": "section",
|
| 547 |
+
"content": {
|
| 548 |
+
"title": "Select a stock ticker"
|
| 549 |
+
},
|
| 550 |
+
"isCodeManaged": false,
|
| 551 |
+
"position": 1,
|
| 552 |
+
"parentId": "c0f99a9e-5004-4e75-a6c6-36f17490b134",
|
| 553 |
+
"handlers": {},
|
| 554 |
+
"visible": true
|
| 555 |
+
},
|
| 556 |
+
"8yxe1itvlcq4zhpi": {
|
| 557 |
+
"id": "8yxe1itvlcq4zhpi",
|
| 558 |
+
"type": "tab",
|
| 559 |
+
"content": {
|
| 560 |
+
"name": "Income data"
|
| 561 |
+
},
|
| 562 |
+
"isCodeManaged": false,
|
| 563 |
+
"position": 2,
|
| 564 |
+
"parentId": "yzujnjalyh2s2x16",
|
| 565 |
+
"handlers": {},
|
| 566 |
+
"visible": true
|
| 567 |
+
},
|
| 568 |
+
"tmiso5qe0e0jfl4i": {
|
| 569 |
+
"id": "tmiso5qe0e0jfl4i",
|
| 570 |
+
"type": "dataframe",
|
| 571 |
+
"content": {
|
| 572 |
+
"dataframe": "@{income_statement_df}"
|
| 573 |
+
},
|
| 574 |
+
"isCodeManaged": false,
|
| 575 |
+
"position": 0,
|
| 576 |
+
"parentId": "8yxe1itvlcq4zhpi",
|
| 577 |
+
"handlers": {},
|
| 578 |
+
"visible": true
|
| 579 |
+
},
|
| 580 |
+
"x6p3vxia2xlpbbib": {
|
| 581 |
+
"id": "x6p3vxia2xlpbbib",
|
| 582 |
+
"type": "button",
|
| 583 |
+
"content": {
|
| 584 |
+
"text": "Visualize income statement"
|
| 585 |
+
},
|
| 586 |
+
"isCodeManaged": false,
|
| 587 |
+
"position": 1,
|
| 588 |
+
"parentId": "1yuilwwrhm40gxtx",
|
| 589 |
+
"handlers": {
|
| 590 |
+
"wf-click": "generate_income_analysis"
|
| 591 |
+
},
|
| 592 |
+
"visible": true
|
| 593 |
+
},
|
| 594 |
+
"oo7y10uo68z3ayf8": {
|
| 595 |
+
"id": "oo7y10uo68z3ayf8",
|
| 596 |
+
"type": "plotlygraph",
|
| 597 |
+
"content": {
|
| 598 |
+
"spec": "@{bar_graph}"
|
| 599 |
+
},
|
| 600 |
+
"isCodeManaged": false,
|
| 601 |
+
"position": 2,
|
| 602 |
+
"parentId": "i23vdas64ziuiazm",
|
| 603 |
+
"handlers": {
|
| 604 |
+
"plotly-click": "charts.update_bar_graph"
|
| 605 |
+
},
|
| 606 |
+
"visible": "show_bar_graph.visible"
|
| 607 |
+
},
|
| 608 |
+
"a8a854zgzdrcel9j": {
|
| 609 |
+
"id": "a8a854zgzdrcel9j",
|
| 610 |
+
"type": "dropdowninput",
|
| 611 |
+
"content": {
|
| 612 |
+
"label": "Output language",
|
| 613 |
+
"options": "@{output_language}"
|
| 614 |
+
},
|
| 615 |
+
"isCodeManaged": false,
|
| 616 |
+
"position": 3,
|
| 617 |
+
"parentId": "i23vdas64ziuiazm",
|
| 618 |
+
"handlers": {
|
| 619 |
+
"wf-option-change": "prompt_parameters_lang"
|
| 620 |
+
},
|
| 621 |
+
"visible": "show_analysis_text.language"
|
| 622 |
+
},
|
| 623 |
+
"1c3vvmgyhvkm9d6e": {
|
| 624 |
+
"id": "1c3vvmgyhvkm9d6e",
|
| 625 |
+
"type": "horizontalstack",
|
| 626 |
+
"content": {},
|
| 627 |
+
"isCodeManaged": false,
|
| 628 |
+
"position": 1,
|
| 629 |
+
"parentId": "i23vdas64ziuiazm",
|
| 630 |
+
"handlers": {},
|
| 631 |
+
"visible": "show_income_metrics.visible"
|
| 632 |
+
},
|
| 633 |
+
"e7kux7h89zec8cmh": {
|
| 634 |
+
"id": "e7kux7h89zec8cmh",
|
| 635 |
+
"type": "metric",
|
| 636 |
+
"content": {
|
| 637 |
+
"name": "Operating Margin",
|
| 638 |
+
"note": "",
|
| 639 |
+
"metricValue": "@{operating_margin}"
|
| 640 |
+
},
|
| 641 |
+
"isCodeManaged": false,
|
| 642 |
+
"position": 0,
|
| 643 |
+
"parentId": "1c3vvmgyhvkm9d6e",
|
| 644 |
+
"handlers": {},
|
| 645 |
+
"visible": true
|
| 646 |
+
},
|
| 647 |
+
"0u3afw3gbxbj8h1x": {
|
| 648 |
+
"id": "0u3afw3gbxbj8h1x",
|
| 649 |
+
"type": "separator",
|
| 650 |
+
"content": {},
|
| 651 |
+
"isCodeManaged": false,
|
| 652 |
+
"position": 1,
|
| 653 |
+
"parentId": "1c3vvmgyhvkm9d6e",
|
| 654 |
+
"handlers": {},
|
| 655 |
+
"visible": true
|
| 656 |
+
},
|
| 657 |
+
"yxm3uezkrgpl11fc": {
|
| 658 |
+
"id": "yxm3uezkrgpl11fc",
|
| 659 |
+
"type": "metric",
|
| 660 |
+
"content": {
|
| 661 |
+
"name": "Gross Margin",
|
| 662 |
+
"note": "",
|
| 663 |
+
"metricValue": "@{gross_margin}"
|
| 664 |
+
},
|
| 665 |
+
"isCodeManaged": false,
|
| 666 |
+
"position": 2,
|
| 667 |
+
"parentId": "1c3vvmgyhvkm9d6e",
|
| 668 |
+
"handlers": {},
|
| 669 |
+
"visible": true
|
| 670 |
+
},
|
| 671 |
+
"nmdddxrvpgirasj6": {
|
| 672 |
+
"id": "nmdddxrvpgirasj6",
|
| 673 |
+
"type": "metric",
|
| 674 |
+
"content": {
|
| 675 |
+
"name": "EBIDTA Margin",
|
| 676 |
+
"note": "",
|
| 677 |
+
"metricValue": "@{ebitda_margin}"
|
| 678 |
+
},
|
| 679 |
+
"isCodeManaged": false,
|
| 680 |
+
"position": 4,
|
| 681 |
+
"parentId": "1c3vvmgyhvkm9d6e",
|
| 682 |
+
"handlers": {},
|
| 683 |
+
"visible": true
|
| 684 |
+
},
|
| 685 |
+
"xlzf1vlkmxokw9yj": {
|
| 686 |
+
"id": "xlzf1vlkmxokw9yj",
|
| 687 |
+
"type": "separator",
|
| 688 |
+
"content": {},
|
| 689 |
+
"isCodeManaged": false,
|
| 690 |
+
"position": 3,
|
| 691 |
+
"parentId": "1c3vvmgyhvkm9d6e",
|
| 692 |
+
"handlers": {},
|
| 693 |
+
"visible": true
|
| 694 |
+
},
|
| 695 |
+
"c52e2wkln9shvcoq": {
|
| 696 |
+
"id": "c52e2wkln9shvcoq",
|
| 697 |
+
"type": "section",
|
| 698 |
+
"content": {
|
| 699 |
+
"title": "",
|
| 700 |
+
"containerBackgroundColor": "#FFE999"
|
| 701 |
+
},
|
| 702 |
+
"isCodeManaged": false,
|
| 703 |
+
"position": 0,
|
| 704 |
+
"parentId": "18wepug77yr8m1iu",
|
| 705 |
+
"handlers": {},
|
| 706 |
+
"visible": "demo_mode.visible"
|
| 707 |
+
},
|
| 708 |
+
"3knng5h0zv8i3xra": {
|
| 709 |
+
"id": "3knng5h0zv8i3xra",
|
| 710 |
+
"type": "text",
|
| 711 |
+
"content": {
|
| 712 |
+
"text": "@{tab_message}",
|
| 713 |
+
"useMarkdown": "yes"
|
| 714 |
+
},
|
| 715 |
+
"isCodeManaged": false,
|
| 716 |
+
"position": 0,
|
| 717 |
+
"parentId": "c52e2wkln9shvcoq",
|
| 718 |
+
"handlers": {},
|
| 719 |
+
"visible": ""
|
| 720 |
+
},
|
| 721 |
+
"rhomvmilcrm8f2r1": {
|
| 722 |
+
"id": "rhomvmilcrm8f2r1",
|
| 723 |
+
"type": "button",
|
| 724 |
+
"content": {
|
| 725 |
+
"text": "Summarize earnings"
|
| 726 |
+
},
|
| 727 |
+
"isCodeManaged": false,
|
| 728 |
+
"position": 2,
|
| 729 |
+
"parentId": "1yuilwwrhm40gxtx",
|
| 730 |
+
"handlers": {
|
| 731 |
+
"wf-click": "summarize_earnings"
|
| 732 |
+
},
|
| 733 |
+
"visible": true
|
| 734 |
+
},
|
| 735 |
+
"1o0ui3hahmjblams": {
|
| 736 |
+
"id": "1o0ui3hahmjblams",
|
| 737 |
+
"type": "text",
|
| 738 |
+
"parentId": "c0f99a9e-5004-4e75-a6c6-36f17490b134",
|
| 739 |
+
"content": {
|
| 740 |
+
"text": "Made with \u2764\ufe0f using [Writer Framework](https://github.com/writer/writer-framework/)",
|
| 741 |
+
"useMarkdown": "yes",
|
| 742 |
+
"alignment": "center"
|
| 743 |
+
},
|
| 744 |
+
"handlers": {},
|
| 745 |
+
"position": 4,
|
| 746 |
+
"visible": true
|
| 747 |
+
}
|
| 748 |
+
}
|
| 749 |
+
}
|
pyproject.toml
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[tool.poetry]
|
| 2 |
+
name = "writer-framework-default"
|
| 3 |
+
version = "0.1.0"
|
| 4 |
+
description = ""
|
| 5 |
+
authors = ["Your Name <[email protected]>"]
|
| 6 |
+
readme = "README.md"
|
| 7 |
+
|
| 8 |
+
[tool.poetry.dependencies]
|
| 9 |
+
python = "^3.10.0"
|
| 10 |
+
writer = {version = "^0.6.0"}
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
[build-system]
|
| 14 |
+
requires = ["poetry-core"]
|
| 15 |
+
build-backend = "poetry.core.masonry.api"
|