Skip to main content

MoneyWarp โ€“ Bend time. Model cash.

Project description

MoneyWarp ๐Ÿ’ฐโฐ

Bend time. Model cash.

Release Build status codecov License

โš ๏ธ Development Stage Notice

MoneyWarp is currently in active development and should be considered alpha/pre-release software. While the core functionality is implemented and tested, the API may change between versions. Use in production environments at your own risk.

  • โœ… Core classes (Money, InterestRate, CashFlow, Loan) are stable
  • โœ… Comprehensive test suite with 469 tests
  • โš ๏ธ API may evolve based on user feedback
  • โœ… Published to PyPI
  • ๐Ÿšง Additional features and schedulers in development

MoneyWarp is a Python library for working with the time value of money. It treats loans, annuities, and investments as simple cash flows through time โ€” and gives you the tools to warp them back and forth between present, future, and everything in between.

๐Ÿš€ Features

  • ๐Ÿ•ฐ๏ธ Time Machine (Warp) - Travel to any date and see loan state as of that moment
  • ๐Ÿ”ข Calculate PMT, NPV, IRR, MIRR and other core finance functions with scipy
  • โณ Track loans and repayments as evolving cash-flow streams
  • ๐ŸŒ€ Explore "what if" timelines by bending payments across time
  • ๐Ÿ’ฐ High-precision calculations using Decimal arithmetic
  • ๐Ÿ“Š Progressive Price Schedules (French amortization system)
  • ๐Ÿ“ˆ Inverted Price Schedules (Constant Amortization System - SAC)
  • ๐ŸŽฏ Flexible payment scheduling with irregular due dates
  • ๐Ÿ“… Easy date generation with smart month-end handling via python-dateutil
  • ๐Ÿ”’ Type-safe interest rates with explicit percentage handling
  • ๐Ÿงฎ Robust numerics powered by scipy for IRR and financial calculations
  • โš–๏ธ Fine engine with fines, mora interest, and configurable grace periods
  • ๐Ÿญ Sugar payment methods โ€” pay_installment() and anticipate_payment() for natural workflows

๐Ÿ“ฆ Installation

pip install money-warp

Or with Poetry:

poetry add money-warp

๐ŸŽฏ Quick Start

Basic Loan Analysis

from datetime import datetime
from money_warp import Money, InterestRate, Loan, generate_monthly_dates

# Create a $10,000 loan at 5% annual interest
principal = Money("10000.00")
rate = InterestRate("5% a")  # 5% annually

# Generate monthly payment dates easily
start_date = datetime(2024, 1, 15)
due_dates = generate_monthly_dates(start_date, 12)

# Generate the loan
loan = Loan(principal, rate, due_dates)

# Get the payment schedule
schedule = loan.get_amortization_schedule()
print(f"Monthly payment: {schedule[0].payment_amount}")
print(f"Total interest: {schedule.total_interest}")

# Track actual payments
loan.record_payment(Money("856.07"), datetime(2024, 2, 1))
print(f"Remaining balance: {loan.current_balance}")

Cash Flow Analysis

from money_warp import CashFlow, CashFlowItem, Money
from datetime import datetime

# Create cash flow items
items = [
    CashFlowItem(Money("1000.00"), datetime(2024, 1, 1), "Initial deposit", "deposit"),
    CashFlowItem(Money("-50.00"), datetime(2024, 2, 1), "Monthly fee", "fee"),
    CashFlowItem(Money("200.00"), datetime(2024, 3, 1), "Interest payment", "interest"),
]

# Analyze the cash flow
cash_flow = CashFlow(items)
print(f"Net cash flow: {cash_flow.net_present_value()}")
print(f"Total deposits: {cash_flow.query.filter_by(category='deposit').sum_amounts()}")

# Filter by date range
recent = cash_flow.query.filter_by(datetime__gte=datetime(2024, 2, 1))
print(f"Recent activity: {recent.sum_amounts()}")

High-Precision Money Handling

from money_warp import Money
from decimal import Decimal

# Create money with high internal precision
money = Money("100.123456789")
print(f"Internal precision: {money.raw_amount}")      # 100.123456789
print(f"Real money (2 decimals): {money.real_amount}") # 100.12
print(f"Display: {money}")                            # 100.12

# Arithmetic maintains precision internally
result = money * 3 / 7
print(f"Calculation result: {result}")  # Precise to 2 decimals for display

Time Machine - Warp to Any Date ๐Ÿ•ฐ๏ธ

Core Philosophy: The loan is always time sensitive... it always filters based on present date regardless if it is warped or not... the warp just changes the present date.

