dbt Chartsで自作の財務分析基盤を可視化してみた話

dbt chartsが利用可能になった、ということなので、実際に使ってみた。
データソースは自作の財務分析基盤。EDINET報告書/JPX適時開示・日足終値を収集・加工している。

ClaudeProの$20プランでSonnet5.5を使った。自作の基盤はDuckDB/Prefect/dbtで作っていて、
同じdbtファミリーとなるが、Claudeはdbtの上に来るため正直dbtファミリーとしてdbt-chartsが
あるメリットをあまり感じなかった。Claudeがmanifest相当の内容を理解してしまうし、
DuckDBにアクセスしてデータを読むことで、ymlのメタデータを超える理解をしてしまう。
むしろ、メタデータに嘘が書かれていてClaudeを惑わしてしまい、途中基盤側を修正したりした。

財務や適時開示といったメジャーなオープンデータなので指標の集計はLLMの知識で解決できたが、
これが企業の中のクローズドなデータだったら、説明する層が必要になると思う。

dbt-charts は Vega-Lite という描画ライブラリをベースとしている。
一般的なチャートは用意されていたが、カスタマイズ性は並かな…と思った。
あまり思った通りの表示にならない。

Vegaという、描画要素を全てjsonで書く低レイヤーの描画ライブラリの上に、
より高水準の Vega-Lite があり、その過程である程度機能が落ちているように見える。
「少ない記述で、よく使う種類のグラフを宣言的に書く」という趣旨らしい。

dbt chartsの構成ファイルとしてymlを書いて、それが宣言的な記述になって、
Vega-Liteにマップされる、という感じ。

type=lineで終値比較

まずは終値比較。

NTT, KDDI, Softbank, 楽天 について、1年前の終値を100とし、終値を重ねてみてください。

Telecom indexed

type=barで通期のバリュエーション推移

dbt charts で、通信4社(NTT・KDDI・ソフトバンク・楽天)の通期(2021〜2025年)の
主要指標を、実データで横棒グラフにしてください(PNG出力)。

– 構成: 縦軸=決算期、指標ごとのパネル(1段目: 時価総額・PER・PBR、2段目: ROE・ROA・EPS)、
4社のグループ棒、棒に数値ラベル、順序は NTT → KDDI → ソフトバンク → 楽天
– 時価総額・PER・PBR: 開示日(submit_date_time の日付)の翌日以降で最初の取引日の値
– EPS: 開示値 × period_end_cum_adj(分割調整後)
– ROE・ROA: % 表示(ROA は net_income / total_assets)

Real telecom annual

type=areaで時価総額積み上げ比較

dbt charts で、通信4社(NTT・KDDI・ソフトバンク・楽天)の時価総額の日次推移を
積み上げ面グラフにしてください(2021年〜、実データ、PNG出力)。

– データ: mart__jpx_edinet__daily_valuation_indicators の market_cap(兆円)
– 銘柄: jpx_code 9432 / 9433 / 9434 / 4755
– 積み順: 下から NTT → KDDI → ソフトバンク → 楽天
– 横軸: 年ラベル(2022〜2026)を横書きで毎年表示

Real telecom marketcap area

type=scatterで全上場企業のPBRxROE分布

株価純資産倍率(PBR)、つまり、時価総額 ÷ 純資産で、市場が会社の純資産の何倍で評価しているか。
自己資本利益率(PER)、つまり、純利益 ÷ 純資産で、株主のお金でどれだけ稼いだか。
両者は PBR = PER x ROE で繋がっている。PERが同程度ならROEが高いほどPBRも高くなるはず。

会社の資産価値(解散価値)に対して株価が割安になっている、
つまり株価が1株当たり純資産を下回っている状態の会社が多数あることで有名。
PBRを1倍より大きくすることが要請されている。

PBRを対数軸とすると、PBR1倍割れの銘柄のPERの分布がわかる。
基本的にはPBR1倍割れの銘柄はROEも低いが、左上にROEが高いものもある。
雪印メグミルク(2270)、大和ハウス工業(1925)、石原産業(4028)、サンフロンティア不動産(8934)などが
低PBRだが比較的ROEが高い。北陸電力(9505)、西日本鉄道(9031)も同じグルーピングだが、
自己資本比率が低くROEが高めに出やすい。

dbt charts で、全上場会社の PBR × ROE の散布図を、実データで1枚の画像(PNG)に
上下2パネルで出してください。上: PBR 線形軸、下: PBR 対数軸。

