Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -3,28 +3,50 @@ from bs4 import BeautifulSoup
|
|
3 |
import pandas as pd
|
4 |
from io import StringIO
|
5 |
from datetime import datetime, timedelta
|
6 |
-
from openai import OpenAI
|
7 |
-
import gradio as gr
|
8 |
|
|
|
|
|
|
|
|
|
|
|
9 |
OPENROUTER_API_KEY = "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"
|
10 |
|
11 |
HEADERS = {
|
12 |
-
'User-Agent':
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
'Accept-Language': 'en-US,en;q=0.9',
|
14 |
-
'Referer': 'https://www.google.com/'
|
|
|
|
|
|
|
15 |
}
|
16 |
|
17 |
-
|
|
|
|
|
18 |
url = f'https://www.marketwatch.com/investing/stock/{symbol}'
|
19 |
response = requests.get(url, headers=HEADERS)
|
20 |
if response.status_code == 200:
|
21 |
soup = BeautifulSoup(response.text, 'html.parser')
|
22 |
price_tag = soup.find('bg-quote', class_='value')
|
23 |
if price_tag:
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
end_date = datetime.now()
|
29 |
start_date = end_date - timedelta(days=days)
|
30 |
start_date_str = start_date.strftime('%m/%d/%Y 00:00:00')
|
@@ -39,12 +61,15 @@ def get_historical_data(symbol: str, days=30):
|
|
39 |
if response.status_code == 200:
|
40 |
try:
|
41 |
df = pd.read_csv(StringIO(response.text))
|
42 |
-
return df
|
43 |
-
except Exception:
|
44 |
-
return
|
45 |
-
|
46 |
-
|
47 |
-
|
|
|
|
|
|
|
48 |
return """
|
49 |
Technical Analysis: Core Concepts & Formulas
|
50 |
-------------------------------------------
|
@@ -119,72 +144,45 @@ Key Technical Indicators and Their Formulas:
|
|
119 |
- Hammer, Shooting Star, Engulfing, Doji, Morning/Evening Star, etc.
|
120 |
"""
|
121 |
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
---
|
138 |
-
|
139 |
-
**Technical Analysis Documentation:**
|
140 |
-
{get_technical_analysis_docs()}
|
141 |
-
|
142 |
-
**Instructions:**
|
143 |
-
You must perform the entire analysis in one go — do not ask for any further data or clarification.
|
144 |
-
Perform the full process:
|
145 |
-
1. Review the historical OHLCV data provided.
|
146 |
-
2. Perform a rigorous, step-by-step technical analysis using the full range of indicators.
|
147 |
-
3. Identify trends, chart patterns, volume analysis, risk management.
|
148 |
-
4. Predict the next day’s closing price.
|
149 |
-
5. Justify your prediction with detailed reasoning.
|
150 |
-
---
|
151 |
-
**Step-by-Step Analysis Plan:**
|
152 |
-
1. Data Review and Preparation
|
153 |
-
2. Chart and Trend Analysis
|
154 |
-
3. Apply Core Technical Indicators
|
155 |
-
4. Pattern Recognition
|
156 |
-
5. Advanced Analysis
|
157 |
-
6. Confirmation and Risk Management
|
158 |
-
7. Prediction and Justification
|
159 |
-
8. Review and Backtesting (Optional)
|
160 |
-
---
|
161 |
-
**Output Format:**
|
162 |
-
- Predicted Price for Next Day:
|
163 |
-
- Detailed Reasoning:
|
164 |
-
- Trend analysis and key levels
|
165 |
-
- Indicator values and interpretations
|
166 |
-
- Patterns identified
|
167 |
-
- Volume analysis
|
168 |
-
- Confidence level and uncertainty factors
|
169 |
-
- Additional insights or warnings
|
170 |
-
"""
|
171 |
-
client = OpenAI(
|
172 |
-
base_url="https://openrouter.ai/api/v1",
|
173 |
-
api_key=OPENROUTER_API_KEY,
|
174 |
)
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
|
|
187 |
)
|
188 |
|
189 |
if __name__ == "__main__":
|
190 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
import pandas as pd
|
4 |
from io import StringIO
|
5 |
from datetime import datetime, timedelta
|
|
|
|
|
6 |
|
7 |
+
from langchain.tools import tool
|
8 |
+
from langchain.agents import initialize_agent, Tool
|
9 |
+
from langchain_openai import ChatOpenAI
|
10 |
+
|
11 |
+
# === Configuration ===
|
12 |
OPENROUTER_API_KEY = "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"
|
13 |
|
14 |
HEADERS = {
|
15 |
+
'User-Agent': (
|
16 |
+
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
|
17 |
+
'AppleWebKit/537.36 (KHTML, like Gecko) '
|
18 |
+
'Chrome/124.0.0.0 Safari/537.36'
|
19 |
+
),
|
20 |
+
'Accept': (
|
21 |
+
'text/html,application/xhtml+xml,application/xml;'
|
22 |
+
'q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8'
|
23 |
+
),
|
24 |
'Accept-Language': 'en-US,en;q=0.9',
|
25 |
+
'Referer': 'https://www.google.com/',
|
26 |
+
'Connection': 'keep-alive',
|
27 |
+
'Cache-Control': 'max-age=0',
|
28 |
+
'Upgrade-Insecure-Requests': '1'
|
29 |
}
|
30 |
|
31 |
+
@tool("GetCurrentPrice")
|
32 |
+
def get_current_price(symbol: str) -> str:
|
33 |
+
"""Get the current price for a stock symbol (e.g., 'AAPL')."""
|
34 |
url = f'https://www.marketwatch.com/investing/stock/{symbol}'
|
35 |
response = requests.get(url, headers=HEADERS)
|
36 |
if response.status_code == 200:
|
37 |
soup = BeautifulSoup(response.text, 'html.parser')
|
38 |
price_tag = soup.find('bg-quote', class_='value')
|
39 |
if price_tag:
|
40 |
+
price = price_tag.get_text(strip=True)
|
41 |
+
return f"{symbol.upper()} current price: ${price} (from MarketWatch)"
|
42 |
+
else:
|
43 |
+
return "Stock price not found."
|
44 |
+
else:
|
45 |
+
return f"Failed to retrieve stock page. Status code: {response.status_code}"
|
46 |
+
|
47 |
+
@tool("GetHistoricalData")
|
48 |
+
def get_historical_data(symbol: str, days: int = 5000) -> str:
|
49 |
+
"""Get the last N days of historical OHLCV data for a stock symbol as CSV."""
|
50 |
end_date = datetime.now()
|
51 |
start_date = end_date - timedelta(days=days)
|
52 |
start_date_str = start_date.strftime('%m/%d/%Y 00:00:00')
|
|
|
61 |
if response.status_code == 200:
|
62 |
try:
|
63 |
df = pd.read_csv(StringIO(response.text))
|
64 |
+
return f"Historical data for {symbol.upper()} (from MarketWatch):\n" + df.head(10).to_csv(index=False)
|
65 |
+
except Exception as e:
|
66 |
+
return f"Failed to parse CSV data: {e}"
|
67 |
+
else:
|
68 |
+
return f"Failed to download historical data. Status code: {response.status_code}"
|
69 |
+
|
70 |
+
@tool("GetTechnicalAnalysisDocs")
|
71 |
+
def get_technical_analysis_docs(_: str = "") -> str:
|
72 |
+
"""Get documentation for technical analysis indicators."""
|
73 |
return """
|
74 |
Technical Analysis: Core Concepts & Formulas
|
75 |
-------------------------------------------
|
|
|
144 |
- Hammer, Shooting Star, Engulfing, Doji, Morning/Evening Star, etc.
|
145 |
"""
|
146 |
|
147 |
+
tools = [
|
148 |
+
Tool.from_function(
|
149 |
+
get_current_price,
|
150 |
+
name="GetCurrentPrice",
|
151 |
+
description="Get the current price for a stock symbol (e.g., AAPL)"
|
152 |
+
),
|
153 |
+
Tool.from_function(
|
154 |
+
get_historical_data,
|
155 |
+
name="GetHistoricalData",
|
156 |
+
description="Get the last N days of historical OHLCV data for a stock symbol as CSV"
|
157 |
+
),
|
158 |
+
Tool.from_function(
|
159 |
+
get_technical_analysis_docs,
|
160 |
+
name="GetTechnicalAnalysisDocs",
|
161 |
+
description="Provide documentation for technical analysis indicators"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
162 |
)
|
163 |
+
]
|
164 |
+
|
165 |
+
llm = ChatOpenAI(
|
166 |
+
openai_api_key=OPENROUTER_API_KEY,
|
167 |
+
openai_api_base="https://openrouter.ai/api/v1",
|
168 |
+
model_name="google/gemma-3n-e4b-it:free"
|
169 |
+
)
|
170 |
+
|
171 |
+
agent = initialize_agent(
|
172 |
+
tools,
|
173 |
+
llm,
|
174 |
+
agent="zero-shot-react-description",
|
175 |
+
verbose=True # This will show all reasoning and tool usage!
|
176 |
)
|
177 |
|
178 |
if __name__ == "__main__":
|
179 |
+
print("Welcome to the Stock Analysis Agent!")
|
180 |
+
print("Ask anything about stocks, technical analysis, or predictions.")
|
181 |
+
print("Type 'exit' to quit.")
|
182 |
+
while True:
|
183 |
+
user_input = input("\nYour question: ")
|
184 |
+
if user_input.lower() in ["exit", "quit"]:
|
185 |
+
print("Goodbye!")
|
186 |
+
break
|
187 |
+
result = agent.run(user_input)
|
188 |
+
print("\nAgent's answer:\n", result)
|