from money_warp import Warp, Loan, Money, InterestRate
from datetime import datetime

# Create a loan and make some payments
loan = Loan(Money("10000"), InterestRate("5% a"), [datetime(2024, 1, 15)])
loan.record_payment(Money("500"), datetime(2024, 1, 10), "Payment 1")
loan.record_payment(Money("600"), datetime(2024, 2, 10), "Payment 2") 
loan.record_payment(Money("700"), datetime(2024, 3, 10), "Payment 3")

print(f"Current balance: {loan.current_balance}")  # All payments applied

# Warp to the past - only see payments made by that date
with Warp(loan, datetime(2024, 1, 20)) as past_loan:
    print(f"Balance on Jan 20: {past_loan.current_balance}")  # Only first payment
    print(f"Payments made: {len(past_loan._actual_payments)}")  # 2 items (interest + principal)

# Warp to the future - see all payments up to that date  
with Warp(loan, datetime(2025, 1, 1)) as future_loan:
    print(f"Balance in future: {future_loan.current_balance}")  # All payments applied
    print(f"Days since last payment: {future_loan.days_since_last_payment()}")  # From warped date

# Original loan unchanged
print(f"Back to present: {loan.current_balance}")

Key Features:

  • ๐Ÿ•ฐ๏ธ Natural time filtering: Loans automatically show state as of any date
  • ๐Ÿ”„ Safe cloning: Original loan never modified during time travel
  • ๐Ÿ“… Flexible date formats: Accepts strings, datetime objects, or date objects
  • ๐Ÿšซ No nested warps: Prevents dangerous time paradoxes
  • โšก Instant calculations: Balance and payment history update automatically

Interest Rate Conversions

from money_warp import InterestRate

# Create rates with explicit formats
annual_rate = InterestRate("5.25% a")     # 5.25% annually  
monthly_rate = InterestRate("0.4167% m")  # 0.4167% monthly
daily_rate = InterestRate("3% d")         # 3% daily (extreme example)

# Convert between frequencies
print(f"Annual: {annual_rate}")
print(f"As monthly: {annual_rate.to_monthly()}")
print(f"As daily: {annual_rate.to_daily()}")

# Safe decimal/percentage handling
print(f"As decimal: {annual_rate.as_decimal}")      # 0.0525
print(f"As percentage: {annual_rate.as_percentage}") # 5.25

Easy Date Generation ๐Ÿ“…

Simplified with python-dateutil for robust date handling:

from datetime import datetime
from money_warp import (
    generate_monthly_dates,
    generate_biweekly_dates,
    generate_weekly_dates,
    generate_quarterly_dates,
    generate_annual_dates,
    generate_custom_interval_dates,
)

# Monthly payments (handles end-of-month intelligently)
monthly_dates = generate_monthly_dates(datetime(2024, 1, 31), 12)
print(f"Jan 31 โ†’ Feb 29 โ†’ Mar 29...")  # Smart month-end handling

# Bi-weekly payments (every 14 days)
biweekly_dates = generate_biweekly_dates(datetime(2024, 1, 1), 26)
print(f"26 payments over ~1 year")

# Weekly payments
weekly_dates = generate_weekly_dates(datetime(2024, 1, 1), 52)

# Quarterly payments
quarterly_dates = generate_quarterly_dates(datetime(2024, 1, 15), 4)

# Annual payments
annual_dates = generate_annual_dates(datetime(2024, 1, 1), 30)  # 30-year loan

# Custom intervals (every N days)
custom_dates = generate_custom_interval_dates(datetime(2024, 1, 1), 10, 45)  # Every 45 days

# Use with loans immediately
loan = Loan(
    principal=Money("50000"),
    interest_rate=InterestRate("3.5% annual"),
    due_dates=monthly_dates  # Just plug in the generated dates!
)

Key Features:

  • ๐Ÿ—“๏ธ Smart date handling: Uses python-dateutil for robust month arithmetic
  • ๐Ÿ“… End-of-month intelligence: Jan 31 โ†’ Feb 29 โ†’ Mar 29 (maintains consistency)
  • ๐ŸŽฏ Simple API: Just datetime and int parameters, no complex options
  • โšก Instant integration: Generated dates work directly with Loan objects
  • ๐Ÿ”’ Type-safe: Full type annotations and validation

### Present Value and IRR Analysis ๐Ÿงฎ

**Powered by scipy for robust numerical calculations:**

