kabukit 0.5.2__py3-none-any.whl → 0.5.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
kabukit/core/prices.py CHANGED
@@ -17,6 +17,26 @@ if TYPE_CHECKING:
17
17
 
18
18
  class Prices(Base):
19
19
  def truncate(self, every: str | timedelta | Expr) -> Self:
20
+ """時系列データを指定された頻度で集計し、切り詰める。
21
+
22
+ このメソッドは、日次などの時系列データを指定された頻度(例: 月次、週次)で
23
+ 集計し、新しい時間軸に切り詰めます。集計方法は以下の通りです。
24
+
25
+ * `Open`: 各期間の最初の`Open`値
26
+ * `High`: 各期間の最大`High`値
27
+ * `Low`: 各期間の最小`Low`値
28
+ * `Close`: 各期間の最後の`Close`値
29
+ * `Volume`: 各期間の`Volume`の合計
30
+ * `TurnoverValue`: 各期間の`TurnoverValue`の合計
31
+
32
+ Args:
33
+ every (str | timedelta | Expr): 切り詰める頻度を指定します。
34
+ 例: "1d" (日次), "1mo" (月次), `timedelta`オブジェクト,
35
+ または Polars の `Expr` オブジェクト。
36
+
37
+ Returns:
38
+ Self: 指定された頻度で切り詰められた新しいPricesオブジェクト。
39
+ """
20
40
  data = (
21
41
  self.data.group_by(pl.col("Date").dt.truncate(every), "Code")
22
42
  .agg(
@@ -29,6 +49,7 @@ class Prices(Base):
29
49
  )
30
50
  .sort("Code", "Date")
31
51
  )
52
+
32
53
  return self.__class__(data)
33
54
 
34
55
  def with_adjusted_shares(self, statements: Statements) -> Self:
@@ -47,19 +68,22 @@ class Prices(Base):
47
68
  新しい列(`AdjustedIssuedShares`, `AdjustedTreasuryShares`)として
48
69
  追加されます。
49
70
 
50
- .. note::
51
- この計算は、決算発表間の株式数の変動が、株式分割・併合
52
- (`AdjustmentFactor`)にのみ起因すると仮定しています。
53
- 期中に行われる増資や自己株式取得など、`AdjustmentFactor`に
54
- 反映されないイベントによる株式数の変動は考慮されません。
55
-
56
71
  Args:
57
72
  statements (Statements): 財務データを提供する`Statements`オブジェクト。
58
73
 
59
74
  Returns:
60
75
  Self: `AdjustedIssuedShares`および`AdjustedTreasuryShares`列が
61
76
  追加された、新しいPricesオブジェクト。
77
+
78
+ Note:
79
+ この計算は、決算発表間の株式数の変動が、株式分割・併合
80
+ (`AdjustmentFactor`)にのみ起因すると仮定しています。
81
+ 期中に行われる増資や自己株式取得など、`AdjustmentFactor`に
82
+ 反映されないイベントによる株式数の変動は考慮されません。
62
83
  """
84
+ if "AdjustedIssuedShares" in self.data.columns:
85
+ return self
86
+
63
87
  shares = statements.shares().rename({"Date": "ReportDate"})
64
88
 
65
89
  adjusted = (
@@ -89,6 +113,23 @@ class Prices(Base):
89
113
 
90
114
  return self.__class__(data)
91
115
 
116
+ @property
117
+ def _outstanding_shares_expr(self) -> pl.Expr:
118
+ """調整済み発行済株式数を計算する Polars 式を返す。
119
+
120
+ Raises:
121
+ KeyError: 必要な列が存在しない場合は KeyError を送出する。
122
+ """
123
+ required_cols = {"AdjustedIssuedShares", "AdjustedTreasuryShares"}
124
+
125
+ if not required_cols.issubset(self.data.columns):
126
+ missing = required_cols - set(self.data.columns)
127
+ msg = f"必要な列が存在しません: {missing}。"
128
+ msg += "事前に .with_adjusted_shares() を呼び出してください。"
129
+ raise KeyError(msg)
130
+
131
+ return pl.col("AdjustedIssuedShares") - pl.col("AdjustedTreasuryShares")
132
+
92
133
  def with_market_cap(self) -> Self:
93
134
  """時価総額を計算し、列として追加する。
94
135
 
@@ -99,17 +140,18 @@ class Prices(Base):
99
140
  計算式:
