Skip to main content

Site-Calc Investment Client

Python client for Site-Calc investment planning API - long-term capacity planning and ROI analysis.

Installation

pip install site-calc-investment

Quick Start

from datetime import datetime
from zoneinfo import ZoneInfo
from site_calc_investment import InvestmentClient
from site_calc_investment.models import (
    Resolution,
    Site,
    Battery,
    ElectricityImport,
    ElectricityExport,
    InvestmentPlanningRequest,
    InvestmentParameters,
    OptimizationConfig,
)
from site_calc_investment.models.requests import TimeSpanInvestment

# Initialize client
client = InvestmentClient(base_url="https://api.site-calc.example.com", api_key="inv_your_api_key_here")

# Create 1-week planning horizon (1-hour resolution)
timespan = TimeSpanInvestment(
    start=datetime(2025, 1, 1, tzinfo=ZoneInfo("Europe/Prague")),
    intervals=168,  # 1 week = 7 days × 24 hours
    resolution=Resolution.HOUR_1,
)

# Generate hourly prices (example: day/night pattern)
prices = [30.0 if h % 24 < 6 else 80.0 if 8 <= h % 24 < 20 else 50.0 for h in range(168)]

# Define devices (NO ancillary_services field)
battery = Battery(
    name="Battery1",
    properties={"capacity": 10.0, "max_power": 5.0, "efficiency": 0.90, "initial_soc": 0.5},
    investment={"capital_cost": 500000, "annual_opex": 5000},  # For client-side NPV
)

grid_import = ElectricityImport(name="GridImport", properties={"price": prices, "max_import": 10.0})

grid_export = ElectricityExport(name="GridExport", properties={"price": prices, "max_export": 10.0})

site = Site(site_id="investment_site", devices=[battery, grid_import, grid_export])

# Global investment parameters (per-device costs live on the devices)
inv_params = InvestmentParameters(
    discount_rate=0.05,
    project_lifetime_years=10,  # Required field
)

# Create and submit optimization request
request = InvestmentPlanningRequest(
    sites=[site],
    timespan=timespan,
    investment_parameters=inv_params,
    optimization_config=OptimizationConfig(
        objective="maximize_profit",  # Options: maximize_profit, minimize_cost, maximize_self_consumption
        time_limit_seconds=300,  # Max 3600 seconds (60 min)
    ),
)

job = client.create_planning_job(request)
result = client.wait_for_completion(job.job_id, poll_interval=5, timeout=600)

print(f"Status: {result.status}")
print(f"Solver: {result.summary.solver_status}")
print(f"Profit: €{result.summary.expected_profit:,.2f}")

Features

  • ✅ Long-term capacity planning (1-10 years)
  • ✅ Investment ROI analysis (NPV, IRR, payback)
  • ✅ Per-device investment costs (capital_cost / annual_opex) for client-side NPV
  • ✅ Capacity reservations: per-period capacity limits and charges with automatic cheapest-tariff assignment
  • ✅ BESS investment sizing: optimizer-sized battery power (MW) and energy capacity (MWh)
  • ✅ Czech distribution-tariff import device (monthly T1/T2 capacity tariff, 2027 structure)
  • ✅ Scenario comparison utilities
  • ✅ Financial analysis helpers
  • ✅ 1-hour resolution optimization
  • ✅ Multi-site optimization
  • ✅ Type-safe Pydantic models
  • ✅ Automatic retry and error handling
  • ✅ Job management (cancel single or all jobs)

Capabilities

Feature Value
Max Horizon 100,000 intervals (~11 years at 1-hour)
Resolution 1-hour only
ANS Support No
Binary Variables Relaxed to continuous
Timeout 3600 seconds (60 minutes) max

Supported Devices

  • Battery (NO ANS; optional power_sizing / capacity_sizing reservations let the optimizer size installed MW / MWh)
  • CHP - Combined Heat and Power (continuous operation)
  • Heat Accumulator
  • Photovoltaic: photovoltaic_nonsteerable (exact profile) / photovoltaic_steerable (curtailable up to a max-power profile)
  • Fixed Production / Fixed Consumption (follow a power profile exactly)
  • Max-Power Production / Consumption (steerable in [0, max] at a linear EUR/MWh cost or value)
  • Heat Demand
  • Electricity Demand
  • Electricity Import/Export (market interface; optional capacity_reservation for per-period grid capacity tariffs)
  • Czech Distribution Import (cz_distribution_import: electricity import billed under the Czech monthly T1/T2 capacity tariff)
  • Gas Import (market interface)
  • Heat Export (market interface)

