A modular Python library for multi-account portfolio trade allocation
Project description
realloc
A modular Python library for managing and rebalancing multi-account investment portfolios.
It handles account-aware trade allocation, portfolio-level targets, and execution constraints across multiple real-world accounts.
Features
- Allocate trades across multiple accounts
- Enforce constraints (e.g. no negative positions, long-only models)
- Fully tested with
pytest - Clean, modular, extensible API
- Includes plugin architecture allowing for custom exporters, validators, and rebalancers.
Installation
Clone the repo and install in editable mode:
git clone https://github.com/yourname/realloc.git
cd realloc
pip install -e .[dev]
Quick Start
from realloc import Account, PortfolioModel, PortfolioAllocator
Define accounts
accounts = [ Account("IRA", "A1", 1000, {"AAPL": 5}, {}), Account("Taxable", "A2", 2000, {"GOOG": 3}, {}) ]
Define target model
model = PortfolioModel("Balanced", {"AAPL": 0.5, "GOOG": 0.5})
Define prices
prices = {"AAPL": 100, "GOOG": 200}
Ok now what? You've got everything you need to do a basic trade, but how? This is where we try to allow the user to take control. Don't get us wrong! We've built ready-made objects to do the work and they do.
However, if you professionally rebalanced portfolios, you'll know there's an art to it and there's not always one answer. We're just saying we recognize that. But, that topic is for another day.
So back to basic rebalancing. Essentially, it's iterative (trial and error). We loop through accounts and positions checking cash, checking targets vs. actual until we arrive at a set of trades.
The next step is to calculate portfolio level trades. For that we've provided three functions:
calculate_portfolio_positions,calculate_target_shares, compute_portfolio_trades
Call these in this order to get a list of portfolio level trades. Yeah, we could have a wrapper, maybe we'll make one, maybe not.
PortfolioStateManager, while not required will help you manage the state of everything while calculating trades. You can roll your own but why?
Instantiate a new PortfolioStateManager.
Now you're ready to try to rebalance. For this quick start we have a basic but tested built-in rebalancer. It's in pluggable but you can import directly.
from realloc.plugins.rebalancers.default_rebalancer import DefaultRebalancer
rebalancer = DefaultRebalancer(...)
rebalancer.execute_rebalance
BOOM! Trades. They're not tax-aware, and no constraints like "Don't buy stock DVL" are in place. But that's actually more common than you'd think. So if you're not concerned about taxes or constraints, you'll probably be ok.
But how do I get the trades into a format, so I don't have to hand input. Ah, we have a plugin for exporting. Ours is basic, but you can build a broker-specific one.
from realloc.plugins.exporters import csv_exporters
But wait, there's more!
rebalance-cli
This is a ready-made script that demonstrates a full re-balance (not just a slice re-balance) of realloc.
Input Format
To use rebalance-cli, you must provide a JSON file with:
prices: { symbol → float }accounts: list of "account" dictionariesmodel:Portfoliomodel withnameandtargets
Example:
{
"prices": { "AAPL": 100, "GOOG": 100 },
"accounts": [
{ "label": "A", "account_number": "1", "cash": 1000, "positions": { "AAPL": 5 } }
],
"model": {
"label": "Balanced",
"targets": { "AAPL": 0.6, "GOOG": 0.4 }
}
}
Several Plugin Types are available
1. Rebalancer PluginsCustomize how trades are allocated across accounts:
from realloc import PortfolioModel, Account, PortfolioStateManager from realloc.plugins.core.base import RebalancerPlugin
Use the default rebalancer
rebalancer = RebalancerPlugin.load_rebalancer("default")
Execute rebalance using the plugin
trades = rebalancer.execute_rebalance( tam=PortfolioStateManager(...), target_shares={"F":100, "HPQ":50}
2. Export Plugins
Format trades for different brokers:
from realloc.plugins.core.base import Exporter
Export trades to CSV
exporter = Exporter.load_exporter("csv", path="trades.csv") exporter.export(trades)
3. Validator Plugins
Add custom trade validation rules:
from realloc.plugins.core.base import TradeValidator
# Validate minimum trade value
validator = TradeValidator.load_validator("minimum_value", min_value=100) is_valid, message = validator.validate(trade)
Using Plugins with CLI
The rebalance-cli supports plugins through command-line arguments:
bash
# List available plugins
list-plugins
# Use an exporter plugin
rebalance-cli input.json --exporter csv --export-path trades.csv
Available Plugins
- Rebalancers:
default: Standard rebalancing algorithm
- Exporters:
csv: Export trades to CSV format
- Validators:
max_position: Enforce maximum position sizesminimum_value: Enforce minimum trade values
## 📄 License
MIT License.
## 🙌 Contributing
Pull requests welcome!
Please open an issue or contact first if proposing large changes.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file realloc-0.1.4.tar.gz.
File metadata
- Download URL: realloc-0.1.4.tar.gz
- Upload date:
- Size: 26.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ff9614b174747b625b789298256b3dc02fb7ce6fc037ce5ae5830bad7abedc79
|
|
| MD5 |
05004d21fac98bef3472c07c86d6af00
|
|
| BLAKE2b-256 |
c8e4ca1bc3cd03b9afc98d6f8e2be91435c423320c7bf70897d0c8e6f6abbf82
|
File details
Details for the file realloc-0.1.4-py3-none-any.whl.
File metadata
- Download URL: realloc-0.1.4-py3-none-any.whl
- Upload date:
- Size: 27.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f3feeab53f2289198be841b0c241cd37f8a9e4e01cf1597eb3e943169f02bbeb
|
|
| MD5 |
d8fd33cc581fe321ab8d1122d150e78e
|
|
| BLAKE2b-256 |
86ee5540aee06a22312ef6c90a333509524006ef6e2e8a15ad1c0961341d5d29
|