100
141
  時価総額 = 調整前終値 * (調整済み発行済株式数 - 調整済み自己株式数)
101
142
 
102
- Note:
103
- このメソッドを呼び出す前に、`with_adjusted_shares()` を
104
- 実行して、調整済みの株式数列を事前に計算しておく必要があります。
105
-
106
143
  Returns:
107
144
  Self: `MarketCap` 列が追加された、新しいPricesオブジェクト。
145
+
146
+ Note:
147
+ このメソッドを呼び出す前に、`with_adjusted_shares()` あるいは
148
+ `with_yields()` を実行して、調整済みの株式数列を事前に計算して
149
+ おく必要があります。
108
150
  """
109
- shares = pl.col("AdjustedIssuedShares") - pl.col("AdjustedTreasuryShares")
110
151
  data = self.data.with_columns(
111
- (pl.col("RawClose") * shares).round(0).alias("MarketCap"),
152
+ (pl.col("RawClose") * self._outstanding_shares_expr).alias("MarketCap"),
112
153
  )
154
+
113
155
  return self.__class__(data)
114
156
 
115
157
  def with_equity(self, statements: Statements) -> Self:
@@ -121,12 +163,44 @@ class Prices(Base):
121
163
  Returns:
122
164
  Self: `Equity` 列が追加された、新しいPricesオブジェクト。
123
165
  """
166
+ if "Equity" in self.data.columns:
167
+ return self
168
+
124
169
  data = self.data.join_asof(
125
170
  statements.equity(),
126
171
  on="Date",
127
172
  by="Code",
128
173
  check_sortedness=False,
129
174
  )
175
+
176
+ return self.__class__(data)
177
+
178
+ def with_book_value_yield(self) -> Self:
179
+ """時系列の一株あたり純資産と純資産利回りを列として追加する。
180
+
181
+ 計算式:
182
+ 一株あたり純資産 = 純資産 / (調整済み発行済株式数 - 調整済み自己株式数)
183
+ 純資産利回り = 一株あたり純資産 / 調整前終値
184
+
185
+ Returns:
186
+ Self: `BookValuePerShare`, `BookValueYield` 列が追加された、
187
+ 新しいPricesオブジェクト。
188
+
189
+ Note:
190
+ このメソッドを呼び出す前に、`with_equity()` および
191
+ `with_adjusted_shares()` を実行して、純資産および調整済み株式数
192
+ 列を事前に計算しておく必要があります。
193
+ """
194
+ data = self.data.with_columns(
195
+ (pl.col("Equity") / self._outstanding_shares_expr).alias(
196
+ "BookValuePerShare",
197
+ ),
198
+ ).with_columns(
199
+ (pl.col("BookValuePerShare") / pl.col("RawClose")).alias(
200
+ "BookValueYield",
201
+ ),
202
+ )
203
+
130
204
  return self.__class__(data)
131
205
 
132
206
  def with_forecast_profit(self, statements: Statements) -> Self:
@@ -138,12 +212,42 @@ class Prices(Base):
138
212
  Returns:
139
213
  Self: `ForecastProfit` 列が追加された、新しいPricesオブジェクト。
140
214
  """
215
+ if "ForecastProfit" in self.data.columns:
216
+ return self
217
+
141
218
  data = self.data.join_asof(
142
219
  statements.forecast_profit(),
143
220
  on="Date",
144
221
  by="Code",
145
222
  check_sortedness=False,
146
223
  )
224
+
225
+ return self.__class__(data)
226
+
227
+ def with_earnings_yield(self) -> Self:
228
+ """時系列の一株あたり純利益と収益利回り(純利益利回り)を列として追加する。
229
+
230
+ 計算式:
231
+ 一株あたり純利益 = 予想純利益 / (調整済み発行済株式数 - 調整済み自己株式数)
232
+ 収益利回り = 一株あたり純利益 / 調整前終値
233
+
234
+ Returns:
235
+ Self: `EarningsPerShare`, `EarningsYield` 列が追加された、
236
+ 新しいPricesオブジェクト。
237
+
238
+ Note:
239
+ このメソッドを呼び出す前に、`with_forecast_profit()` および
240
+ `with_adjusted_shares()` を実行して、予想純利益および調整済み株式数
241
+ 列を事前に計算しておく必要があります。
242
+ """
243
+ data = self.data.with_columns(
244
+ (pl.col("ForecastProfit") / self._outstanding_shares_expr).alias(
245
+ "EarningsPerShare",
246
+ ),
247
+ ).with_columns(
248
+ (pl.col("EarningsPerShare") / pl.col("RawClose")).alias("EarningsYield"),
249
+ )
250
+
147
251
  return self.__class__(data)
148
252
 
149
253
  def with_forecast_dividend(self, statements: Statements) -> Self:
@@ -155,10 +259,75 @@ class Prices(Base):
155
259
  Returns:
156
260
  Self: `ForecastDividend` 列が追加された、新しいPricesオブジェクト。
157
261
  """
