kabukit 0.5.2__tar.gz → 0.5.4__tar.gz

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.
Files changed (40) hide show
  1. {kabukit-0.5.2 → kabukit-0.5.4}/PKG-INFO +1 -1
  2. {kabukit-0.5.2 → kabukit-0.5.4}/pyproject.toml +1 -1
  3. kabukit-0.5.4/src/kabukit/core/prices.py +434 -0
  4. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/core/statements.py +1 -2
  5. kabukit-0.5.2/src/kabukit/core/prices.py +0 -164
  6. {kabukit-0.5.2 → kabukit-0.5.4}/LICENSE +0 -0
  7. {kabukit-0.5.2 → kabukit-0.5.4}/README.md +0 -0
  8. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/__init__.py +0 -0
  9. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/analysis/__init__.py +0 -0
  10. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/analysis/indicators.py +0 -0
  11. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/analysis/preprocess.py +0 -0
  12. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/analysis/screener.py +0 -0
  13. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/analysis/visualization.py +0 -0
  14. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/cli/__init__.py +0 -0
  15. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/cli/app.py +0 -0
  16. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/cli/auth.py +0 -0
  17. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/cli/get.py +0 -0
  18. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/core/__init__.py +0 -0
  19. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/core/base.py +0 -0
  20. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/core/client.py +0 -0
  21. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/core/info.py +0 -0
  22. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/core/list.py +0 -0
  23. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/core/reports.py +0 -0
  24. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/edinet/__init__.py +0 -0
  25. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/edinet/client.py +0 -0
  26. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/edinet/concurrent.py +0 -0
  27. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/edinet/doc.py +0 -0
  28. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/jquants/__init__.py +0 -0
  29. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/jquants/client.py +0 -0
  30. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/jquants/concurrent.py +0 -0
  31. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/jquants/info.py +0 -0
  32. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/jquants/prices.py +0 -0
  33. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/jquants/schema.py +0 -0
  34. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/jquants/statements.py +0 -0
  35. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/py.typed +0 -0
  36. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/utils/__init__.py +0 -0
  37. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/utils/concurrent.py +0 -0
  38. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/utils/config.py +0 -0
  39. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/utils/date.py +0 -0
  40. {kabukit-0.5.2 → kabukit-0.5.4}/src/kabukit/utils/params.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: kabukit
3
- Version: 0.5.2
3
+ Version: 0.5.4
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>
@@ -4,7 +4,7 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "kabukit"
7
- version = "0.5.2"
7
+ version = "0.5.4"
8
8
  description = "A Python toolkit for Japanese financial market data, supporting J-Quants and EDINET APIs."
9
9
  readme = "README.md"
10
10
  license = { file = "LICENSE" }
