Skip to content

Optimizes charging and discharging hours for your Alpha ESS system based on day-ahead electricity prices

Notifications You must be signed in to change notification settings

michaelkrasa/AlphaESS-charging-optimizer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

36 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

⚑ AlphaESS Charging Optimizer

Dynamic battery arbitrage against Czech day-ahead electricity prices

Quick Start β€’ Lambda Deploy β€’ How It Works β€’ Configuration


Automatically charge your AlphaESS battery when electricity is cheap and discharge when expensive. Uses 15-minute price slots from OTE (Czech day-ahead market) to maximize savings through smart arbitrage cycles.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  πŸ’° CHEAP (Valley)          πŸ’Έ EXPENSIVE (Peak)                 β”‚
β”‚  ════════════════          ═══════════════════                  β”‚
β”‚  03:00-06:00 @ 45€         17:00-20:00 @ 180€                   β”‚
β”‚  ↓ CHARGE ↓                ↓ DISCHARGE ↓                        β”‚
β”‚  Grid β†’ Battery            Battery β†’ Home                       β”‚
β”‚                                                                 β”‚
β”‚  Spread: 135 €/MWh  ✨                                          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

✨ Features

Feature Description
πŸ” Dynamic Detection Auto-detects valleys & peaks from daily price patterns
πŸ”„ Arbitrage Cycles Pairs charge windows with discharge windows for max spread
πŸ”‹ Battery-Aware Sizes windows based on actual SOC and capacity
πŸ“Š 15-min Granularity Uses OTE's 96 daily price slots for precision
☁️ Serverless Ready Deploy to AWS Lambda or run locally

πŸš€ Quick Start

Prerequisites

  • Python 3.12+
  • uv (fast Python package manager)
  • AlphaESS Open API credentials

Installation

# Clone
git clone https://github.com/michaelkrasa/AlphaESS-charging-optimizer.git
cd AlphaESS-charging-optimizer

# Install dependencies
uv sync

Configuration

Create a .env file with your credentials:

cp .env.example .env
# Edit .env with your values
# Required - AlphaESS API
APP_ID=your_alpha_ess_app_id
APP_SECRET=your_alpha_ess_app_secret
SERIAL_NUMBER=your_system_serial

Tune behavior in config.yaml:

charge_rate_kw: 5        # Battery charge rate in kW
price_multiplier: 1.2    # Valley/peak threshold vs daily mean
min_soc: 10              # Don't discharge below this %
max_soc: 100             # Charge target %

Run

# Default: Single optimization for today (run at midnight)
uv run python -m src.optimizer

# Dry run for a specific day (no API changes)
uv run python -m src.optimizer --date 15

☁️ AWS Lambda Deployment

Run as a serverless function - no server required, pay only for execution time.

Quick Deploy

# 1. Configure (edit .env with AWS settings)
cp .env.example .env

# 2. Deploy to AWS
./deploy-lambda.sh

The script will:

  • βœ… Build Docker image (arm64 for Graviton)
  • βœ… Push to Amazon ECR
  • βœ… Update Lambda function
  • βœ… Configure environment variables

Lambda Configuration

Setting Value
Architecture arm64 (Graviton)
Timeout 30 seconds
Memory 256 MB
Trigger EventBridge @ 00:00 UTC daily

Lambda Execution

Lambda runs once at 00:00 daily and optimizes for the current day. No configuration needed - just schedule it via EventBridge.

Schedule with EventBridge

# Daily at 00:00 UTC (01:01 CET)
aws events put-rule \
  --name "ess-daily-optimization" \
  --schedule-expression "cron(1 0 * * ? *)"

🧠 How It Works

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Fetch 96    │────▢│  Detect      │────▢│  Build       β”‚
β”‚  Price Slots β”‚     β”‚  Valleys &   β”‚     β”‚  Arbitrage   β”‚
β”‚  (15-min)    β”‚     β”‚  Peaks       β”‚     β”‚  Cycles      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                                 β”‚
                                                 β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Done! βœ…    │◀────│  Program     │◀────│  Size to     β”‚
