settfex 0.2.1__tar.gz → 0.3.0__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.
- {settfex-0.2.1 → settfex-0.3.0}/.github/workflows/release.yml +2 -8
- {settfex-0.2.1 → settfex-0.3.0}/CHANGELOG.md +12 -0
- {settfex-0.2.1 → settfex-0.3.0}/CONTRIBUTING.md +6 -0
- {settfex-0.2.1 → settfex-0.3.0}/PKG-INFO +1 -1
- settfex-0.3.0/RELEASING.md +73 -0
- settfex-0.3.0/examples/tfex/03_underlying_price.ipynb +564 -0
- {settfex-0.2.1 → settfex-0.3.0}/pyproject.toml +1 -1
- {settfex-0.2.1 → settfex-0.3.0}/settfex/__init__.py +1 -1
- {settfex-0.2.1 → settfex-0.3.0}/settfex/services/tfex/__init__.py +11 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/services/tfex/constants.py +1 -0
- settfex-0.3.0/settfex/services/tfex/underlying_price.py +253 -0
- settfex-0.3.0/tests/services/tfex/test_underlying_price.py +143 -0
- {settfex-0.2.1 → settfex-0.3.0}/uv.lock +1 -1
- {settfex-0.2.1 → settfex-0.3.0}/.editorconfig +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/.github/copilot-instructions.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/.github/dependabot.yml +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/.github/instructions/core-architectrual-principles.instructions.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/.github/instructions/documentation-standards.instructions.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/.github/instructions/file-organization.instructions.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/.github/instructions/git-commit.instructions.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/.github/instructions/python-dependency-management.instructions.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/.github/prompts/Coding.prompt.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/.github/prompts/Git-Commit-Reviewer.prompt.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/.github/prompts/Prompt-Engineer.prompt.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/.github/prompts/Python-Architect.prompt.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/.github/workflows/ci.yml +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/.github/workflows/security.yml +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/.gitignore +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/.pre-commit-config.yaml +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/.python-version +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/CODE_OF_CONDUCT.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/COMPREHENSIVE_AUDIT.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/LICENSE +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/MANIFEST.in +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/README.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/SECURITY.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/docs/guide/PYTHON_LIBRARY_BEST_PRACTICES.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/docs/index.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/docs/settfex/services/set/API_PROTECTION_NOTE.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/docs/settfex/services/set/board_of_director.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/docs/settfex/services/set/corporate_action.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/docs/settfex/services/set/financial.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/docs/settfex/services/set/highlight_data.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/docs/settfex/services/set/list.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/docs/settfex/services/set/nvdr_holder.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/docs/settfex/services/set/price_performance.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/docs/settfex/services/set/profile_company.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/docs/settfex/services/set/profile_stock.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/docs/settfex/services/set/shareholder.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/docs/settfex/services/set/trading_stat.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/docs/settfex/services/tfex/list.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/docs/settfex/services/tfex/trading_statistics.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/docs/settfex/utils/data_fetcher.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/docs/settfex/utils/session_caching.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/docs/solution/FINDINGS.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/docs/solution/Performance Boost Session Caching Implementation.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/docs/solution/SESSION_CACHE_SUMMARY.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/docs/solution/SOLUTION_100_PERCENT.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/examples/README.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/examples/set/01_stock_list.ipynb +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/examples/set/02_highlight_data.ipynb +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/examples/set/03_stock_profile.ipynb +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/examples/set/04_company_profile.ipynb +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/examples/set/05_corporate_action.ipynb +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/examples/set/06_shareholder.ipynb +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/examples/set/07_nvdr_holder.ipynb +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/examples/set/08_board_of_director.ipynb +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/examples/set/09_trading_statistics.ipynb +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/examples/set/10_price_performance.ipynb +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/examples/set/11_financial.ipynb +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/examples/set/README.md +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/examples/set/cpall_balance_sheet.csv +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/examples/set/market_dashboard_20251005_173221.csv +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/examples/set/market_dashboard_20251005_210737.csv +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/examples/set/market_dashboard_20251006_091440.csv +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/examples/set/thailand_banking_stocks.csv +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/examples/set/thailand_set_main_board.csv +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/examples/set/thailand_stock_universe.csv +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/examples/tfex/01_series_list.ipynb +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/examples/tfex/02_trading_statistics.ipynb +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/py.typed +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/services/__init__.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/services/set/__init__.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/services/set/constants.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/services/set/list.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/services/set/stock/__init__.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/services/set/stock/board_of_director.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/services/set/stock/chart_quotation.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/services/set/stock/corporate_action.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/services/set/stock/financial/__init__.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/services/set/stock/financial/financial.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/services/set/stock/highlight_data.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/services/set/stock/latest_historical_trading.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/services/set/stock/nvdr_holder.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/services/set/stock/price_performance.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/services/set/stock/profile_company.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/services/set/stock/profile_stock.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/services/set/stock/shareholder.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/services/set/stock/stock.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/services/set/stock/trading_stat.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/services/set/stock/utils.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/services/tfex/list.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/services/tfex/trading_statistics.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/utils/__init__.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/utils/data_fetcher.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/utils/http.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/utils/logging.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/utils/parsing.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/utils/session_cache.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/settfex/utils/session_manager.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/tests/__init__.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/tests/conftest.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/tests/services/__init__.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/tests/services/set/__init__.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/tests/services/set/stock/financial/__init__.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/tests/services/set/stock/financial/test_financial.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/tests/services/set/test_board_of_director.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/tests/services/set/test_client.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/tests/services/set/test_corporate_action.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/tests/services/set/test_historical.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/tests/services/set/test_realtime.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/tests/services/set/test_shareholder.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/tests/services/tfex/__init__.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/tests/services/tfex/test_client.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/tests/services/tfex/test_historical.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/tests/services/tfex/test_list.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/tests/services/tfex/test_realtime.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/tests/services/tfex/test_trading_statistics.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/tests/utils/__init__.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/tests/utils/test_data_fetcher.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/tests/utils/test_formatting.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/tests/utils/test_http.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/tests/utils/test_logging.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/tests/utils/test_parsing.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/tests/utils/test_session_manager.py +0 -0
- {settfex-0.2.1 → settfex-0.3.0}/tests/utils/test_validation.py +0 -0
|
@@ -141,7 +141,6 @@ jobs:
|
|
|
141
141
|
path: dist/
|
|
142
142
|
|
|
143
143
|
- name: Extract changelog section
|
|
144
|
-
id: changelog
|
|
145
144
|
run: |
|
|
146
145
|
VERSION="${{ needs.validate.outputs.version }}"
|
|
147
146
|
python3 - "$VERSION" <<'PYEOF'
|
|
@@ -152,19 +151,14 @@ jobs:
|
|
|
152
151
|
match = re.search(pattern, content, re.DOTALL)
|
|
153
152
|
notes = match.group(1).strip() if match else f"Release v{version}"
|
|
154
153
|
with open("release_notes.txt", "w") as f:
|
|
155
|
-
f.write(notes)
|
|
154
|
+
f.write(notes + "\n")
|
|
156
155
|
PYEOF
|
|
157
|
-
{
|
|
158
|
-
echo 'notes<<CHANGELOG_EOF'
|
|
159
|
-
cat release_notes.txt
|
|
160
|
-
echo 'CHANGELOG_EOF'
|
|
161
|
-
} >> "$GITHUB_OUTPUT"
|
|
162
156
|
|
|
163
157
|
- name: Create GitHub Release
|
|
164
158
|
uses: softprops/action-gh-release@v2
|
|
165
159
|
with:
|
|
166
160
|
name: "settfex v${{ needs.validate.outputs.version }}"
|
|
167
|
-
|
|
161
|
+
body_path: release_notes.txt
|
|
168
162
|
prerelease: ${{ needs.validate.outputs.is_prerelease }}
|
|
169
163
|
files: dist/*
|
|
170
164
|
make_latest: ${{ needs.validate.outputs.is_prerelease == 'false' }}
|
|
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.3.0] - 2026-06-17
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **TFEX underlying-price service** (`get_underlying_price`, `TFEXUnderlyingPriceService`,
|
|
13
|
+
`UnderlyingPrice`): fetches the underlying instrument price for a TFEX series via
|
|
14
|
+
`GET /api/set/tfex/series/{symbol}/underlying-price`. For SET50 index options/futures the underlying
|
|
15
|
+
is the **SET50 index spot** — exposes last/prior/high/low, change, total volume/value, and P/E + P/BV.
|
|
16
|
+
Mirrors the existing TFEX service pattern (SessionManager/Incapsula bypass, NaN-rejecting hardened
|
|
17
|
+
parsing, `get_*` convenience function + `*_raw` variant); 100% module test coverage. Adds the
|
|
18
|
+
`verify_underlying_price.py` script and the `examples/tfex/03_underlying_price.ipynb` notebook.
|
|
19
|
+
|
|
8
20
|
## [0.2.1] - 2026-06-17
|
|
9
21
|
|
|
10
22
|
Robustness and concurrency hardening release. No public API changes — function
|
|
@@ -61,6 +61,12 @@ Detailed engineering guidelines live in [`.github/instructions/`](.github/instru
|
|
|
61
61
|
4. Ensure the quality gate passes.
|
|
62
62
|
5. Open a PR using the template and link any related issue.
|
|
63
63
|
|
|
64
|
+
## Releasing
|
|
65
|
+
|
|
66
|
+
Releases go through a single path: bump the version, update `CHANGELOG.md`, merge to `main`,
|
|
67
|
+
then push a `vX.Y.Z` git tag. The tag triggers CI to publish to PyPI (via OIDC) and create the
|
|
68
|
+
GitHub Release. See [`RELEASING.md`](RELEASING.md) for the exact steps and the one-time setup.
|
|
69
|
+
|
|
64
70
|
## Reporting security issues
|
|
65
71
|
|
|
66
72
|
Please do **not** open public issues for vulnerabilities — see
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: settfex
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Async Python library for fetching real-time and historical data from the Stock Exchange of Thailand (SET) and Thailand Futures Exchange (TFEX)
|
|
5
5
|
Project-URL: Homepage, https://github.com/lumduan/settfex
|
|
6
6
|
Project-URL: Documentation, https://github.com/lumduan/settfex#readme
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Releasing settfex
|
|
2
|
+
|
|
3
|
+
settfex publishes to PyPI through **one canonical path: pushing a `vX.Y.Z` git tag.**
|
|
4
|
+
|
|
5
|
+
The tag triggers [`.github/workflows/release.yml`](.github/workflows/release.yml), which:
|
|
6
|
+
|
|
7
|
+
1. validates the tag matches `pyproject.toml`,
|
|
8
|
+
2. runs the full CI gate (ruff, format, mypy, pytest),
|
|
9
|
+
3. builds the sdist + wheel,
|
|
10
|
+
4. publishes to PyPI via an **OIDC Trusted Publisher** (no API token), and
|
|
11
|
+
5. creates the GitHub Release with the changelog body + built artifacts.
|
|
12
|
+
|
|
13
|
+
There is intentionally **no second PyPI upload path in the repo** — the workflow is the only
|
|
14
|
+
thing that runs `twine`. Its publish step uses `skip-existing: true`, so re-tagging (or a one-off
|
|
15
|
+
manual rescue) never hard-fails on an already-published file.
|
|
16
|
+
|
|
17
|
+
## Cut a release
|
|
18
|
+
|
|
19
|
+
1. Bump the version in **both** `pyproject.toml` and `settfex/__init__.py` (keep them in sync).
|
|
20
|
+
2. Add a `## [X.Y.Z] - YYYY-MM-DD` section to `CHANGELOG.md`.
|
|
21
|
+
3. Commit, open a PR, and merge to `main`.
|
|
22
|
+
4. From an up-to-date `main`, tag and push:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
git checkout main && git pull --ff-only
|
|
26
|
+
git tag -a vX.Y.Z -m "settfex X.Y.Z"
|
|
27
|
+
git push origin vX.Y.Z
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
CI does the rest — watch:
|
|
31
|
+
<https://github.com/lumduan/settfex/actions/workflows/release.yml>
|
|
32
|
+
|
|
33
|
+
> **Maintainer convenience.** A local, gitignored `scripts/publish.sh` performs the same tag
|
|
34
|
+
> push behind pre-flight checks (version sync between `pyproject.toml` and `settfex/__init__.py`,
|
|
35
|
+
> a clean/synced `main`, the CHANGELOG section, and tag uniqueness). It never runs `twine`; it
|
|
36
|
+
> only tags. It is not shipped in the repo because the tag push above is the real interface.
|
|
37
|
+
|
|
38
|
+
## One-time setup: PyPI Trusted Publisher (required for the OIDC publish)
|
|
39
|
+
|
|
40
|
+
This must be done once on pypi.org or the publish step will fail. On
|
|
41
|
+
<https://pypi.org/manage/project/settfex/settings/publishing/>, add a **GitHub Actions**
|
|
42
|
+
publisher:
|
|
43
|
+
|
|
44
|
+
| Field | Value |
|
|
45
|
+
|---|---|
|
|
46
|
+
| Owner | `lumduan` |
|
|
47
|
+
| Repository | `settfex` |
|
|
48
|
+
| Workflow name | `release.yml` |
|
|
49
|
+
| Environment | `pypi` |
|
|
50
|
+
|
|
51
|
+
Then create the `pypi` environment under **GitHub → Settings → Environments** (it can be empty;
|
|
52
|
+
the workflow references `environment: pypi`).
|
|
53
|
+
|
|
54
|
+
## Break-glass: manual publish (fallback only)
|
|
55
|
+
|
|
56
|
+
Use **only** if the tag/CI path is unavailable (e.g. an Actions outage). Requires a
|
|
57
|
+
project-scoped token in a gitignored `.env` (`PYPI_TOKEN=pypi-…`):
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
rm -rf dist
|
|
61
|
+
uv run python -m build
|
|
62
|
+
uv run twine check dist/*
|
|
63
|
+
uv run twine upload dist/* --username __token__ --password "$PYPI_TOKEN"
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Prefer the tag-driven path. Because CI uses `skip-existing: true`, a later tag for the same
|
|
67
|
+
version still succeeds and just backfills the GitHub Release.
|
|
68
|
+
|
|
69
|
+
## Recommended follow-up
|
|
70
|
+
|
|
71
|
+
Single-source the version (e.g. Hatchling `[tool.hatch.version] path = "settfex/__init__.py"`
|
|
72
|
+
with `dynamic = ["version"]`) so `pyproject.toml` and the package can never drift again. The
|
|
73
|
+
release workflow's validate step reads `project.version`, so adjust it if you switch.
|