BackcastPro 0.3.4__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.
@@ -0,0 +1,131 @@
1
+ from .lib.jquants import jquants
2
+ from .lib.e_api import e_api
3
+ from .lib.kabusap import kabusap
4
+ from .lib.stooq import stooq_daily_quotes
5
+ from .db_stocks_daily import db_stocks_daily
6
+ from .lib.util import _Timestamp
7
+
8
+ import pandas as pd
9
+ import threading
10
+ from datetime import datetime
11
+ import logging
12
+
13
+ logger = logging.getLogger(__name__)
14
+ logger.setLevel(logging.INFO)
15
+
16
+
17
+ class stocks_price:
18
+ """
19
+ 銘柄の株価データを取得するためのクラス
20
+ """
21
+
22
+ def __init__(self):
23
+ self.db = db_stocks_daily()
24
+
25
+ def get_japanese_stock_price_data(
26
+ self, code="", from_: datetime = None, to: datetime = None
27
+ ) -> pd.DataFrame:
28
+ # 銘柄コードの検証
29
+ if not code or not isinstance(code, str) or not code.strip():
30
+ raise ValueError("銘柄コードが指定されていません")
31
+
32
+ # from_/to の柔軟入力(str/date/pd.Timestamp)を正規化
33
+ norm_from = _Timestamp(from_)
34
+ norm_to = _Timestamp(to)
35
+
36
+ if norm_from and norm_to and norm_from > norm_to:
37
+ raise ValueError("開始日が終了日より後になっています")
38
+
39
+ # DBファイルの準備(存在しなければFTPからダウンロードを試行)
40
+ self.db.ensure_db_ready(code)
41
+
42
+ # 1) cacheフォルダから取得
43
+ df = self.db.load_stock_prices_from_cache(code, norm_from, norm_to)
44
+ if df is not None and not df.empty:
45
+ return df
46
+
47
+ # 2) 立花証券 e-支店から取得
48
+ if not hasattr(self, "e_shiten"):
49
+ self.e_shiten = e_api()
50
+ if self.e_shiten.isEnable:
51
+ df = self.e_shiten.get_daily_quotes(code=code, from_=norm_from, to=norm_to)
52
+ if df is not None and not df.empty:
53
+ # DataFrameをcacheフォルダに保存
54
+ ## 非同期、遅延を避けるためデーモンスレッドで実行
55
+ threading.Thread(
56
+ target=self.db.save_stock_prices, args=(code, df), daemon=True
57
+ ).start()
58
+ return df
59
+
60
+ # 3) J-Quantsから取得
61
+ if not hasattr(self, "jq"):
62
+ self.jq = jquants()
63
+ if self.jq.isEnable:
64
+ df = self.jq.get_daily_quotes(code=code, from_=norm_from, to=norm_to)
65
+ if df is not None and not df.empty:
66
+ # DataFrameをcacheフォルダに保存
67
+ ## 非同期、遅延を避けるためデーモンスレッドで実行
68
+ threading.Thread(
69
+ target=self.db.save_stock_prices, args=(code, df), daemon=True
70
+ ).start()
71
+ return df
72
+
73
+ # 4) stooqから取得
74
+ df = stooq_daily_quotes(code=code, from_=norm_from, to=norm_to)
75
+ if df is not None and not df.empty:
76
+ # DataFrameをcacheフォルダに保存
77
+ ## 非同期、遅延を避けるためデーモンスレッドで実行
78
+ threading.Thread(
79
+ target=self.db.save_stock_prices, args=(code, df), daemon=True
80
+ ).start()
81
+ return df
82
+
83
+ raise ValueError(f"日本株式銘柄の取得に失敗しました: {code}")
84
+
85
+
86
+ def get_stock_daily(code, from_: datetime = None, to: datetime = None) -> pd.DataFrame:
87
+ """
88
+ 株価四本値(/prices/daily_quotes)
89
+
90
+ - 株価は分割・併合を考慮した調整済み株価(小数点第2位四捨五入)と調整前の株価を取得することができます。
91
+ - データの取得では、銘柄コード(code)または日付(date)の指定が必須となります。
92
+
93
+ Args:
94
+ code: 銘柄コード(例: "7203.JP")
95
+ from_: 開始日(datetime, str, または None)
96
+ to: 終了日(datetime, str, または None)
97
+
98
+ Returns:
99
+ DataFrame: 株価データ(DatetimeIndexとして日付がインデックスに設定されている)
100
+ """
101
+ from .stocks_price import stocks_price
102
+ __sp__ = stocks_price()
103
+
104
+ # 株価データを取得(内部で自動的にデータベースに保存される)
105
+ df = __sp__.get_japanese_stock_price_data(code=code, from_=from_, to=to)
106
+
107
+ # DatetimeIndexであることを保証
108
+ if df is not None and not df.empty:
109
+ if not isinstance(df.index, pd.DatetimeIndex):
110
+ # Date列がある場合はそれをインデックスに設定
111
+ if 'Date' in df.columns:
112
+ df = df.copy()
113
+ df['Date'] = pd.to_datetime(df['Date'])
114
+ df = df.set_index('Date')
115
+ elif 'date' in df.columns:
116
+ df = df.copy()
117
+ df['date'] = pd.to_datetime(df['date'])
118
+ df = df.set_index('date')
119
+ df.index.name = 'Date'
120
+ else:
121
+ import warnings
122
+ warnings.warn(
123
+ f"get_stock_daily('{code}') が返したDataFrameにDate列がなく、"
124
+ "インデックスもDatetimeIndexではありません。",
125
+ stacklevel=2
126
+ )
127
+ # 日付順にソート
128
+ if isinstance(df.index, pd.DatetimeIndex):
129
+ df = df.sort_index()
130
+
131
+ return df