섹터 유니버스 분리와 월간 갱신 정합화
This commit is contained in:
@@ -174,6 +174,28 @@ def normalize_legacy_source_markers(sheet: str, records: list[dict[str, Any]]) -
|
||||
source = record.get("Source")
|
||||
if isinstance(source, str) and "sector_targets.json" in source:
|
||||
record["Source"] = source.replace("sector_targets.json", "sector_universe")
|
||||
source_url = str(record.get("Source_URL") or "").strip()
|
||||
transport_mode = str(record.get("Transport_Mode") or "").strip()
|
||||
if record.get("Source") in (None, "", "DEFAULT_TEMPLATE"):
|
||||
if "finance.naver.com/item/main.naver?code=" in source_url:
|
||||
record["Source"] = "NAVER_ETF_PAGE"
|
||||
if not transport_mode:
|
||||
record["Transport_Mode"] = "HTML_SERVER_RENDERED"
|
||||
elif source_url:
|
||||
record["Source"] = "SHEET_INPUT"
|
||||
if not transport_mode:
|
||||
record["Transport_Mode"] = "MANUAL_OR_TEMPLATE"
|
||||
else:
|
||||
record["Source"] = "SHEET_INPUT"
|
||||
if not transport_mode:
|
||||
record["Transport_Mode"] = "MANUAL_OR_TEMPLATE"
|
||||
elif record.get("Source") == "NAVER_ETF_PAGE_FAIL_LAYOUT_CHANGED" and not transport_mode:
|
||||
record["Transport_Mode"] = "LAYOUT_CHANGED"
|
||||
elif record.get("Source") == "REPRESENTATIVE_STOCK_PROXY" and not transport_mode:
|
||||
record["Transport_Mode"] = "HTML_SERVER_RENDERED"
|
||||
sector = str(record.get("Sector") or "").strip()
|
||||
if sector:
|
||||
record["Sector_Check"] = sector
|
||||
return records
|
||||
|
||||
|
||||
@@ -1428,6 +1450,80 @@ def convert_xlsx_to_json(xlsx_path: Path, output_path: Path) -> None:
|
||||
result["data"][sheet] = normalize_legacy_source_markers(sheet, dataframe_records(df))
|
||||
result["metadata"]["sheets_included"].append(sheet)
|
||||
|
||||
sector_source_map: dict[str, str] = {}
|
||||
sector_universe_rows = result["data"].get("sector_universe")
|
||||
if isinstance(sector_universe_rows, list):
|
||||
for row in sector_universe_rows:
|
||||
if not isinstance(row, dict):
|
||||
continue
|
||||
sector = str(row.get("Sector") or "").strip()
|
||||
if not sector:
|
||||
continue
|
||||
source = str(row.get("Source") or "").strip() or "SHEET_INPUT"
|
||||
sector_source_map.setdefault(sector, source)
|
||||
|
||||
sector_flow_rows = result["data"].get("sector_flow")
|
||||
if isinstance(sector_flow_rows, list):
|
||||
split_finance_map = {
|
||||
"금융/은행": [
|
||||
("은행", "091170", "KODEX 은행"),
|
||||
("증권", "0111J0", "HANARO 증권고배당TOP3플러스"),
|
||||
("지주회사", "307520", "TIGER 지주회사"),
|
||||
]
|
||||
}
|
||||
normalized_rows: list[dict[str, Any]] = []
|
||||
for row in sector_flow_rows:
|
||||
if not isinstance(row, dict):
|
||||
continue
|
||||
sector = str(row.get("Sector") or "").strip()
|
||||
if not sector:
|
||||
continue
|
||||
source = str(row.get("Universe_Source") or "").strip() or sector_source_map.get(sector, "SHEET_INPUT")
|
||||
row["Universe_Source"] = source
|
||||
if sector in split_finance_map:
|
||||
for split_sector, split_ticker, split_name in split_finance_map[sector]:
|
||||
cloned = dict(row)
|
||||
cloned["Sector"] = split_sector
|
||||
cloned["Proxy_Ticker"] = split_ticker
|
||||
cloned["Proxy_Name"] = split_name
|
||||
cloned["Proxy_Type"] = "ETF"
|
||||
cloned["ETF_Code"] = split_ticker
|
||||
cloned["Reason"] = "PRE_SPLIT_FINANCE_FLOW_CARRYOVER"
|
||||
cloned["Universe_Source"] = "NAVER_ETF_PAGE"
|
||||
normalized_rows.append(cloned)
|
||||
else:
|
||||
normalized_rows.append(row)
|
||||
result["data"]["sector_flow"] = normalized_rows
|
||||
|
||||
sector_flow_history_rows = result["data"].get("sector_flow_history")
|
||||
if isinstance(sector_flow_history_rows, list):
|
||||
split_finance_map = {
|
||||
"금융/은행": [
|
||||
("은행", "091170", "KODEX 은행"),
|
||||
("증권", "0111J0", "HANARO 증권고배당TOP3플러스"),
|
||||
("지주회사", "307520", "TIGER 지주회사"),
|
||||
]
|
||||
}
|
||||
normalized_history: list[dict[str, Any]] = []
|
||||
for row in sector_flow_history_rows:
|
||||
if not isinstance(row, dict):
|
||||
continue
|
||||
sector = str(row.get("Sector") or "").strip()
|
||||
if not sector:
|
||||
continue
|
||||
if sector in split_finance_map:
|
||||
for split_sector, split_ticker, split_name in split_finance_map[sector]:
|
||||
cloned = dict(row)
|
||||
cloned["Sector"] = split_sector
|
||||
cloned["Proxy_Ticker"] = split_ticker
|
||||
cloned["Proxy_Name"] = split_name
|
||||
cloned["Proxy_Type"] = "ETF"
|
||||
cloned["Reason"] = "PRE_SPLIT_FINANCE_FLOW_CARRYOVER"
|
||||
normalized_history.append(cloned)
|
||||
else:
|
||||
normalized_history.append(row)
|
||||
result["data"]["sector_flow_history"] = normalized_history
|
||||
|
||||
# harness_context 시트가 없으면 메타에 경고 기록
|
||||
if "_harness_context" not in result["data"]:
|
||||
result["metadata"]["harness_context_missing"] = (
|
||||
|
||||
Reference in New Issue
Block a user