fin68 0.1.3__cp312-cp312-win_amd64.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.
- fin68/__init__.py +323 -0
- fin68/__init__.pyi +81 -0
- fin68/_core/__init__.py +0 -0
- fin68/_version.py +17 -0
- fin68/auth/__init__.py +0 -0
- fin68/auth/api_key.py +0 -0
- fin68/clients/__init__.py +3 -0
- fin68/clients/base.py +17 -0
- fin68/clients/eod/MarketEod.py +142 -0
- fin68/clients/eod/MarketEod.pyi +95 -0
- fin68/clients/eod/SectorEod.py +146 -0
- fin68/clients/eod/SectorEod.pyi +86 -0
- fin68/clients/eod/StockEod.py +134 -0
- fin68/clients/eod/StockEod.pyi +92 -0
- fin68/clients/eod/__init__.py +6 -0
- fin68/clients/eod/helper.py +65 -0
- fin68/clients/eod/icb_types.py +111 -0
- fin68/clients/eod_main.py +169 -0
- fin68/clients/eod_main.pyi +102 -0
- fin68/clients/financials.py +0 -0
- fin68/clients/index.py +0 -0
- fin68/clients/info.py +0 -0
- fin68/config.py +0 -0
- fin68/exceptions.py +28 -0
- fin68/models/__init__.py +0 -0
- fin68/models/base.py +0 -0
- fin68/models/eod.py +0 -0
- fin68/models/financials.py +0 -0
- fin68/models/index.py +0 -0
- fin68/models/meta.py +0 -0
- fin68/transport/__init__.py +0 -0
- fin68/transport/cache.py +0 -0
- fin68/transport/http.py +0 -0
- fin68/transport/rate_limiter.py +0 -0
- fin68/types.py +90 -0
- fin68/utils/__init__.py +5 -0
- fin68/utils/_validate_date_eod.py +9 -0
- fin68/utils/convert.py +0 -0
- fin68/utils/pagination.py +0 -0
- fin68/utils/time.py +0 -0
- fin68/validators.py +0 -0
- fin68-0.1.3.dist-info/METADATA +129 -0
- fin68-0.1.3.dist-info/RECORD +55 -0
- fin68-0.1.3.dist-info/WHEEL +5 -0
- fin68-0.1.3.dist-info/licenses/LICENSE +21 -0
- fin68-0.1.3.dist-info/top_level.txt +2 -0
- private_core/__init__.py +1 -0
- private_core/auth_core.cp312-win_amd64.pyd +0 -0
- private_core/eod_core.cp312-win_amd64.pyd +0 -0
- private_core/financials_core.cp312-win_amd64.pyd +0 -0
- private_core/helpers.cp312-win_amd64.pyd +0 -0
- private_core/http_core.cp312-win_amd64.pyd +0 -0
- private_core/index_core.cp312-win_amd64.pyd +0 -0
- private_core/progress.cp312-win_amd64.pyd +0 -0
- private_core/utils_core.cp312-win_amd64.pyd +0 -0
@@ -0,0 +1,169 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
"""
|
4
|
+
fin68.clients.eod
|
5
|
+
=================
|
6
|
+
|
7
|
+
Cung cấp lớp `EodClient` — giao diện bậc cao (facade) cho toàn bộ nhóm
|
8
|
+
chức năng liên quan đến dữ liệu EOD (End-Of-Day).
|
9
|
+
Mỗi nhóm con (`stock`, `market`, `sector`) tương ứng với một loại dữ liệu EOD
|
10
|
+
cụ thể và được đóng gói trong các lớp `StockEod`, `MarketEod`, `SectorEod`.
|
11
|
+
|
12
|
+
Notes
|
13
|
+
-----
|
14
|
+
- `EodClient` không trực tiếp gọi HTTP API, mà ủy quyền cho các lớp con.
|
15
|
+
- Mọi request được gửi thông qua `HttpSession` (đã được xác thực sẵn bởi `Fin68Client`).
|
16
|
+
- Các phương thức trong `StockEod`, `MarketEod`, `SectorEod` đều trả về `pandas.DataFrame`
|
17
|
+
hoặc `dict` tùy theo tham số `as_dataframe`.
|
18
|
+
|
19
|
+
See Also
|
20
|
+
--------
|
21
|
+
Fin68Client
|
22
|
+
Entry point chính của SDK, dùng để khởi tạo `EodClient`.
|
23
|
+
BaseClient
|
24
|
+
Lớp cơ sở quản lý session và xử lý logic chung.
|
25
|
+
"""
|
26
|
+
|
27
|
+
from typing import TYPE_CHECKING
|
28
|
+
|
29
|
+
from .base import BaseClient
|
30
|
+
from .eod import MarketEod, SectorEod, StockEod
|
31
|
+
|
32
|
+
if TYPE_CHECKING:
|
33
|
+
from private_core.http_core import HttpSession
|
34
|
+
|
35
|
+
__all__ = ["EodClient"]
|
36
|
+
|
37
|
+
|
38
|
+
class EodClient(BaseClient):
|
39
|
+
"""
|
40
|
+
Lớp facade cấp cao tập hợp các namespace dữ liệu EOD (End-of-Day).
|
41
|
+
|
42
|
+
Cho phép người dùng truy cập nhanh vào các nhóm dữ liệu:
|
43
|
+
- `EodClient.stock`: dữ liệu EOD của từng mã cổ phiếu.
|
44
|
+
- `EodClient.market`: dữ liệu chỉ số thị trường (VNINDEX, HNXINDEX, UPCOM...).
|
45
|
+
- `EodClient.sector`: dữ liệu EOD tổng hợp theo ngành (ICB, VNSector...).
|
46
|
+
|
47
|
+
Parameters
|
48
|
+
----------
|
49
|
+
session : HttpSession
|
50
|
+
Phiên HTTP đã xác thực, được truyền từ `Fin68Client`.
|
51
|
+
|
52
|
+
Attributes
|
53
|
+
----------
|
54
|
+
stock : StockEod
|
55
|
+
Namespace xử lý dữ liệu EOD của cổ phiếu (OHLCV, phân tích kỹ thuật, v.v.).
|
56
|
+
market : MarketEod
|
57
|
+
Namespace cho dữ liệu thị trường chung (VNINDEX, HNX, UPCOM).
|
58
|
+
sector : SectorEod
|
59
|
+
Namespace cho dữ liệu theo ngành, dùng để theo dõi chỉ số và hiệu suất ICB.
|
60
|
+
|
61
|
+
Examples
|
62
|
+
--------
|
63
|
+
>>> from fin68 import client
|
64
|
+
>>> with client(api_key="sk_live_...") as cli:
|
65
|
+
... df = cli.eod.stock.ohlcv("HPG", start="2024-01-01", end="2024-06-30")
|
66
|
+
... idx = cli.eod.market.index("VNINDEX")
|
67
|
+
... sec = cli.eod.sector.performance("ICB01010")
|
68
|
+
|
69
|
+
Notes
|
70
|
+
-----
|
71
|
+
- `EodClient` không lưu trữ dữ liệu nội bộ; mỗi lần gọi đều là request HTTP mới.
|
72
|
+
- Có thể mở rộng bằng cách thêm namespace khác (ví dụ: `fundamental`, `derivative`).
|
73
|
+
"""
|
74
|
+
|
75
|
+
def __init__(self, session: "HttpSession") -> None:
|
76
|
+
"""
|
77
|
+
Khởi tạo các namespace EOD con (stock, market, sector).
|
78
|
+
|
79
|
+
Parameters
|
80
|
+
----------
|
81
|
+
session : HttpSession
|
82
|
+
Phiên HTTP đã xác thực từ `Fin68Client`.
|
83
|
+
"""
|
84
|
+
super().__init__(session=session)
|
85
|
+
self.stock: StockEod = StockEod(session=self.session)
|
86
|
+
"""
|
87
|
+
Namespace dữ liệu EOD cho **cổ phiếu (Stock-level)**.
|
88
|
+
|
89
|
+
Cung cấp các endpoint chuyên biệt để truy xuất dữ liệu End-of-Day (EOD)
|
90
|
+
cho từng mã cổ phiếu riêng lẻ — phù hợp cho các tác vụ như:
|
91
|
+
- Phân tích giá lịch sử (OHLCV)
|
92
|
+
- Tính toán chỉ báo kỹ thuật (MA, RSI, MACD, Bollinger, v.v.)
|
93
|
+
- So sánh hiệu suất cổ phiếu giữa các mã
|
94
|
+
|
95
|
+
Methods chính
|
96
|
+
--------------
|
97
|
+
- `ohlcv(symbol, start=None, end=None, interval="1D")`
|
98
|
+
→ Lấy dữ liệu OHLCV (Open, High, Low, Close, Volume) theo ngày, tuần, tháng…
|
99
|
+
|
100
|
+
Parameters
|
101
|
+
----------
|
102
|
+
symbol : str or list[str]
|
103
|
+
Mã cổ phiếu hoặc danh sách mã (VD: `"HPG"`, `["HPG", "VCB"]`)
|
104
|
+
|
105
|
+
Examples
|
106
|
+
--------
|
107
|
+
>>> cli.eod.stock.ohlcv("HPG", start="2024-01-01", end="2024-06-30")
|
108
|
+
>>> cli.eod.stock.ohlcv(["HPG", "VCB", "FPT"], interval="1W")
|
109
|
+
"""
|
110
|
+
|
111
|
+
self.market: MarketEod = MarketEod(session=self.session)
|
112
|
+
"""
|
113
|
+
Namespace dữ liệu EOD cho **chỉ số thị trường (Market-level)**.
|
114
|
+
|
115
|
+
Cung cấp dữ liệu tổng hợp cho các chỉ số thị trường phổ biến như:
|
116
|
+
- VNINDEX (sàn HOSE)
|
117
|
+
- VN30 (rổ 30 cổ phiếu vốn hóa lớn)
|
118
|
+
- HNX, HNX30 (sàn Hà Nội)
|
119
|
+
- UPCOM (thị trường UPCOM)
|
120
|
+
|
121
|
+
Dữ liệu này giúp phân tích xu hướng toàn thị trường, đo lường biến động,
|
122
|
+
và so sánh hiệu suất giữa các sàn.
|
123
|
+
|
124
|
+
Methods chính
|
125
|
+
--------------
|
126
|
+
- `ohlcv(symbol, start=None, end=None, interval="1D")`
|
127
|
+
→ Lấy dữ liệu OHLCV của các chỉ số (VNINDEX, VN30, HNX, …)
|
128
|
+
|
129
|
+
Parameters
|
130
|
+
----------
|
131
|
+
symbol : {"VNINDEX", "VN30", "HNX", "HNX30", "UPCOM"} or list
|
132
|
+
Tên chỉ số hoặc danh sách chỉ số.
|
133
|
+
|
134
|
+
Examples
|
135
|
+
--------
|
136
|
+
>>> cli.eod.market.ohlcv("VNINDEX", start="2024-01-01", end="2024-06-30")
|
137
|
+
>>> cli.eod.market.ohlcv(["VNINDEX", "VN30", "HNX"])
|
138
|
+
"""
|
139
|
+
|
140
|
+
self.sector: SectorEod = SectorEod(session=self.session)
|
141
|
+
"""
|
142
|
+
Namespace dữ liệu EOD cho **ngành và nhóm ngành (Sector-level)**.
|
143
|
+
|
144
|
+
Cung cấp dữ liệu tổng hợp theo mã ICB (Industry Classification Benchmark),
|
145
|
+
phản ánh biến động và hiệu suất trung bình của từng ngành hoặc tiểu ngành.
|
146
|
+
Thường dùng trong phân tích xoay vòng ngành (sector rotation) hoặc theo dõi
|
147
|
+
xu hướng dòng tiền giữa các nhóm cổ phiếu.
|
148
|
+
|
149
|
+
Methods chính
|
150
|
+
--------------
|
151
|
+
- `ohlcv(symbol, start=None, end=None, interval="1D")`
|
152
|
+
→ Lấy dữ liệu OHLCV trung bình theo ngành hoặc nhóm ngành.
|
153
|
+
|
154
|
+
Parameters
|
155
|
+
----------
|
156
|
+
symbol : str or list[str]
|
157
|
+
Mã ngành theo chuẩn ICB (VD: `"ICB01010"`, `"ICB03020"`).
|
158
|
+
|
159
|
+
Examples
|
160
|
+
--------
|
161
|
+
>>> cli.eod.sector.ohlcv("ICB01010", start="2024-01-01", end="2024-06-30")
|
162
|
+
>>> cli.eod.sector.ohlcv(["ICB01010", "ICB03020"], interval="1W")
|
163
|
+
|
164
|
+
Notes
|
165
|
+
-----
|
166
|
+
- Dữ liệu ngành được tính theo trọng số vốn hóa.
|
167
|
+
- Thường dùng để xác định nhóm ngành dẫn dắt thị trường.
|
168
|
+
"""
|
169
|
+
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# fin68/clients/<your_module_name>.pyi
|
2
|
+
from typing import TYPE_CHECKING
|
3
|
+
from .base import BaseClient
|
4
|
+
from .eod import MarketEod, SectorEod, StockEod
|
5
|
+
|
6
|
+
if TYPE_CHECKING:
|
7
|
+
from private_core.http_core import HttpSession
|
8
|
+
|
9
|
+
__all__: list[str]
|
10
|
+
|
11
|
+
class EodClient(BaseClient):
|
12
|
+
"""
|
13
|
+
Facade EOD: gom các namespace `stock`, `market`, `sector`.
|
14
|
+
"""
|
15
|
+
|
16
|
+
stock: StockEod
|
17
|
+
"""
|
18
|
+
Namespace dữ liệu EOD cho **cổ phiếu (Stock-level)**.
|
19
|
+
|
20
|
+
Cung cấp các endpoint chuyên biệt để truy xuất dữ liệu End-of-Day (EOD)
|
21
|
+
cho từng mã cổ phiếu riêng lẻ — phù hợp cho các tác vụ như:
|
22
|
+
- Phân tích giá lịch sử (OHLCV)
|
23
|
+
- Tính toán chỉ báo kỹ thuật (MA, RSI, MACD, Bollinger, v.v.)
|
24
|
+
- So sánh hiệu suất cổ phiếu giữa các mã
|
25
|
+
|
26
|
+
Methods chính
|
27
|
+
--------------
|
28
|
+
- `ohlcv(symbol, start=None, end=None, interval="1D")`
|
29
|
+
→ Lấy dữ liệu OHLCV (Open, High, Low, Close, Volume) theo ngày, tuần, tháng…
|
30
|
+
|
31
|
+
Parameters
|
32
|
+
----------
|
33
|
+
symbol : str or list[str]
|
34
|
+
Mã cổ phiếu hoặc danh sách mã (VD: `"HPG"`, `["HPG", "VCB"]`)
|
35
|
+
|
36
|
+
Examples
|
37
|
+
--------
|
38
|
+
>>> cli.eod.stock.ohlcv("HPG", start="2024-01-01", end="2024-06-30")
|
39
|
+
>>> cli.eod.stock.ohlcv(["HPG", "VCB", "FPT"], interval="1W")
|
40
|
+
"""
|
41
|
+
|
42
|
+
market: MarketEod
|
43
|
+
"""
|
44
|
+
Namespace dữ liệu EOD cho **chỉ số thị trường (Market-level)**.
|
45
|
+
|
46
|
+
Cung cấp dữ liệu tổng hợp cho các chỉ số thị trường phổ biến như:
|
47
|
+
- VNINDEX (sàn HOSE)
|
48
|
+
- VN30 (rổ 30 cổ phiếu vốn hóa lớn)
|
49
|
+
- HNX, HNX30 (sàn Hà Nội)
|
50
|
+
- UPCOM (thị trường UPCOM)
|
51
|
+
|
52
|
+
Dữ liệu này giúp phân tích xu hướng toàn thị trường, đo lường biến động,
|
53
|
+
và so sánh hiệu suất giữa các sàn.
|
54
|
+
|
55
|
+
Methods chính
|
56
|
+
--------------
|
57
|
+
- `ohlcv(symbol, start=None, end=None, interval="1D")`
|
58
|
+
→ Lấy dữ liệu OHLCV của các chỉ số (VNINDEX, VN30, HNX, …)
|
59
|
+
|
60
|
+
Parameters
|
61
|
+
----------
|
62
|
+
symbol : {"VNINDEX", "VN30", "HNX", "HNX30", "UPCOM"} or list
|
63
|
+
Tên chỉ số hoặc danh sách chỉ số.
|
64
|
+
|
65
|
+
Examples
|
66
|
+
--------
|
67
|
+
>>> cli.eod.market.ohlcv("VNINDEX", start="2024-01-01", end="2024-06-30")
|
68
|
+
>>> cli.eod.market.ohlcv(["VNINDEX", "VN30", "HNX"])
|
69
|
+
"""
|
70
|
+
|
71
|
+
sector: SectorEod
|
72
|
+
"""
|
73
|
+
Namespace dữ liệu EOD cho **ngành và nhóm ngành (Sector-level)**.
|
74
|
+
|
75
|
+
Cung cấp dữ liệu tổng hợp theo mã ICB (Industry Classification Benchmark),
|
76
|
+
phản ánh biến động và hiệu suất trung bình của từng ngành hoặc tiểu ngành.
|
77
|
+
Thường dùng trong phân tích xoay vòng ngành (sector rotation) hoặc theo dõi
|
78
|
+
xu hướng dòng tiền giữa các nhóm cổ phiếu.
|
79
|
+
|
80
|
+
Methods chính
|
81
|
+
--------------
|
82
|
+
- `ohlcv(icb_code, start=None, end=None, interval="1D")`
|
83
|
+
→ Lấy dữ liệu OHLCV trung bình theo ngành hoặc nhóm ngành.
|
84
|
+
|
85
|
+
Parameters
|
86
|
+
----------
|
87
|
+
icb_code : str or list[str]
|
88
|
+
Mã ngành theo chuẩn ICB (VD: `"ICB01010"`, `"ICB03020"`).
|
89
|
+
|
90
|
+
Examples
|
91
|
+
--------
|
92
|
+
>>> cli.eod.sector.ohlcv("ICB01010", start="2024-01-01", end="2024-06-30")
|
93
|
+
>>> cli.eod.sector.ohlcv(["ICB01010", "ICB03020"], interval="1W")
|
94
|
+
|
95
|
+
Notes
|
96
|
+
-----
|
97
|
+
- Dữ liệu ngành được tính theo trọng số vốn hóa.
|
98
|
+
- Thường dùng để xác định nhóm ngành dẫn dắt thị trường.
|
99
|
+
"""
|
100
|
+
|
101
|
+
|
102
|
+
def __init__(self, session: "HttpSession") -> None: ...
|
File without changes
|
fin68/clients/index.py
ADDED
File without changes
|
fin68/clients/info.py
ADDED
File without changes
|
fin68/config.py
ADDED
File without changes
|
fin68/exceptions.py
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from typing import Any, Optional
|
4
|
+
|
5
|
+
|
6
|
+
class Fin68Error(Exception):
|
7
|
+
"""Base exception for all Fin68 client errors."""
|
8
|
+
|
9
|
+
|
10
|
+
class ConfigurationError(Fin68Error):
|
11
|
+
"""Raised when the client is misconfigured."""
|
12
|
+
|
13
|
+
|
14
|
+
class HttpError(Fin68Error):
|
15
|
+
"""Raised when an HTTP call returns an unexpected status code."""
|
16
|
+
|
17
|
+
def __init__(self, message: str, *, status_code: Optional[int] = None, payload: Any = None) -> None:
|
18
|
+
super().__init__(message)
|
19
|
+
self.status_code = status_code
|
20
|
+
self.payload = payload
|
21
|
+
|
22
|
+
|
23
|
+
class ApiKeyValidationError(Fin68Error):
|
24
|
+
"""Raised when the backend rejects or cannot validate the API key."""
|
25
|
+
|
26
|
+
|
27
|
+
class DataDecodingError(Fin68Error):
|
28
|
+
"""Raised when raw API data cannot be transformed into the expected format."""
|
fin68/models/__init__.py
ADDED
File without changes
|
fin68/models/base.py
ADDED
File without changes
|
fin68/models/eod.py
ADDED
File without changes
|
File without changes
|
fin68/models/index.py
ADDED
File without changes
|
fin68/models/meta.py
ADDED
File without changes
|
File without changes
|
fin68/transport/cache.py
ADDED
File without changes
|
fin68/transport/http.py
ADDED
File without changes
|
File without changes
|
fin68/types.py
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from datetime import datetime
|
4
|
+
from enum import Enum
|
5
|
+
from typing import Iterator, List, Optional
|
6
|
+
|
7
|
+
from pydantic import BaseModel, Field, HttpUrl
|
8
|
+
|
9
|
+
|
10
|
+
class MessageType(str, Enum):
|
11
|
+
|
12
|
+
"""Enumerates possible backend message categories."""
|
13
|
+
|
14
|
+
NOTIFY_UPGRADE_VERSION = "notify_upgrade_version"
|
15
|
+
NOTIFY_API_KEY_EXPIRING = "notify_api_key_expiring"
|
16
|
+
NOTIFY_API_KEY_EXPIRED = "notify_api_key_expired"
|
17
|
+
MAINTENANCE = "maintenance"
|
18
|
+
INFO = "info"
|
19
|
+
WARNING = "warning"
|
20
|
+
ERROR = "error"
|
21
|
+
|
22
|
+
|
23
|
+
class BackendMessage(BaseModel):
|
24
|
+
"""Represents a notification emitted by the Fin68 backend."""
|
25
|
+
|
26
|
+
message: str = Field(..., description="Human readable message to display to the user.")
|
27
|
+
type: MessageType = Field(
|
28
|
+
MessageType.INFO,
|
29
|
+
description="Category describing how the client should surface the message.",
|
30
|
+
)
|
31
|
+
doc_url: Optional[HttpUrl] = Field(
|
32
|
+
None,
|
33
|
+
description="Optional URL with more context or remediation instructions.",
|
34
|
+
)
|
35
|
+
|
36
|
+
def is_upgrade_notice(self) -> bool:
|
37
|
+
return self.type == MessageType.NOTIFY_UPGRADE_VERSION
|
38
|
+
|
39
|
+
|
40
|
+
class ApiKeyMeta(BaseModel):
|
41
|
+
"""Metadata describing the current API key state returned by the backend."""
|
42
|
+
|
43
|
+
api_key: str = Field(..., description="Echo of the API key that was validated.")
|
44
|
+
is_active: bool = Field(..., description="Indicates whether the API key is currently active.")
|
45
|
+
expires_at: Optional[datetime] = Field(
|
46
|
+
None, description="Timestamp (ISO 8601) indicating when the API key expires."
|
47
|
+
)
|
48
|
+
max_requests_per_day: Optional[int] = Field(
|
49
|
+
None, description="Daily request quota associated with the API key, if applicable."
|
50
|
+
)
|
51
|
+
requests_remaining: Optional[int] = Field(
|
52
|
+
None, description="Number of requests remaining in the current quota window."
|
53
|
+
)
|
54
|
+
|
55
|
+
|
56
|
+
class VersionInfo(BaseModel):
|
57
|
+
"""Represents the compatibility information between client and backend versions."""
|
58
|
+
|
59
|
+
client_version: str = Field(..., description="Version of fin68 currently running on the client.")
|
60
|
+
backend_version: Optional[str] = Field(
|
61
|
+
None,
|
62
|
+
description="Latest version reported by the backend. None when the backend skips the check.",
|
63
|
+
)
|
64
|
+
minimum_supported_version: Optional[str] = Field(
|
65
|
+
None, description="Lowest client version that remains supported by the backend."
|
66
|
+
)
|
67
|
+
|
68
|
+
def requires_upgrade(self) -> bool:
|
69
|
+
if not self.backend_version:
|
70
|
+
return False
|
71
|
+
return self.backend_version != self.client_version
|
72
|
+
|
73
|
+
def is_out_of_support(self) -> bool:
|
74
|
+
if not self.minimum_supported_version:
|
75
|
+
return False
|
76
|
+
return self.client_version < self.minimum_supported_version
|
77
|
+
|
78
|
+
|
79
|
+
class ApiKeyValidationResponse(BaseModel):
|
80
|
+
"""Canonical schema describing the backend response for API key validation."""
|
81
|
+
|
82
|
+
meta: ApiKeyMeta = Field(..., description="Metadata regarding the API key.")
|
83
|
+
version: VersionInfo = Field(..., description="Compatibility information for fin68 client versions.")
|
84
|
+
messages: Optional[List[BackendMessage]] = Field(
|
85
|
+
None, description="Optional notifications or instructions for the caller."
|
86
|
+
)
|
87
|
+
|
88
|
+
def iter_messages(self) -> Iterator[BackendMessage]:
|
89
|
+
for message in self.messages or []:
|
90
|
+
yield message
|
fin68/utils/__init__.py
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
from datetime import datetime
|
2
|
+
from typing import Optional
|
3
|
+
def _validate_date_eod(val: Optional[str], name: str):
|
4
|
+
if val is None:
|
5
|
+
return
|
6
|
+
try:
|
7
|
+
datetime.strptime(val, "%Y-%m-%d")
|
8
|
+
except ValueError:
|
9
|
+
raise ValueError(f"Tham số '{name}' phải có định dạng YYYY-MM-DD, ví dụ '2023-01-01'.")
|
fin68/utils/convert.py
ADDED
File without changes
|
File without changes
|
fin68/utils/time.py
ADDED
File without changes
|
fin68/validators.py
ADDED
File without changes
|
@@ -0,0 +1,129 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: fin68
|
3
|
+
Version: 0.1.3
|
4
|
+
Summary: High-performance Python client for the Fin68 financial data platform.
|
5
|
+
Author: Fin68 Team
|
6
|
+
Project-URL: Homepage, https://fin68.vn
|
7
|
+
Project-URL: Documentation, https://fin68.vn/docs/fin68py/
|
8
|
+
Keywords: fin68,finance,market-data,api-client,vietnam
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
10
|
+
Classifier: Intended Audience :: Developers
|
11
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
12
|
+
Classifier: Operating System :: Microsoft :: Windows
|
13
|
+
Classifier: Operating System :: POSIX :: Linux
|
14
|
+
Classifier: Operating System :: MacOS
|
15
|
+
Classifier: Programming Language :: Python
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
20
|
+
Classifier: Topic :: Office/Business :: Financial
|
21
|
+
Classifier: Topic :: Software Development :: Libraries
|
22
|
+
Requires-Python: >=3.10
|
23
|
+
Description-Content-Type: text/markdown
|
24
|
+
Requires-Dist: pandas>=2.1.2
|
25
|
+
Requires-Dist: requests>=2.31.0
|
26
|
+
Requires-Dist: pydantic>=2.4.0
|
27
|
+
Provides-Extra: dev
|
28
|
+
Requires-Dist: pytest>=7.4; extra == "dev"
|
29
|
+
Requires-Dist: cibuildwheel>=2.17.0; extra == "dev"
|
30
|
+
Requires-Dist: twine>=5.0.0; extra == "dev"
|
31
|
+
Requires-Dist: python-dotenv>=1.0.0; extra == "dev"
|
32
|
+
|
33
|
+
# 🐍 Fin68 Python SDK
|
34
|
+
|
35
|
+
> **Fin68** mang tới bộ **client Python hiệu năng cao** để truy cập **hệ sinh thái dữ liệu tài chính Việt Nam**.
|
36
|
+
> Thư viện được thiết kế **an toàn**, **linh hoạt** và **tối ưu cho ba nền tảng:**
|
37
|
+
> 🪟 Windows | 🐧 Linux | 🍎 macOS
|
38
|
+
|
39
|
+
---
|
40
|
+
|
41
|
+
## 🚀 Cài đặt
|
42
|
+
|
43
|
+
Cài đặt trực tiếp từ [PyPI](https://pypi.org/project/fin68/):
|
44
|
+
|
45
|
+
```bash
|
46
|
+
pip install fin68
|
47
|
+
```
|
48
|
+
|
49
|
+
Yêu cầu:
|
50
|
+
|
51
|
+
- Python ≥ 3.9
|
52
|
+
- pandas ≥ 2.1.2
|
53
|
+
- requests
|
54
|
+
|
55
|
+
📘 [Tài liệu hướng dẫn](https://fin68.vn/docs/fin68py/)
|
56
|
+
|
57
|
+
---
|
58
|
+
|
59
|
+
## ⚙️ Khởi tạo nhanh
|
60
|
+
|
61
|
+
Ví dụ cơ bản để lấy dữ liệu giá đóng cửa của cổ phiếu **HPG** | chỉ số **VNINDEX** | ngành **Ngân hàng** trong năm 2023:
|
62
|
+
|
63
|
+
```python
|
64
|
+
import fin68 as fn
|
65
|
+
|
66
|
+
client = fn.client(apiKey="YOUR_API_KEY")
|
67
|
+
# Dữ liệu cổ phiếu
|
68
|
+
Stock = client.eod.stock
|
69
|
+
data = Stock.ohlcv(symbol="HPG", start="2023-01-01", end="2023-12-31")
|
70
|
+
|
71
|
+
# Dữ liệu chỉ số index
|
72
|
+
Market = client.eod.market
|
73
|
+
data = Market.ohlcv(symbol="VNINDEX", start="2023-01-01", end="2023-12-31")
|
74
|
+
|
75
|
+
# Dữ liệu ngành
|
76
|
+
Sector = client.eod.sector
|
77
|
+
data = Sector.ohlcv(symbol="Ngân hàng", start="2023-01-01", end="2023-12-31")
|
78
|
+
print(data)
|
79
|
+
```
|
80
|
+
|
81
|
+
📘 **Kết quả trả về** là `pandas.DataFrame` gồm các cột: `Date`, `Open`, `High`, `Low`, `Close`, `Volume`.
|
82
|
+
|
83
|
+
---
|
84
|
+
|
85
|
+
## 🧩 Cấu trúc thư viện
|
86
|
+
|
87
|
+
Fin68 được chia thành nhiều **client module** riêng biệt, mỗi module phụ trách một mảng dữ liệu:
|
88
|
+
|
89
|
+
| Module | Mô tả | Ví dụ truy cập |
|
90
|
+
|:--------|:------|:---------------|
|
91
|
+
| `client.eod` | Dữ liệu cuối ngày (EOD) | `client.eod.stock.ohlcv(symbol="HPG")` |
|
92
|
+
| `client.info` | Thông tin doanh nghiệp & cổ phiếu | `client.info.overview("VNM")` |
|
93
|
+
| `client.financials` | Báo cáo tài chính | `client.financials.statement("HPG")` |
|
94
|
+
|
95
|
+
|
96
|
+
Tất cả đều trả về **DataFrame** hoặc **dict** để dễ dàng xử lý trong phân tích định lượng.
|
97
|
+
|
98
|
+
---
|
99
|
+
|
100
|
+
## 🔐 Bảo mật & hiệu năng
|
101
|
+
|
102
|
+
- Tự động xác thực bằng `apiKey`
|
103
|
+
- Kết nối HTTP được tối ưu hóa với `requests.Session`
|
104
|
+
- Tuân thủ chuẩn [PEP 561](https://peps.python.org/pep-0561/) – hỗ trợ gợi ý kiểu (type hints)
|
105
|
+
|
106
|
+
---
|
107
|
+
|
108
|
+
## 📚 Bắt đầu khám phá
|
109
|
+
|
110
|
+
👉 Tiếp tục đọc tại:
|
111
|
+
|
112
|
+
- [**Tổng quan API**](api/index.md)
|
113
|
+
- [**Clients: EOD, Info, Financials, Index**](api/clients/base.md)
|
114
|
+
- [**Các kiểu dữ liệu & validator**](api/types.md)
|
115
|
+
|
116
|
+
Hoặc tra cứu chi tiết từng hàm trong **sidebar bên trái**.
|
117
|
+
|
118
|
+
---
|
119
|
+
|
120
|
+
## 🧠 Giấy phép & Liên hệ
|
121
|
+
|
122
|
+
- **License:** MIT
|
123
|
+
- **Tác giả:** Fin68 Development Team
|
124
|
+
- **Website:** [https://fin68.vn](https://fin68.vn)
|
125
|
+
- **Liên hệ hỗ trợ:** [support@fin68.vn](mailto:support@fin68.vn)
|
126
|
+
|
127
|
+
---
|
128
|
+
|
129
|
+
> 💡 _Fin68 – Nền tảng dữ liệu mở, giúp nhà đầu tư, doanh nghiệp và lập trình viên tiếp cận dữ liệu tài chính Việt Nam một cách nhanh chóng và hiệu quả._
|
@@ -0,0 +1,55 @@
|
|
1
|
+
fin68/__init__.py,sha256=Qwwk5NXEl-3ZbnvF3Y9fPvgKc2Ffad-Ec7Wll_epxpU,10984
|
2
|
+
fin68/__init__.pyi,sha256=VyxwLnRp9jG1ftRTtaTsoVHfDuBOkUSk9D3YYc8ZVrM,2889
|
3
|
+
fin68/_core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
|
+
fin68/_version.py,sha256=Miy39GKfoqA50BJmvNJF0oM0HrS-YtQ0RSqCnWYDgas,449
|
5
|
+
fin68/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
|
+
fin68/auth/api_key.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
|
+
fin68/clients/__init__.py,sha256=emNdDfexkRGsmN8BzLb6IMHPL5XL69Ix2DKQkpmCY-Y,60
|
8
|
+
fin68/clients/base.py,sha256=c4nBokHD5Z6AcbwDlJqEcWqJgpR5XO0Kk0janer05_E,437
|
9
|
+
fin68/clients/eod/MarketEod.py,sha256=SksmOFrCdJ5jS5dpqjSygMDsvoPW_OsuxvgSKHDN6u8,5425
|
10
|
+
fin68/clients/eod/MarketEod.pyi,sha256=DQwKsjy3JJCBVgrS0qhK_425V80xj3dvvYK_N9Eqr8o,3020
|
11
|
+
fin68/clients/eod/SectorEod.py,sha256=3ycOp43erCENdxL6LhtfvvSx4sH90vg-539bwNIuBcY,5636
|
12
|
+
fin68/clients/eod/SectorEod.pyi,sha256=2LgBpRcesb4gHVr8jEtZcH6f19OAk_c0IIrynVguvBM,2670
|
13
|
+
fin68/clients/eod/StockEod.py,sha256=dlA91Vi9Pz0ZMwZ3wiTTOnsUO5bk4ow0d1W5aB9iVos,5230
|
14
|
+
fin68/clients/eod/StockEod.pyi,sha256=AnjtdGTt_g4RDLNpEDRj3WO2pFZb4DHup79HgbmkEUk,2862
|
15
|
+
fin68/clients/eod/__init__.py,sha256=C_8YSlNzgT6KyQFpMSqiXi7X-HNIYQUHywqeRoXuOLY,214
|
16
|
+
fin68/clients/eod/helper.py,sha256=e9aHP6mBlFAqbsxdvPDN4QfBJBsDvu3WD7aivFWss50,2374
|
17
|
+
fin68/clients/eod/icb_types.py,sha256=HD1EOshUIX8FZ4AGLfqvLGiGo5Xkngjkzmpc6ZUO-Ew,9714
|
18
|
+
fin68/clients/eod_main.py,sha256=bRB3H7kHXsnkvM8w2A7zYa8g9r-lbwwiK19-SVZVsmM,6650
|
19
|
+
fin68/clients/eod_main.pyi,sha256=Py3q_9sSv0OwWQVE0kQG3cRK_CttqXUG_bMfxBQaQiY,3610
|
20
|
+
fin68/clients/financials.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
21
|
+
fin68/clients/index.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
22
|
+
fin68/clients/info.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
23
|
+
fin68/config.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
24
|
+
fin68/exceptions.py,sha256=IEp-RszfxerBa_9VmcUFy7tZdrlkDbWC8ttb7am0BgE,823
|
25
|
+
fin68/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
26
|
+
fin68/models/base.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
27
|
+
fin68/models/eod.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
28
|
+
fin68/models/financials.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
29
|
+
fin68/models/index.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
30
|
+
fin68/models/meta.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
31
|
+
fin68/transport/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
32
|
+
fin68/transport/cache.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
33
|
+
fin68/transport/http.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
34
|
+
fin68/transport/rate_limiter.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
35
|
+
fin68/types.py,sha256=4n6KAj2xbfkIuBgRxCziMQTjOG-S3X7WqK4kNEOI5rc,3399
|
36
|
+
fin68/utils/__init__.py,sha256=AD5czCwEaVsmhEAzuoH42gzQtoAPreFLKgIdaj-LSYw,99
|
37
|
+
fin68/utils/_validate_date_eod.py,sha256=SYpm6Cby0kASQVC6T_gp7BFqsKoE4IGThTJzgbu7Gjo,341
|
38
|
+
fin68/utils/convert.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
39
|
+
fin68/utils/pagination.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
40
|
+
fin68/utils/time.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
41
|
+
fin68/validators.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
42
|
+
fin68-0.1.3.dist-info/METADATA,sha256=WQJU026G3WbwTEJgH1MExAReD1Kx-4QqhhESlNxhXpE,4327
|
43
|
+
fin68-0.1.3.dist-info/RECORD,,
|
44
|
+
fin68-0.1.3.dist-info/WHEEL,sha256=8UP9x9puWI0P1V_d7K2oMTBqfeLNm21CTzZ_Ptr0NXU,101
|
45
|
+
fin68-0.1.3.dist-info/licenses/LICENSE,sha256=M9_oL5hb_TZvkWVrs6-il0pN0qL5EtrZltPdMjDTh6U,1088
|
46
|
+
fin68-0.1.3.dist-info/top_level.txt,sha256=n5B1oMic_osRJc9rEt3WlyWIascYf7Vs9uJax3aDXs8,19
|
47
|
+
private_core/__init__.py,sha256=YvYth5DYCmm67_fLv5fOrqz7_KXaYtiL0lUclLwI3vg,14
|
48
|
+
private_core/auth_core.cp312-win_amd64.pyd,sha256=S5Z3KdjdsWyMtFPd9Dq9DbScVI-6W5DPqTJKzS8KK2M,53248
|
49
|
+
private_core/eod_core.cp312-win_amd64.pyd,sha256=ICUsPWKNu3cxAStyq8-WmbqWM-FjIgtfG5sQedUoKmc,66048
|
50
|
+
private_core/financials_core.cp312-win_amd64.pyd,sha256=ZLapWdcV0l7_R1PxzAa8BW_naebv9auX901sHzLiawg,16896
|
51
|
+
private_core/helpers.cp312-win_amd64.pyd,sha256=f4x8dkAqNFIFadTFbP6nsFjUYeRUmnI5oPsYoM5Uerg,22016
|
52
|
+
private_core/http_core.cp312-win_amd64.pyd,sha256=NpUeLAFOMK6Vp2dFXYhdHurvAwREd9AzB7NMqo9_RGg,73728
|
53
|
+
private_core/index_core.cp312-win_amd64.pyd,sha256=z9gGlO5QBt-bLIHdjahBaDcFEN4XeSUiLblO5kknGQQ,16896
|
54
|
+
private_core/progress.cp312-win_amd64.pyd,sha256=9ZQp9hVX4h9wQ_g1s3ne0lGUkdngDIjLFpxBjra3QbM,97280
|
55
|
+
private_core/utils_core.cp312-win_amd64.pyd,sha256=zz6rr9IG9KnjKx7m7OYan_Aq3QVoU3UzJwZC_LGUBqo,16896
|
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2025 Fin68 Team
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|