【グラフ改造記】ポートフォリオ可視化ツールをアップデートしたら、もはやアプリになってた件w
以前の記事でポートフォリオをグラフ化した話を書きましたが、またやりました。
今回は初動検知グラフの追加・セクタータブ切り替え・ソースコードのリファクタリングまで一気にやった開発記録です。
投資の話はこちらの途中経過記事をどうぞ。
発端:ユーソナーを見逃した事件w
今日、ヒートマップをボーッと眺めていたらふと気づいてしまいました。
ユーソナー(431A)が+10.55%爆上がりしてる……!!
6/9時点では含み損-312円(-13.71%)だったのに、6/10には-105円(-4.62%)まで回復。1日で+207円の大改善です。
でも正直、SBIの画面で29銘柄の数字を眺めているだけでは全然気づかなかった。ヒートマップで面積と色を見ていたから「あれ、この銘柄なんか違う?」ってなったんですよね。
「前週比の上昇率をグラフにしたら、もっと早く初動を検知できるんじゃ?」
これが今回の改造の発端です。
⑤ 株価変化率グラフ(初動検知)を追加した
実装の考え方
最初は「スクショの前日比(%)列をそのまま転記する」方式を考えていたのですが、気づきました。
「SECTORSのpnl配列を使えばデータ追加不要じゃないですか?」
セクター別折れ線グラフには、各銘柄の週ごとのpnl(含み損益額)が配列で全部入っています。その差分から変化率を計算すれば、別途データを持つ必要がない。
// SECTORSから銘柄別pnlをフラット化
function buildStockPnlMap() {
const map = {};
SECTORS.forEach(sec => {
sec.stocks.forEach(st => { map[st.name] = st.pnl; });
});
return map;
}
既存データを活用するだけなので、毎週のスクショ更新ワークフローが変わらないのが最大のポイントです。
タブ切り替え(直近 / 約1週間前)
1日だけの変化率だと「たまたまその日に動いた」なのか「じわじわトレンドが変わっている」なのかが判別しにくい。なのでタブで切り替えられるようにしました。
const datasets = {
recent: { fromIdx: lastIdx - 1, toIdx: lastIdx }, // 直近
week1: { fromIdx: weekAgoIdx, toIdx: lastIdx }, // 約1週間前
};
比較期間はタブに連動して自動表示されます。「比較期間:6/8 → 6/10」という感じで、基準日が一目でわかる仕様にしました。
実際に使ってみたら
「約1週間前」タブに切り替えたらキッコーマンが+3.23%でじわじわ上昇中なのが一発で見えました。
含み益はすでに+12.10%あるので「既保有だから追加不要」と思っていたのですが、変化率グラフで見ると強い銘柄がさらに強くなっていることがわかる。「幅を広げるか厚みを増すか」の判断材料として使えます。

④ セクター別損益推移をタブ切り替えに改修した
問題:縦に長すぎる
6セクターを縦に並べていたので、グラフページが縦に長くなりすぎていました。Bootstrapのグリッドを導入して2カラム化したのですが、それでもまだ長い。
そこでセクタータブ切り替えに変更しました。
// タブクリックでセクターを切り替え
function renderSector(idx) {
const sector = allSectors[idx];
if (currentChart) { currentChart.destroy(); }
currentChart = new Chart(canvas.getContext("2d"), { ... });
}
「すべてのセクター」タブも追加
全体の流れを俯瞰したいときのために、先頭に「📊 すべてのセクター」タブも追加。全29銘柄がセクターカラーで色分けされて表示されます。
使い方のイメージ:
- 「すべてのセクター」で全体を俯瞰
- 気になるセクターのタブに切り替えて深掘り
- 該当セクターの銘柄の線の動きを確認
グラフの高さも600pxに拡大して、線が重なって見づらかった問題も解消しました。

ソースコードのリファクタリング
グラフの機能を追加していくうちに、JS全体に色コードがハードコードされて散乱してきました。26年エンジニアの佐藤さん(クロちゃんではなく本人)の一言。
「シンプルであることがバグを産まない秘訣なんでねw」
ということで、まとめて整理しました。
CSS:デザイントークンを整理
:root {
/* 損益カラー(SBI慣習:赤=利益・緑=損失) */
--pnl-pos: #cc0000;
--pnl-neg: #007a3d;
/* フォント */
--font-chart: bold 10px 'M PLUS 1p', sans-serif;
}
変数名を意味が伝わる名前に整理。以前は--greenと--redがSBI色慣習で逆になっていたのを--pnl-pos/--pnl-negに改名しました。
JS:カラー定数Cに一元管理
const C = {
pos: "#cc0000", // 利益(SBI赤)
neg: "#007a3d", // 損失(SBI緑)
accent: "#1a6fa8",
text: "#4a4540",
grid: "#e8e2d8",
font: "bold 10px 'M PLUS 1p', sans-serif",
};
JS全体に散在していた#cc0000や#007a3dを全部C.pos/C.negに統一。色を変えたいときはCオブジェクトの1行を変えるだけでOKになりました。
rgbaヘルパー関数
透明度バリアントが各所にrgba(204,0,0,0.75)みたいな形で散在していたので、ヘルパー関数にまとめました。
const rgba = (isPos, alpha) => isPos
? `rgba(204,0,0,${alpha})`
: `rgba(0,122,61,${alpha})`;
// 使う側はこうなる
backgroundColor: rgba(s.pnl >= 0, 0.75)
タブUIの共通クラス化
②ヒートマップのフィルターボタンと⑤変化率グラフのタブ、それぞれ別々にインラインスタイルで書いていたのをtab-btnクラスに統一しました。
.tab-btn { ... }
.tab-btn.active { background: var(--accent); color: #fff; }
今後タブを追加するときはtab-btnクラスをつけるだけで見た目が揃います。
現状のグラフ構成(2026/6/10時点)
| グラフ | 内容 |
|---|---|
| ① トータル推移 | 投資額・時価総額・含み損益の推移(デュアルY軸) |
| ② ヒートマップ | 銘柄別評価額×含み損益率(フィルター付き) |
| ③ 銘柄別含み損益 | 含み損益率の棒グラフ(±8%破線付き) |
| ④ セクター別損益推移 | セクタータブ切り替え式の折れ線グラフ |
| ⑤ 株価変化率(初動検知) | 直近/約1週間前のタブ切り替え・変化率棒グラフ |
毎週のワークフローはスクショを渡すだけでクロちゃんがデータを更新してくれます。追加したグラフも自動で対応します。
おわりに
「グラフにして」って言っただけなのに、気づいたらポートフォリオ管理アプリになってましたw
来月あたりデータが溜まってきたら「1ヶ月前比較」タブも追加予定です。SECTORSのpnl配列にデータが積み上がっていくだけで自動対応できる設計にしてあるので、追加は1行書くだけで済みます。
可視化→気づき→アクションの流れが自然に回るツールになってきた気がします。次はユーソナーみたいな急騰を自動ハイライトする機能も追加したいなぁ……(チラッ)
免責事項
本記事は個人の投資記録・開発記録です。特定の銘柄への投資を推奨するものではありません。投資は自己責任でお願いします。
