Releases: redchupa/kr_finance_kit
Release list
v0.1.61 — per-position breakdown attribute on portfolio sensor
Portfolio sensors used to surface aggregate totals only (KR value/pl, US value/pl, KRW total/pl). Useful for summary cards, useless for a per-ticker holdings table — Lovelace template helpers can't reach into entry.data["positions"] directly.
sensor.fi_portfolio_krw_pl now ships a positions attribute:
positions:
- ticker: 005930
market: KR
quantity: 10
avg_price: 100000
current_price: 296000
value: 2960000
cost: 1000000
pl: 1960000
pl_pct: 196.0
- ticker: AAPL
market: US
...Markdown card example:
{% for p in state_attr('sensor.fi_portfolio_krw_pl', 'positions') %}
| {{ p.ticker }} | {{ p.quantity }} | {{ p.avg_price }} | {{ p.current_price }} | {{ p.pl_pct }}% |
{% endfor %}Read from coordinator.data — no extra fetches. Skips positions whose live quote hasn't arrived yet so the table never shows NaN. KR-first sort, then ticker.
131 / 135 tests pass.
v0.1.60 — i18n: 'detailed attributes' option in plain language
The toggle for the detailed-attributes option used to read "폴링마다 1회 추가 HTTP" and listed snake_case yfinance keys — phrasing meant for the people writing the integration, not for the people clicking the checkbox.
Rewritten label + description in both Korean and English to use Home-Assistant-user language:
Label (체크박스 옆 라벨)
종목 상세 정보 포함 (52주 최고/최저, 이동평균, 거래량, 배당, PER, 장 상태)
Description (라벨 아래 안내문)
각 종목 sensor에 깊이 있는 정보를 함께 받아옵니다 — 52주 최고/최저가, 50일·200일 이동평균선, 당일 고가/저가/거래량, 배당금·배당수익률, 주가수익비율(PER), 장 전/장 마감 후 시간외 가격, 장 상태(개장/마감). 단점: 종목 하나마다 야후 파이낸스에 데이터 요청이 한 번씩 더 들어갑니다. 종목 10개면 매 갱신마다 추가 요청 10번. 종목이 많으면 트래픽이 늘고 가끔 갱신이 느려질 수 있으니, 차트나 상세 분석이 꼭 필요할 때만 켜는 걸 추천합니다.
No behaviour change. 131 / 135 tests pass.
v0.1.59 — docs: avg_price example wording (no ambiguous trailing period)
The avg_price field description used to read Apple 180.5달러 → 180.5. 환산값으로 미리 변환하지 마세요. — the period after 180.5 looked like part of the decimal, so a user couldn't tell whether the input should be 180.5 or 180.5. (with a trailing dot).
Rewrite the examples in services.yaml + translations/{ko,en}.json to wrap the input in backticks and add an explicit parenthetical:
- 🇰🇷 KR — 평단가가 60,000원이면
60000입력 (콤마·통화기호 없이 숫자만) - 🇺🇸 US — 평단가가 180.5달러면
180.5입력 (소수점 가능)
No code changes. Behaviour unchanged. 131 / 135 tests pass.
v0.1.58 — harden add_position validation + clearer unit guidance
Why
Earlier the `add_position` schema was just `cv.string` + `vol.Coerce(float)`. That accepted empty tickers, internal whitespace, special characters, emoji, HTML / SQL injection attempts, zero, negatives, NaN, Infinity, and values above 10⁹. None of those would silently match a real quote — the result was a permanently-stuck position the user couldn't see fail. And the field descriptions said "in market currency" with no concrete examples, so users holding both KR and US had to guess at the unit.
What changes
Validation (hard fail at schema level)
- Ticker — `^[A-Za-z0-9][A-Za-z0-9.-]{0,19}$`. Empty, internal whitespace, special characters, Korean text, emoji, HTML / SQL injection attempts, > 20 chars → `vol.Invalid` before the handler runs.
- Quantity / avg_price — coerce-to-float, then reject NaN / ±Infinity / zero / negatives / values above 10⁹. The upper bound catches the common "pasted total cost instead of per-share avg" mistake.
- Market — KR / US only (unchanged, but error message clearer).
Better descriptions
- services.yaml + translations/{ko,en}.json unified: ticker shows 🇰🇷 `005930`, `035720.KQ` · 🇺🇸 `AAPL`, `BRK-B`. avg_price spells out "한국 종목 60,000원 → 60000, Apple $180.5 → 180.5" with the per-share clarification. Market radio now reads "KR (한국 주식)" / "US (미국 주식)" instead of bare codes.
Soft handler warning
When market=KR is paired with an alphabetic ticker, or market=US with an all-digit ticker, the handler still proceeds but logs a warning suggesting the user double-check.
Tests
`tests/test_services_validation.py` adds 76 parametrized cases — real ticker shapes accepted, rejection cases for every garbage class, NaN / inf / zero / negative / oversized numbers, and full schema integration.
Tests
131 / 135 pass (4 skipped: optional yfinance live tests).
v0.1.57 — docs: avg_price currency unit + crypto unsupported note
Why
The `add_position` service silently expected KR positions in KRW and US positions in USD, but the field description just said "in market currency" with no concrete example. Users holding both markets had to guess, and users with crypto/FX/futures tickers (the OTHER market) didn't realise `add_position` rejects those entirely.
What changes
- services.yaml — all descriptions unified to English, explicit "KR = KRW, US = USD, don't pre-convert" wording on `avg_price`, top-level service description flags crypto/FX/futures as price-only.
- translations/ko.json + en.json — mirror the same wording for the localised HA UI (translations override `services.yaml` when your HA language matches).
- README.md + README.en.md — bold avg_price row, ⚠ note that crypto/FX/futures are price-only, 💱 note that explains the integration handles the FX conversion itself.
TL;DR for users
- 한국 종목 평단가 → 원 (KRW) 그대로 입력
- 미국 종목 평단가 → 달러 (USD) 그대로 입력
- 환산 금지 — 통합이 자동으로 USD/KRW 환산해서 `sensor.fi_portfolio_krw_total` / `sensor.fi_portfolio_krw_pl` 에 합산
- 비트코인·암호화폐·환율·선물 → 보유 추적 미지원. 시세 sensor만 제공.
Tests
55/55 pass. No behaviour change.
v0.1.56 — fix: options dict shadowed entry.data on upgraded installs
Bug
`OptionsFlow._current()` and `sensor._entry_value()` both used `entry.options or entry.data`. The moment `entry.options` held a partial dict — for example because v0.1.54's `_save_positions` had written a six-key subset on every `add_position` call — the OR shadowed `entry.data` entirely.
Symptoms on v0.1.55:
- Options screen pre-filled ticker / label inputs with blanks even though the values were still in `entry.data`
- Saving the form persisted the blanks, wiping the user's tickers
- `sensor.py` skipped `include_global_indices`, `include_detailed_attrs`, `target_currency_krw` entities because the toggles never made it past the OR
- 글로벌 지수·USD→KRW 토글이 옵션 화면에 빠진 것처럼 보이는 부수 효과
Fix
Merge `{**entry.data, **entry.options}` in both places. Whatever options actually carries wins; `entry.data` covers everything options never re-saved. This is the same pattern `coordinator._config` was using all along.
Recovery on existing installs
- HACS → Update KR Finance Kit → v0.1.56
- Settings → Devices & Services → KR Finance Kit → CONFIGURE
- The options screen now pre-fills your real ticker values
- Tick "글로벌 지수 포함 (NIKKEI, HANGSENG, FTSE, DAX)" (and any other toggle you actually want)
- Save — auto-reload — `sensor.fi_*` 모두 살아남
Tests
55/55 pass.
v0.1.55 — fix: add_position silently dropped half the entry options
Bug
`services._save_positions` rebuilt `entry.options` from scratch using an explicit allow-list of six keys. Every other option the user had set was silently dropped on every `add_position` / `remove_position` call:
- `other_tickers` (crypto / FX / futures)
- `kr_ticker_names`, `us_ticker_labels`, `other_ticker_labels`
- `include_us_indices`, `include_global_indices`
- `target_currency_krw`
- `portfolio_pl_alert_pct`
- `disclosure_categories`
- `include_detailed_attrs`
Symptom — any sensor backed by one of those dropped options came back "restored / unavailable" on the next reload. The coordinator no longer saw the tickers, the sensor platform skipped them in `add_entities`, and HA's `restore_state` cache surfaced the last value as unavailable forever.
This bug was latent before v0.1.54 because the dashboard generally just looked at indices/FX/portfolio; v0.1.54's i18n + slug-sanitizer changes made the symptom visible the moment a user added a position post-upgrade.
Fix
Spread existing `entry.options` and only overwrite the positions slot. Every other field survives untouched.
```python
new_options = {**(entry.options or {}), CONF_POSITIONS: positions}
```
Recovery on existing installs
If your `other_tickers` / labels / toggles are missing after running `add_position` on v0.1.54 or earlier: open the integration Options screen, re-enter the affected fields, save. Saving auto-reloads and the sensors come back online.
Tests
55/55 pass.
v0.1.54 — i18n entity friendly_name + English entity_id migration
Why this release
Pre-0.1.31 sessions of this integration baked Korean device names into HA entity_ids (e.g. sensor.hangug_sijang_jipyo_kospi). For overseas HACS users this was unreadable; for Korean users it conflicted with the README examples (sensor.fi_*). v0.1.54 fixes the root cause and sweeps existing installs.
What changed
- 🌐 Entity friendly names follow your HA language —
_attr_translation_key+translations/{ko,en}.jsonmean the portfolio sensors and disclosure / P/L-alert binary_sensors show "한국 보유 평가금액" in Korean HA and "KR portfolio value" in English HA. Theentity_idslug stays English no matter what. - 🔠 All device names switched to English — "KR Indices", "US Indices", "Global Indices", "Portfolio", "Disclosure {corp_code}". The slug fallback can no longer leak Korean characters into
entity_id. - 🧹 Slug sanitizer — non-
[a-z0-9_]characters (hyphens, equals signs, whitespace) collapse to a single underscore.BTC-USD→sensor.fi_other_btc_usd,EUR=X→sensor.fi_other_eur_x, etc. — consistent for every QuoteSensor. - 🚚 One-shot entity_id migration — on next setup, any pre-0.1.31 Korean-slug entity is renamed to its new
fi_*form. History + statistics stay attached. - 📝 README rewritten holdings walkthrough — points at Developer Tools → Actions tab (HA 2024.8+ renamed "Services" → "Actions"), field-by-field table, bulk-import YAML example.
Upgrade impact
- New installs: zero change — already produced
fi_*entity_ids since 0.1.31. - Pre-0.1.31 installs: entity_ids rename automatically on HA restart.
⚠️ Anyentity_id:references in your own automations/scripts/dashboards need to be updated manually to the newsensor.fi_*form. The integration logs each rename so you can grep for them.
Tests
55/55 pass.
v0.1.53 — 단기 변동률 옵션 제거, 8개 고정 윈도우 자동 생성
변경
v0.1.52에서 도입한 "단기 변동률 윈도우 분" CSV 옵션이 사용자 입장에서 거추장스럽다는 피드백 → 옵션 제거 + sensor가 항상 8개 윈도우 attribute 자동 생성.
사용자 흐름
Before (v0.1.52)
- 옵션 화면에
15, 30, 60CSV 입력 - 블루프린트 number에 15 입력
After (v0.1.53)
- 블루프린트 number에 15 입력 (옵션 변경 없음)
자동 노출되는 attribute
모든 QuoteSensor에 다음 8개 자동:
- `change_pct_1min`
- `change_pct_5min`
- `change_pct_15min`
- `change_pct_30min`
- `change_pct_60min`
- `change_pct_90min`
- `change_pct_120min`
- `change_pct_180min`
종목별로 다른 분 트리거는 그대로 — 블루프린트 자동화를 여러 개 만들기 (예 자동화 1: 종목=[삼성], 윈도우=15 / 자동화 2: 종목=[BTC], 윈도우=60).
검증
55/55 unit tests 통과 (schema serialize 가드 포함). 8 files 변경 — sensor / config_flow / const / 3 locale / blueprint / README 둘.
How to update via HACS
HACS → KR Finance Kit → ⋮ → "저장소 정보 다시 가져오기" → v0.1.53 → HA 완전 재시작 → 옵션 화면에 단기 변동률 항목 사라짐 / sensor attribute는 자동 노출 / 블루프린트 number 입력에 8개 값 중 하나 (1·5·15·30·60·90·120·180) 선택.
v0.1.52 — 단기 변동률 분 자유 입력 + README 전체 재작성
두 가지 묶음
1. 단기 변동률 분을 자유 입력 (15/30/60 고정 X)
사용자 요청: "15분 30분 1시간보다는 시간을 입력받는 게 좋을거 같아. 예를 들어 31분이면 31을 입력받는 거지"
- 새 옵션 "단기 변동률 윈도우 분" (CSV) — 기본 `15, 30, 60`. 31분 원하면 `15, 30, 31, 60` 같이 추가.
- sensor가 입력 분마다 `change_pct_min` attribute 동적 생성 (예: `change_pct_31min`).
- ring buffer maxlen 70 → 300 (5시간) 으로 확장 — 300분 이내 어떤 분이든 지원.
- 블루프린트 `short_window_alert.yaml` 의 select 드롭다운 → number 입력 (1~300, step=1). trigger는 state + template condition으로 동적 attribute key 해석.
- 입력 파서 `_parse_minutes_csv` 가 잘못된 값 (음수, 300 초과, 문자) 무시 + 기본값 fallback.
2. README 전체 재작성 (한·영)
14 release 누적 정보를 v0.1.52 기준으로 재정리:
- 한눈에 보는 옵션 13개 테이블
- 카테고리별 sensor 목록 (지수 / 시세 / 포트폴리오 / 공시 / event bus)
- 블루프린트 3종 (단기 변동률 자유 입력 반영)
- yaml 자동화 예시 2개
- 마이그레이션 가이드 단일 테이블 (≤v0.1.31 → v0.1.52까지)
- FAQ 단순화
변경 폭
11 files, 445 inserts / 583 deletes. 55/55 unit tests 통과. `_parse_minutes_csv` 7개 케이스 검증 (whitespace, dedup, out-of-range, empty, None).
How to update via HACS
HACS → KR Finance Kit → ⋮ → "저장소 정보 다시 가져오기" → v0.1.52 → HA 완전 재시작 (translation cache flush) → 옵션 화면 "단기 변동률 윈도우 분" 항목에 원하는 분 입력 (예: `15, 30, 31, 60`) → 블루프린트 import (또는 기존 자동화 편집 → number 입력에 31) → `change_pct_31min` attribute가 sensor에 30초 ~ 31분 안에 생김.