β”‚              β”‚     β”‚  AlphaESS    β”‚     β”‚  Battery     β”‚
β”‚              β”‚     β”‚  API         β”‚     β”‚  SOC         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Price Analysis

  1. Smooth prices with moving average to reduce noise
  2. Calculate daily mean price
  3. Detect valleys: price < mean / price_multiplier
  4. Detect peaks: price > mean Γ— price_multiplier
  5. Find mid-day dips between peaks for extra opportunities

Arbitrage Matching

  • Each valley pairs with the next sequential peak
  • Discharge windows extend to cover all profitable hours
  • Up to 2 cycles per day (AlphaESS API limitation)

Battery Intelligence

  • Reads actual SOC from device
  • Pulls capacity (gross Γ— usable %)
  • Sizes charge windows to actual need
  • Accounts for consumption between windows

βš™οΈ Configuration

Environment Variables (.env)

Variable Required Description
APP_ID βœ… AlphaESS API app ID
APP_SECRET βœ… AlphaESS API secret
SERIAL_NUMBER βœ… Your ESS serial number
AWS_ACCOUNT_ID Lambda AWS account for ECR
ECR_REPO Lambda ECR repository name

Optimization Settings (config.yaml)

Setting Default Description
charge_rate_kw 5 Battery charge rate in kW
price_multiplier 1.2 Threshold factor vs daily mean
min_soc 10 Minimum discharge SOC %
max_soc 100 Target charge SOC %
avg_day_load_kw 1.8 Avg household load for SOC estimation
min_window_slots 2 Minimum window size (Γ—15 min)
smoothing_window 2 Price smoothing window (Γ—15 min)

πŸ“ Project Structure

β”œβ”€β”€ src/                    # Core application modules
β”‚   β”œβ”€β”€ optimizer.py        # Main optimizer orchestration
β”‚   β”œβ”€β”€ models.py           # Data models (PriceWindow, ArbitrageCycle, etc.)
β”‚   β”œβ”€β”€ price_analyzer.py   # Price analysis and valley/peak detection
β”‚   β”œβ”€β”€ battery_manager.py  # Battery state calculations
β”‚   β”œβ”€β”€ ess_client.py       # AlphaESS API client
β”‚   └── price_cache.py      # Price caching logic
β”œβ”€β”€ utils/                  # Utility scripts
β”‚   └── fetch_december_prices.py  # Price data fetcher for testing
β”œβ”€β”€ tests/                  # Test suite
β”‚   β”œβ”€β”€ test_ess.py         # Main test suite
β”‚   β”œβ”€β”€ test_december_2025.py  # December 2025 price data tests
β”‚   └── test_data/          # Test price data files
β”œβ”€β”€ config.py               # Configuration loader
β”œβ”€β”€ config.yaml             # Optimization settings
β”œβ”€β”€ lambda_handler.py       # AWS Lambda entry point
β”œβ”€β”€ Dockerfile              # Lambda container (arm64)
β”œβ”€β”€ deploy-lambda.sh        # One-command AWS deployment
β”œβ”€β”€ .env.example            # Environment template
└── pyproject.toml          # Project dependencies (UV)

πŸ§ͺ Testing

# Run all tests
uv run pytest tests/ -v

# Run specific test file
uv run pytest tests/test_ess.py -v

# Run December 2025 data tests
uv run pytest tests/test_december_2025.py -v

⏰ Automation

Cron (Linux/macOS)

# Run daily at 00:00 (midnight + 1 minute)
1 0 * * * cd /path/to/AlphaESS-charging-optimizer && uv run python -m src.optimizer

AWS Lambda + EventBridge

See Lambda Deployment section above.


πŸ“ Notes

  • Target market: Czech OTE day-ahead prices (15-min granularity)
  • API limitation: Max 2 charge + 2 discharge windows per day
  • Schedule: Run at 00:00 daily to optimize for that day (prices are published the day before)

πŸ“„ License

MIT


Happy arbitrage! βš‘πŸ”‹

About

Optimizes charging and discharging hours for your Alpha ESS system based on day-ahead electricity prices

Topics

Resources

Stars

Watchers

Forks

Contributors 2

  •  
  •