– 1社1点。PBR は daily_valuation_indicators の最新日、ROE は各社の最新の通期の値
– 点の色: 会計基準(日本基準=淡い灰青、IFRS=オレンジ、US GAAP=濃い青)。多数派を先に描く
– 点の大きさ: 時価総額(億円の常用対数 + 1)
– 外れ値除外: PBR 0以下・10超、ROE -50〜60% の外
– ROE は % 表示、点の透明度 0.6、タイトルは大文字を変換しない

Real pbr roe scatter pair

type=pie,donutでPBRレンジ構成比,会計基準ごとの時価総額

円グラフとドーナツ。ドーナツは円グラフが流用されている。

dbt charts で、全上場会社の構成比を、ドーナツと円グラフの2枚を左右に並べた1枚の画像(PNG)にしてください(実データ)。

– 左(ドーナツ): 最新日の PBR レンジ別の会社数(PBR 0 超)。区分は 0.5未満 / 0.5〜1倍 / 1〜2倍 / 2〜3倍 / 3倍以上、
各区分に「社数」ラベル、中央に合計会社数。1倍割れは橙系、1倍以上は青系の色。
– 右(円グラフ): 会計基準別の時価総額(兆円)。会計基準は各社の最新の通期の値。
色は 日本基準=淡い灰青、IFRS=オレンジ、US GAAP=濃い青。各スライスに「基準名 + 兆円」ラベル。

Real pie donut

type=kpiで市場サマリー

自力でラベルを並べなくても、1つのチャートで値を表示できる。

dbt charts で、全上場会社の市場サマリーを KPI 3枚を1行に並べたボードにして、
実データで PNG 出力してください。

– 対象日: daily_valuation_indicators の最新日。補足に「前年同日比」(1年前以前で直近の取引日との差)
– KPI 1: PBR 1倍割れの会社の割合(PBR 0 超の会社のうち PBR 1 未満、% 表示、差はポイント)
– KPI 2: PBR 中央値(PBR 0 超、小数2桁)
– KPI 3: PER 中央値(PER 0 超〜100 以下、小数1桁)

Real market kpi

type=tableで時価総額1000億円以上のPBR1倍割れROE10%超え企業一覧

これは説明不要。何も考えずに多用しそう。

– 並び: ROE の降順、全行を表示(ページ分割しない)
– 列: コード / 会社名 / 会計基準 / PBR(倍)/ ROE(%)/ PER(倍)/ 時価総額(億円)/ 自己資本比率(%)

Real screening table

type=heatmapでPBRレンジxROEレンジ会社数分布

dbt charts で、全上場会社の PBR × ROE の会社数ヒートマップを、実データで PNG 出力してください。

– 縦軸: 最新日の PBR(上が高い)。12 階級: 0.25未満 / 0.25-0.5 / 0.5-0.75 / 0.75-1 / 1-1.25 / 1.25-1.5 / 1.5-2 / 2-2.5 / 2.5-3 / 3-4 / 4-5 / 5以上(PBR 0 超の会社)
– 横軸: 各社の最新の通期 ROE(左が低い)。12 階級: -10%未満 / -10〜0% / 0〜2.5% / 2.5〜5% / 5〜7.5% / 7.5〜10% / 10〜12.5% / 12.5〜15% / 15〜20% / 20〜25% / 25〜30% / 30%以上
– マスの値: 会社数(色が濃いほど多い)。配色は橙〜赤(dbt-seq-rust)

Real pbr roe heatmap

type=pointmapで本店所在地都道府県を日本地図にマップする

むちゃくちゃ苦戦した。日本地図は外部から持ってこないと表示されない。
しかも、webサーバでホストしないといけない。
もっと工夫すると出来るのかもしれないが、少なくとも公式に説明はない。

dbt charts で、本店所在地の都道府県別の時価総額合計を、日本地図の上に点の大きさで表した PNG を、実データで出してください(type: point_map)。

– 集計: 最新日の market_cap を、各社の最新の通期の prefecture(本店所在地)ごとに合計(兆円)
– 点の位置: 47 都道府県庁所在地の緯度・経度(SQL に埋め込み)。点の大きさ = 時価総額合計
– 背景: 日本の都道府県境界(amay077/JapanPrefGeoJson 由来を簡略化したもの)。灰色の塗り、白い枠線
– 描画は scripts/dct_render.py 経由で行い、境界データは手元の HTTP サーバ(ポート 8765)で配信する

Real prefecture map

まとめ

自作の財務分析基盤をdbt chartsで可視化してみた。
JavaScriptを書けない環境でもdbtファミリーで可視化まで完結させられることを確認した。
ymlで宣言的に図を書けるのでシンプルな構成に良い。