open-finance-toolkit 0.1.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.
Files changed (33) hide show
  1. open_finance_toolkit-0.1.0/.gitignore +220 -0
  2. open_finance_toolkit-0.1.0/CHANGELOG.md +28 -0
  3. open_finance_toolkit-0.1.0/LICENSE +21 -0
  4. open_finance_toolkit-0.1.0/PKG-INFO +169 -0
  5. open_finance_toolkit-0.1.0/README.md +113 -0
  6. open_finance_toolkit-0.1.0/docs/adding-a-bank-format.md +78 -0
  7. open_finance_toolkit-0.1.0/docs/publishing-to-pypi.md +64 -0
  8. open_finance_toolkit-0.1.0/docs/roadmap.md +36 -0
  9. open_finance_toolkit-0.1.0/docs/usage.md +165 -0
  10. open_finance_toolkit-0.1.0/examples/dashboard/README.md +15 -0
  11. open_finance_toolkit-0.1.0/examples/dashboard/app.py +757 -0
  12. open_finance_toolkit-0.1.0/examples/dashboard/requirements.txt +3 -0
  13. open_finance_toolkit-0.1.0/examples/quickstart.py +44 -0
  14. open_finance_toolkit-0.1.0/examples/sample_debit_credit.csv +17 -0
  15. open_finance_toolkit-0.1.0/examples/sample_transactions.csv +11 -0
  16. open_finance_toolkit-0.1.0/pyproject.toml +62 -0
  17. open_finance_toolkit-0.1.0/src/open_finance_toolkit/__init__.py +51 -0
  18. open_finance_toolkit-0.1.0/src/open_finance_toolkit/__main__.py +7 -0
  19. open_finance_toolkit-0.1.0/src/open_finance_toolkit/categorize.py +218 -0
  20. open_finance_toolkit-0.1.0/src/open_finance_toolkit/cli.py +79 -0
  21. open_finance_toolkit-0.1.0/src/open_finance_toolkit/duplicates.py +97 -0
  22. open_finance_toolkit-0.1.0/src/open_finance_toolkit/exceptions.py +42 -0
  23. open_finance_toolkit-0.1.0/src/open_finance_toolkit/formats.py +219 -0
  24. open_finance_toolkit-0.1.0/src/open_finance_toolkit/importer.py +187 -0
  25. open_finance_toolkit-0.1.0/src/open_finance_toolkit/parsing.py +41 -0
  26. open_finance_toolkit-0.1.0/src/open_finance_toolkit/py.typed +0 -0
  27. open_finance_toolkit-0.1.0/src/open_finance_toolkit/schema.py +13 -0
  28. open_finance_toolkit-0.1.0/src/open_finance_toolkit/summary.py +102 -0
  29. open_finance_toolkit-0.1.0/tests/test_categorize.py +93 -0
  30. open_finance_toolkit-0.1.0/tests/test_cli.py +50 -0
  31. open_finance_toolkit-0.1.0/tests/test_duplicates.py +66 -0
  32. open_finance_toolkit-0.1.0/tests/test_importer.py +229 -0
  33. open_finance_toolkit-0.1.0/tests/test_summary.py +104 -0
