AllocationO2
Tactical asset allocation library with Rust backend
Project Structure
The project consists of two main parts:
-
Rust Backend (
rust_backend/): Core functionality implemented in Rust- Fast and efficient portfolio optimization algorithms
- Asset allocation strategies
- Portfolio analytics
-
Python Package (
allocation_o2/): Python interface using PyO3- User-friendly API for Python users
- Data visualization and analysis
Features
- High-performance asset allocation strategies implemented in Rust
- Ability to compile custom Rust strategy files
- Pythonic interface for easy integration with data science workflows
Installation
Requirements
- Rust (latest stable)
- Python 3.10+
- C compiler (for building Rust extensions)
From Source
Clone the repository and install:
git clone https://github.com/VladKochetov007/allocation_o2
cd AllocationO2
make install
From PyPI
pip install allocation-o2
Development Mode
For development, install in editable mode:
make develop
Usage
Basic Example
import numpy as np
from numpy.typing import NDArray
from allocation_o2 import create_allocator_class
# Create your own allocation strategy
class MyAllocationStrategy:
@property
def min_observations(self) -> int:
return 1
def predict(self, x: NDArray[np.float64]) -> NDArray[np.float64]:
# Your allocation strategy logic here
n_assets = x.shape[0]
return np.ones(n_assets) / n_assets
# Create your own allocation strategy
MyAllocator = create_allocator_class(
MyAllocationStrategy,
param_info={
"min_observations": (int, 1),
}
)
# Create an allocator instance
allocator = MyAllocator()
# Generate price data
prices = np.random.random((5, 100)) # 5 assets, 100 time steps
# Get allocation weights
weights = allocator.predict(prices)
print(weights) # Array of weights, sum of which equals 1.0
Custom Rust Strategies
You can create custom allocation strategies directly in Rust for better performance.
Compiling a Custom Rust Strategy
Use the command line interface to compile your custom Rust strategy:
python -m allocation_o2 compile path/to/your_strategy.rs
This will compile your Rust file into a shared library (.so) and place it in the same directory. You can specify an alternative output location:
python -m allocation_o2 compile path/to/your_strategy.rs -o path/to/output.so
Creating a Custom Rust Strategy
To create a custom Rust strategy, use the template in the examples directory (examples/strategy_template.rs) as a starting point. Your strategy must implement the AllocationStrategy trait and be registered with PyO3.
Example rust strategy:
use ndarray::ArrayD;
use pyo3::prelude::*;
// Import from allocation_o2
use allocation_o2::allocation::traits::AllocationStrategy;
use allocation_o2::register_strategy;
use allocation_o2::allocation::py_bindings::{numpy_to_ndarray, ndarray_to_numpy};
#[pyclass]
pub struct MyCustomStrategy {
#[pyo3(get, set)]
pub min_observations: usize,
}
#[pymethods]
impl MyCustomStrategy {
#[new]
fn new() -> Self {
Self {
min_observations: 1,
}
}
fn predict(&self, py: Python, input: &PyAny) -> PyResult<PyObject> {
let input_array = numpy_to_ndarray(py, input)?;
let output_array = self.predict_impl(&input_array);
ndarray_to_numpy(py, output_array)
}
}
impl AllocationStrategy for MyCustomStrategy {
fn min_observations(&self) -> usize {
self.min_observations
}
fn predict(&self, input: &ArrayD<f64>) -> ArrayD<f64> {
self.predict_impl(input)
}
}
impl MyCustomStrategy {
fn predict_impl(&self, input: &ArrayD<f64>) -> ArrayD<f64> {
// Your allocation strategy logic here
// For demonstration, we'll use equal weights
let shape = input.shape();
let n_assets = shape[1];
let mut weights = ArrayD::zeros(vec![shape[0], shape[1]]);
let equal_weight = 1.0 / n_assets as f64;
for w in weights.iter_mut() {
*w = equal_weight;
}
weights
}
}
#[pymodule]
fn my_custom_strategy(_py: Python, m: &PyModule) -> PyResult<()> {
register_strategy!(m, MyCustomStrategy);
Ok(())
}
Examples
Examples are not included in the package installation and should be created by the user themselves. The repository contains examples for reference:
# Run random weight example (only from source code)
make build_examples
Creating a wheel package
To create a wheel package for distribution:
make wheel
License
This project is licensed under the MIT License - see the LICENSE file for details.
Metadata
Release files for allocation-o2 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| allocation_o2-1.1.0.tar.gz | 2.9 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| allocation_o2-1.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 5.9 MB
Release files / allocation_o2-1.1.0.tar.gz
| Download URL | allocation_o2-1.1.0.tar.gz |
|---|---|
| Size | 2.9 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
55b996ac49731ee48344098049e9076d83af6b7034586589080f03cb8025e574
|
|
BLAKE2b-256 checksum How to use checksums |
b92034c3804001f7858bece38a43ce6fde63539c04f942b94df2d7dd7916066a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.10
|
Release files / allocation_o2-1.1.0-py3-none-any.whl
| Download URL | allocation_o2-1.1.0-py3-none-any.whl |
|---|---|
| Size | 3.0 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d8fe9da4e5664eee5595ffd90b7b90b3fdab2248fdd98ef8804118c47e57bae3
|
|
BLAKE2b-256 checksum How to use checksums |
1dd77dddaff25b2c9ab410a2038f24cbc775d52b4c03287acfb2d1c621c14510
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.10
|