Benjamin Consolvo commited on
Commit
3824258
·
1 Parent(s): e193a12

session state streamlit

Browse files
Files changed (1) hide show
  1. app.py +42 -9
app.py CHANGED
@@ -1,12 +1,10 @@
1
  import streamlit as st
2
  st.set_page_config(layout="wide")
3
-
4
  import yfinance as yf
5
  # import alpaca as tradeapi
6
  import alpaca_trade_api as alpaca
7
  from newsapi import NewsApiClient
8
  from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer
9
-
10
  from datetime import datetime, timedelta
11
  import streamlit as st
12
  import pandas as pd
@@ -57,6 +55,14 @@ class AlpacaTrader:
57
  return None
58
 
59
  def sell(self, symbol, qty):
 
 
 
 
 
 
 
 
60
  try:
61
  order = self.alpaca.submit_order(symbol=symbol, qty=qty, side='sell', type='market', time_in_force='day')
62
  logger.info(f"Sold {qty} shares of {symbol}")
@@ -262,12 +268,32 @@ class TradingApp:
262
  self.auto_trade_log = [] # Store automatic trade actions
263
 
264
  def display_charts(self):
265
- # Create 12 individual dynamic price plots in a 4x3 grid using Plotly (3 columns, 4 rows)
266
  symbols = list(self.data.keys())
267
  symbol_to_name = self.analyzer.symbol_to_name
268
  n = len(symbols)
269
- cols = 3
270
- rows = 4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
271
  subplot_titles = [
272
  f"{symbol} - {symbol_to_name.get(symbol, '')}" for symbol in symbols
273
  ]
@@ -290,9 +316,9 @@ class TradingApp:
290
  )
291
  fig.update_layout(
292
  title="Top Volume Stocks - Price Charts (Since 2023)",
293
- height=2000,
294
  showlegend=False,
295
- dragmode=False, # Disable global dragmode
296
  )
297
  # Enable scroll-zoom for each subplot (individual zoom)
298
  fig.update_layout(
@@ -402,6 +428,9 @@ def load_auto_trade_log():
402
  except Exception:
403
  return None
404
 
 
 
 
405
  def main():
406
  st.title("Stock Trading Application")
407
 
@@ -409,9 +438,13 @@ def main():
409
  st.error("Please configure your API keys in secrets.toml")
410
  return
411
 
412
- app = TradingApp()
 
 
 
 
413
 
414
- # Start background thread only once (on first run)
415
  if "auto_trade_thread_started" not in st.session_state:
416
  thread = threading.Thread(target=background_auto_trade, args=(app,), daemon=True)
417
  thread.start()
 
1
  import streamlit as st
2
  st.set_page_config(layout="wide")
 
3
  import yfinance as yf
4
  # import alpaca as tradeapi
5
  import alpaca_trade_api as alpaca
6
  from newsapi import NewsApiClient
7
  from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer
 
8
  from datetime import datetime, timedelta
9
  import streamlit as st
10
  import pandas as pd
 
55
  return None
56
 
57
  def sell(self, symbol, qty):
58
+ # Check if position exists and has enough quantity before attempting to sell
59
+ positions = {p.symbol: float(p.qty) for p in self.alpaca.list_positions()}
60
+ if symbol not in positions:
61
+ logger.warning(f"No position in {symbol}. Sell not attempted.")
62
+ return None
63
+ if positions[symbol] < qty:
64
+ logger.warning(f"Not enough shares to sell: {qty} requested, {positions[symbol]} available for {symbol}. Sell not attempted.")
65
+ return None
66
  try:
67
  order = self.alpaca.submit_order(symbol=symbol, qty=qty, side='sell', type='market', time_in_force='day')
68
  logger.info(f"Sold {qty} shares of {symbol}")
 
268
  self.auto_trade_log = [] # Store automatic trade actions
269
 
270
  def display_charts(self):
271
+ # Dynamically adjust columns based on number of stocks and available width
272
  symbols = list(self.data.keys())
273
  symbol_to_name = self.analyzer.symbol_to_name
274
  n = len(symbols)
275
+
276
+ # Use Streamlit's layout to get available width and adjust columns accordingly
277
+ # Default to 3 columns, but adjust for small or large n
278
+ min_col_width = 350 # px, minimum width per plot for readability
279
+ max_cols = max(1, min(6, n)) # Don't exceed 6 columns for readability
280
+
281
+ # Try to get the container width from Streamlit (fallback to 1200px)
282
+ container_width = st.get_option("deprecation.showPyplotGlobalUse") # Not a real width, just placeholder
283
+ # Since Streamlit does not provide actual window width, use st.columns to adapt layout
284
+ # Calculate columns based on n for best fit
285
+ if n <= 3:
286
+ cols = n
287
+ elif n <= 6:
288
+ cols = 3
289
+ elif n <= 8:
290
+ cols = 4
291
+ elif n <= 12:
292
+ cols = 4
293
+ else:
294
+ cols = 5
295
+
296
+ rows = (n + cols - 1) // cols
297
  subplot_titles = [
298
  f"{symbol} - {symbol_to_name.get(symbol, '')}" for symbol in symbols
299
  ]
 
316
  )
317
  fig.update_layout(
318
  title="Top Volume Stocks - Price Charts (Since 2023)",
319
+ height=max(400 * rows, 600),
320
  showlegend=False,
321
+ dragmode=False,
322
  )
323
  # Enable scroll-zoom for each subplot (individual zoom)
324
  fig.update_layout(
 
428
  except Exception:
429
  return None
430
 
431
+ # Add this at the top after imports to suppress Streamlit reruns on widget interaction
432
+ st.experimental_set_query_params() # This is a no-op but ensures Streamlit doesn't rerun due to query params
433
+
434
  def main():
435
  st.title("Stock Trading Application")
436
 
 
438
  st.error("Please configure your API keys in secrets.toml")
439
  return
440
 
441
+ # Prevent Streamlit from rerunning the script on every widget interaction
442
+ # Use session state to persist objects and only update when necessary
443
+ if "app_instance" not in st.session_state:
444
+ st.session_state["app_instance"] = TradingApp()
445
+ app = st.session_state["app_instance"]
446
 
447
+ # Only start the background thread once
448
  if "auto_trade_thread_started" not in st.session_state:
449
  thread = threading.Thread(target=background_auto_trade, args=(app,), daemon=True)
450
  thread.start()