262
+ if "ForecastDividend" in self.data.columns:
263
+ return self
264
+
158
265
  data = self.data.join_asof(
159
266
  statements.forecast_dividend(),
160
267
  on="Date",
161
268
  by="Code",
162
269
  check_sortedness=False,
163
270
  )
271
+
164
272
  return self.__class__(data)
273
+
274
+ def with_dividend_yield(self) -> Self:
275
+ """時系列の一株あたり配当金と配当利回りを列として追加する。
276
+
277
+ 計算式:
278
+ 一株あたり配当金 = 予想年間配当総額 / (調整済み発行済株式数 - 調整済み自己株式数)
279
+ 配当利回り = 一株あたり配当金 / 調整前終値
280
+
281
+ Returns:
282
+ Self: `DividendPerShare`, `DividendYield` 列が追加された、
283
+ 新しいPricesオブジェクト。
284
+
285
+ Note:
286
+ このメソッドを呼び出す前に、`with_forecast_dividend()` および
287
+ `with_adjusted_shares()` を実行して、予想年間配当総額および調整済み株式数
288
+ 列を事前に計算しておく必要があります。
289
+ """ # noqa: E501
290
+ data = self.data.with_columns(
291
+ (pl.col("ForecastDividend") / self._outstanding_shares_expr).alias(
292
+ "DividendPerShare",
293
+ ),
294
+ ).with_columns(
295
+ (pl.col("DividendPerShare") / pl.col("RawClose")).alias("DividendYield"),
296
+ )
297
+
298
+ return self.__class__(data)
299
+
300
+ def with_yields(self, statements: Statements) -> Self:
301
+ """すべての利回り関連指標を計算し、列として追加する。
302
+
303
+ このメソッドは、以下の利回り関連指標をまとめて計算し、DataFrameに
304
+ 追加するコンビニエンスメソッドです。
305
+
306
+ * 純資産利回り (`BookValueYield`)
307
+ * 収益利回り (`EarningsYield`)
308
+ * 配当利回り (`DividendYield`)
309
+
310
+ 内部で `with_adjusted_shares()`, `with_equity()`,
311
+ `with_book_value_yield()`, `with_forecast_profit()`,
312
+ `with_earnings_yield()`, `with_forecast_dividend()`,
313
+ `with_dividend_yield()` を呼び出します。
314
+ これらのメソッドはべき等であるため、重複して呼び出されても
315
+ 無駄な計算は行われません。
316
+
317
+ Args:
318
+ statements (Statements): 財務データを提供する`Statements`オブジェクト。
319
+
320
+ Returns:
321
+ Self: `BookValuePerShare`, `BookValueYield`, `EarningsPerShare`,
322
+ `EarningsYield`, `DividendPerShare`, `DividendYield` 列が追加された、
323
+ 新しいPricesオブジェクト。
324
+ """
325
+ return (
326
+ self.with_adjusted_shares(statements)
327
+ .with_equity(statements)
328
+ .with_book_value_yield()
329
+ .with_forecast_profit(statements)
330
+ .with_earnings_yield()
331
+ .with_forecast_dividend(statements)
332
+ .with_dividend_yield()
333
+ )
@@ -12,7 +12,7 @@ if TYPE_CHECKING:
12
12
 
13
13
  class Statements(Base):
14
14
  def shares(self) -> DataFrame:
15
- """発行済株式数を取得する。"""
15
+ """発行済株式数および自己株式数を取得する。"""
16
16
  return self.data.filter(
17
17
  pl.col("IssuedShares").is_not_null(),
18
18
  ).select(
@@ -20,7 +20,6 @@ class Statements(Base):
20
20
  "Code",
21
21
  "IssuedShares",
22
22
  "TreasuryShares",
23
- "AverageOutstandingShares",
24
23
  )
