Repository navigation
Expand file tree
/
Copy pathapp.py
More file actions
126 lines (108 loc) · 4.62 KB
/
Copy pathapp.py
File metadata and controls
126 lines (108 loc) · 4.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# app.py
# Main entry point for the Streamlit application.
import streamlit as st
import logging
from datetime import datetime, timedelta
import os
from dotenv import load_dotenv
from src.stocks import is_valid_stock_code
from src.config import (
MAX_LOGIN_ATTEMPTS,
LOCKOUT_MINUTES,
DEFAULT_INITIAL_CAPITAL,
DEFAULT_RISK_TOLERANCE,
)
from src.workers.queue_worker import start_worker
from stock_analysis import analyse_stock
load_dotenv()
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(name)s: %(message)s")
logger = logging.getLogger(__name__)
start_worker()
st.set_page_config(layout="wide")
# --- Authentication ---
PASSKEY = os.getenv("PASSKEY")
hide_streamlit_style = """
<style>
#MainMenu {visibility: hidden;}
header {visibility: hidden;}
footer {visibility: hidden;}
</style>
"""
st.markdown(hide_streamlit_style, unsafe_allow_html=True)
if "authenticated" not in st.session_state:
st.session_state.authenticated = False
if "incorrect_count" not in st.session_state:
st.session_state.incorrect_count = 0
if "pending_stock" not in st.session_state:
st.session_state.pending_stock = None
if st.session_state.get("locked_until"):
if datetime.now() < st.session_state.locked_until:
remaining = int((st.session_state.locked_until - datetime.now()).total_seconds())
st.error(f"Too many incorrect password attempts. Please wait {remaining} seconds before trying again.")
st.stop()
else:
st.session_state.incorrect_count = 0
st.session_state.locked_until = None
if not st.session_state.authenticated:
st.title("Login")
password = st.text_input("Enter Passkey", type="password")
if st.button("Login"):
if password == PASSKEY:
st.session_state.authenticated = True
st.session_state.incorrect_count = 0
st.success("Access Granted!")
st.rerun()
else:
st.session_state.incorrect_count += 1
if st.session_state.incorrect_count >= MAX_LOGIN_ATTEMPTS:
st.session_state.locked_until = datetime.now() + timedelta(minutes=LOCKOUT_MINUTES)
st.error(f"Too many incorrect password attempts. Locked out for {LOCKOUT_MINUTES} minutes.")
st.stop()
remaining = MAX_LOGIN_ATTEMPTS - st.session_state.incorrect_count
st.error(f"Incorrect passkey. Attempt {st.session_state.incorrect_count} of {MAX_LOGIN_ATTEMPTS}.")
st.stop()
# --- Poll for pending stock result ---
if st.session_state.pending_stock:
from src.storage.cache import get_stock_analysis
pending = st.session_state.pending_stock
cached = get_stock_analysis(pending)
if cached:
st.session_state.pending_stock = None
st.success(f"Analysis for {pending} is ready!")
st.markdown(cached)
st.stop()
else:
st.info(f"Analysis for {pending} is still processing...")
st.info("Click the button again to check if results are ready.")
st.session_state.pending_stock = pending
# --- Main Application UI ---
st.title("All India Stock Analysis Agent")
st.write("Enter the stock code below to generate analysis for it")
stock = st.text_input("Stock analysis", placeholder="STOCK SYMBOL e.g., TATAMOTORS")
initial_capital = st.number_input("Initial capital:", value=DEFAULT_INITIAL_CAPITAL, step=1, format="%d")
button_placeholder = st.empty()
if button_placeholder.button("Generate Analysis"):
if stock and is_valid_stock_code(stock) is not None:
stock = stock.strip()
button_placeholder.empty()
logger.info("Query for %s", stock)
result = analyse_stock(stock, initial_capital, DEFAULT_RISK_TOLERANCE)
if "queued" in result.lower() or "already in the queue" in result.lower():
st.session_state.pending_stock = stock
st.info(result)
st.info("The page will re-check automatically. You can also click the button again to check manually.")
else:
st.session_state.pending_stock = None
st.subheader("Generated Stock Analysis")
st.markdown(result)
else:
st.error("Please enter a valid stock code.")
st.markdown(
"""
<div style="text-align: center; font-size: small; color: gray; margin-top: 2rem;">
<p><strong>Disclaimer:</strong> This content is generated by AI and provided for informational purposes only. It is not intended as financial, legal, or professional advice by any actual human.</p>
<p>Please consult with a qualified professional before making any decisions based on this information.</p>
</div>
""",
unsafe_allow_html=True
)