Spaces:
Running
Running
Benjamin Consolvo
commited on
Commit
·
3824258
1
Parent(s):
e193a12
session state streamlit
Browse files
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 |
-
#
|
266 |
symbols = list(self.data.keys())
|
267 |
symbol_to_name = self.analyzer.symbol_to_name
|
268 |
n = len(symbols)
|
269 |
-
|
270 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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=
|
294 |
showlegend=False,
|
295 |
-
dragmode=False,
|
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 |
-
|
|
|
|
|
|
|
|
|
413 |
|
414 |
-
#
|
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()
|