25
24
 
26
25
  def equity(self) -> DataFrame:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: kabukit
3
- Version: 0.5.2
3
+ Version: 0.5.3
4
4
  Summary: A Python toolkit for Japanese financial market data, supporting J-Quants and EDINET APIs.
5
5
  Author: daizutabi
6
6
  Author-email: daizutabi <daizutabi@gmail.com>
@@ -13,9 +13,9 @@ kabukit/core/base.py,sha256=YQfGw3P2QshRdut3KhtrAleVvnFsIPOw5oGA9azypAA,1695
13
13
  kabukit/core/client.py,sha256=tVq1r3zpOfjmOtnRI1KPZHgTgBZYIpJzfw15i2kAM48,676
14
14
  kabukit/core/info.py,sha256=5BX7mDavF6g-b0KzHgKIFHUS5701BoaHtw1JcHSsy94,174
15
15
  kabukit/core/list.py,sha256=AjnXzC9XIu21l6IBEHHAS5VAnfxTfkAA9m1WAOZJNa8,174
16
- kabukit/core/prices.py,sha256=4jL6ItbyVov-G-JuZhvZTzqTDeisHJ9rEPH9wpf3pUg,6382
16
+ kabukit/core/prices.py,sha256=YGhz6ZjfC86aZ0pM4NFxceXTs2gTmO2hVdPd5DawV14,13316
17
17
  kabukit/core/reports.py,sha256=ch_xe84GbB17JTfmY3ArQqneQ2XOuvrAykBTAyNmWuM,177
18
- kabukit/core/statements.py,sha256=BNVmzTF_GvckRj3TfZT5ZoSBfnK32RzJM8YHpkz-h6Y,2806
18
+ kabukit/core/statements.py,sha256=_n4-8G284e6y_MwhvUq4xBK4bapQHk-Zmwu09C_r7wU,2790
19
19
  kabukit/edinet/__init__.py,sha256=PKa4D-jVpeoOkdVp9NwwpgAiGEBjqvmJLmpzF-9SlVk,101
20
20
  kabukit/edinet/client.py,sha256=BlM7pjXpKweOo-ses41JiKinqRn4qerMN5NF7hgYKgg,3275
21
21
  kabukit/edinet/concurrent.py,sha256=2YPzIFuuOB8-gL3CnHIlP486QH5d21qjKNKGCFK7Hzk,4707
@@ -33,7 +33,7 @@ kabukit/utils/concurrent.py,sha256=m2zVqJUz4xFVpNbEc9YEaj3Jmbl82njupdm4_rBOoYQ,4
33
33
  kabukit/utils/config.py,sha256=Jp-2TCnIj_QqA71FzYCkHXbvXvhw_1JVl4PR0foA1vM,618
34
34
  kabukit/utils/date.py,sha256=DEC6Ac5LS8eiW6JtrmcD3U1pX4qzXtx4ale0swpO4Ag,937
35
35
  kabukit/utils/params.py,sha256=qcaJbf6CWPUoZAZsYDTaZSnBUWeAersbWnR_iiYW9GM,1108
36
- kabukit-0.5.2.dist-info/WHEEL,sha256=n2u5OFBbdZvCiUKAmfnY1Po2j3FB_NWfuUlt5WiAjrk,79
37
- kabukit-0.5.2.dist-info/entry_points.txt,sha256=vvX771TemoM-35vVizW3JJ70HvRXnd2tX4P1Btzyoxs,46
38
- kabukit-0.5.2.dist-info/METADATA,sha256=HCAafrEHVXPOwUFGWhmBK2Q0UFhMcpbMAZk8ZxAWHpo,3207
39
- kabukit-0.5.2.dist-info/RECORD,,
36
+ kabukit-0.5.3.dist-info/WHEEL,sha256=n2u5OFBbdZvCiUKAmfnY1Po2j3FB_NWfuUlt5WiAjrk,79
37
+ kabukit-0.5.3.dist-info/entry_points.txt,sha256=vvX771TemoM-35vVizW3JJ70HvRXnd2tX4P1Btzyoxs,46
38
+ kabukit-0.5.3.dist-info/METADATA,sha256=B1p6W0ztcfnlZ2i1x6IpAjobxlffOATdoSngUxu6ztc,3207
39
+ kabukit-0.5.3.dist-info/RECORD,,