@@ -10,7 +10,6 @@ from langdetect import detect
1010
1111def get_stock_codes_and_names():
1212 url = "https://site2.sbisec.co.jp/ETGate/?OutSide=on&_ControlID=WPLETmgR001Control&_PageID=WPLETmgR001Mdtl20&_DataStoreID=DSWPLETmgR001Control&_ActionID=DefaultAID&getFlg=on&burl=search_market&cat1=market&cat2=none&dir=info&file=market_meigara_400.html"
13-
1413 response = requests.get(url)
1514 if response.status_code != 200:
1615 print(f"Failed to fetch the webpage. Status code: {response.status_code}")
@@ -131,64 +130,63 @@ def calculate_stock_trend(stock_data):
131130 else:
132131 return "Neutral"
133132
134- def get_action_recommendation(public_opinion, stock_trend, stock_price_data):
133+ def display_stock_info(stock, rank):
134+ print(f"{rank}. {stock['company_name']} ({stock['stock_number']}):")
135+ print(f" Current Price: ¥{stock['current_stock_price']:.2f}" if stock['current_stock_price'] else " Current Price: N/A")
136+ print(f" Nikkei's Impression: {stock['nikkei_sentiment']}")
137+ print(f" Yahoo's Impression: {stock['yahoo_sentiment']}")
138+ print(f" Overall Sentiment: {stock['overall_sentiment']}")
139+ print(f" Stock Trend: {stock['stock_trend']}")
140+ print(f" Recommendation: {stock['action_recommendation']}")
141+ print()
142+
143+ def get_action_recommendation(public_opinion, stock_trend, stock_price_data, purchase_price=None):
135144 if not stock_price_data:
136145 return "Insufficient data for recommendation"
137146
138- opinion_score = {
139- "Very Positive": 2, "Positive": 1, "Neutral": 0, "Negative": -1, "Very Negative": -2
140- }
141- trend_score = {
142- "Strong Uptrend": 2, "Uptrend": 1, "Neutral": 0, "Downtrend": -1, "Strong Downtrend": -2
143- }
147+ opinion_score = {"Very Positive": 2, "Positive": 1, "Neutral": 0, "Negative": -1, "Very Negative": -2}
148+ trend_score = {"V-Shape Recovery": 1, "Upward Trend": 1, "Downward Trend": -1, "No specific pattern identified": 0}
144149
145- total_score = opinion_score[ public_opinion] + trend_score[ stock_trend]
150+ total_score = opinion_score.get( public_opinion, 0) + trend_score.get( stock_trend, 0)
146151
147- # Calculate average price and standard deviation
148152 prices = [price for _, price in stock_price_data]
153+ current_price = prices[0]
149154 avg_price = np.mean(prices)
150155 std_dev = np.std(prices)
151156
152- current_price = stock_price_data[0][1] # Most recent price
157+ owns_stock = purchase_price is not None
153158
154- if total_score >= 2:
155- # Buy recommendation: Set target slightly below current price
156- target_price = max(current_price * 0.98, avg_price - 0.5 * std_dev)
157- return f"Buy (Target: ¥{target_price:.2f})"
158- elif total_score <= -2:
159- # Sell recommendation: Set target slightly above current price
160- target_price = min(current_price * 1.02, avg_price + 0.5 * std_dev)
161- return f"Sell (Target: ¥{target_price:.2f})"
159+ if owns_stock:
160+ price_change = (current_price - purchase_price) / purchase_price * 100
161+
162+ if total_score > 0:
163+ action = "Hold"
164+ explanation = f"Positive outlook. You're currently up {price_change:.2f}%. Consider holding for potential further gains."
165+ elif total_score < 0:
166+ action = "Consider Selling"
167+ explanation = f"Negative outlook. You're currently {'up' if price_change > 0 else 'down'} {abs(price_change):.2f}%. Consider selling to {'lock in profits' if price_change > 0 else 'minimize losses'}."
168+ else:
169+ action = "Hold and Monitor"
170+ explanation = f"Mixed signals. You're currently {'up' if price_change > 0 else 'down'} {abs(price_change):.2f}%. Monitor the stock closely for changes in sentiment or market trends."
171+
172+ if price_change > 20:
173+ explanation += " However, with significant gains, consider taking partial profits."
174+ elif price_change < -20:
175+ explanation += " However, with significant losses, reassess your investment thesis."
162176 else:
163- return "Hold"
177+ if total_score > 0:
178+ target_price = max(current_price * 0.99, avg_price - 0.5 * std_dev)
179+ action = f"Consider Buying (Target: ¥{target_price:.2f})"
180+ explanation = "Positive outlook. Consider buying near the suggested target price."
181+ elif total_score < 0:
182+ action = "Hold Off"
183+ explanation = "Negative outlook. It might be better to wait for a more favorable entry point."
184+ else:
185+ action = "Monitor"
186+ explanation = "Mixed signals. Monitor the stock for a clearer trend before making a decision."
164187
165- def display_stock_info(stock, rank):
166- print(f"{rank}. {stock['company_name']} ({stock['stock_number']}):")
167- print(f" Current Price: ¥{stock['current_stock_price']:.2f}" if stock['current_stock_price'] else " Current Price: N/A")
168- print(f" Nikkei's Impression: {stock['nikkei_sentiment']}")
169- print(f" Yahoo's Impression: {stock['yahoo_sentiment']}")
170- print(f" Overall Public Opinion: {stock['overall_sentiment']}")
171- print(f" Stock Trend: {stock['stock_trend']}")
172- print(f" Action: {stock['action']}")
173- print()
188+ return f"{action}\nExplanation: {explanation}"
174189
175- def display_detailed_analysis(stock):
176- print(f"\nDetailed Analysis for {stock['company_name']} ({stock['stock_number']}):")
177- print(f"Current Price: ¥{stock['current_stock_price']:.2f}" if stock['current_stock_price'] else "Current Price: N/A")
178- print(f"Nikkei's Impression: {stock['nikkei_sentiment']}")
179- print(f"Yahoo's Impression: {stock['yahoo_sentiment']}")
180- print(f"Overall Public Opinion: {stock['overall_sentiment']}")
181- print(f"Stock Trend: {stock['stock_trend']}")
182- print(f"Action: {stock['action']}")
183- print("\nNikkei News:")
184- for i, news in enumerate(stock['nikkei_news'], 1):
185- print(f" {i}. {news['title']}")
186- print(f" URL: {news['url']}")
187- print("\nYahoo Finance News:")
188- for i, news in enumerate(stock['yahoo_news'], 1):
189- print(f" {i}. {news['title']}")
190- print(f" URL: {news['url']}")
191- print()
192190
193191def interactive_results_display(stock_analysis):
194192 current_index = 0
@@ -199,16 +197,19 @@ def interactive_results_display(stock_analysis):
199197 if current_index + 10 >= len(stock_analysis):
200198 print("End of list reached.")
201199
202- user_input = input("Type 'continue' to see more results, '#<rank>' to see detailed analysis for a stock, '#buy', '#sell', or '#hold' to see top stocks for each action , or 'exit' to quit: ").strip().lower()
200+ user_input = input("Type 'continue' to see more results, '#<rank>' to see detailed analysis for a stock, '#recommend' to see top recommended stocks , or 'exit' to quit: ").strip().lower()
203201
204202 if user_input == 'continue' and current_index + 10 < len(stock_analysis):
205203 current_index += 10
206204 elif user_input.startswith('#'):
207- if user_input[1:] in ['buy', 'sell', 'hold']:
208- action = user_input[1:].capitalize()
209- top_stocks = [s for s in stock_analysis if s['action'].startswith(action)][:5]
210- print(f"\nTop 5 stocks to {action}:")
211- for i, stock in enumerate(top_stocks, 1):
205+ if user_input[1:] == 'recommend':
206+ recommended_stocks = sorted(
207+ [s for s in stock_analysis if 'Buy' in s['action_recommendation'] or 'Hold' in s['action_recommendation']],
208+ key=lambda x: x['current_stock_price'],
209+ reverse=True
210+ )[:5]
211+ print("\nTop 5 Recommended Stocks:")
212+ for i, stock in enumerate(recommended_stocks, 1):
212213 display_stock_info(stock, i)
213214 else:
214215 try:
@@ -222,7 +223,29 @@ def interactive_results_display(stock_analysis):
222223 elif user_input == 'exit':
223224 break
224225 else:
225- print("Invalid input. Please type 'continue', '#<rank>', '#buy', '#sell', '#hold', or 'exit'.")
226+ print("Invalid input. Please type 'continue', '#<rank>', '#recommend', or 'exit'.")
227+
228+ def display_detailed_analysis(stock):
229+ print(f"\nDetailed Analysis for {stock['company_name']} ({stock['stock_number']}):")
230+ print(f"Current Price: ¥{stock['current_stock_price']:.2f}" if stock['current_stock_price'] else "Current Price: N/A")
231+ if stock['purchase_price']:
232+ print(f"Purchase Price: ¥{stock['purchase_price']:.2f}")
233+ price_change = ((stock['current_stock_price'] - stock['purchase_price']) / stock['purchase_price']) * 100
234+ print(f"Price Change: {price_change:.2f}%")
235+ print(f"Nikkei's Impression: {stock['nikkei_sentiment']}")
236+ print(f"Yahoo's Impression: {stock['yahoo_sentiment']}")
237+ print(f"Overall Sentiment: {stock['overall_sentiment']}")
238+ print(f"Stock Trend: {stock['stock_trend']}")
239+ print(f"Recommendation: {stock['action_recommendation']}")
240+ print("\nNikkei News:")
241+ for i, news in enumerate(stock['nikkei_news'], 1):
242+ print(f" {i}. {news['title']}")
243+ print(f" URL: {news['url']}")
244+ print("\nYahoo Finance News:")
245+ for i, news in enumerate(stock['yahoo_news'], 1):
246+ print(f" {i}. {news['title']}")
247+ print(f" URL: {news['url']}")
248+ print()
226249
227250def main():
228251 stock_data = get_stock_codes_and_names()
@@ -240,6 +263,8 @@ def main():
240263
241264 for stock_number, company_name in stock_data:
242265 try:
266+ print(f"Processing {company_name} ({stock_number})...")
267+
243268 nikkei_news_data = scrape_nikkei_news(stock_number)
244269 yahoo_finance_news_data = scrape_yahoo_finance_news(stock_number)
245270
@@ -256,7 +281,7 @@ def main():
256281 current_stock_price = stock_price_data[0][1] if stock_price_data else None
257282 stock_trend = calculate_stock_trend(stock_price_data)
258283
259- action = get_action_recommendation(overall_sentiment, stock_trend, stock_price_data) if stock_price_data else "Insufficient data"
284+ action_recommendation = get_action_recommendation(overall_sentiment, stock_trend, stock_price_data)
260285
261286 stock_analysis.append({
262287 'stock_number': stock_number,
@@ -266,7 +291,7 @@ def main():
266291 'yahoo_sentiment': yahoo_finance_overall_sentiment,
267292 'overall_sentiment': overall_sentiment,
268293 'stock_trend': stock_trend,
269- 'action ': action ,
294+ 'action_recommendation ': action_recommendation ,
270295 'nikkei_news': nikkei_news_data,
271296 'yahoo_news': yahoo_finance_news_data
272297 })
0 commit comments