Skip to content

Commit 28c73c9

Browse files
authored
Merge pull request #203 from FunD-StockProject/refactor/cron-tue-to-thu
Refactor: 종목 데이터 업데이트 요일을 화요일에서 목요일로 변경
2 parents c3c9803 + 0adc14d commit 28c73c9

File tree

4 files changed

+27
-46
lines changed

4 files changed

+27
-46
lines changed

scripts/import_stocks.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ def map_overseas_exchange(exchange_id, exchange_code):
4949

5050
def process_korea_stocks():
5151
"""국내 주식 종목 데이터 처리"""
52-
base_dir = os.path.join(os.path.dirname(__file__), '..', 'open-trading-api', 'stocks_info')
52+
# stocks_info 디렉토리를 base_dir로 사용
53+
base_dir = os.path.join(os.path.dirname(__file__), 'stocks_info')
5354
os.makedirs(base_dir, exist_ok=True)
5455

5556
stocks = []
@@ -130,7 +131,8 @@ def process_korea_stocks():
130131

131132
def process_overseas_stocks():
132133
"""해외 주식 종목 데이터 처리"""
133-
base_dir = os.path.join(os.path.dirname(__file__), '..', 'open-trading-api', 'stocks_info')
134+
# stocks_info 디렉토리를 base_dir로 사용
135+
base_dir = os.path.join(os.path.dirname(__file__), 'stocks_info')
134136
os.makedirs(base_dir, exist_ok=True)
135137

136138
stocks = []

scripts/stocks_info/kis_kospi_code_mst.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ def kospi_master_download(base_dir, verbose=False):
1313
if (verbose): print(f"current directory is {cwd}")
1414
ssl._create_default_https_context = ssl._create_unverified_context
1515

16-
import os
1716
urllib.request.urlretrieve("https://new.real.download.dws.co.kr/common/master/kospi_code.mst.zip",
1817
os.path.join(base_dir, "kospi_code.zip"))
1918