Every device also accepts an optional investment block ({"capital_cost": EUR, "annual_opex": EUR/year}) used only for client-side NPV/IRR analysis -- it is stripped from the API payload.

Job Management

The client provides methods for managing optimization jobs:

# Create a job
job = client.create_planning_job(request)
print(f"Job ID: {job.job_id}")

# Check job status
status = client.get_job_status(job.job_id)
print(f"Status: {status.status}, Progress: {status.progress}%")

# Wait for completion
result = client.wait_for_completion(job.job_id, poll_interval=30, timeout=7200)

# Cancel a single job
cancelled = client.cancel_job(job.job_id)

# Cancel all pending/running jobs (bulk cancel)
result = client.cancel_all_jobs()
print(f"Cancelled {result['cancelled_count']} jobs")

Financial Analysis

from site_calc_investment.analysis import (
    calculate_investment_metrics,
    calculate_npv,
    calculate_irr,
    calculate_payback_period,
    compare_scenarios,
)

# All-in-one: NPV/IRR/payback from annual aggregates + device investment blocks
metrics = calculate_investment_metrics(
    annual_revenues=result.investment_metrics.annual_revenue_by_year,
    annual_costs=result.investment_metrics.annual_costs_by_year,  # already includes capacity-reservation charges
    discount_rate=0.05,
    devices=site.devices,
)
print(metrics["npv"], metrics["irr"], metrics["payback_period_years"])

# NPV calculation
npv = calculate_npv(cash_flows=annual_revenues, discount_rate=0.05, initial_investment=-1500000)

# IRR calculation
irr = calculate_irr([-1500000] + annual_revenues)

# Scenario comparison
comparison = compare_scenarios([result_5mw, result_10mw, result_15mw], names=["5 MW", "10 MW", "15 MW"])
print(comparison)  # DataFrame with NPV, IRR, costs, revenues

MCP Server (LLM Integration)

The package includes an MCP server for use with Claude Desktop, ChatGPT, and other MCP-compatible LLM tools.

Installation

pip install site-calc-investment[mcp]

Claude Desktop Configuration

Add to claude_desktop_config.json:

{
  "mcpServers": {
    "site-calc-investment": {
      "command": "uvx",
      "args": ["--from", "site-calc-investment[mcp]", "site-calc-investment-mcp"],
      "env": {
        "INVESTMENT_API_URL": "http://your-api-url",
        "INVESTMENT_API_KEY": "inv_your_key_here",
        "INVESTMENT_DATA_DIR": "/path/to/data/directory"
      }
    }
  }
}

For local development against a source checkout, use uv run --directory instead:

{
  "mcpServers": {
    "site-calc-investment": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/client-investment", "site-calc-investment-mcp"],
      "env": {
        "INVESTMENT_API_URL": "http://your-api-url",
        "INVESTMENT_API_KEY": "inv_your_key_here",
        "INVESTMENT_DATA_DIR": "/path/to/data/directory"
      }
    }
  }
}

ChatGPT Configuration

ChatGPT supports MCP via streaming HTTP or SSE (stdio is not supported). This requires:

  • An eligible ChatGPT plan with Developer Mode access (Pro, Plus, Business, Enterprise, or Education). Business plan restricts Developer Mode to admins/owners; other plans may have similar admin gating.
  • Developer Mode enabled (navigate to Settings -- the exact path may vary by account type)

Step 1 -- Start the MCP server in HTTP mode:

cd /path/to/client-investment
INVESTMENT_API_URL="http://your-api-url" \
INVESTMENT_API_KEY="inv_your_key_here" \
INVESTMENT_DATA_DIR="/path/to/data" \
uv run fastmcp run site_calc_investment.mcp.server:mcp --transport http --port 8000

Step 2 -- Expose to the internet (for local development):

