Skip to content

Commit 2c6040d

Browse files
authored
Update JPX 400 Company Stock Analysis
1 parent 47b4038 commit 2c6040d

1 file changed

Lines changed: 80 additions & 55 deletions

File tree

JPX 400 Company Stock Analysis

Lines changed: 80 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ from langdetect import detect
1010

1111
def 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

193191
def 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

227250
def 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

Comments
 (0)