src/main/java/com/fund/stockProject/global/scheduler/StockUpdateScheduler.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ public class StockUpdateScheduler {
1818
private final StockImportService stockImportService;
1919

2020
/**
21-
* 매주 화요일 새벽 3시에 종목 마스터 데이터 업데이트
21+
* 매주 목요일 새벽 3시에 종목 마스터 데이터 업데이트
2222
* Python 스크립트를 실행하여 최신 종목 데이터를 수집하고 DB에 반영합니다.
2323
*/
24-
@Scheduled(cron = "0 0 3 * * TUE", zone = "Asia/Seoul") // 매주 화요일 3시 실행
24+
@Scheduled(cron = "0 0 3 * * THU", zone = "Asia/Seoul") // 매주 목요일 3시 실행
2525
public void updateStockMaster() {
2626
log.info("Starting weekly stock master update scheduler");
2727

src/main/java/com/fund/stockProject/stock/service/StockImportService.java

Lines changed: 21 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,12 @@ public void importStocksFromJson(String jsonFilePath) {
6262
int invalidated = 0;
6363
int preserved = 0;
6464

65+
// 기존 종목들을 symbol로 조회하여 Map으로 변환 (성능 최적화)
66+
Map<String, Stock> existingStocksMap = stockRepository.findAll().stream()
67+
.collect(Collectors.toMap(Stock::getSymbol, stock -> stock, (existing, replacement) -> existing));
68+
6569
// 1. 종목 마스터에 있는 종목 처리 (추가/업데이트)
70+
List<Stock> stocksToSave = new ArrayList<>();
6671
for (Map<String, Object> stockData : stocksData) {
6772
try {
6873
String symbol = (String) stockData.get("symbol");
@@ -86,63 +91,38 @@ public void importStocksFromJson(String jsonFilePath) {
8691
continue;
8792
}
8893

89-
// 섹터 코드 매핑 (KIS 업종 코드 → DomesticSector 또는 OverseasSector)
90-
// KIS에서 제공하는 공식 업종 코드를 그대로 사용합니다.
91-
if (sectorCodeStr != null && !sectorCodeStr.isEmpty() && !sectorCodeStr.equals("nan")) {
92-
if (exchangeNum == EXCHANGENUM.KOSPI || exchangeNum == EXCHANGENUM.KOSDAQ) {
93-
// 국내 주식: DomesticSector 사용
94-
DomesticSector domesticSector = DomesticSector.fromCode(sectorCodeStr, exchangeNum);
95-
if (domesticSector == DomesticSector.UNKNOWN) {
96-
log.debug("Domestic sector mapping failed: code={}, exchange={}, stock={}. Using UNKNOWN.",
97-
sectorCodeStr, exchangeNum, symbol);
98-
} else {
99-
log.trace("Mapped KIS sector code: {} -> DomesticSector: {} for stock: {}",
100-
sectorCodeStr, domesticSector, symbol);
101-
}
102-
} else if (exchangeNum == EXCHANGENUM.NAS || exchangeNum == EXCHANGENUM.NYS || exchangeNum == EXCHANGENUM.AMS) {
103-
// 해외 주식: OverseasSector 사용
104-
OverseasSector overseasSector = OverseasSector.fromCode(sectorCodeStr);
105-
if (overseasSector == OverseasSector.UNKNOWN) {
106-
log.debug("Overseas sector mapping failed: code={}, exchange={}, stock={}. Using UNKNOWN.",
107-
sectorCodeStr, exchangeNum, symbol);
108-
} else {
109-
log.trace("Mapped KIS sector code: {} -> OverseasSector: {} for stock: {}",
110-
sectorCodeStr, overseasSector, symbol);
111-
}
112-
}
113-
}
114-
94+
Stock stock;
11595
// 기존 종목 확인
116-
Optional<Stock> existingStock = stockRepository.findBySymbol(symbol);
117-
118-
if (existingStock.isPresent()) {
96+
if (existingStocksMap.containsKey(symbol)) {
11997
// 기존 종목 업데이트
120-
Stock stock = existingStock.get();
98+
stock = existingStocksMap.get(symbol);
12199
stock.updateSymbolNameIfNull(symbolName);
122100
// 종목 마스터에 있으므로 valid = true로 설정
123101
setStockValid(stock, true);
124-
// 섹터 업데이트
125-
if (sectorCodeStr != null && !sectorCodeStr.isEmpty() && !sectorCodeStr.equals("nan")) {
126-
stock.setSectorByExchange(sectorCodeStr, exchangeNum);
127-
}
128-
stockRepository.save(stock);
129102
updated++;
130103
} else {
131104
// 새 종목 생성
132-
Stock stock = createStock(symbol, symbolName, securityName, exchangeNum, true);
133-
// 섹터 설정
134-
if (sectorCodeStr != null && !sectorCodeStr.isEmpty() && !sectorCodeStr.equals("nan")) {
135-
stock.setSectorByExchange(sectorCodeStr, exchangeNum);
136-
}
137-
stockRepository.save(stock);
105+
stock = createStock(symbol, symbolName, securityName, exchangeNum, true);
138106
saved++;
139107
}
108+
109+
// 섹터 업데이트
110+
if (sectorCodeStr != null && !sectorCodeStr.isEmpty() && !sectorCodeStr.equals("nan")) {
111+
stock.setSectorByExchange(sectorCodeStr, exchangeNum);
112+
}
113+
114+
stocksToSave.add(stock);
140115

141116
} catch (Exception e) {
142117
log.error("Error processing stock: {}", stockData, e);
143118
skipped++;
144119
}
145120
}
121+
122+
// 배치로 저장
123+
if (!stocksToSave.isEmpty()) {
124+
stockRepository.saveAll(stocksToSave);
125+
}
146126

147127
// 2. 종목 마스터에 없는 종목 찾기
148128
List<Stock> allStocks = stockRepository.findAll();

0 commit comments

Comments
 (0)