@@ -0,0 +1,434 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ import polars as pl
6
+
7
+ from .base import Base
8
+
9
+ if TYPE_CHECKING:
10
+ from datetime import timedelta
11
+ from typing import Self
12
+
13
+ from polars import DataFrame, Expr
14
+
15
+ from .statements import Statements
16
+
17
+
18
+ class Prices(Base):
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
+ """
40
+ data = (
41
+ self.data.group_by(pl.col("Date").dt.truncate(every), "Code")
42
+ .agg(
43
+ pl.col("Open").drop_nulls().first(),
44
+ pl.col("High").max(),
45
+ pl.col("Low").min(),
46
+ pl.col("Close").drop_nulls().last(),
47
+ pl.col("Volume").sum(),
48
+ pl.col("TurnoverValue").sum(),
49
+ )
50
+ .sort("Code", "Date")
51
+ )
52
+
53
+ return self.__class__(data)
54
+
55
+ def with_adjusted_shares(self, statements: Statements) -> Self:
56
+ """日次の調整済み株式数を計算し、列として追加する。
57
+
58
+ 決算短信で報告される株式数(例:発行済株式総数)は、四半期ごとなど
59
+ 特定の日付のデータです。一方で、株式分割や併合は日々発生し、株式数を
60
+ 変動させます。
61
+ このメソッドは、直近の決算で報告された株式数を、日々の調整係数
62
+ (`AdjustmentFactor`) を用いて補正し、日次ベースの時系列データとして
63
+ 提供します。これにより、日々の時価総額計算などが正確に行えるようになります。
64
+
65
+ 具体的には、`statements`から`IssuedShares`(発行済株式総数)と
66
+ `TreasuryShares`(自己株式数)を取得し、それぞれを調整します。
67
+ 計算結果は、元の列名との混同を避けるため、接頭辞`Adjusted`を付与した
68
+ 新しい列(`AdjustedIssuedShares`, `AdjustedTreasuryShares`)として
69
+ 追加されます。
70
+
71
+ Args:
72
+ statements (Statements): 財務データを提供する`Statements`オブジェクト。
73
+
74
+ Returns:
75
+ Self: `AdjustedIssuedShares`および`AdjustedTreasuryShares`列が
76
+ 追加された、新しいPricesオブジェクト。
77
+
78
+ Note:
79
+ この計算は、決算発表間の株式数の変動が、株式分割・併合
80
+ (`AdjustmentFactor`)にのみ起因すると仮定しています。
81
+ 期中に行われる増資や自己株式取得など、`AdjustmentFactor`に
82
+ 反映されないイベントによる株式数の変動は考慮されません。
83
+ """
84
+ if "AdjustedIssuedShares" in self.data.columns:
85
+ return self
86
+
87
+ shares = statements.shares().rename({"Date": "ReportDate"})
88
+
89
+ adjusted = (
90
+ self.data.join_asof(
91
+ shares,
92
+ left_on="Date",
93
+ right_on="ReportDate",
94
+ by="Code",
95
+ check_sortedness=False,
96
+ )
97
+ .with_columns(
98
+ (1.0 / pl.col("AdjustmentFactor"))
99
+ .cum_prod()
100
+ .over("Code", "ReportDate")
101
+ .alias("CumulativeRatio"),
102
+ )
103
+ .with_columns(
104
+ (pl.col("IssuedShares", "TreasuryShares") * pl.col("CumulativeRatio"))
105
+ .round(0)
106
+ .cast(pl.Int64)
107
+ .name.prefix("Adjusted"),
108
+ )
109
+ .select(
110
+ "Date",
111
+ "Code",
112
+ "ReportDate",
113
+ "AdjustedIssuedShares",
114
+ "AdjustedTreasuryShares",
115
+ )
116
+ )
117
+
118
+ data = self.data.join(adjusted, on=["Date", "Code"], how="left")
119
+
120
+ return self.__class__(data)
121
+
122
+ @property
123
+ def _outstanding_shares_expr(self) -> pl.Expr:
124
+ """調整済み発行済株式数を計算する Polars 式を返す。
125
+
126
+ Raises:
127
+ KeyError: 必要な列が存在しない場合は KeyError を送出する。
128
+ """
129
+ required_cols = {"AdjustedIssuedShares", "AdjustedTreasuryShares"}
130
+
131
+ if not required_cols.issubset(self.data.columns):
132
+ missing = required_cols - set(self.data.columns)
133
+ msg = f"必要な列が存在しません: {missing}。"
134
+ msg += "事前に .with_adjusted_shares() を呼び出してください。"
135
+ raise KeyError(msg)
136
+
137
+ return pl.col("AdjustedIssuedShares") - pl.col("AdjustedTreasuryShares")
138
+
139
+ def with_market_cap(self) -> Self:
140
+ """時価総額を計算し、列として追加する。
141
+
142
+ このメソッドは、日々の調整前終値 (`RawClose`) と、調整済みの発行済株式数
143
+ (`AdjustedIssuedShares`) および自己株式数 (`AdjustedTreasuryShares`)
144
+ を基に、日次ベースの時価総額を計算します。
145
+
146
+ 計算式:
147
+ 時価総額 = 調整前終値 * (調整済み発行済株式数 - 調整済み自己株式数)
148
+
149
+ Returns:
150
+ Self: `MarketCap` 列が追加された、新しいPricesオブジェクト。
151
+
152
+ Note:
153
+ このメソッドを呼び出す前に、`with_adjusted_shares()` あるいは
154
+ `with_yields()` を実行して、調整済みの株式数列を事前に計算して
155
+ おく必要があります。
156
+ """
157
+ data = self.data.with_columns(
158
+ (pl.col("RawClose") * self._outstanding_shares_expr).alias("MarketCap"),
159
+ )
160
+
161
+ return self.__class__(data)
162
+
163
+ def with_equity(self, statements: Statements) -> Self:
164
+ """時系列の純資産を列として追加する。
165
+
166
+ Args:
167
+ statements (Statements): 財務データを提供する`Statements`オブジェクト。
168
+
169
+ Returns:
170
+ Self: `Equity` 列が追加された、新しいPricesオブジェクト。
171
+ """
172
+ if "Equity" in self.data.columns:
173
+ return self
174
+
175
+ data = self.data.join_asof(
176
+ statements.equity(),
177
+ on="Date",
178
+ by="Code",
179
+ check_sortedness=False,
180
+ )
181
+
182
+ return self.__class__(data)
183
+
184
+ def with_book_value_yield(self) -> Self:
185
+ """時系列の一株あたり純資産と純資産利回りを列として追加する。
186
+
187
+ 計算式:
188
+ 一株あたり純資産 = 純資産 / (調整済み発行済株式数 - 調整済み自己株式数)
189
+ 純資産利回り = 一株あたり純資産 / 調整前終値
190
+
191
+ Returns:
192
+ Self: `BookValuePerShare`, `BookValueYield` 列が追加された、
193
+ 新しいPricesオブジェクト。
194
+
195
+ Note:
196
+ このメソッドを呼び出す前に、`with_equity()` および
197
+ `with_adjusted_shares()` を実行して、純資産および調整済み株式数
198
+ 列を事前に計算しておく必要があります。
199
+ """
200
+ data = self.data.with_columns(
201
+ (pl.col("Equity") / self._outstanding_shares_expr).alias(
202
+ "BookValuePerShare",
203
+ ),
204
+ ).with_columns(
205
+ (pl.col("BookValuePerShare") / pl.col("RawClose")).alias(
206
+ "BookValueYield",
207
+ ),
208
+ )
209
+
210
+ return self.__class__(data)
211
+
212
+ def with_forecast_profit(self, statements: Statements) -> Self:
213
+ """時系列の予想純利益を列として追加する。
214
+
215
+ Args:
216
+ statements (Statements): 財務データを提供する`Statements`オブジェクト。
217
+
218
+ Returns:
219
+ Self: `ForecastProfit` 列が追加された、新しいPricesオブジェクト。
220
+ """
221
+ if "ForecastProfit" in self.data.columns:
222
+ return self
223
+
224
+ data = self.data.join_asof(
225
+ statements.forecast_profit(),
226
+ on="Date",
227
+ by="Code",
228
+ check_sortedness=False,
229
+ )
230
+
231
+ return self.__class__(data)
232
+
233
+ def with_earnings_yield(self) -> Self:
234
+ """時系列の一株あたり純利益と収益利回り(純利益利回り)を列として追加する。
235
+
236
+ 計算式:
237
+ 一株あたり純利益 = 予想純利益 / (調整済み発行済株式数 - 調整済み自己株式数)
238
+ 収益利回り = 一株あたり純利益 / 調整前終値
239
+
240
+ Returns:
241
+ Self: `EarningsPerShare`, `EarningsYield` 列が追加された、
242
+ 新しいPricesオブジェクト。
243
+
244
+ Note:
245
+ このメソッドを呼び出す前に、`with_forecast_profit()` および
246
+ `with_adjusted_shares()` を実行して、予想純利益および調整済み株式数
247
+ 列を事前に計算しておく必要があります。
248
+ """
249
+ data = self.data.with_columns(
250
+ (pl.col("ForecastProfit") / self._outstanding_shares_expr).alias(
251
+ "EarningsPerShare",
252
+ ),
253
+ ).with_columns(
254
+ (pl.col("EarningsPerShare") / pl.col("RawClose")).alias("EarningsYield"),
255
+ )
256
+
257
+ return self.__class__(data)
258
+
259
+ def with_forecast_dividend(self, statements: Statements) -> Self:
260
+ """時系列の予想年間配当総額を列として追加する。
261
+
262
+ Args:
263
+ statements (Statements): 財務データを提供する`Statements`オブジェクト。
264
+
265
+ Returns:
266
+ Self: `ForecastDividend` 列が追加された、新しいPricesオブジェクト。
267
+ """
268
+ if "ForecastDividend" in self.data.columns:
269
+ return self
270
+
271
+ data = self.data.join_asof(
272
+ statements.forecast_dividend(),
273
+ on="Date",
274
+ by="Code",
275
+ check_sortedness=False,
276
+ )
277
+
278
+ return self.__class__(data)
279
+
280
+ def with_dividend_yield(self) -> Self:
281
+ """時系列の一株あたり配当金と配当利回りを列として追加する。
282
+
283
+ 計算式:
284
+ 一株あたり配当金 = 予想年間配当総額 / (調整済み発行済株式数 - 調整済み自己株式数)
285
+ 配当利回り = 一株あたり配当金 / 調整前終値
286
+
287
+ Returns:
288
+ Self: `DividendPerShare`, `DividendYield` 列が追加された、
289
+ 新しいPricesオブジェクト。
290
+
291
+ Note:
292
+ このメソッドを呼び出す前に、`with_forecast_dividend()` および
293
+ `with_adjusted_shares()` を実行して、予想年間配当総額および調整済み株式数
294
+ 列を事前に計算しておく必要があります。
295
+ """ # noqa: E501
296
+ data = self.data.with_columns(
297
+ (pl.col("ForecastDividend") / self._outstanding_shares_expr).alias(
298
+ "DividendPerShare",
299
+ ),
300
+ ).with_columns(
301
+ (pl.col("DividendPerShare") / pl.col("RawClose")).alias("DividendYield"),
302
+ )
303
+
304
+ return self.__class__(data)
305
+
306
+ def with_yields(self, statements: Statements) -> Self:
307
+ """すべての利回り関連指標を計算し、列として追加する。
308
+
309
+ このメソッドは、以下の利回り関連指標をまとめて計算し、DataFrameに
310
+ 追加するコンビニエンスメソッドです。
311
+
312
+ * 純資産利回り (`BookValueYield`)
313
+ * 収益利回り (`EarningsYield`)
314
+ * 配当利回り (`DividendYield`)
315
+
316
+ 内部で `with_adjusted_shares()`, `with_equity()`,
317
+ `with_book_value_yield()`, `with_forecast_profit()`,
318
+ `with_earnings_yield()`, `with_forecast_dividend()`,
319
+ `with_dividend_yield()` を呼び出します。
320
+ これらのメソッドはべき等であるため、重複して呼び出されても
321
+ 無駄な計算は行われません。
322
+
323
+ Args:
324
+ statements (Statements): 財務データを提供する`Statements`オブジェクト。
325
+
326
+ Returns:
327
+ Self: `BookValuePerShare`, `BookValueYield`, `EarningsPerShare`,
328
+ `EarningsYield`, `DividendPerShare`, `DividendYield` 列が追加された、
329
+ 新しいPricesオブジェクト。
330
+ """
331
+ return (
332
+ self.with_adjusted_shares(statements)
333
+ .with_equity(statements)
334
+ .with_book_value_yield()
335
+ .with_forecast_profit(statements)
336
+ .with_earnings_yield()
337
+ .with_forecast_dividend(statements)
338
+ .with_dividend_yield()
339
+ )
340
+
341
+ def period_stats(self) -> DataFrame:
342
+ """各期ごとの各種利回りおよび調整済み終値の統計量を計算し、DataFrameを返す。
343
+
344
+ このメソッドは、`Code`と`ReportDate`で定義される各期(決算期間)ごとに、
345
+ 以下の指標の統計量(始値、高値、安値、終値、平均値)を計算し、新しいDataFrameを
346
+ 返します。
347
+
348
+ 対象指標:
349
+ * `BookValueYield` (純資産利回り)
350
+ * `EarningsYield` (収益利回り)
351
+ * `DividendYield` (配当利回り)
352
+ * `Close` (調整済み終値)
353
+
354
+ 統計量の種類:
355
+ * `_PeriodOpen`: 各期の最初の値
356
+ * `_PeriodHigh`: 各期の最大値
357
+ * `_PeriodLow`: 各期の最小値
358
+ * `_PeriodClose`: 各期の最後の値
359
+ * `_PeriodMean`: 各期の平均値
360
+
361
+ Note:
362
+ このメソッドを呼び出す前に、対象となる利回りカラムと`Close`、
363
+ そして`ReportDate`が`self.data`に存在している必要があります。
364
+ 通常、`with_yields()` メソッドを呼び出すことで、これらの前提条件が
365
+ 満たされます。
366
+
367
+ Returns:
368
+ DataFrame: 統計量カラムが追加された、新しいDataFrameオブジェクト。
369
+ """
370
+ # 必要なカラムが存在するかチェック
371
+ required_cols = {
372
+ "BookValueYield",
373
+ "EarningsYield",
374
+ "DividendYield",
375
+ "Close",
376
+ "ReportDate",
377
+ }
378
+ if not required_cols.issubset(self.data.columns):
379
+ missing = required_cols - set(self.data.columns)
380
+ msg = f"必要な列が存在しません: {missing}。"
381
+ msg += "事前に `with_yields()` メソッドなどを呼び出してください。"
382
+ raise KeyError(msg)
383
+
384
+ # 統計量を計算するカラムのリスト
385
+ target_cols = ["BookValueYield", "EarningsYield", "DividendYield", "Close"]
386
+
387
+ # 各カラムに対して統計量を計算する式を生成
388
+ aggs: list[pl.Expr] = []
389
+ for col in target_cols:
390
+ aggs.extend(
391
+ [
392
+ pl.col(col).drop_nulls().first().alias(f"{col}_PeriodOpen"),
393
+ pl.col(col).max().alias(f"{col}_PeriodHigh"),
394
+ pl.col(col).min().alias(f"{col}_PeriodLow"),
395
+ pl.col(col).drop_nulls().last().alias(f"{col}_PeriodClose"),
396
+ pl.col(col).mean().alias(f"{col}_PeriodMean"),
397
+ ],
398
+ )
399
+
400
+ # CodeとReportDateでグループ化し、統計量を計算
401
+ return self.data.group_by("Code", "ReportDate", maintain_order=True).agg(aggs)
402
+
403
+ def with_period_stats(self) -> Self:
404
+ """各期ごとの各種利回りおよび調整済み終値の統計量を計算し、列として追加する。
405
+
406
+ このメソッドは、`Code`と`ReportDate`で定義される各期(決算期間)ごとに、
407
+ 以下の指標の統計量(始値、高値、安値、終値、平均値)を計算し、新しい列として追加します。
408
+
409
+ 対象指標:
410
+ * `BookValueYield` (純資産利回り)
411
+ * `EarningsYield` (収益利回り)
412
+ * `DividendYield` (配当利回り)
413
+ * `Close` (調整済み終値)
414
+
415
+ 統計量の種類:
416
+ * `_PeriodOpen`: 各期の最初の値
417
+ * `_PeriodHigh`: 各期の最大値
418
+ * `_PeriodLow`: 各期の最小値
419
+ * `_PeriodClose`: 各期の最後の値
420
+ * `_PeriodMean`: 各期の平均値
421
+
422
+ Note:
423
+ このメソッドを呼び出す前に、対象となる利回りカラムと`Close`、
424
+ そして`ReportDate`が`self.data`に存在している必要があります。
425
+ 通常、`with_yields()` メソッドを呼び出すことで、これらの前提条件が
426
+ 満たされます。
427
+
428
+ Returns:
429
+ Self: 統計量カラムが追加された、新しいPricesオブジェクト。
430
+ """
431
+ stats = self.period_stats()
432
+ data = self.data.join(stats, on=["Code", "ReportDate"], how="left")
433
+
434
+ return self.__class__(data)
@@ -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,164 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import TYPE_CHECKING
4
-
5
- import polars as pl
6
-
7
- from .base import Base
8
-
9
- if TYPE_CHECKING:
10
- from datetime import timedelta
11
- from typing import Self
12
-
13
- from polars import Expr
14
-
15
- from .statements import Statements
16
-
17
-
18
- class Prices(Base):
19
- def truncate(self, every: str | timedelta | Expr) -> Self:
20
- data = (
21
- self.data.group_by(pl.col("Date").dt.truncate(every), "Code")
22
- .agg(
23
- pl.col("Open").drop_nulls().first(),
24
- pl.col("High").max(),
25
- pl.col("Low").min(),
26
- pl.col("Close").drop_nulls().last(),
27
- pl.col("Volume").sum(),
28
- pl.col("TurnoverValue").sum(),
29
- )
30
- .sort("Code", "Date")
31
- )
32
- return self.__class__(data)
33
-
34
- def with_adjusted_shares(self, statements: Statements) -> Self:
35
- """日次の調整済み株式数を計算し、列として追加する。
36
-
37
- 決算短信で報告される株式数(例:発行済株式総数)は、四半期ごとなど
38
- 特定の日付のデータです。一方で、株式分割や併合は日々発生し、株式数を
39
- 変動させます。
40
- このメソッドは、直近の決算で報告された株式数を、日々の調整係数
41
- (`AdjustmentFactor`) を用いて補正し、日次ベースの時系列データとして
42
- 提供します。これにより、日々の時価総額計算などが正確に行えるようになります。
43
-
44
- 具体的には、`statements`から`IssuedShares`(発行済株式総数)と
45
- `TreasuryShares`(自己株式数)を取得し、それぞれを調整します。
46
- 計算結果は、元の列名との混同を避けるため、接頭辞`Adjusted`を付与した
47
- 新しい列(`AdjustedIssuedShares`, `AdjustedTreasuryShares`)として
48
- 追加されます。
49
-
50
- .. note::
51
- この計算は、決算発表間の株式数の変動が、株式分割・併合
52
- (`AdjustmentFactor`)にのみ起因すると仮定しています。
53
- 期中に行われる増資や自己株式取得など、`AdjustmentFactor`に
54
- 反映されないイベントによる株式数の変動は考慮されません。
55
-
56
- Args:
57
- statements (Statements): 財務データを提供する`Statements`オブジェクト。
58
-
59
- Returns:
60
- Self: `AdjustedIssuedShares`および`AdjustedTreasuryShares`列が
61
- 追加された、新しいPricesオブジェクト。
62
- """
63
- shares = statements.shares().rename({"Date": "ReportDate"})
64
-
65
- adjusted = (
66
- self.data.join_asof(
67
- shares,
68
- left_on="Date",
69
- right_on="ReportDate",
70
- by="Code",
71
- check_sortedness=False,
72
- )
73
- .with_columns(
74
- (1.0 / pl.col("AdjustmentFactor"))
75
- .cum_prod()
76
- .over("Code", "ReportDate")
77
- .alias("CumulativeRatio"),
78
- )
79
- .with_columns(
80
- (pl.col("IssuedShares", "TreasuryShares") * pl.col("CumulativeRatio"))
81
- .round(0)
82
- .cast(pl.Int64)
83
- .name.prefix("Adjusted"),
84
- )
85
- .select("Date", "Code", "AdjustedIssuedShares", "AdjustedTreasuryShares")
86
- )
87
-
88
- data = self.data.join(adjusted, on=["Date", "Code"], how="left")
89
-
90
- return self.__class__(data)
91
-
92
- def with_market_cap(self) -> Self:
93
- """時価総額を計算し、列として追加する。
94
-
95
- このメソッドは、日々の調整前終値 (`RawClose`) と、調整済みの発行済株式数
96
- (`AdjustedIssuedShares`) および自己株式数 (`AdjustedTreasuryShares`)
97
- を基に、日次ベースの時価総額を計算します。
98
-
99
- 計算式:
100
- 時価総額 = 調整前終値 * (調整済み発行済株式数 - 調整済み自己株式数)
101
-
102
- Note:
103
- このメソッドを呼び出す前に、`with_adjusted_shares()` を
104
- 実行して、調整済みの株式数列を事前に計算しておく必要があります。
105
-
106
- Returns:
107
- Self: `MarketCap` 列が追加された、新しいPricesオブジェクト。
108
- """
109
- shares = pl.col("AdjustedIssuedShares") - pl.col("AdjustedTreasuryShares")
110
- data = self.data.with_columns(
111
- (pl.col("RawClose") * shares).round(0).alias("MarketCap"),
112
- )
113
- return self.__class__(data)
114
-
115
- def with_equity(self, statements: Statements) -> Self:
116
- """時系列の純資産を列として追加する。
117
-
118
- Args:
119
- statements (Statements): 財務データを提供する`Statements`オブジェクト。
120
-
121
- Returns:
122
- Self: `Equity` 列が追加された、新しいPricesオブジェクト。
123
- """
124
- data = self.data.join_asof(
125
- statements.equity(),
126
- on="Date",
127
- by="Code",
128
- check_sortedness=False,
129
- )
130
- return self.__class__(data)
131
-
132
- def with_forecast_profit(self, statements: Statements) -> Self:
133
- """時系列の予想純利益を列として追加する。
134
-
135
- Args:
136
- statements (Statements): 財務データを提供する`Statements`オブジェクト。
137
-
138
- Returns:
139
- Self: `ForecastProfit` 列が追加された、新しいPricesオブジェクト。
140
- """
141
- data = self.data.join_asof(
142
- statements.forecast_profit(),
143
- on="Date",
144
- by="Code",
145
- check_sortedness=False,
146
- )
147
- return self.__class__(data)
148
-
149
- def with_forecast_dividend(self, statements: Statements) -> Self:
150
- """時系列の予想年間配当総額を列として追加する。
151
-
152
- Args:
153
- statements (Statements): 財務データを提供する`Statements`オブジェクト。
154
-
155
- Returns:
156
- Self: `ForecastDividend` 列が追加された、新しいPricesオブジェクト。
157
- """
158
- data = self.data.join_asof(
159
- statements.forecast_dividend(),
160
- on="Date",
161
- by="Code",
162
- check_sortedness=False,
163
- )
164
- return self.__class__(data)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes