QuantumLearner commited on
Commit
79f536f
·
verified ·
1 Parent(s): 5f1a3e2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +96 -27
app.py CHANGED
@@ -9,7 +9,7 @@ import plotly.graph_objects as go
9
 
10
  from dateutil.relativedelta import relativedelta
11
 
12
- st.set_page_config(page_title="Congress Trading Activity", layout="wide")
13
 
14
  API_KEY = os.getenv("FMP_API_KEY")
15
 
@@ -85,6 +85,12 @@ run_button = st.sidebar.button("Run Analysis")
85
  st.title("Congress Trades Analysis")
86
  st.write("Analyze the latest trades reported by members of Congress. From the Senate and from the House.")
87
 
 
 
 
 
 
 
88
  if run_button:
89
  # Use asynchronous fetching for both Senate and House
90
  senate_data = load_data_async(SENATE_BASE_URL, pages=5)
@@ -107,6 +113,69 @@ if run_button:
107
  (house_data["disclosureDate"] >= pd.to_datetime(start_date))
108
  ]
109
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  # Prepare chart data for Senate
111
  senate_chart_data = pd.DataFrame()
112
  if not senate_data.empty:
@@ -130,11 +199,6 @@ if run_button:
130
  combined_data.dropna(subset=["amount", "ticker"], inplace=True)
131
  combined_data = combined_data[combined_data["amount"] > 0]
132
 
133
- # Standardize trade type
134
- def standardize_trade_type(t):
135
- if "sale" in t or "sold" in t or "sell" in t:
136
- return "sale"
137
- return "purchase"
138
  combined_data["tradeType"] = combined_data["rawType"].apply(standardize_trade_type)
139
  combined_data["count"] = 1
140
 
@@ -157,7 +221,6 @@ if run_button:
157
  .groupby(["ticker", "chamber", "tradeType"], as_index=False)
158
  .agg({"amount": "sum", "count": "sum"})
159
  )
160
- # Create Plotly figure
161
  fig = go.Figure()
162
  for chamber in chart_data["chamber"].unique():
163
  for trade in ["purchase", "sale"]:
@@ -176,21 +239,25 @@ if run_button:
176
  fig.update_layout(
177
  barmode="stack",
178
  xaxis_tickangle=-45,
 
 
 
179
  width=40 * len(top_tickers),
180
- height=400,
181
- title="Total Amount per Ticker"
182
  )
183
  with st.container(border=True):
184
  st.plotly_chart(fig, use_container_width=True)
185
 
186
- # Reorder Senate columns
 
 
187
  if not senate_data.empty:
188
  desired_order_senate = [
189
- "office",
190
- "dateRecieved",
191
- "symbol",
192
- "type",
193
- "amount",
194
  "assetDescription"
195
  ]
196
  existing_senate_cols = [c for c in desired_order_senate if c in senate_data.columns]
@@ -198,14 +265,21 @@ if run_button:
198
  reordered_senate_cols = existing_senate_cols + remaining_senate_cols
199
  senate_data = senate_data[reordered_senate_cols]
200
 
201
- # Reorder House columns
 
 
 
 
 
 
 
202
  if not house_data.empty:
203
  desired_order_house = [
204
- "representative",
205
- "disclosureDate",
206
- "ticker",
207
- "type",
208
- "amount",
209
  "assetDescription"
210
  ]
211
  existing_house_cols = [c for c in desired_order_house if c in house_data.columns]
@@ -213,14 +287,9 @@ if run_button:
213
  reordered_house_cols = existing_house_cols + remaining_house_cols
214
  house_data = house_data[reordered_house_cols]
215
 
216
- with st.container(border=True):
217
- st.subheader("Senate Data")
218
- st.write("Latest Transaction in Senate. Please sort the table by **`disclosureDate`** and/or **`dateRecieved`** columns.")
219
- st.dataframe(senate_data, use_container_width=True)
220
-
221
  with st.container(border=True):
222
  st.subheader("House Data")
223
- st.write("Latest Transaction in House. Please sort the table by **`disclosureDate`** and/or **`transactionDate`** columns.")
224
  st.dataframe(house_data, use_container_width=True)
225
  else:
226
  st.write("Set filters and press Run to load data.")
 
9
 
10
  from dateutil.relativedelta import relativedelta
11
 
12
+ st.set_page_config(page_title="Congress Stock Trades", layout="wide")
13
 
14
  API_KEY = os.getenv("FMP_API_KEY")
15
 
 
85
  st.title("Congress Trades Analysis")
86
  st.write("Analyze the latest trades reported by members of Congress. From the Senate and from the House.")
87
 
88
+ # Function to standardize trade type
89
+ def standardize_trade_type(t):
90
+ if "sale" in t or "sold" in t or "sell" in t:
91
+ return "sale"
92
+ return "purchase"
93
+
94
  if run_button:
95
  # Use asynchronous fetching for both Senate and House
96
  senate_data = load_data_async(SENATE_BASE_URL, pages=5)
 
113
  (house_data["disclosureDate"] >= pd.to_datetime(start_date))
114
  ]
115
 
