younginpiniti commited on
Commit
1411904
·
1 Parent(s): 8e9b019

feat: 데이터셋 생성 로직을 추가하고 관련 의존성을 업데이트했습니다.

Browse files
Files changed (2) hide show
  1. app.py +42 -38
  2. requirements.txt +2 -2
app.py CHANGED
@@ -7,17 +7,13 @@
7
  import gradio as gr
8
  import yfinance as yf
9
  import pandas as pd
10
- import numpy as np
11
  from datetime import datetime, timedelta
12
  from zoneinfo import ZoneInfo
13
  from datasets import Dataset
14
  from huggingface_hub import HfApi
15
  import os
16
  import time
17
- import io
18
  import logging
19
- import traceback
20
- import requests
21
 
22
  # 로깅 설정
23
  logging.basicConfig(level=logging.INFO)
@@ -29,51 +25,59 @@ HF_TOKEN = os.environ.get("HF_TOKEN", "")
29
 
30
  def get_all_us_tickers():
31
  """
32
- 공식 FTP에서 나스닥(Q) + 뉴욕증권거래소(N) 보통주 티커 목록을 가져옴.
33
- - 스: nasdaqtrader.com/dynamic/SymDir/nasdaqtraded.txt
34
- - 파이프(|) 구분 CSV, 'Listing Exchange' 컬럼으로 거래소 구분
35
- Q = , N = 뉴욕증권거래소(NYSE)
36
- - 필터링: 테스트 종목, ETF, 우선주, 워런트, 유닛 등 제외
37
- - 보통주(Common Stock)만 추출
38
  반환: (nasdaq_tickers, nyse_tickers, all_tickers)
39
  """
40
- try:
41
- ftp_url = "https://www.nasdaqtrader.com/dynamic/SymDir/nasdaqtraded.txt"
42
- df = pd.read_csv(ftp_url, sep="|")
43
-
44
- # 1. 마지막 행은 메타데이터("File Creation Time: ...")이므로 제거
45
- df = df[:-1]
46
-
47
- # 2. 테스트 종목 제외
48
- if "Test Issue" in df.columns:
49
- df = df[df["Test Issue"] == "N"]
50
 