@@ -0,0 +1,220 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[codz]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py.cover
50
+ *.lcov
51
+ .hypothesis/
52
+ .pytest_cache/
53
+ cover/
54
+
55
+ # Translations
56
+ *.mo
57
+ *.pot
58
+
59
+ # Django stuff:
60
+ *.log
61
+ local_settings.py
62
+ db.sqlite3
63
+ db.sqlite3-journal
64
+
65
+ # Flask stuff:
66
+ instance/
67
+ .webassets-cache
68
+
69
+ # Scrapy stuff:
70
+ .scrapy
71
+
72
+ # Sphinx documentation
73
+ docs/_build/
74
+
75
+ # PyBuilder
76
+ .pybuilder/
77
+ target/
78
+
79
+ # Jupyter Notebook
80
+ .ipynb_checkpoints
81
+
82
+ # IPython
83
+ profile_default/
84
+ ipython_config.py
85
+
86
+ # pyenv
87
+ # For a library or package, you might want to ignore these files since the code is
88
+ # intended to run in multiple environments; otherwise, check them in:
89
+ # .python-version
90
+
91
+ # pipenv
92
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
93
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
94
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
95
+ # install all needed dependencies.
96
+ # Pipfile.lock
97
+
98
+ # uv
99
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
100
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
101
+ # commonly ignored for libraries.
102
+ # uv.lock
103
+
104
+ # poetry
105
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
106
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
107
+ # commonly ignored for libraries.
108
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
109
+ # poetry.lock
110
+ # poetry.toml
111
+
112
+ # pdm
113
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
114
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
115
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
116
+ # pdm.lock
117
+ # pdm.toml
118
+ .pdm-python
119
+ .pdm-build/
120
+
121
+ # pixi
122
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
123
+ # pixi.lock
124
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
125
+ # in the .venv directory. It is recommended not to include this directory in version control.
126
+ .pixi/*
127
+ !.pixi/config.toml
128
+
129
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
130
+ __pypackages__/
131
+
132
+ # Celery stuff
133
+ celerybeat-schedule*
134
+ celerybeat.pid
135
+
136
+ # Redis
137
+ *.rdb
138
+ *.aof
139
+ *.pid
140
+
141
+ # RabbitMQ
142
+ mnesia/
143
+ rabbitmq/
144
+ rabbitmq-data/
145
+
146
+ # ActiveMQ
147
+ activemq-data/
148
+
149
+ # SageMath parsed files
150
+ *.sage.py
151
+
152
+ # Environments
153
+ .env
154
+ .envrc
155
+ .venv
156
+ env/
157
+ venv/
158
+ ENV/
159
+ env.bak/
160
+ venv.bak/
161
+
162
+ # Spyder project settings
163
+ .spyderproject
164
+ .spyproject
165
+
166
+ # Rope project settings
167
+ .ropeproject
168
+
169
+ # mkdocs/Zensical documentation
170
+ /site
171
+
172
+ # mypy
173
+ .mypy_cache/
174
+ .dmypy.json
175
+ dmypy.json
176
+
177
+ # Pyre type checker
178
+ .pyre/
179
+
180
+ # pytype static type analyzer
181
+ .pytype/
182
+
183
+ # Cython debug symbols
184
+ cython_debug/
185
+
186
+ # PyCharm
187
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
188
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
189
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
190
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
191
+ # .idea/
192
+
193
+ # Abstra
194
+ # Abstra is an AI-powered process automation framework.
195
+ # Ignore directories containing user credentials, local state, and settings.
196
+ # Learn more at https://abstra.io/docs
197
+ .abstra/
198
+
199
+ # Visual Studio Code
200
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore that
201
+ # can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
202
+ # and can be added to the global gitignore or merged into this file. However, if you prefer, you
203
+ # could uncomment the following to ignore the entire vscode folder
204
+ # .vscode/
205
+ # Temporary file for partial code execution
206
+ tempCodeRunnerFile.py
207
+
208
+ # Ruff stuff:
209
+ .ruff_cache/
210
+
211
+ # PyPI configuration file
212
+ .pypirc
213
+
214
+ # Marimo
215
+ marimo/_static/
216
+ marimo/_lsp/
217
+ __marimo__/
218
+
219
+ # Streamlit
220
+ .streamlit/secrets.toml
@@ -0,0 +1,28 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are recorded here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
5
+ uses [Semantic Versioning](https://semver.org/).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.1.0] - 2026-11-12
10
+
11
+ First release as a reusable library. It grew out of the Personal Finance
12
+ Analytics dashboard.
13
+
14
+ ### Added
15
+ - `load_transactions` and `clean_transactions` to read and standardise CSVs, with automatic layout detection and skipping of lines above the table.
16
+ - Layouts: `standard`, `generic-debit-credit`, `generic-signed`, and unverified `hdfc`, `sbi`, `icici`, `axis`.
17
+ - `categorize`, a keyword-based categoriser with built-in rules and support for your own.
18
+ - `mark_duplicates`, `find_duplicates`, `remove_duplicates`.
19
+ - `totals`, `summarize` (by month or year) and `spending_by_category`.
20
+ - A command-line tool: `open-finance-toolkit summary` and `open-finance-toolkit categories`.
21
+ - Tests, continuous integration, contribution guidelines and issue templates.
22
+
23
+ ### Changed
24
+ - The Streamlit dashboard moved to `examples/dashboard/` and is otherwise unchanged.
25
+
26
+ ### Fixed
27
+ - ISO dates such as `2026-11-01` are no longer read day-first (which turned them into 11 January). This fix is in the library. The demo dashboard still has the old behaviour.
28
+ - A blank category now becomes `Uncategorised` instead of the text `nan`.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Itz-https
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.
@@ -0,0 +1,169 @@
1
+ Metadata-Version: 2.5
2
+ Name: open-finance-toolkit
3
+ Version: 0.1.0
4
+ Summary: Clean, categorise and summarise bank transaction CSVs, with support for Indian bank statement formats.
5
+ Project-URL: Homepage, https://github.com/Itz-https/open-finance-toolkit
6
+ Project-URL: Documentation, https://github.com/Itz-https/open-finance-toolkit/tree/main/docs
7
+ Project-URL: Issues, https://github.com/Itz-https/open-finance-toolkit/issues
8
+ Project-URL: Changelog, https://github.com/Itz-https/open-finance-toolkit/blob/main/CHANGELOG.md
9
+ Author: Itz-https
10
+ License: MIT License
11
+
12
+ Copyright (c) 2026 Itz-https
13
+
14
+ Permission is hereby granted, free of charge, to any person obtaining a copy
15
+ of this software and associated documentation files (the "Software"), to deal
16
+ in the Software without restriction, including without limitation the rights
17
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18
+ copies of the Software, and to permit persons to whom the Software is
19
+ furnished to do so, subject to the following conditions:
20
+
21
+ The above copyright notice and this permission notice shall be included in all
22
+ copies or substantial portions of the Software.
23
+
24
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30
+ SOFTWARE.
31
+ License-File: LICENSE
32
+ Keywords: bank statement,csv,finance,india,pandas,personal finance,transactions
33
+ Classifier: Development Status :: 3 - Alpha
34
+ Classifier: Intended Audience :: Developers
35
+ Classifier: License :: OSI Approved :: MIT License
36
+ Classifier: Programming Language :: Python :: 3
37
+ Classifier: Programming Language :: Python :: 3.9
38
+ Classifier: Programming Language :: Python :: 3.10
39
+ Classifier: Programming Language :: Python :: 3.11
40
+ Classifier: Programming Language :: Python :: 3.12
41
+ Classifier: Programming Language :: Python :: 3.13
42
+ Classifier: Topic :: Office/Business :: Financial
43
+ Classifier: Typing :: Typed
44
+ Requires-Python: >=3.9
45
+ Requires-Dist: pandas>=2.0
46
+ Provides-Extra: dashboard
47
+ Requires-Dist: plotly; extra == 'dashboard'
48
+ Requires-Dist: streamlit; extra == 'dashboard'
49
+ Provides-Extra: dev
50
+ Requires-Dist: build; extra == 'dev'
51
+ Requires-Dist: pytest-cov; extra == 'dev'
52
+ Requires-Dist: pytest>=7; extra == 'dev'
53
+ Requires-Dist: ruff; extra == 'dev'
54
+ Requires-Dist: twine; extra == 'dev'
55
+ Description-Content-Type: text/markdown
56
+
57
+ # Open Finance Toolkit
58
+
59
+ Clean, categorise and summarise bank transaction CSVs in Python, with a focus on Indian bank statement formats.
60
+
61
+ [![CI](https://github.com/Itz-https/open-finance-toolkit/actions/workflows/ci.yml/badge.svg)](https://github.com/Itz-https/open-finance-toolkit/actions/workflows/ci.yml)
62
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
63
+
64
+ > **Status: alpha (v0.1).** The core works and is tested, but the bank layouts for HDFC, SBI, ICICI and Axis are built from commonly seen column headers and have **not yet been checked against real statements**. If you have a statement from any bank, you can help. See [Contributing](#contributing).
65
+
66
+ ## Why this exists
67
+
68
+ Every bank exports transactions slightly differently. Some put account details above the table. Some use separate Debit and Credit columns, others one signed Amount column. Dates may be `03/04/2026` or `2026-04-03`, and amounts look like `1,25,000.50`. Every developer who builds a budgeting tool ends up rewriting the same cleaning code.
69
+
70
+ Open Finance Toolkit does that part once, so you can focus on your app.
71
+
72
+ - Reads messy statement CSVs and returns one clean, standard table
73
+ - Detects the layout automatically and skips lines above the table
74
+ - Categorises transactions with simple rules you can read and extend
75
+ - Flags duplicate transactions without deleting anything behind your back
76
+ - Calculates income, expenses, savings and savings rate
77
+ - Summarises by month or year
78
+ - Runs entirely on your computer. No network calls, no accounts, no tracking.
79
+
80
+ ## Install
81
+
82
+ ```bash
83
+ pip install open-finance-toolkit
84
+ ```
85
+
86
+ Requires Python 3.9 or newer. The only dependency is `pandas`.
87
+
88
+ > The package is not on PyPI yet. Until the first release, install from GitHub:
89
+ > `pip install git+https://github.com/Itz-https/open-finance-toolkit.git`
90
+
91
+ ## Quick start
92
+
93
+ ```python
94
+ from open_finance_toolkit import load_transactions, categorize, summarize, totals
95
+
96
+ transactions = load_transactions("statement.csv") # any supported layout
97
+ transactions = categorize(transactions) # fill in categories
98
+
99
+ print(totals(transactions))
100
+ print(summarize(transactions, by="month"))
101
+ ```
102
+
103
+ Example output from the included fictional statement:
104
+
105
+ ```text
106
+ Income: 85,312.00
107
+ Expenses: 32,567.50
108
+ Savings: 52,744.50
109
+ Savings rate: 61.8%
110
+
111
+ Period Income Expenses Savings SavingsRate
112
+ 2026-10 85312.0 32567.5 52744.5 61.825417
113
+ ```
114
+
115
+ Run the full tour with `python examples/quickstart.py`.
116
+
117
+ ### Command line
118
+
119
+ ```bash
120
+ open-finance-toolkit summary statement.csv --by month
121
+ open-finance-toolkit categories statement.csv
122
+ ```
123
+
124
+ ## What you get back
125
+
126
+ `load_transactions` returns a pandas DataFrame with the same columns no matter which bank the file came from:
127
+
128
+ | Column | Meaning |
129
+ |---|---|
130
+ | `Date` | Transaction date (datetime) |
131
+ | `Type` | `Income` or `Expense` |
132
+ | `Category` | Category, or `Uncategorised` until you call `categorize` |
133
+ | `Amount` | Always positive |
134
+ | `Description` | The bank's narration text |
135
+
136
+ ## Supported layouts
137
+
138
+ | Layout | Status |
139
+ |---|---|
140
+ | `standard`: Date, Type, Category, Amount | Verified (the original dashboard format) |
141
+ | `generic-debit-credit`: any file with separate Debit and Credit columns | Works on test data, not yet on real statements |
142
+ | `generic-signed`: any file with one signed Amount column | Works on test data, not yet on real statements |
143
+ | `hdfc`, `sbi`, `icici`, `axis` | **Unverified.** Based on commonly seen headers |
144
+
145
+ Anything the named layouts miss usually still loads through the generic ones. Details and how to add a bank are in [docs/adding-a-bank-format.md](docs/adding-a-bank-format.md).
146
+
147
+ ## Documentation
148
+
149
+ - [Usage guide](docs/usage.md): every function with examples
150
+ - [Adding a bank format](docs/adding-a-bank-format.md)
151
+ - [Roadmap](docs/roadmap.md)
152
+ - [Publishing to PyPI](docs/publishing-to-pypi.md) (for maintainers)
153
+ - [Changelog](CHANGELOG.md)
154
+
155
+ ## The demo dashboard
156
+
157
+ The original Streamlit dashboard lives in [`examples/dashboard`](examples/dashboard) as a demo of what you can build on top of the library.
158
+
159
+ ## Contributing
160
+
161
+ Contributions of every size are welcome, including fixing a typo. The most valuable thing you can do is **verify or add a bank format**: open a [bank format request](https://github.com/Itz-https/open-finance-toolkit/issues/new?template=bank_format_request.yml) with the column headers of your statement (never the real transactions). Read [CONTRIBUTING.md](CONTRIBUTING.md) to get started.
162
+
163
+ ## Privacy
164
+
165
+ Never post real statements, account numbers or personal details in issues or pull requests. The test data in this repository is entirely fictional.
166
+
167
+ ## License
168
+
169
+ [MIT](LICENSE)
@@ -0,0 +1,113 @@
1
+ # Open Finance Toolkit
2
+
3
+ Clean, categorise and summarise bank transaction CSVs in Python, with a focus on Indian bank statement formats.
4
+
5
+ [![CI](https://github.com/Itz-https/open-finance-toolkit/actions/workflows/ci.yml/badge.svg)](https://github.com/Itz-https/open-finance-toolkit/actions/workflows/ci.yml)
6
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
7
+
8
+ > **Status: alpha (v0.1).** The core works and is tested, but the bank layouts for HDFC, SBI, ICICI and Axis are built from commonly seen column headers and have **not yet been checked against real statements**. If you have a statement from any bank, you can help. See [Contributing](#contributing).
9
+
10
+ ## Why this exists
11
+
12
+ Every bank exports transactions slightly differently. Some put account details above the table. Some use separate Debit and Credit columns, others one signed Amount column. Dates may be `03/04/2026` or `2026-04-03`, and amounts look like `1,25,000.50`. Every developer who builds a budgeting tool ends up rewriting the same cleaning code.
13
+
14
+ Open Finance Toolkit does that part once, so you can focus on your app.
15
+
16
+ - Reads messy statement CSVs and returns one clean, standard table
17
+ - Detects the layout automatically and skips lines above the table
18
+ - Categorises transactions with simple rules you can read and extend
19
+ - Flags duplicate transactions without deleting anything behind your back
20
+ - Calculates income, expenses, savings and savings rate
21
+ - Summarises by month or year
22
+ - Runs entirely on your computer. No network calls, no accounts, no tracking.
23
+
24
+ ## Install
25
+
26
+ ```bash
27
+ pip install open-finance-toolkit
28
+ ```
29
+
30
+ Requires Python 3.9 or newer. The only dependency is `pandas`.
31
+
32
+ > The package is not on PyPI yet. Until the first release, install from GitHub:
33
+ > `pip install git+https://github.com/Itz-https/open-finance-toolkit.git`
34
+
35
+ ## Quick start
36
+
37
+ ```python
38
+ from open_finance_toolkit import load_transactions, categorize, summarize, totals
39
+
40
+ transactions = load_transactions("statement.csv") # any supported layout
41
+ transactions = categorize(transactions) # fill in categories
42
+
43
+ print(totals(transactions))
44
+ print(summarize(transactions, by="month"))
45
+ ```
46
+
47
+ Example output from the included fictional statement:
48
+
49
+ ```text
50
+ Income: 85,312.00
51
+ Expenses: 32,567.50
52
+ Savings: 52,744.50
53
+ Savings rate: 61.8%
54
+
55
+ Period Income Expenses Savings SavingsRate
56
+ 2026-10 85312.0 32567.5 52744.5 61.825417
57
+ ```
58
+
59
+ Run the full tour with `python examples/quickstart.py`.
60
+
61
+ ### Command line
62
+
63
+ ```bash
64
+ open-finance-toolkit summary statement.csv --by month
65
+ open-finance-toolkit categories statement.csv
66
+ ```
67
+
68
+ ## What you get back
69
+
70
+ `load_transactions` returns a pandas DataFrame with the same columns no matter which bank the file came from:
71
+
72
+ | Column | Meaning |
73
+ |---|---|
74
+ | `Date` | Transaction date (datetime) |
75
+ | `Type` | `Income` or `Expense` |
76
+ | `Category` | Category, or `Uncategorised` until you call `categorize` |
77
+ | `Amount` | Always positive |
78
+ | `Description` | The bank's narration text |
79
+
80
+ ## Supported layouts
81
+
82
+ | Layout | Status |
83
+ |---|---|
84
+ | `standard`: Date, Type, Category, Amount | Verified (the original dashboard format) |
85
+ | `generic-debit-credit`: any file with separate Debit and Credit columns | Works on test data, not yet on real statements |
86
+ | `generic-signed`: any file with one signed Amount column | Works on test data, not yet on real statements |
87
+ | `hdfc`, `sbi`, `icici`, `axis` | **Unverified.** Based on commonly seen headers |
88
+
89
+ Anything the named layouts miss usually still loads through the generic ones. Details and how to add a bank are in [docs/adding-a-bank-format.md](docs/adding-a-bank-format.md).
90
+
91
+ ## Documentation
92
+
93
+ - [Usage guide](docs/usage.md): every function with examples
94
+ - [Adding a bank format](docs/adding-a-bank-format.md)
95
+ - [Roadmap](docs/roadmap.md)
96
+ - [Publishing to PyPI](docs/publishing-to-pypi.md) (for maintainers)
97
+ - [Changelog](CHANGELOG.md)
98
+
99
+ ## The demo dashboard
100
+
101
+ The original Streamlit dashboard lives in [`examples/dashboard`](examples/dashboard) as a demo of what you can build on top of the library.
102
+
103
+ ## Contributing
104
+
105
+ Contributions of every size are welcome, including fixing a typo. The most valuable thing you can do is **verify or add a bank format**: open a [bank format request](https://github.com/Itz-https/open-finance-toolkit/issues/new?template=bank_format_request.yml) with the column headers of your statement (never the real transactions). Read [CONTRIBUTING.md](CONTRIBUTING.md) to get started.
106
+
107
+ ## Privacy
108
+
109
+ Never post real statements, account numbers or personal details in issues or pull requests. The test data in this repository is entirely fictional.
110
+
111
+ ## License
112
+
113
+ [MIT](LICENSE)
@@ -0,0 +1,78 @@
1
+ # Adding or verifying a bank format
2
+
3
+ A *layout* tells the library which column headers mean what. Adding a bank is usually one small entry in `src/open_finance_toolkit/formats.py`.
4
+
5
+ ## Step 1: collect only what is safe to share
6
+
7
+ From your statement you need:
8
+
9
+ 1. The **header row** (the line with column names).
10
+ 2. Any lines **above** the header (bank name, account details). Replace personal details with fake ones.
11
+ 3. How **dates** look, with a made-up example such as `05/11/26`.
12
+ 4. How **amounts** are shown: separate Debit and Credit columns, one signed column, or an extra Dr/Cr column.
13
+
14
+ Never share real transactions, names, account numbers or balances.
15
+
16
+ ## Step 2: see what already happens
17
+
18
+ Create a tiny fake file with your header row and two invented rows, then run:
19
+
20
+ ```python
21
+ from open_finance_toolkit import load_transactions
22
+ df = load_transactions("fake.csv")
23
+ print(df.attrs["layout"])
24
+ print(df)
25
+ ```
26
+
27
+ If the dates, types and amounts look right, the existing generic layout already works. Tell us in an issue. That is a valuable contribution because it lets us mark the layout verified.
28
+
29
+ ## Step 3: add a layout
30
+
31
+ Open `formats.py` and add an entry to `LAYOUTS`, **above** the two `generic-` entries:
32
+
33
+ ```python
34
+ Layout(
35
+ name="kotak",
36
+ label="Kotak Mahindra Bank (unverified)",
37
+ kind="debit_credit",
38
+ date=("transactiondate",),
39
+ description=("narration",),
40
+ debit=("debitamount",),
41
+ credit=("creditamount",),
42
+ ),
43
+ ```
44
+
45
+ Header names are written **normalised**: lower-case, with everything except letters and digits removed. `Withdrawal Amount (INR )` becomes `withdrawalamountinr`.
46
+
47
+ `kind` is one of:
48
+
49
+ | kind | Amounts look like |
50
+ |---|---|
51
+ | `debit_credit` | Separate Debit and Credit columns |
52
+ | `signed` | One Amount column, negative means money out |
53
+ | `typed` | A Type column says Income or Expense |
54
+
55
+ Leave `verified` off until someone has checked the layout against a real statement. Set `verified=True` only in a pull request that says who checked it, and with what kind of statement (savings, credit card, and so on).
56
+
57
+ ## Step 4: add a test
58
+
59
+ In `tests/test_importer.py`, add your header to the `test_other_bank_style_headers` parameter list:
60
+
61
+ ```python
62
+ ("Transaction Date,Narration,Debit Amount,Credit Amount", "kotak"),
63
+ ```
64
+
65
+ Run `pytest`.
66
+
67
+ ## Step 5: open a pull request
68
+
69
+ Mention the bank, the type of statement, and whether you tested a real file. Do not attach the file.
70
+
71
+ ## Things we cannot handle yet
72
+
73
+ Help is welcome with these:
74
+
75
+ - Statements where one column holds both the amount and `Dr`/`Cr` (for example `1,250.00 Dr`)
76
+ - Credit card statements that use a different sign convention
77
+ - PDF statements (the library reads CSV only)
78
+ - Statements with several account sections in one file
@@ -0,0 +1,64 @@
1
+ # Publishing to PyPI (maintainers)
2
+
3
+ PyPI is where `pip install open-finance-toolkit` downloads packages from. This project publishes **automatically from GitHub** using *trusted publishing*, so there are no passwords or tokens to store, and you can do the whole thing from a web browser.
4
+
5
+ > **Important:** a version number on PyPI can never be reused or replaced, even if you delete the release. Always test before releasing.
6
+
7
+ ## One-time setup
8
+
9
+ ### 1. Create a PyPI account
10
+ 1. Register at <https://pypi.org/account/register/> with an email address you control.
11
+ 2. Turn on **two-factor authentication** in your account settings. PyPI requires it to publish.
12
+
13
+ ### 2. Tell PyPI to trust this repository
14
+ Because the project does not exist on PyPI yet, you register a *pending publisher*:
15
+
16
+ 1. On PyPI, open your account menu, then **Your projects**, then **Publishing**.
17
+ 2. Under **Add a new pending publisher**, choose **GitHub** and fill in:
18
+ - PyPI project name: `open-finance-toolkit`
19
+ - Owner: `Itz-https`
20
+ - Repository name: `open-finance-toolkit`
21
+ - Workflow name: `publish.yml`
22
+ - Environment name: `pypi`
23
+ 3. Save.
24
+
25
+ ### 3. Create the matching environment on GitHub
26
+ 1. In the repository, open **Settings**, then **Environments**, then **New environment**.
27
+ 2. Name it exactly `pypi`.
28
+ 3. Optional but recommended: tick **Required reviewers** and add yourself, so a release waits for your approval.
29
+
30
+ ## Releasing a version
31
+
32
+ ### 1. Prepare
33
+ 1. Make sure the **CI** badge on the README is green on `main`.
34
+ 2. Edit `src/open_finance_toolkit/__init__.py` and set `__version__` (for example `"0.1.0"`).
35
+ 3. In `CHANGELOG.md`, move the items from **Unreleased** into a new version heading with today's date.
36
+ 4. Commit these changes to `main` (through a pull request if you prefer).
37
+
38
+ ### 2. Publish a GitHub release
39
+ 1. Go to **Releases**, then **Draft a new release**.
40
+ 2. Click **Choose a tag** and type `v0.1.0` (the version with a `v` in front). Choose **Create new tag**.
41
+ 3. Set the title to `v0.1.0` and paste the changelog notes.
42
+ 4. Click **Publish release**.
43
+
44
+ ### 3. Watch it
45
+ Open the **Actions** tab. The *Publish to PyPI* workflow builds the package and uploads it. It stops with an error if the tag and `__version__` do not match, which protects you from mistakes.
46
+
47
+ ### 4. Check
48
+ 1. Open <https://pypi.org/project/open-finance-toolkit/>.
49
+ 2. In a clean Python environment, run `pip install open-finance-toolkit` and then `open-finance-toolkit --version`.
50
+ 3. Add a PyPI badge to the README:
51
+ ```markdown
52
+ [![PyPI](https://img.shields.io/pypi/v/open-finance-toolkit.svg)](https://pypi.org/project/open-finance-toolkit/)
53
+ ```
54
+ 4. Update the README install note, since it will no longer need the "not on PyPI yet" warning.
55
+
56
+ ## If something goes wrong
57
+
58
+ - **The workflow fails before uploading.** Nothing was published. Fix the problem, delete the release and tag, and publish again.
59
+ - **The name is taken or the publisher is rejected.** Re-check the five values in step 2 of one-time setup. They must match exactly, including the workflow file name.
60
+ - **A bad version went out.** On PyPI, open the release and use **Yank**. Users will stop getting it by default. Then publish a new version with a higher number, such as `0.1.1`.
61
+
62
+ ## Version numbers
63
+
64
+ We use [Semantic Versioning](https://semver.org/): `MAJOR.MINOR.PATCH`. While the project is at `0.x`, minor versions may change behaviour. Bug fixes increase the last number.