ngrok http 8000

For production, deploy the server to a publicly accessible host instead.

Step 3 -- Add to ChatGPT:

  1. Open ChatGPT Settings > Apps & Connectors (or Connectors) > Advanced settings > Enable Developer Mode
  2. Click Create app
  3. Enter the ngrok HTTPS URL (e.g. https://abc123.ngrok.io/mcp) as the server endpoint
  4. Name: "Site-Calc Investment", Description: "Investment planning optimization tools"
  5. Click Refresh to load the tool list

Note: ChatGPT shows tool call details and may require manual confirmation for actions. The save_data_file tool requires the server to have local filesystem access.

Tools (17)

Tool Description
get_version Get server and package version info
create_scenario Create a new draft scenario
add_device Add a device (battery, CHP, PV, etc.), optionally with an investment cost block
set_timespan Set optimization time horizon
set_investment_params Set global financial parameters (discount rate, project lifetime)
review_scenario Review scenario before submission
remove_device Remove a device
delete_scenario Delete a scenario
list_scenarios List all draft scenarios
submit_scenario Submit for optimization
get_job_status Check job progress
get_job_result Get optimization results (incl. capacity reservation summaries)
cancel_job Cancel a job
list_jobs List all jobs
get_device_schema Get device property schema
save_data_file Save generated data as CSV
fetch_url Download a file (e.g. CSV price data) from a URL

save_data_file lets the LLM write generated data (price arrays, demand profiles) to local CSV files, which can then be referenced in add_device properties.

See docs/MCP_SERVER_SPEC.md for full specification.

Documentation

Full documentation available at: https://github.com/stranma/site-calc-investment#readme

Examples

See examples/ directory for complete examples:

  • capacity_planning.py - 10-year capacity planning workflow
  • roi_analysis.py - Investment ROI calculation
  • scenario_comparison.py - Compare device configurations

Requirements

  • Python ≥ 3.10
  • API key with inv_ prefix (investment client)

Key Differences from Operational Client

  • ❌ No /optimal-bidding endpoint
  • ❌ No ancillary_services on devices
  • ❌ No 15-minute resolution (1-hour only)
  • ✅ Up to 100,000 intervals (vs. 296)
  • ✅ Investment metrics (NPV, IRR, payback)
  • ✅ Financial analysis helpers

Development

# Install with dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Format code
ruff format .

# Type check
mypy site_calc_investment

License

MIT License

Support


Part of the Site-Calc platform.

Metadata

Release files for site-calc-investment 1.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for site-calc-investment 1.4.0
File Size Uploaded
site_calc_investment-1.4.0.tar.gz 249.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for site-calc-investment 1.4.0
File Interpreter ABI Platform
site_calc_investment-1.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 302.8 kB

Release files / site_calc_investment-1.4.0.tar.gz

Download URL site_calc_investment-1.4.0.tar.gz
Size 249.5 kB
Tags Source
SHA-256 checksum
How to use checksums
b2e94e6885233fe468e6cc23c88bc2d91ae5f9dfd0ec0d228c8af776630ff0c2
BLAKE2b-256 checksum
How to use checksums
ce3c9e1a0607d58d530aad276754b6741fd581cb863f57004002b6228bf1463a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Release files / site_calc_investment-1.4.0-py3-none-any.whl

Download URL site_calc_investment-1.4.0-py3-none-any.whl
Size 53.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
803d5009d57c16bf2b76c383cb59bef7c8962fd7e93fe2cabc9d41f22db08f1e
BLAKE2b-256 checksum
How to use checksums
e4432e0e128710fc46a455b0723cb9908f0cbdc0cc662ab869019beda40a7c50
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Release history Release notifications | RSS feed

1.5.5

2 release files

1.5.4

2 release files

1.5.3

2 release files

1.5.2

2 release files

1.5.1

2 release files

1.5.0

2 release files

This release

1.4.0 This release

2 release files

1.3.0

2 release files

1.2.9

2 release files

1.2.7

2 release files

1.2.6

2 release files

1.2.5

2 release files

1.2.4

2 release files

1.2.3

2 release files

1.2.2

2 release files

1.2.1

2 release files

1.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page