116
+ # ---------------------------
117
+ # Time Series Chart Data Preparation
118
+ # ---------------------------
119
+ # Prepare Senate time series data
120
+ if not senate_data.empty:
121
+ senate_time = senate_data.copy()
122
+ senate_time["trade_date"] = senate_time["dateRecieved"]
123
+ senate_time["tradeType"] = senate_time["type"].str.lower().apply(standardize_trade_type)
124
+ senate_time["transactionVolume"] = 1
125
+ senate_time["parsed_amount"] = senate_time["amount"].apply(parse_amount_range)
126
+ else:
127
+ senate_time = pd.DataFrame()
128
+
129
+ # Prepare House time series data
130
+ if not house_data.empty:
131
+ house_time = house_data.copy()
132
+ house_time["trade_date"] = house_time["disclosureDate"]
133
+ house_time["tradeType"] = house_time["type"].str.lower().apply(standardize_trade_type)
134
+ house_time["transactionVolume"] = 1
135
+ house_time["parsed_amount"] = house_time["amount"].apply(parse_amount_range)
136
+ else:
137
+ house_time = pd.DataFrame()
138
+
139
+ time_series_data = pd.concat([senate_time, house_time], ignore_index=True)
140
+ time_series_data = time_series_data.dropna(subset=["trade_date", "transactionVolume", "parsed_amount"])
141
+
142
+ time_grouped = (
143
+ time_series_data
144
+ .groupby(["trade_date", "tradeType"], as_index=False)
145
+ .agg(total_transactions=("transactionVolume", "sum"),
146
+ avg_amount=("parsed_amount", "mean"))
147
+ )
148
+ time_grouped.sort_values("trade_date", inplace=True)
149
+
150
+ # Create Plotly time series bar chart
151
+ fig_time = go.Figure()
152
+ for trade in ["purchase", "sale"]:
153
+ df_subset = time_grouped[time_grouped["tradeType"] == trade]
154
+ if not df_subset.empty:
155
+ fig_time.add_trace(go.Bar(
156
+ x=df_subset["trade_date"],
157
+ y=df_subset["total_transactions"],
158
+ name=trade,
159
+ customdata=df_subset["avg_amount"],
160
+ hovertemplate="Date: %{x|%Y-%m-%d}<br>Total Transactions: %{y}<br>Avg Amount: %{customdata:.2f}<extra></extra>"
161
+ ))
162
+ fig_time.update_layout(
163
+ barmode="group",
164
+ xaxis_title="Date",
165
+ yaxis_title="Total Transaction Count",
166
+ title="Time Series of Trade Volume",
167
+ height=400
168
+ )
169
+
170
+ # ---------------------------
171
+ # Display Time Series Chart in Container
172
+ # ---------------------------
173
+ with st.container(border=True):
174
+ st.plotly_chart(fig_time, use_container_width=True)
175
+
176
+ # ---------------------------
177
+ # Chart: Total Amount per Ticker
178
+ # ---------------------------
179
  # Prepare chart data for Senate
180
  senate_chart_data = pd.DataFrame()
181
  if not senate_data.empty:
 
199
  combined_data.dropna(subset=["amount", "ticker"], inplace=True)
200
  combined_data = combined_data[combined_data["amount"] > 0]
201
 
 
 
 
 
 
202
  combined_data["tradeType"] = combined_data["rawType"].apply(standardize_trade_type)
203
  combined_data["count"] = 1
204
 
 
221
  .groupby(["ticker", "chamber", "tradeType"], as_index=False)
222
  .agg({"amount": "sum", "count": "sum"})
223
  )
 
224
  fig = go.Figure()
225
  for chamber in chart_data["chamber"].unique():
226
  for trade in ["purchase", "sale"]:
 
239
  fig.update_layout(
240
  barmode="stack",
241
  xaxis_tickangle=-45,
242
+ xaxis_title="Ticker",
243
+ yaxis_title="Total Amount",
244
+ title="Total Amount per Ticker",
245
  width=40 * len(top_tickers),
246
+ height=400
 
247
  )
248
  with st.container(border=True):
249
  st.plotly_chart(fig, use_container_width=True)
250
 
251
+ # ---------------------------
252
+ # Reorder and Display Senate Table
253
+ # ---------------------------
254
  if not senate_data.empty:
255
  desired_order_senate = [
256
+ "office",
257
+ "dateRecieved",
258
+ "symbol",
259
+ "type",
260
+ "amount",
261
  "assetDescription"
262
  ]
263
  existing_senate_cols = [c for c in desired_order_senate if c in senate_data.columns]
 
265
  reordered_senate_cols = existing_senate_cols + remaining_senate_cols
266
  senate_data = senate_data[reordered_senate_cols]
267
 
268
+ with st.container(border=True):
269
+ st.subheader("Senate Data")
270
+ st.write("Latest Transaction in Senate. Please sort by **`disclosureDate`** and/or **`dateRecieved`**.")
271
+ st.dataframe(senate_data, use_container_width=True)
272
+
273
+ # ---------------------------
274
+ # Reorder and Display House Table
275
+ # ---------------------------
276
  if not house_data.empty:
277
  desired_order_house = [
278
+ "representative",
279
+ "disclosureDate",
280
+ "ticker",
281
+ "type",
282
+ "amount",
283
  "assetDescription"
284
  ]
285
  existing_house_cols = [c for c in desired_order_house if c in house_data.columns]
 
287
  reordered_house_cols = existing_house_cols + remaining_house_cols
288
  house_data = house_data[reordered_house_cols]
289
 
 
 
 
 
 
290
  with st.container(border=True):
291
  st.subheader("House Data")
292
+ st.write("Latest Transaction in House. Please sort by **`disclosureDate`** and/or **`transactionDate`**.")
293
  st.dataframe(house_data, use_container_width=True)
294
  else:
295
  st.write("Set filters and press Run to load data.")