51
- # 3. ETF 제외
52
- if "ETF" in df.columns:
53
- df = df[df["ETF"] == "N"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
 
55
- # 4. [핵심] 보통주만 추출 - Security Name에 보통주 키워드가 포함된 것만
56
- # Common Stock, Common Shares, Ordinary Shares 등
57
- common_stock_filter = df["Security Name"].str.contains(
58
- "Common Stock|Common Shares|Ordinary Shares",
59
- case=False, na=False
60
- )
61
- df = df[common_stock_filter]
62
-
63
- # 5. [핵심] 티커에 특수문자($, ., -) 포함된 파생 종목 제외
64
- # 보통주 티커는 순수 알파벳으로만 구성됨
65
- df = df[~df["Symbol"].str.contains(r'[\$\.\-]', na=False)]
 
 
 
 
66
 
67
- # 6. 거래소별 분류
68
- nasdaq_tickers = sorted(df[df["Listing Exchange"] == "Q"]["Symbol"].unique().tolist())
69
- nyse_tickers = sorted(df[df["Listing Exchange"] == "N"]["Symbol"].unique().tolist())
70
  all_tickers = sorted(list(set(nasdaq_tickers + nyse_tickers)))
71
 
72
  logger.info(f"나스닥: {len(nasdaq_tickers)}개, 뉴욕: {len(nyse_tickers)}개, 전체: {len(all_tickers)}개 로드 완료")
73
  return nasdaq_tickers, nyse_tickers, all_tickers
74
 
75
  except Exception as e:
76
- logger.error(f" FTP 티커 로드 실패: {e}")
77
  return [], [], []
78
 
79
 
 
7
  import gradio as gr
8
  import yfinance as yf
9
  import pandas as pd
 
10
  from datetime import datetime, timedelta
11
  from zoneinfo import ZoneInfo
12
  from datasets import Dataset
13
  from huggingface_hub import HfApi
14
  import os
15
  import time
 
16
  import logging
 
 
17
 
18
  # 로깅 설정
19
  logging.basicConfig(level=logging.INFO)
 
25
 
26
  def get_all_us_tickers():
27
  """
28
+ 야후 파이낸스크리너(yf.screen)를 사용하여 나스닥 + 뉴욕증권거래소 티커 목록을 가져옴.
29
+ - 닥은 3개 마켓으로 구성: NMS(글로벌셀렉트), NGM(글로벌마켓), NCM(캐피털마켓)
30
+ - 뉴욕증권거래소: NYQ
31
+ - yfinance 내장 기능이라 별도 데이터 소 불필요, HF Spaces에서도 동작
 
 
32
  반환: (nasdaq_tickers, nyse_tickers, all_tickers)
33
  """
 
 
 
 
 
 
 
 
 
 
34
 
35
+ def _fetch_exchange_tickers(exchange_code):
36
+ """야후 스크리너에서 특정 거래소의 전체 티커를 페이징으로 가져오기"""
37
+ query = yf.EquityQuery("eq", ["exchange", exchange_code])
38
+ symbols = []
39
+ offset = 0
40
+
41
+ while True:
42
+ result = yf.screen(query, size=250, offset=offset)
43
+ quotes = result.get("quotes", [])
44
+ if not quotes:
45
+ break
46
+ for quote in quotes:
47
+ sym = quote.get("symbol", "")
48
+ # [필터] '-', '.', '$'가 포함된 티커는 우선주, 유닛, 워런트 등 파생 종목이므로 제외
49
+ if sym and not any(c in sym for c in ["-", ".", "$"]):
50
+ symbols.append(sym)
51
+ offset += len(quotes)
52
+ total = result.get("total", 0)
53
+ if offset >= total:
54
+ break
55
+
56
+ return sorted(list(set(symbols)))
57
 
58
+ try:
59
+ # 나스닥: 3개 마켓 합산
60
+ # NMS = NASDAQ Global Select Market
61
+ # NGM = NASDAQ Global Market
62
+ # NCM = NASDAQ Capital Market
63
+ nasdaq_tickers = []
64
+ for market_code in ["NMS", "NGM", "NCM"]:
65
+ tickers = _fetch_exchange_tickers(market_code)
66
+ logger.info(f" 나스닥 {market_code}: {len(tickers)}개 로드")
67
+ nasdaq_tickers.extend(tickers)
68
+ nasdaq_tickers = sorted(list(set(nasdaq_tickers)))
69
+
70
+ # 뉴욕증권거래소(NYSE): NYQ
71
+ nyse_tickers = _fetch_exchange_tickers("NYQ")
72
+ logger.info(f" 뉴욕 NYQ: {len(nyse_tickers)}개 로드")
73
 
 
 
 
74
  all_tickers = sorted(list(set(nasdaq_tickers + nyse_tickers)))
75
 
76
  logger.info(f"나스닥: {len(nasdaq_tickers)}개, 뉴욕: {len(nyse_tickers)}개, 전체: {len(all_tickers)}개 로드 완료")
77
  return nasdaq_tickers, nyse_tickers, all_tickers
78
 
79
  except Exception as e:
80
+ logger.error(f"야후 크리너 티커 로드 실패: {e}")
81
  return [], [], []
82
 
83
 
requirements.txt CHANGED
@@ -1,6 +1,6 @@
1
  gradio==6.6.0
2
- yfinance>=0.2.36
3
  pandas>=2.0.0
4
  datasets>=2.16.0
5
  huggingface_hub>=0.20.0
6
- requests
 
1
  gradio==6.6.0
2
+ yfinance>=1.0
3
  pandas>=2.0.0
4
  datasets>=2.16.0
5
  huggingface_hub>=0.20.0
6
+