ポートフォリオ可視化スクリプト(1) - 配当月一覧-¶
ポートフォリオの配当月を表示するスクリプト.
ソースコード¶
dividend__month.py¶
import os, sys, json5, jinja2, shutil
import yfinance as yf
import pandas as pd
# ========================================================= #
# === dividend__month.py === #
# ========================================================= #
def dividend__month():
# ------------------------------------------------- #
# --- [1] load settings.json --- #
# ------------------------------------------------- #
settingFile = "dat/settings.json"
with open( settingFile, "r" ) as f:
params = ( json5.load( f ) )
tickers = params["tickers"]
slist = pd.read_csv( "dat/jpx_stock.csv", encoding="utf-8" )
ticker_dict = {}
for ticker in tickers:
nmatch = slist[ slist["コード"] == ticker.strip( ".T" ) ]
if ( not( nmatch.empty ) ):
ticker_dict[ticker] = ( nmatch.iloc[0]["銘柄名"] ).strip()
# ------------------------------------------------- #
# --- [2] 配当月を調査 --- #
# ------------------------------------------------- #
month_to_tickers = {i: [] for i in range(1, 13)}
for code, name in ticker_dict.items():
ticker = yf.Ticker(code)
dividends = ticker.dividends
months = dividends.index.month.unique()
for month in months:
if name not in month_to_tickers[month]:
month_to_tickers[month].append(name)
# ------------------------------------------------- #
# --- [3] 月ラベルを付けてJinja2用に整形 --- #
# ------------------------------------------------- #
month_labels = {
1: "1月", 2: "2月", 3: "3月", 4: "4月", 5: "5月", 6: "6月",
7: "7月", 8: "8月", 9: "9月", 10: "10月", 11: "11月", 12: "12月"
}
table_data = [
{"month": month_labels[m], "names": month_to_tickers[m]}
for m in range(1, 13)
]
# ------------------------------------------------- #
# --- [4] Jinja2テンプレートでHTML出力 --- #
# ------------------------------------------------- #
env = jinja2.Environment( loader=jinja2.FileSystemLoader("templates") )
template = env.get_template( "month_template.html" )
rendered_html = template.render(
title ="配当月カレンダー",
table = table_data,
css_path ="custom.css"
)
htmlFile = "html/month.html"
with open(htmlFile, "w", encoding="utf-8") as f:
f.write( rendered_html )
print(" output :: {}".format( htmlFile) )
shutil.copy( "templates/custom.css", "html/" )
# ========================================================= #
# === Execution of Pragram === #
# ========================================================= #
if ( __name__=="__main__" ):
dividend__month()
settings.json¶
{
"items": {
"dividend.yield" : { "name": "配当利回り (%)" , "min":3.5, "max":5.0, },
"dividend.ratio" : { "name": "配当性向 (%)" , "min":10.0, "max":50.0, },
"oprIncome" : { "name": "営業利益率 (%)" , "min":10.0, "max":null, },
"EPS" : { "name": "EPS (円)" , "min":null, "max":null, },
"PER" : { "name": "PER" , "min":5.0, "max":15.0, },
"PBR" : { "name": "PBR" , "min":0.5, "max":1.5, },
"ROE" : { "name": "ROE (%)" , "min":8.0, "max":null, },
"ROA" : { "name": "ROA (%)" , "min":5.0, "max":null, },
"equityRatio" : { "name": "自己資本比率 (%)" , "min":50.0, "max":null, },
"currentRatio" : { "name": "流動比率 (%)" , "min":200.0, "max":null, },
"cashRatio" : { "name": "現金比率 (%)" , "min":50.0, "max":null, },
},
"tickers": [
"2169.T", "2267.T", "2914.T", "3076.T", "3479.T", "3763.T", "3817.T", "4008.T",
"4752.T", "4928.T", "5020.T", "5108.T", "5192.T", "5334.T", "5388.T", "5401.T",
"5464.T", "5589.T", "6113.T", "6247.T", "6268.T", "6301.T", "7247.T", "7820.T",
"7921.T", "7994.T", "7995.T", "8002.T", "8053.T", "8058.T", "8316.T", "8411.T",
"8424.T", "8425.T", "8439.T", "8584.T", "8593.T", "8898.T", "9432.T", "9433.T",
"9513.T", "9795.T", "9799.T", "9986.T",
],
"settings":{
"cssFile" : "templates/custom.css" ,
"stockStatus.htmlFile" : "html/stockStatus.html",
"stockStatus.templateFile": "table_template.html" ,
},
}
month_template.html¶
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>{{ title }}</title>
<link rel="stylesheet" href="{{ css_path }}">
</head>
<body>
<h2>{{ title }}</h2>
<table class="styled-table">
<thead>
<tr>
<th class="month-col">月</th>
<th class="name-col">配当銘柄</th>
</tr>
</thead>
<tbody>
{% for row in table %}
<tr>
<td>{{ row.month }}</td>
<td>
<ul>
{% for name in row.names %}
<li>{{ name }}</li>
{% endfor %}
</ul>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
custom.css¶
/************************************
** 比較表 全体レイアウト(3列対応)
************************************/
.compare-box {
display: flex;
max-width: 1000px;
margin: 0 auto 2rem;
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0, 0, 0, .2);
background: #fef9ed;
flex-wrap: nowrap;
}
/* 各列共通 */
.compare-left-wrap {
width: 50.0%;
overflow: hidden;
}
.compare-middle-wrap,
.compare-right-wrap {
width: 25.0%;
overflow: hidden;
}
/************************************
** 各列のタイトル(修正)
************************************/
.compare-left-head,
.compare-middle-head,
.compare-right-head {
background: #1f3b5b;
color: #fff;
font-weight: bold;
font-size: 15px;
height: 65px;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
padding: 0 1em;
}
.compare-left-head { border-radius: 4px 0 0 0; }
.compare-right-head { border-radius: 0 4px 0 0; }
/************************************
** 判定のマーク(◎ / ✗)色付け
************************************/
.check-true {
color: green;
font-weight: bold;
}
.check-false {
color: red;
font-weight: bold;
}
/************************************
** 各列の本文
************************************/
.compare-left,
.compare-middle,
.compare-right {
padding: 1.5em;
font-size: 15px;
line-height: 2;
text-align: justify;
text-justify: inter-ideograph;
}
/************************************
** 左列:番号付きリスト(項目名)
************************************/
.compare-box .list-number {
counter-reset: number;
list-style: none !important;
padding: 0 !important;
margin: 0 !important;
border: none !important;
}
.compare-box .list-number li {
position: relative;
margin: 0 !important;
padding: 0.5em 0 0.5em 2em !important;
line-height: 1.8;
border-bottom: 1px dashed #cdcdcd;
}
.compare-box .list-number li:before {
counter-increment: number;
content: counter(number);
background-color: #1f3b5b;
color: #fff;
position: absolute;
font-weight: bold;
font-size: 12px;
border-radius: 50%;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 18px;
height: 18px;
line-height: 18px;
text-align: center;
}
.compare-box .list-number li:last-child {
border: none;
}
/************************************
** 中・右列:記号なしリスト(値・判定)
************************************/
.list-no-bullet {
list-style: none !important;
padding: 0 !important;
margin: 0 !important;
border: none !important;
}
.list-no-bullet li {
padding: 0.5em 0 0.5em 2em !important;
margin: 0 !important;
border-bottom: 1px dashed #cdcdcd;
line-height: 1.8;
}
.list-no-bullet li:last-child {
border: none;
}
/************************************
** マーク ◎ / x
************************************/
.check-icon-true::before {
content: "✔";
display: inline-block;
background-color: #d4f4dd; /* 薄緑 */
color: #1a7f37; /* 濃い緑 */
font-weight: bold;
border-radius: 50%;
width: 24px;
height: 24px;
line-height: 24px;
text-align: center;
font-size: 14px;
box-shadow: 0 0 2px rgba(0,0,0,0.2);
}
.check-icon-false::before {
content: "✘";
display: inline-block;
background-color: #fde2e2; /* 薄赤 */
color: #d32f2f; /* 濃い赤 */
font-weight: bold;
border-radius: 50%;
width: 24px;
height: 24px;
line-height: 24px;
text-align: center;
font-size: 14px;
box-shadow: 0 0 2px rgba(0,0,0,0.2);
}
.compare-left-head,
.compare-middle-head,
.compare-right-head {
background: #1f3b5b;
color: #fff;
font-weight: bold;
font-size: 15px;
height: 65px;
display: flex;
justify-content: center;
align-items: center;
flex: 1;
padding: 0;
margin: 0;
box-sizing: border-box;
}
.compare-left-head { border-radius: 4px 0 0 0; }
.compare-middle-head { border-radius: 0 0 0 0; } /* 明示的に入れる */
.compare-right-head { border-radius: 0 4px 0 0; }
/* ---------------------------------------------- */
/* --- month.py --- */
/* ---------------------------------------------- */
/* 表全体 */
.styled-table {
border-collapse: collapse;
margin: 20px auto;
font-size: 1em;
width: 90%;
border: 1px solid #1f355e; /* 紺色の枠線 */
background-color: #ffffff; /* 白背景 */
text-align: left;
}
/* セル共通 */
.styled-table th,
.styled-table td {
border: 1px solid #1f355e; /* 紺色の枠線 */
padding: 8px;
vertical-align: top;
}
/* ヘッダー */
.styled-table th {
background-color: #1f355e; /* 紺色背景 */
color: white; /* 白文字 */
}
/* 奇数行背景(白に統一したい場合はこれを削除してOK) */
.styled-table tr:nth-child(even) {
background-color: #ffffff; /* 背景は白に */
}
/* 列幅と左寄せ */
.month-col {
width: 20%;
text-align: left;
}
.name-col {
width: 80%;
text-align: left;
}
/* 箇条書きのスタイル */
.name-col ul {
margin: 0;
padding-left: 1em;
}
.name-col li {
margin-bottom: 0.3em;
}
出力¶
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>配当月カレンダー</title>
<link rel="stylesheet" href="custom.css">
</head>
<body>
<h2>配当月カレンダー</h2>
<table class="styled-table">
<thead>
<tr>
<th class="month-col">月</th>
<th class="name-col">配当銘柄</th>
</tr>
</thead>
<tbody>
<tr>
<td>1月</td>
<td>
<ul>
</ul>
</td>
</tr>
<tr>
<td>2月</td>
<td>
<ul>
</ul>
</td>
</tr>
<tr>
<td>3月</td>
<td>
<ul>
<li>ヤクルト本社</li>
<li>日本たばこ産業</li>
<li>プロシップ</li>
<li>SRAホールディングス</li>
<li>住友精化</li>
<li>昭和システムエンジニアリング</li>
<li>ENEOSホールディングス</li>
<li>三ツ星ベルト</li>
<li>日本特殊陶業</li>
<li>クニミネ工業</li>
<li>日本製鉄</li>
<li>モリ工業</li>
<li>アマダ</li>
<li>日阪製作所</li>
<li>ナブテスコ</li>
<li>小松製作所</li>
<li>ミクニ</li>
<li>ニホンフラッシュ</li>
<li>オカムラ</li>
<li>バルカー</li>
<li>丸紅</li>
<li>住友商事</li>
<li>三菱商事</li>
<li>三井住友フィナンシャルグループ</li>
<li>みずほフィナンシャルグループ</li>
<li>芙蓉総合リース</li>
<li>みずほリース</li>
<li>東京センチュリー</li>
<li>ジャックス</li>
<li>三菱HCキャピタル</li>
<li>センチュリー21・ジャパン</li>
<li>日本電信電話</li>
<li>KDDI</li>
<li>電源開発</li>
<li>ステップ</li>
<li>旭情報サービス</li>
<li>蔵王産業</li>
</ul>
</td>
</tr>
<tr>
<td>4月</td>
<td>
<ul>
</ul>
</td>
</tr>
<tr>
<td>5月</td>
<td>
<ul>
<li>TAKARA & COMPANY</li>
</ul>
</td>
</tr>
<tr>
<td>6月</td>
<td>
<ul>
<li>CDS</li>
<li>日本たばこ産業</li>
<li>あい ホールディングス</li>
<li>ブリヂストン</li>
<li>ナブテスコ</li>
</ul>
</td>
</tr>
<tr>
<td>7月</td>
<td>
<ul>
</ul>
</td>
</tr>
<tr>
<td>8月</td>
<td>
<ul>
</ul>
</td>
</tr>
<tr>
<td>9月</td>
<td>
<ul>
<li>ヤクルト本社</li>
<li>日本たばこ産業</li>
<li>SRAホールディングス</li>
<li>住友精化</li>
<li>ノエビアホールディングス</li>
<li>ENEOSホールディングス</li>
<li>三ツ星ベルト</li>
<li>日本特殊陶業</li>
<li>クニミネ工業</li>
<li>日本製鉄</li>
<li>モリ工業</li>
<li>アマダ</li>
<li>日阪製作所</li>
<li>ナブテスコ</li>
<li>小松製作所</li>
<li>ミクニ</li>
<li>ニホンフラッシュ</li>
<li>オカムラ</li>
<li>バルカー</li>
<li>丸紅</li>
<li>住友商事</li>
<li>三菱商事</li>
<li>三井住友フィナンシャルグループ</li>
<li>みずほフィナンシャルグループ</li>
<li>芙蓉総合リース</li>
<li>みずほリース</li>
<li>東京センチュリー</li>
<li>ジャックス</li>
<li>三菱HCキャピタル</li>
<li>センチュリー21・ジャパン</li>
<li>日本電信電話</li>
<li>KDDI</li>
<li>電源開発</li>
<li>ステップ</li>
<li>旭情報サービス</li>
<li>蔵王産業</li>
</ul>
</td>
</tr>
<tr>
<td>10月</td>
<td>
<ul>
</ul>
</td>
</tr>
<tr>
<td>11月</td>
<td>
<ul>
<li>TAKARA & COMPANY</li>
</ul>
</td>
</tr>
<tr>
<td>12月</td>
<td>
<ul>
<li>CDS</li>
<li>日本たばこ産業</li>
<li>あい ホールディングス</li>
<li>ブリヂストン</li>
<li>オートサーバー</li>
<li>ナブテスコ</li>
</ul>
</td>
</tr>
</tbody>
</table>
</body>
</html>