```python
from money_warp import CashFlow, CashFlowItem, Money, InterestRate
from money_warp import present_value, irr, modified_internal_rate_of_return
from datetime import datetime

# Create an investment cash flow
items = [
    CashFlowItem(Money("-10000"), datetime(2024, 1, 1), "Initial investment", "investment"),
    CashFlowItem(Money("3000"), datetime(2024, 12, 31), "Year 1 return", "return"),
    CashFlowItem(Money("4000"), datetime(2025, 12, 31), "Year 2 return", "return"),
    CashFlowItem(Money("5000"), datetime(2026, 12, 31), "Year 3 return", "return"),
]
cash_flow = CashFlow(items)

# Calculate Present Value at 8% discount rate
discount_rate = InterestRate("8% annual")
pv = present_value(cash_flow, discount_rate)
print(f"Present Value at 8%: {pv}")

# Calculate Internal Rate of Return
investment_irr = irr(cash_flow)
print(f"IRR: {investment_irr}")  # Should be ~9.7%

# Calculate Modified IRR with different reinvestment assumptions
finance_rate = InterestRate("10% annual")      # Cost of capital
reinvestment_rate = InterestRate("6% annual")  # Reinvestment rate
mirr = modified_internal_rate_of_return(cash_flow, finance_rate, reinvestment_rate)
print(f"MIRR: {mirr}")

# Loan IRR (borrower's perspective)
loan = Loan(Money("10000"), InterestRate("5% annual"), [datetime(2024, 12, 31)])
loan_irr = loan.irr()  # Sugar syntax using loan's expected cash flow
print(f"Loan IRR: {loan_irr}")  # Should be ~5% (loan's own rate)

# Present Value of loan using different discount rate
loan_pv = loan.present_value(InterestRate("8% annual"))
print(f"Loan PV at 8%: {loan_pv}")  # Negative from borrower's perspective

Key Features:

  • ๐Ÿ”ฌ Scipy-powered: Uses scipy.optimize.brentq for robust root finding
  • ๐Ÿ“Š Automatic bracketing: Finds IRR solutions reliably across complex cash flows
  • ๐Ÿ•ฐ๏ธ Time Machine integration: Use Warp to calculate IRR from any date
  • ๐Ÿญ Sugar syntax: loan.irr() and loan.present_value() convenience methods
  • ๐Ÿ’ฐ High precision: Maintains decimal precision throughout calculations

## ๐Ÿ—๏ธ Architecture

MoneyWarp is built around four core concepts:

### ๐Ÿ’ฐ Money
High-precision monetary amounts using Python's `Decimal` for accuracy:
- **Internal precision**: Stores full decimal precision
- **Display precision**: Shows 2 decimal places for "real money"
- **Arithmetic safety**: No floating-point errors

### ๐Ÿ“ˆ InterestRate  
Type-safe interest rate handling with explicit conversions:
- **Clear representation**: Eliminates 0.05 vs 5% confusion
- **Frequency conversion**: Annual โ†” Monthly โ†” Daily โ†” Quarterly
- **String parsing**: `"5.25% annual"` or `"0.004167 monthly"`

### ๐Ÿ’ธ CashFlow
Container for cash flow analysis with SQLAlchemy-style querying:
- **CashFlowItem**: Individual transactions with amount, date, description, category
- **CashFlow**: Collection with filtering, summing, and analysis methods
- **Query interface**: `cashflow.query.filter_by(category='interest').sum_amounts()`

### ๐Ÿฆ Loan
State machine for loan analysis with configurable schedulers:
- **Expected vs Actual**: Compare planned payments with reality
- **Payment allocation**: Fines โ†’ Interest โ†’ Principal priority
- **Fine engine**: Automatic fines and mora interest for overdue payments
- **Sugar methods**: `pay_installment()` and `anticipate_payment()` for natural workflows
- **Flexible scheduling**: Any list of due dates, not just monthly
- **Multiple schedulers**: PMT-based, fixed payment, custom algorithms

## ๐Ÿ“Š Supported Calculations

### Loan Schedules
- **Progressive Price Schedule** (French amortization system)
- **Inverted Price Schedule** (Constant Amortization System - SAC)
- **Fixed payment amounts** with interest/principal allocation
- **Irregular payment dates** with daily compounding
- **Bullet loans** (single payment at maturity)

### Time Value of Money Functions
- **Present Value (PV)**: Discount future cash flows to present value
- **Net Present Value (NPV)**: Sum of discounted cash flows
- **Internal Rate of Return (IRR)**: Rate where NPV equals zero
- **Modified IRR (MIRR)**: IRR with different financing/reinvestment rates
- **Present Value of Annuities**: Regular payment streams
- **Present Value of Perpetuities**: Infinite payment streams
- **Discount Factors**: Time value calculations

### Financial Functions
- **PMT**: Payment calculation for loans and annuities
- **Daily compounding**: Precise interest calculations
- **Amortization schedules**: Complete payment breakdowns
- **Balance tracking**: Outstanding principal over time
- **Robust numerics**: Scipy-powered calculations for complex scenarios

## ๐Ÿงช Testing & Validation

MoneyWarp includes comprehensive test coverage with validation against established financial libraries:

- **469 total tests** with 100% core functionality coverage
- **Reference validation** against [cartaorobbin/loan-calculator](https://github.com/cartaorobbin/loan-calculator)
- **Edge case handling**: Zero interest, irregular schedules, high precision
- **Property-based testing**: Parametrized tests across various scenarios

## ๐ŸŽฏ Use Cases

### Personal Finance
- **Mortgage analysis**: Compare different loan terms and rates
- **Payment tracking**: Monitor actual vs expected payments
- **Refinancing decisions**: Calculate savings from rate changes

### Investment Analysis  
- **Cash flow modeling**: Track investment returns over time
- **Scenario analysis**: "What if" calculations with different assumptions
- **Performance measurement**: Calculate actual returns vs projections

### Financial Planning
- **Loan comparison**: Evaluate different lending options
- **Payment scheduling**: Optimize payment timing for cash flow
- **Interest calculation**: Precise daily compounding for any scenario

## ๐Ÿ”ฎ Roadmap

- โœ… **Time Machine (Warp)**: Travel to any date and analyze loan state - *COMPLETED*
- โœ… **Inverted Price Scheduler**: Constant Amortization System (SAC) - *COMPLETED*
- โœ… **Present Value Functions**: PV, NPV, annuities, perpetuities - *COMPLETED*
- โœ… **IRR Functions**: IRR, MIRR with scipy-powered numerics - *COMPLETED*
- โœ… **Date Generation Utilities**: Smart payment scheduling - *COMPLETED*
- โœ… **Fine Engine**: Fines, mora interest, grace periods - *COMPLETED*
- โœ… **Payment Sugar Methods**: `pay_installment()`, `anticipate_payment()` - *COMPLETED*
- **Additional Schedulers**: Custom schedules, balloon payments
- **Performance optimization**: Vectorized calculations for large datasets
- **Advanced TVM**: Bond pricing, option valuation

## ๐Ÿค Contributing

We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.rst) for details.

## ๐Ÿ“„ License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## ๐Ÿ™ Acknowledgments

- Inspired by the time value of money concepts and validated against [cartaorobbin/loan-calculator](https://github.com/cartaorobbin/loan-calculator)
- Built with modern Python practices using Poetry, pytest, and pre-commit hooks
- Follows the Zen of Python: "Beautiful is better than ugly. Explicit is better than implicit."

---

**MoneyWarp** - Because time is money, and money should bend to your will. ๐Ÿ’ฐโฐ

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

money_warp-0.1.0.tar.gz (35.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

money_warp-0.1.0-py3-none-any.whl (37.7 kB view details)

Uploaded Python 3

File details

Details for the file money_warp-0.1.0.tar.gz.

File metadata

  • Download URL: money_warp-0.1.0.tar.gz
  • Upload date:
  • Size: 35.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for money_warp-0.1.0.tar.gz
Algorithm Hash digest
SHA256 f991adfbb282e4b76ef3fce730b1867c7009ce6169cb897e7aeda773ce467e6d
MD5 b7cac2c00da9c710ed2bc9c2ea7f9eca
BLAKE2b-256 dce90cf7d5f97551bde35eb86ab0734fe681cc5cb0cd4cbcec2a7532c73274f9

See more details on using hashes here.

Provenance

The following attestation bundles were made for money_warp-0.1.0.tar.gz:

Publisher: on-release-pypi.yml on tomascorrea/money-warp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file money_warp-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: money_warp-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 37.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for money_warp-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e8252cea41f7a069f6104ebdf9f23567c4bf2d983809a1845a3069fd292e5a4f
MD5 5c46419b4d61b602261b178e5cfae576
BLAKE2b-256 ce313f357aeff0f3b79dd4776f96166404018333ae3168bac28fc25e6bb716b8

See more details on using hashes here.

Provenance

The following attestation bundles were made for money_warp-0.1.0-py3-none-any.whl:

Publisher: on-release-pypi.yml on tomascorrea/money-warp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page