BANY
A collection of scripts to...
- Convert text in a PDF into YNAB transactions
- Split a series of transactions between people
- Solve the constrained partitioning problem for investing
Setup
export LANG=en_US.UTF-8
uv run bany --help
Commands
bany extract
Create YNAB transactions from a PDF
Examples
- Run the extract command to parse a PDF and upload transactions to YNAB
export LANG=en_US.UTF-8
uv run bany extract pdf --inp /path/to/pdf --config config.yaml
uv run bany extract pdf --inp /path/to/pdf --config config.yaml --upload
config.yaml
- Some examples can be found in the
./cfgdirectory - Define rules to match patterns in the text of a PDF
- Define the transactions to create from these matches
# Regular Expressions defined for date like values
dates:
Force Date:
value: |-
2023-01-01
Check Date:
regex: |-
Check\s+Date\s+(?P<DATE>{MONTHS}\s+\d+,?\s+\d\d\d\d)
# Regular Expressions defined for money like values
amounts:
401K:
group: EARNINGS
inflow: true
regex: |-
401K\s+
(?P<HOURS>{NUMBER})\s+
(?P<MONEY>{AMOUNT})\s+
(?P<TOTAL>{AMOUNT})
Salary:
group: EARNINGS
inflow: true
regex: |-
REGULAR\s+
(?P<RATES>{NUMBER})\s+
(?P<HOURS>{NUMBER})\s+
(?P<MONEY>{AMOUNT})\s+
(?P<TOTAL>{AMOUNT})
TOTAL-EARNINGS:
group: EARNINGS
inflow: true
total: true
regex: |-
Gross\s+Earnings\s+
(?P<HOURS>{NUMBER})\s+
(?P<MONEY>{AMOUNT})\s+
(?P<TOTAL>{AMOUNT})
# Transactions to push to a YNAB budget (these may reference the matches defined above)
transactions:
- budget: 2023
account: 'Checking'
category: 'Internal Master Category: Inflow: Ready to Assign'
payee: Company
color: red
amount: Salary
date: Check Date
- budget: 2023
account: 'Company'
category: 'Investment: Fidelity'
payee: 'Transfer : Fidelity : Syapse'
memo: 2023
color: yellow
amount: 401K
date: Check Date
bany split
This is a script to help split transactions between multiple people.
Examples
This script opens an interactive loop.
export LANG=en_US.UTF-8
uv run bany split
Run a series of commands
You can run a series of commands defined in a text file (see example in ./cfg directory.
split -a 12.79 -p Costco -C Food -d Dad=1 Adam=0 Doug=0 -c Adam=1
split -a 7.49 -p Costco -C Food -d Dad=1 Adam=0 Doug=0 -c Adam=1
summarize
bany > @ costco.txt
Show the possible commands
bany > help
Documented commands (use 'help -v' for verbose/'help <topic>' for details):
My Category
===========
clear delete show split summarize tax tip
Uncategorized
=============
help history quit set shortcuts
Split some transactions between some people
bany > split --amount 10.00 --payee GroceryStore --category Food --debit Alice=2/5 Bob=3/5 --credit Bob=1
group amount rate payee category debtors creditors Alice Bob Alice.w Bob.w Alice.$ Bob.$ Who Delta
0 0 $10.00 0 GroceryStore Food (Alice, Bob) (Bob) 400 600 0.4 0.6 $4.00 $6.00 - $0.00
bany > split --amount 15.75 --payee Restaurant --category Dinner --debit Alice=1/2 Bob=1/2 --credit Alice=1
group amount rate payee category debtors creditors Alice Bob Alice.w Bob.w Alice.$ Bob.$ Who Delta
0 0 $10.00 0 GroceryStore Food (Alice, Bob) (Bob) 400 600 0.4 0.6 $4.00 $6.00 - $0.00
1 1 $15.75 0 Restaurant Dinner (Alice, Bob) (Alice) 787 787 0.5 0.5 $7.87 $7.88 Alice -$0.01
Add taxes and tips for the previous transaction
bany > tip --amount 5.00 --category Tips
group amount rate payee category debtors creditors Alice Bob Alice.w Bob.w Alice.$ Bob.$ Who Delta
0 0 $10.00 0.00000 GroceryStore Food (Alice, Bob) (Bob) 400 600 0.4 0.6 $4.00 $6.00 - $0.00
1 1 $15.75 0.00000 Restaurant Dinner (Alice, Bob) (Alice) 787 787 0.5 0.5 $7.87 $7.88 Alice -$0.01
2 1 $5.00 0.31746 Restaurant Tips (Alice, Bob) (Alice) 250 250 0.5 0.5 $2.50 $2.50 - $0.00
bany > tax --rate 0.07 --payee SalesTax
group amount rate payee category debtors creditors Alice Bob Alice.w Bob.w Alice.$ Bob.$ Who Delta
0 0 $10.00 0.00000 GroceryStore Food (Alice, Bob) (Bob) 400 600 0.4 0.6 $4.00 $6.00 - $0.00
1 1 $15.75 0.00000 Restaurant Dinner (Alice, Bob) (Alice) 787 787 0.5 0.5 $7.87 $7.88 Alice -$0.01
2 1 $5.00 0.31746 Restaurant Tips (Alice, Bob) (Alice) 250 250 0.5 0.5 $2.50 $2.50 - $0.00
3 1 $1.10 0.07000 SalesTax Dinner (Alice, Bob) (Alice) 55 55 0.5 0.5 $0.55 $0.55 - $0.00
Display the current transactions
bany > show
group amount rate payee category debtors creditors Alice Bob Alice.w Bob.w Alice.$ Bob.$ Who Delta
0 0 $10.00 0.00000 GroceryStore Food (Alice, Bob) (Bob) 400 600 0.4 0.6 $4.00 $6.00 - $0.00
1 1 $15.75 0.00000 Restaurant Dinner (Alice, Bob) (Alice) 787 787 0.5 0.5 $7.87 $7.88 Alice -$0.01
2 1 $5.00 0.31746 Restaurant Tips (Alice, Bob) (Alice) 250 250 0.5 0.5 $2.50 $2.50 - $0.00
3 1 $1.10 0.07000 SalesTax Dinner (Alice, Bob) (Alice) 55 55 0.5 0.5 $0.55 $0.55 - $0.00
Aggregate by categories and people
bany > summarize
amount category payee Alice.$ Bob.$
0 $10.00 Food GroceryStore $4.00 $6.00
1 $15.75 Dinner Restaurant $7.87 $7.88
2 $5.00 Tips Restaurant $2.50 $2.50
3 $1.10 Dinner SalesTax $0.55 $0.55
bany solve
This is a script to solve a math problem.
- I have a few investment funds and want them each to have a certain percent of my savings.
- I need to know which funds to put the money in to reach my desired allocation.
We have a histogram and want to morph it into a new shape
- Given a set of labeled buckets with known item counts...
- Given a new amount of items to place into the buckets...
- Given a desired distribution of items for the buckets...
How should we place the new items into the buckets?
Examples
# The problem will be solved in an unconstrained way by default
# Values can be added or removed from existing bins
uv run bany solve unconstrained --config allocate.yaml
# The problem can be solved in a constrained way as well
# Values can only be added to bins
uv run bany solve constrained --config allocate.yaml
# A Monte Carlo based solver also exists, which is non-deterministic
# Values can be added in fixed sizes
uv run bany solve montecarlo --config allocate.yaml --stepsize 25
Input Distribution
TOTAL level=[0] current_value=[ 6,000.00] optimal_ratio=[1.000] amount_to_add=[ 8,000.00]
├─VIGAX level=[1] current_value=[ 1,000.00] optimal_ratio=[0.220] amount_to_add=[ 0.00]
├─VVIAX level=[1] current_value=[ 1,000.00] optimal_ratio=[0.280] amount_to_add=[ 0.00]
├─VMGMX level=[1] current_value=[ 1,000.00] optimal_ratio=[0.100] amount_to_add=[ 0.00]
├─VMVAX level=[1] current_value=[ 1,000.00] optimal_ratio=[0.150] amount_to_add=[ 0.00]
├─VSGAX level=[1] current_value=[ 1,000.00] optimal_ratio=[0.100] amount_to_add=[ 0.00]
└─VSIAX level=[1] current_value=[ 1,000.00] optimal_ratio=[0.150] amount_to_add=[ 0.00]
Output Distribution
TOTAL level=[0] results_value=[14,000.00] results_ratio=[1.000] amount_to_add=[ 0.00]
├─VIGAX level=[1] results_value=[ 3,080.00] results_ratio=[0.220] amount_to_add=[ 2,080.00]
├─VVIAX level=[1] results_value=[ 3,920.00] results_ratio=[0.280] amount_to_add=[ 2,920.00]
├─VMGMX level=[1] results_value=[ 1,400.00] results_ratio=[0.100] amount_to_add=[ 400.00]
├─VMVAX level=[1] results_value=[ 2,100.00] results_ratio=[0.150] amount_to_add=[ 1,100.00]
├─VSGAX level=[1] results_value=[ 1,400.00] results_ratio=[0.100] amount_to_add=[ 400.00]
└─VSIAX level=[1] results_value=[ 2,100.00] results_ratio=[0.150] amount_to_add=[ 1,100.00]
config.yaml
The input is a hierarchy of bins with current values and desired ratios.
yaml
The input can be given as a YAML file.
- { label: 'TOTAL', optimal_ratio: 100, current_value: 6000, amount_to_add: 8000, children: [
'VIGAX', 'VVIAX', 'VMGMX', 'VMVAX', 'VSGAX', 'VSIAX'] }
- { label: 'VIGAX', optimal_ratio: 22, current_value: 1000, amount_to_add: 0, children: [] }
- { label: 'VVIAX', optimal_ratio: 28, current_value: 1000, amount_to_add: 0, children: [] }
- { label: 'VMGMX', optimal_ratio: 10, current_value: 1000, amount_to_add: 0, children: [] }
- { label: 'VMVAX', optimal_ratio: 15, current_value: 1000, amount_to_add: 0, children: [] }
- { label: 'VSGAX', optimal_ratio: 10, current_value: 1000, amount_to_add: 0, children: [] }
- { label: 'VSIAX', optimal_ratio: 15, current_value: 1000, amount_to_add: 0, children: [] }
You can use regular expressions when specifying the children of a category.
- { label: 'TOTAL', optimal_ratio: 100, current_value: 6000, amount_to_add: 8000, children: ['regex::.*'] }
...
csv
The input can be given as a CSV file.
label optimal_ratio current_value amount_to_add children
0 TOTAL 100.0 6000.0 8000.0 VIGAX;VVIAX;VMGMX;VMVAX;VSGAX;VSIAX
1 VIGAX 22.0 1000.0 0.0
2 VVIAX 28.0 1000.0 0.0
3 VMGMX 10.0 1000.0 0.0
4 VMVAX 15.0 1000.0 0.0
5 VSGAX 10.0 1000.0 0.0
6 VSIAX 15.0 1000.0 0.0
Metadata
Release files for bany 2.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| bany-2.0.1.tar.gz | 75.8 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| bany-2.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 118.6 kB
Release files / bany-2.0.1.tar.gz
| Download URL | bany-2.0.1.tar.gz |
|---|---|
| Size | 75.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ecb870e33b4ef0df8fd7beafdfe45b867e4060c8f70adf77f40e85d1639b531f
|
|
BLAKE2b-256 checksum How to use checksums |
22f66837c5626cf5920e0046e9c8b5e82afe723dede8abc08769174ffdd0e9a5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.3
|
Release files / bany-2.0.1-py3-none-any.whl
| Download URL | bany-2.0.1-py3-none-any.whl |
|---|---|
| Size | 42.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
66cbd97a5a107170751e10d5722d5a3b5931a2a6bdf71e64a3794730f2fe0084
|
|
BLAKE2b-256 checksum How to use checksums |
20d5b64c4948f30cd61a4e4759f155dd4351928b92b0873ef5e3a5eab5f5691f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.3
|
Security for bany 2.0.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.