NISAで投資する人に「利益が生まれる構造を教えて」と問いかける発言が、ニュースになっていました。考察しているうちに、「NISAを正しく理解して使うための計算の画面は作れるか」という話になり、その日のうちにデモ公開・MCP同梱・kappstore出品まで進めました。その記録です。
- デモ: 新NISAの枠の残りと復活を計算する
- 使い方の紹介: note の記事
作る前に確かめた3つ
既存のOSSは無かった。 GitHub で探して出てくるのは、個人の積立シミュレーターくらいでした。どれもスターは0で、ほとんどにライセンスがありません。土台にできるものが無いので、自社で書くことにしました。
検索の需要は、狙う場所で差があった。 Google 広告のキーワードプランナーで測ると、いちばん多いのは「nisa おすすめ」(月22,200回)です。ただ、これは商品を勧める領域で、競合も強い。一方「新 nisa シミュレーション」は月9,900回、「nisa 枠 復活」「ニーサ 枠 復活」は合わせて月4,500回で、どちらも競合が弱い。狙うのはこちらです。
勧めないと、先に決めた。 特定の商品を「これを買うべき」と示すと、投資助言の領域に入ります。制度の計算と、自分で置いた仮定の試算に絞りました。いちばん需要がある「おすすめ」を捨てたのは、この線引きのためです。
ルールを先にテストにした
枠の計算は、答えが1つに決まります。だから画面より先に、金融庁の説明をテストにしました。
- つみたて投資枠は年120万円、成長投資枠は年240万円
- 生涯の枠は簿価で1,800万円、うち成長投資枠は1,200万円まで
- 売っても、その年の年間投資枠は戻らない
- 売った商品の簿価の分が、翌年以降に生涯の枠として復活する
- 2023年までのNISAは外枠
これを手で計算した答えと突き合わせるテストにしました。たとえば「5年で1,800万円を埋めて、6年目に300万円(簿価)売る」なら、6年目の翌年に使える枠は300万円で、6年目のうちに買い直すと上限を超える。こういう例を19件です。
計算の本体(knisa-core.js)は、このテストが全部通るまで直しました。画面はそのあとです。
試算は「構造」を見せる
積立の試算は、年率を式で分けました。
年率 = 配当利回り + 企業の利益の伸び − 信託報酬
「年利5%」と置いて1本の線を引くだけでは、その5%がどこから来るのかが見えません。式で見せれば、増える分の出どころと、手数料で引かれる分が並びます。
値動きの大きさ(年率の標準偏差)を入れると、種つきの乱数で1,500通り試して、下位10%・真ん中・上位10%を出します。同じ入力なら同じ結果になるように、乱数には種を付けています。
踏んだ不具合
取り崩しを入れると、積立の結果まで変わった。 積み立て終わってから毎月取り崩す額を入れる欄を作ったら、積立の結果(真ん中の値や元本割れの確率)まで少しずれました。積み立てと取り崩しで同じ乱数の列を使っていたので、取り崩しの計算が乱数を消費すると、次の試行の積み立てがずれていたのです。取り崩しに別の乱数の列を持たせ、「取り崩しを入れても積立の結果は同じ」というテストを足しました。
スマホで、取引表の「年」の欄が潰れた。 横幅の狭い画面で、年を入れる欄が文字の入らない幅まで縮んでいました。表の中の入力欄に最小の幅を持たせ、表だけ横にスクロールする形にしました。ページ全体ははみ出しません(320・360・390pxで測りました)。
名前を差し替えて置ける形にした
税理士・FPの相談窓口や、会社のNISA説明会で使えるように、社名・ロゴ・色・相談先を knisa-config.php に出しました。
気をつけたのは、設定が無いときは計測をしないことです。当社のデモではアクセス計測を入れていますが、それを本体に書いておくと、買った会社のサイトから当社に計測が飛びます。本体からは会社の情報を全部抜いて、当社のデモだけが自分の設定ファイルで計測を有効にしています。設定なしで表示して、計測タグも社名も0件になることを確かめました。
AIから同じ計算を呼べるようにした
AIアシスタントにNISAの枠を聞くと、「売ったら枠は戻る」とだけ答えて、年間枠と生涯枠の違いや、翌年からという点を落とすことがあります。そこで、同じ計算を MCP サーバー(knisa_mcp.php)として出しました。ツールは4つです。
nisa_rules:枠のルール(出典つき)nisa_check_waku:取引履歴から、年ごとの残り・復活額・上限超過nisa_frame_fill:毎月の積立額が年間枠のどこに入り、生涯の枠が何年で埋まるかnisa_fee_gap:信託報酬の違いで将来いくら差が出るか
MCP は PHP で動かすので、計算も PHP に写しました。ここで怖いのは、画面(JavaScript)と AI(PHP)で答えが食い違うことです。同じ入力を両方に通して、結果が一致するかを確かめるテストを作りました。13件すべて一致しています。MCP そのものも、標準入出力で直接叩いて15件の確認を通し、Claude Code に登録して Connected を確かめています。
出品まで
最後に kappstore に出品しました。配布する zip には、当社のOGP画像やその生成スクリプトのように、自社のデモにしか要らないものは入れていません。社内のパスや計測タグが残っていないことも、機械的に確かめています。
Kurage NISA 枠計算・試算(Kurage App Store)
振り返り
答えが1つに決まる計算は、画面から作り始めると、見た目を直しているうちにルールの細部がずれます。今回はルールを先にテストにしたので、画面・MCP・PHP への書き写しのどこで直しても、テストが通るかどうかで判断できました。
もう1つは、需要のいちばん大きい言葉(「おすすめ」)を最初に捨てたことです。勧めない、と決めたことで、作るものの範囲がはっきりしました。
ほかにも、触ってから決められるデモを置いています。
