Skip to content

Commit 47b4038

Browse files
authored
Update JPX 400 Company Stock Analysis
1 parent 924efe2 commit 47b4038

1 file changed

Lines changed: 40 additions & 55 deletions

File tree

JPX 400 Company Stock Analysis

Lines changed: 40 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -11,32 +11,20 @@ from langdetect import detect
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"
1313

14-
print(f"Fetching URL: {url}")
1514
response = requests.get(url)
16-
17-
print(f"Response status code: {response.status_code}")
18-
1915
if response.status_code != 200:
2016
print(f"Failed to fetch the webpage. Status code: {response.status_code}")
2117
return []
2218

2319
soup = BeautifulSoup(response.content, 'html.parser')
24-
2520
stock_table = soup.find('table', {'class': 'md-l-table-type01'})
26-
2721
if stock_table is None:
28-
print("Could not find table with class 'md-l-table-type01'")
2922
all_tables = soup.find_all('table')
30-
print(f"Number of tables found: {len(all_tables)}")
31-
3223
for table in all_tables:
3324
if table.find('tr'):
3425
stock_table = table
35-
print(f"Using table with classes: {stock_table.get('class', 'No class')}")
3626
break
37-
3827
if stock_table is None:
39-
print("Could not find any suitable table")
4028
return []
4129

4230
stock_data = []
@@ -46,20 +34,14 @@ def get_stock_codes_and_names():
4634
stock_code = cells[0].text.strip()
4735
company_name = cells[1].text.strip()
4836
stock_data.append((stock_code, company_name))
49-
50-
print(f"Found {len(stock_data)} stocks")
5137
return stock_data
5238

5339
def scrape_nikkei_news(stock_number):
5440
url = f"https://www.nikkei.com/nkd/company/news/?scode={stock_number}&ba=1"
5541
response = requests.get(url)
5642
soup = BeautifulSoup(response.content, 'html.parser')
5743
news_items = soup.find_all('a', href=lambda href: href and "/nkd/company/article/" in href)
58-
news_data = []
59-
for item in news_items:
60-
title = item.text.strip()
61-
url = "https://www.nikkei.com" + item['href']
62-
news_data.append({"title": title, "url": url})
44+
news_data = [{"title": item.text.strip(), "url": "https://www.nikkei.com" + item['href']} for item in news_items]
6345
return news_data
6446

6547
def scrape_yahoo_finance_news(stock_number):
@@ -83,12 +65,8 @@ def analyze_sentiment(text, ja_tokenizer, ja_model, en_tokenizer, en_model):
8365
except:
8466
lang = 'ja' # Default to Japanese if detection fails
8567

86-
if lang == 'ja':
87-
tokenizer = ja_tokenizer
88-
model = ja_model
89-
else:
90-
tokenizer = en_tokenizer
91-
model = en_model
68+
tokenizer = ja_tokenizer if lang == 'ja' else en_tokenizer
69+
model = ja_model if lang == 'ja' else en_model
9270

9371
inputs = tokenizer(text, return_tensors="pt", truncation=True, max_length=512)
9472
outputs = model(**inputs)
@@ -121,13 +99,11 @@ def get_stock_data(stock_number):
12199
try:
122100
df = yf.download(ticker, start=start_date, end=end_date)
123101
if df.empty:
124-
print("No data found for the specified stock number.")
125102
return None
126103

127104
df = df.reset_index()
128105
df['Date'] = pd.to_datetime(df['Date'])
129106
stock_data = [(row['Date'], row['Close']) for _, row in df.iterrows()]
130-
131107
stock_data.sort(key=lambda x: x[0], reverse=True)
132108
return stock_data[:30]
133109

@@ -155,7 +131,10 @@ def calculate_stock_trend(stock_data):
155131
else:
156132
return "Neutral"
157133

158-
def get_action_recommendation(public_opinion, stock_trend, current_price):
134+
def get_action_recommendation(public_opinion, stock_trend, stock_price_data):
135+
if not stock_price_data:
136+
return "Insufficient data for recommendation"
137+
159138
opinion_score = {
160139
"Very Positive": 2, "Positive": 1, "Neutral": 0, "Negative": -1, "Very Negative": -2
161140
}
@@ -165,11 +144,20 @@ def get_action_recommendation(public_opinion, stock_trend, current_price):
165144

166145
total_score = opinion_score[public_opinion] + trend_score[stock_trend]
167146

147+
# Calculate average price and standard deviation
148+
prices = [price for _, price in stock_price_data]
149+
avg_price = np.mean(prices)
150+
std_dev = np.std(prices)
151+
152+
current_price = stock_price_data[0][1] # Most recent price
153+
168154
if total_score >= 2:
169-
target_price = current_price * 1.05 # 5% above current price
155+
# Buy recommendation: Set target slightly below current price
156+
target_price = max(current_price * 0.98, avg_price - 0.5 * std_dev)
170157
return f"Buy (Target: ¥{target_price:.2f})"
171158
elif total_score <= -2:
172-
target_price = current_price * 1.05 # 5% above current price for selling
159+
# Sell recommendation: Set target slightly above current price
160+
target_price = min(current_price * 1.02, avg_price + 0.5 * std_dev)
173161
return f"Sell (Target: ¥{target_price:.2f})"
174162
else:
175163
return "Hold"
@@ -237,22 +225,21 @@ def interactive_results_display(stock_analysis):
237225
print("Invalid input. Please type 'continue', '#<rank>', '#buy', '#sell', '#hold', or 'exit'.")
238226

239227
def main():
240-
print("Fetching stock codes and company names from the website...")
241228
stock_data = get_stock_codes_and_names()
242-
print(f"Found {len(stock_data)} stocks.")
243-
229+
if not stock_data:
230+
print("Failed to retrieve stock data. Please check your internet connection and try again.")
231+
return
232+
244233
ja_tokenizer = AutoTokenizer.from_pretrained("jarvisx17/japanese-sentiment-analysis")
245234
ja_model = AutoModelForSequenceClassification.from_pretrained("jarvisx17/japanese-sentiment-analysis")
246235

247236
en_tokenizer = AutoTokenizer.from_pretrained("distilbert-base-uncased-finetuned-sst-2-english")
248237
en_model = AutoModelForSequenceClassification.from_pretrained("distilbert-base-uncased-finetuned-sst-2-english")
249-
238+
250239
stock_analysis = []
251-
240+
252241
for stock_number, company_name in stock_data:
253242
try:
254-
print(f"Analyzing {company_name} ({stock_number})...")
255-
256243
nikkei_news_data = scrape_nikkei_news(stock_number)
257244
yahoo_finance_news_data = scrape_yahoo_finance_news(stock_number)
258245

@@ -269,28 +256,26 @@ def main():
269256
current_stock_price = stock_price_data[0][1] if stock_price_data else None
270257
stock_trend = calculate_stock_trend(stock_price_data)
271258

272-
action = get_action_recommendation(overall_sentiment, stock_trend, current_stock_price) if current_stock_price else "N/A"
259+
action = get_action_recommendation(overall_sentiment, stock_trend, stock_price_data) if stock_price_data else "Insufficient data"
273260

274261
stock_analysis.append({
275-
"company_name": company_name,
276-
"stock_number": stock_number,
277-
"current_stock_price": current_stock_price,
278-
"nikkei_sentiment": nikkei_overall_sentiment,
279-
"yahoo_sentiment": yahoo_finance_overall_sentiment,
280-
"overall_sentiment": overall_sentiment,
281-
"overall_sentiment_value": overall_sentiment_value,
282-
"stock_trend": stock_trend,
283-
"action": action,
284-
"nikkei_news": [{"title": news['title'], "url": news['url']} for news in nikkei_news_data],
285-
"yahoo_news": [{"title": news['title'], "url": news['url']} for news in yahoo_finance_news_data]
262+
'stock_number': stock_number,
263+
'company_name': company_name,
264+
'current_stock_price': current_stock_price,
265+
'nikkei_sentiment': nikkei_overall_sentiment,
266+
'yahoo_sentiment': yahoo_finance_overall_sentiment,
267+
'overall_sentiment': overall_sentiment,
268+
'stock_trend': stock_trend,
269+
'action': action,
270+
'nikkei_news': nikkei_news_data,
271+
'yahoo_news': yahoo_finance_news_data
286272
})
273+
274+
print(f"Processed {company_name} ({stock_number})")
275+
287276
except Exception as e:
288-
print(f"Error analyzing {stock_number}: {e}")
289-
290-
# Sort stocks based on overall sentiment value (higher is better)
291-
stock_analysis.sort(key=lambda x: x["overall_sentiment_value"], reverse=True)
292-
293-
print("\nStock Analysis Results (Sorted from Best to Worst):")
277+
print(f"Error processing {company_name} ({stock_number}): {str(e)}")
278+
294279
interactive_results_display(stock_analysis)
295280

296281
if __name__ == '__main__':

0 commit comments

Comments
 (0)