Skip to content

feat(ratewise): 新增來回換匯成本與計價基準判定工具(PR-A) - #996

Merged
s123104 merged 1 commit into
mainfrom
feat/rate-basis-semantics
Aug 8, 2026
Merged

feat(ratewise): 新增來回換匯成本與計價基準判定工具(PR-A)#996
s123104 merged 1 commit into
mainfrom
feat/rate-basis-semantics

Conversation

@s123104

@s123104 s123104 commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

PRD 2026-08-08-rate-basis-buyback-directionPR-A:純函式模組 + 測試,無使用者可見變更

為什麼需要

「換出去再換回來」會被銀行賺兩次價差,但這個成本從未被量化。以 main 的實際牌告推導,17 幣別的來回損失率全距達 15 倍

幣別 現金賣出 推導買入 來回損失
IDR 0.00218 0.00148 32.11%
VND 0.0014 0.00099 29.29%
PHP 0.5971 0.4651 22.11%
THB 1.0421 0.8521 18.23%
MYR 8.395 6.87 18.17%
KRW 0.02511 0.02121 15.53%
JPY 0.2086 0.1958 6.14%
USD 32.56 31.89 2.06%

中位數 4.76%。換 30000 台幣的 IDR 再換回,損失約 9,633 元

競品(比率網、TaiwanRate)只做「哪家銀行價格好」的橫向比較,不做「這筆交易划不划算」的縱向判斷。

本 PR 內容

utils/roundTripCost.ts

  • computeRoundTripCost(sell, buy) — 以 (sell - buy) / sell 計算損失率,回傳 lossPct / spread / severity
  • deriveCashBuy(bankMid, cashSell)seo-rate-examples 只保留 bankMid = (cashBuy + cashSell) / 2,故買入價需代數還原為 2 * bankMid - cashSell這是還原不是估計,不引入誤差
  • classifyRoundTripSeveritylow < 5%medium 5–15%high >= 15%,門檻依實測分布訂定
  • computeRoundTripLossTwd(twdAmount, cost)

防禦:缺值、非有限數、sell <= 0buy > sell(資料異常)皆回傳 null 而非 0。

utils/rateBasisLabel.ts

計價基準自 #433 的 8 種精簡為 3 種

kind 條件 行為
mid rateMode === 'mid' 「參考中間價(非交易報價)」
cross 兩端皆非 TWD 「交叉換算(經台幣中轉,計入兩次價差)」
direct 其餘 不顯示

捨棄 shop-* 四種 —— 與 RateTypeSelector 的可見狀態重複。優先序 mid > cross > direct:中間價根本不可成交,此警示強於「跨了兩次價差」。

設計原則:恆亮的標籤會退化為視覺壁紙,只在有話要說時出現才具訊號價值。

i18n

四語系補 rateBasis 區塊,含 key 完整性守門與「不得為 direct 建立文案」的反向斷言。

測試

40 tests 通過,含 17 幣別真實牌告迴歸:

  • 所有具 bankMid 的幣別皆可還原買入價並算出成本
  • 還原的買入價恆低於賣出價(價差方向正確)
  • 東南亞現鈔幣別 severity 為 high、USD 為 low

pnpm typecheck 通過。

不在本 PR 範圍

  • schema exchangeRateSpread(PR-B)
  • 幣別頁買回向內容與關鍵字(PR-C)
  • UI 接線 —— 刻意不碰 SingleConverter.tsxlayout.ts,避免與進行中的 fold 工作衝突

@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

⚠️ Deprecation Warning: The deny-licenses option is deprecated for possible removal in the next major release. For more information, see issue 997.

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

✅ SEO 審計通過!所有 2026 標準驗證項目都符合要求。

  • ✅ Sitemap 2026 標準
  • ✅ Breadcrumb Schema
  • ✅ JSON-LD 結構化數據
  • ✅ 內部連結結構

- roundTripCost:以 (sell - buy) / sell 量化換出再換回的損失率,
  含 low/medium/high 分級與台幣損失金額換算
- deriveCashBuy:自 bankMid 代數還原現金買入價(cashBuy = 2*bankMid - cashSell),
  seo-rate-examples 未直接保留買入價
- 報價單位限定 TWD_PER_FOREIGN;換錢所 KRW_PER_TWD(sell 46.0 / buy 46.7)
  方向相反,落入單位保護回傳 null 而非算出反號損失率
- rateBasisLabel:計價基準收斂為 mid/cross/direct 三種,僅揭露
  RateTypeSelector 表達不出來的情境,direct 不顯示標籤
- 四語系補 rateBasis 文案並加 key 完整性守門
- 本次僅交付純函式模組,無使用者可見變更

測試:31 tests 通過(含 17 幣別真實牌告迴歸與換錢所單位保護)、
ratewise 全套 2806 tests 通過、pnpm typecheck 通過
@s123104
s123104 force-pushed the feat/rate-basis-semantics branch from 742817e to 1dda1be Compare August 8, 2026 09:02
@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

✅ SEO 審計通過!所有 2026 標準驗證項目都符合要求。

  • ✅ Sitemap 2026 標準
  • ✅ Breadcrumb Schema
  • ✅ JSON-LD 結構化數據
  • ✅ 內部連結結構

@s123104
s123104 merged commit 2d47aac into main Aug 8, 2026
18 checks passed
@s123104
s123104 deleted the feat/rate-basis-semantics branch August 8, 2026 11:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant