Engineering and Project Management
 

The Carbon Compliance Gap in Maritime Shipping — and How to Close It With Code

Since January 2024, maritime transport has been included in the EU Emissions Trading System (EU ETS). Ships within scope now have obligations to monitor, report, and ultimately surrender EU allowances for covered greenhouse-gas emissions. The phase-in is 40% for 2024 emissions, 70% for 2025 emissions, and 100% from 2026 emissions onward, with surrender taking place in the following compliance cycle. The geographical scope also matters: emissions are treated differently for voyages between EU/EEA ports, voyages between an EU/EEA port and a non-EU/EEA port, and emissions occurring while ships are at EU/EEA ports.

In parallel, FuelEU Maritime, Regulation (EU) 2023/1805, applies from 2025 and introduces a different compliance mechanism based on the greenhouse-gas intensity of energy used on board ships. Its requirements are expressed on a well-to-wake basis and become progressively more stringent over time.

And alongside the EU regimes sits the IMO’s Carbon Intensity Indicator (CII) framework. Since 2023, applicable ships have been required to calculate an annual operational CII and receive an A-to-E rating. A ship rated E for one year, or D for three consecutive years, must submit a corrective action plan showing how it will achieve a C rating or better.

These regimes overlap in their underlying operational data, but they are not three versions of the same calculation.

  • EU ETS is an emissions-allowance regime.
  • FuelEU is an annual greenhouse-gas-intensity and compliance-balance regime.
  • CII is an IMO operational carbon-intensity rating regime.

That distinction matters.

A single voyage can generate data relevant to all three systems, but the resulting compliance calculations operate over different scopes, time periods, methodologies, and regulatory definitions.

The practical result is a data and software problem:

the same fuel-consumption and voyage records may feed several regulatory engines, but those engines cannot safely share the same assumptions.

Most operators still rely heavily on spreadsheets, manually maintained calculation tools, or internal systems whose regulatory assumptions are difficult to inspect and reproduce.

That is where a purpose-built calculation library can help—but only if the software treats the regulations as versioned rules rather than as a handful of constants.

What We Built

euets-calculator is designed as a standalone Python package for calculating maritime carbon-compliance metrics from structured operational data.

The package separates four areas of functionality:

  • EU ETS — emissions and allowance-related calculations
  • FuelEU Maritime — greenhouse-gas-intensity and compliance calculations
  • CII — annual operational carbon-intensity calculations and rating-related analysis
  • Charterparty allocation — contractual allocation scenarios for emissions-related costs

The objective is not to replace a verifier, flag Administration, administering authority, or legal adviser. The objective is narrower and more useful: turn regulatory formulas and operational inputs into deterministic, inspectable calculations that can be tested, versioned, and incorporated into an operational workflow.

 

sample euets-calculator output

eu-ets and fueleu python calculator

 

The package is designed to run locally, with no requirement for a hosted SaaS service, database, or external API for the core calculation path.

# Example: calculate an EU ETS scenario
euets-calc ets \
  --imo 9456789 \
  --voyage-id ROT-HAM-2025-014 \
  --fuel-type VLSFO \
  --quantity 800 \
  --phase-in-year 2025 \
  --eua-price 85

The important architectural principle is that a calculation result should be reproducible from its declared inputs, calculation version, and regulatory configuration.

That is a stronger and more useful proposition than simply claiming that a number is “compliant.”


Three Regulatory Regimes, One Data Problem

The biggest software mistake in maritime carbon compliance is to assume that EU ETS, FuelEU, and CII can be collapsed into one generic carbon calculation.

They cannot.

EU ETS

EU ETS is fundamentally an emissions-pricing and allowance-surrender regime.

For maritime transport, the calculation depends on factors including:

  • the ship’s applicability and characteristics;
  • the relevant greenhouse gases;
  • fuel or energy consumption;
  • applicable emission factors and methodologies;
  • voyage geography;
  • emissions occurring at EU/EEA ports;
  • the applicable reporting/compliance year;
  • the phase-in applicable to the relevant emissions.

The EU MRV system provides an important underlying data layer for the EU maritime climate framework. The European Commission has explicitly described EU ETS maritime and FuelEU Maritime as building on the monitoring, reporting, and verification framework established under EU MRV.

FuelEU Maritime

FuelEU asks a different question:

What is the greenhouse-gas intensity of the energy used on board, and does the ship’s annual result satisfy the applicable limit?

The reference value is 91.16 gCO₂e/MJ, with progressively stricter reduction requirements beginning at 2% in 2025 and ultimately reaching 80% in 2050.

FuelEU therefore requires more than multiplying tonnes of fuel by a tank-to-wake CO₂ factor.

The calculation needs to account for the regulatory treatment of the energy used, the applicable well-to-wake methodology, the relevant fuel pathway and sustainability characteristics where applicable, and the ship’s annual compliance position.

The resulting compliance framework also includes mechanisms such as banking, borrowing and pooling. These mechanisms are part of the regulatory system rather than optional commercial features.

IMO CII

CII is different again.

The IMO describes CII as an annual operational carbon-intensity indicator, with the actual annual CII compared with the required annual CII to determine the ship’s A-to-E rating.

The calculation is linked to transport work and operational data rather than simply to the amount of CO₂ emitted on an individual voyage.

Since 2023, IMO Data Collection System data has been used to calculate operational CII. Aggregated annual data is reported through the flag-State process, and the relevant declaration and reporting cycle follows the calendar year.

The software consequence is straightforward:

Voyage data is an input. It is not necessarily the regulatory unit of compliance.


EU ETS: Make the Phase-In Explicit

The EU ETS maritime phase-in is straightforward once the reporting year and surrender year are not confused.

For emissions attributable to the following reporting years:

Emissions yearPercentage subject to surrender
202440%
202570%
2026 onward100%

The key implementation detail is that surrender follows the reporting year.

A software interface should therefore avoid an ambiguous parameter such as:

--phase-in-year 2025

unless the meaning is explicitly documented.

A better internal model is:

emissions_period = 2025
surrender_period  = 2026
coverage_fraction = 70%

That makes the regulatory relationship explicit and prevents an entire class of off-by-one-year compliance errors.


Geographic Coverage Matters

EU ETS maritime calculations also cannot be reduced to:

fuel × emission factor × phase-in percentage

The geographical scope of the voyage matters.

For example, a voyage between two EU/EEA ports is treated differently from a voyage between an EU/EEA port and a non-EU/EEA port.

A production implementation therefore needs a voyage-scope model capable of distinguishing at least:

  • EU/EEA port → EU/EEA port
  • EU/EEA port → non-EU/EEA port
  • non-EU/EEA port → EU/EEA port
  • emissions while at berth in an EU/EEA port

The calculation engine should derive the applicable coverage from structured voyage data rather than asking an operator to manually type a percentage whenever possible.

That makes the input auditable and reduces the chance that an incorrect coverage percentage becomes a hidden spreadsheet assumption.


Fuel Factors: Precision Starts With Correct Classification

Emission factors need to be treated as regulatory data, not merely constants in source code.

For example, the IMO’s emission-factor material contains a CO₂ factor of approximately 3.114 tonnes CO₂ per tonne of HFO and approximately 1.375 tonnes CO₂ per tonne of methanol.

Those numbers are useful, but a compliance implementation must also document how a commercial fuel label maps to the regulatory fuel category.

Calling every residual marine fuel “VLSFO” and silently assigning the HFO factor is not sufficiently transparent for an audit-grade system.

The software should instead expose something like:

fuel_product = VLSFO
regulatory_fuel_category = HFO
emission_factor_source = MEPC.281(70)
emission_factor_version = <version>

The exact mapping should be explicit and tested.

This is a recurring principle throughout the system:

Never allow a regulatory assumption to hide inside a generic variable name.


A Simple EU ETS Example

For a simplified intra-EU voyage using 1,000 tonnes of fuel and an applicable CO₂ factor of 3.114 tCO₂/t, the physical emissions calculation is:

emissions
= 1,000 × 3.114
= 3,114 tCO₂

For 2025 emissions, applying the 70% phase-in produces:

covered emissions
= 3,114 × 0.70
= 2,179.80 tCO₂

At an illustrative EUA price of €80:

illustrative cost
= 2,179.80 × €80
= €174,384

The arithmetic is exact when the inputs are represented appropriately.

But the example is deliberately simplified.

A production EU ETS engine must separately establish:

  1. whether the ship is in scope;
  2. what emissions are in scope;
  3. which greenhouse gases apply;
  4. the geographical treatment of the voyage;
  5. the applicable emission factor;
  6. the relevant reporting period;
  7. the phase-in;
  8. the applicable rounding and surrender rules;
  9. and the relevant compliance-period treatment.

The purpose of the example is therefore to demonstrate the arithmetic—not to imply that every real voyage can be calculated from three command-line parameters.


FuelEU Maritime: An Annual Compliance Model

FuelEU requires a different architecture.

The regulation establishes progressively tighter limits on the greenhouse-gas intensity of energy used on board ships.

The reduction schedule is:

YearReduction from reference value
20252%
20306%
203514.5%
204031%
204562%
205080%

The reference value is 91.16 gCO₂e/MJ.

The calculation is therefore not simply:

tonnes of fuel × fossil-fuel CO₂ factor

It requires an annual energy and greenhouse-gas accounting model consistent with FuelEU’s methodology.

A useful software abstraction is:

FuelRecordEnergyRecordFuelEU GHG-intensity calculation
    ↓
Annual compliance balance
Bank / borrow / pool mechanisms
    ↓
Compliance result

This architecture also makes a critical distinction possible:

fuel consumption data is not the same thing as FuelEU compliance data.

The latter requires regulatory context.


FuelEU Pooling Is Not Simply Fleet Aggregation

Pooling should also be treated as a regulatory mechanism rather than a generic “sum several ships” operation.

A pool can involve multiple ships and, subject to the applicable rules, can extend beyond a single owner’s fleet.

The software should therefore model a pool explicitly:

Pool
 ├── participating ships
 ├── compliance periods
 ├── individual balances
 ├── pool constraints
 ├── allocation methodology
 └── resulting compliance positions

That is preferable to implementing pooling as:

sum(vessel.balance for vessel in fleet)

because the latter obscures the regulatory constraints that make the operation valid or invalid.


CII: Annual Rating, Not a Voyage-Level Carbon Tax

The CII engine requires the greatest care.

The IMO framework requires applicable ships to calculate an annual operational CII and receive an A-to-E rating. A rating of D for three consecutive years or E for one year triggers the requirement for a corrective action plan.

That means this statement is important:

A single D rating does not by itself trigger the corrective-action-plan requirement.

The software therefore needs historical state.

A CII engine cannot safely evaluate the corrective-action trigger from only the current year’s CII.

It needs something conceptually like:

2024 rating = C
2025 rating = D
2026 rating = D
2027 rating = D

At that point, the three-consecutive-year condition is satisfied.

By contrast:

2024 rating = C
2025 rating = D
2026 rating = C

does not create the same three-year trigger.

This is a strong example of why regulatory software needs state and history, not just formulas.


CII Rating Bands Must Be Ship-Specific

CII ratings cannot be implemented safely as a universal table such as:

A ≤ 0.70
B ≤ ...
C ≤ ...
D ≤ ...
E > 1.10

The applicable CII framework depends on ship category and the relevant reference-line and reduction-factor methodology.

The IMO describes the rating system as comparing the attained annual operational CII with the required annual operational CII and assigning an A-to-E rating.

The engine therefore needs regulatory configuration that incorporates, as applicable:

  • ship type;
  • capacity definition;
  • applicable reference line;
  • reduction factor;
  • required annual CII;
  • rating boundaries;
  • relevant regulatory year;
  • applicable calculation methodology;
  • and subsequent amendments to the IMO guidelines.

The implementation should never expose a generic “CII band” constant without identifying the ship category and regulatory basis behind it.


CII Is Also a Moving Regulatory Target

The CII framework is not static.

IMO’s short-term GHG measures entered into force in 2022, with CII requirements applying from 2023. The framework is under continuing review, and IMO’s current work includes a second phase of review of the short-term GHG measures.

That has a direct software implication:

CII constants cannot be treated as timeless application configuration.

A regulatory calculation should carry a version or effective date.

For example:

cii_methodology_version = "IMO-G1-<effective-version>"
cii_reference_version   = "IMO-G2-<effective-version>"
cii_rating_version      = "IMO-G4-<effective-version>"
calculation_date        = ...

This allows an old result to remain reproducible even after the regulation changes.


CII Corrective Action Is an Engineering Problem, Not a Generic Percentage Table

A CII system can usefully identify possible operational measures, including:

  • hull and propeller maintenance;
  • speed optimization;
  • route optimization;
  • trim optimization;
  • machinery efficiency improvements;
  • waste-heat recovery;
  • air lubrication;
  • energy-efficiency technologies;
  • alternative fuels.

IMO itself identifies operational measures such as hull cleaning and speed/routeing optimization as potential ways of improving carbon intensity.

But the software should not present statements such as:

Speed reduction: 515% improvement
Air lubrication: 515% improvement

as if they were universal regulatory guarantees.

The actual effect depends on the vessel, operating profile, baseline, speed-power relationship, route, weather, machinery, loading condition, and other factors.

A better implementation is to classify these as scenario estimates:

measure = "speed_reduction"
assumed_speed_change = -5%
estimated_cii_change = ...
confidence = "scenario"

That clearly separates a modelled engineering estimate from an IMO-prescribed value.


One Data Layer, Multiple Regulatory Engines

The strongest architectural idea in the package is not that one formula calculates everything.

It is that one trusted operational data model can feed multiple independent regulatory engines.

For example:

                         ┌──────────────────┐
                         │ Operational Data │
                         └────────┬─────────┘
                                  │
             ┌────────────────────┼────────────────────┐
             │                    │                    │
             ▼                    ▼                    ▼
       Voyage / MRV          Annual Energy        Annual DCS /
          data                  data             operational data
             │                    │                    │
             ▼                    ▼                    ▼
        EU ETS Engine       FuelEU Engine         CII Engine
             │                    │                    │
             ▼                    ▼                    ▼
       ETS obligation      FuelEU balance        CII result/rating
             │                    │                    │
             └────────────────────┼────────────────────┘
                                  ▼
                         Audit / provenance layer

This is a much safer architecture than sharing a single generic carbon_emissions() function across all three regimes.

Shared data models are useful.

Shared regulatory assumptions are dangerous.


Technical Architecture

Design Principles
PrincipleImplementation
Explicit precisionUse Decimal where deterministic decimal arithmetic is required
Deterministic calculationsSame versioned inputs and configuration produce the same result
Regulatory versioningRegulatory constants and methodologies carry effective versions/dates
Independent enginesEU ETS, FuelEU and CII calculations remain separately testable
Explicit provenanceInputs, sources, calculation version and regulatory configuration are recorded
Configuration as dataRegulatory parameters are externalized from calculation logic where practical
No unnecessary runtime dependenciesCore calculations remain executable without a database or external service

The original package describes a zero-external-dependency calculation path beyond click and pydantic.

That is a reasonable engineering goal.

But dependency minimization should never be confused with regulatory completeness.


The Four Engines
┌──────────────────────────────────────────────────────────────┐
│                      euets_calculator                        │
├───────────────────┬───────────────────┬──────────────────────┤
│     ETSEngineFuelEUEngineCIIEngine       │
│                   │                   │                      │
│ • compute()       │ • compute()       │ • compute()          │
│ • aggregate()     │ • annual_balance()│ • annual_cii()      │
│ • coverage()      │ • bank()          │ • rating()           │
│ • emission_scope()│ • borrow()        │ • history()          │
│                   │ • pooling()       │ • scenarios()        │
├───────────────────┴───────────────────┴──────────────────────┤
│                Charterparty Allocation Engine                 │
│                                                               │
│ • clause-specific scenarios                                   │
│ • time-based allocation                                       │
│ • DB-value allocation                                         │
│ • bareboat scenarios                                          │
│ • custom contractual allocation                                │
├───────────────────────────────────────────────────────────────┤
│ Models                                                        │
│ FuelRecordVoyageVesselReportingPeriodRegulation  │
├───────────────────────────────────────────────────────────────┤
│ Provenance                                                    │
│ Input manifestRegulatory versionCode versionHash     │
└───────────────────────────────────────────────────────────────┘

The crucial addition is regulatory and calculation provenance.

A result should not merely say:

input_hash = abc123...

It should be possible to identify:

input dataset
regulatory configuration
calculation implementation
software version
calculation timestamp

Regulatory Accuracy: What “Verified” Should Mean

A compliance package should not say simply:

“Every constant has been verified.”

That statement is too broad.

A better claim is:

“Regulatory parameters are maintained against identified primary sources, with automated tests covering the implemented calculation rules.”

The distinction matters because a test can prove that the software consistently implements a specified rule.

It does not prove that:

  • the rule was interpreted correctly;
  • the input data are accurate;
  • the software implements every relevant provision;
  • a particular ship is within scope;
  • the calculation satisfies every reporting requirement;
  • or the result constitutes an official compliance determination.

A mature compliance system therefore needs at least three layers of assurance:

1. Source assurance

Where did the rule come from?

Examples:

  • EU Directive
  • EU Regulation
  • EUR-Lex consolidated text
  • IMO resolution
  • IMO guideline
  • applicable implementing/delegated act
2. Implementation assurance

Does the code implement the source correctly?

Examples:

  • unit tests;
  • boundary tests;
  • regression tests;
  • property tests;
  • independent calculation fixtures.
3. Data assurance

Are the inputs correct?

Examples:

  • bunker delivery notes;
  • fuel-consumption records;
  • MRV records;
  • IMO DCS data;
  • voyage records;
  • ship particulars;
  • verifier-approved data.

A package that only addresses layer 2 should not describe itself as providing complete compliance assurance.


Precision: Why Decimal Helps—and What It Does Not Solve

Using Decimal is a sensible choice for monetary and regulatory calculations where decimal representation and explicit rounding matter.

For example:

Decimal("3.114") * Decimal("1000")

produces a predictable decimal result.

That can be preferable to binary floating-point arithmetic in financial calculations.

But numerical representation is only one component of calculation accuracy.

In maritime carbon compliance, larger errors can arise from:

  • the wrong fuel classification;
  • an incorrect emission factor;
  • incorrect voyage scope;
  • an incorrect regulatory year;
  • an incorrect ship category;
  • incorrect transport-work data;
  • incorrect FuelEU energy or GHG-intensity assumptions;
  • incorrect CII reference data;
  • or incorrect rounding rules.

The engineering objective should therefore be:

deterministic arithmetic plus correct regulatory modelling plus validated inputs.

Not merely:

Decimal instead of float.


Audit Trail by Design

An audit trail should provide evidence of what was calculated, from which inputs, under which rules, and by which software version.

A useful result object might look like:

@dataclass
class CalculationProvenance:
    input_hash: str
    regulation_version: str
    calculation_version: str
    computed_at: datetime

The hash can then protect the integrity of a canonical input representation.

But an important distinction must be made:

A SHA-256 hash is an integrity check, not a reversible record of the inputs.

You cannot reconstruct the original voyage or fuel record from the hash.

Instead, the process should be:

Original inputs
      │
      ▼
Canonical representation
      │
      ▼
SHA-256 hash
      │
      ▼
Stored with calculation result

When the result is later reviewed:

Stored original inputs
        │
        ▼
Same canonicalization
        │
        ▼
Recalculate SHA-256
        │
        ▼
Compare with stored hash

A matching hash demonstrates that the canonicalized inputs are unchanged.

It does not, by itself, demonstrate that the calculation is legally correct.

That distinction should be explicit in all compliance-related documentation.


What an Auditable Result Should Contain

For a production implementation, a result should ideally carry:

Result
├── calculation_id
├── vessel identity
├── voyage / reporting period
├── input dataset identifier
├── canonical input hash
├── regulatory framework
├── regulatory version / effective date
├── software version
├── calculation method
├── emission factors used
├── intermediate calculation values
├── final result
├── rounding policy
└── calculation timestamp

For EU ETS, that might include the applicable geographical coverage and phase-in treatment.

For FuelEU, it should identify the annual energy/GHG-intensity methodology and compliance mechanisms used.

For CII, it should identify the relevant ship category, annual calculation, reference/reduction framework and rating methodology.

This is much closer to an actual audit trail than a single SHA-256 field.


Charterparty Allocation: Keep Contract and Regulation Separate

Carbon-compliance regulation determines the obligation.

The charterparty determines how the commercial parties may allocate that cost between themselves.

Those are different questions.

The package can therefore provide useful contractual scenarios for instruments such as BIMCO clauses and other agreed allocation provisions.

But the software should record the specific contractual basis for the calculation.

For example:

contract_type = time_charter
clause = <identified clause/version>
amendments = <identified amendments>
off_hire_treatment = <specified treatment>
allocation_method = <specified method>

The engine should never imply that a regulatory authority determines the contractual split between owner and charterer.

That split is a matter of the contract and applicable law.

The value of the calculator is that it makes the contractual assumptions explicit and quantifies their financial consequences.


Commercial Case

For Shipowners and Fleet Operators

The cost of an incorrect EU ETS calculation can be asymmetric.

An overestimate can tie up working capital through unnecessary allowance procurement.

An underestimate can result in additional cost, compliance exposure, and potentially reputational consequences.

The operational value of a deterministic calculation engine is therefore not simply that it produces a number.

It produces a number whose inputs, assumptions, methodology and calculation version can be inspected.

That is a much stronger proposition than:

“the spreadsheet says €174,384.”


For Charterers and Cargo Intermediaries

Charterers increasingly need reliable emissions information for commercial, contractual and sustainability purposes.

But a carbon number should not be presented as self-authenticating.

A useful output should allow the recipient to answer:

  • Which voyage?
  • Which fuel record?
  • Which quantity?
  • Which emission factor?
  • Which regulatory scope?
  • Which calculation year?
  • Which methodology?
  • Which software version?

The JSON output can provide that machine-readable structure.

The hash can provide input-integrity evidence.

The calculation metadata can provide provenance.

Together, those are substantially more useful than an isolated emissions number.


For Compliance Officers and P&I Clubs

The most valuable feature is often not the calculation itself.

It is the ability to explain the calculation later.

A compliance review may ask:

Why was this voyage assigned this emissions scope?

Which emission factor was used?

Which regulatory version was applicable?

Why was this CII rating generated?

Which historical ratings were considered?

What data produced this FuelEU balance?

A well-designed system should answer those questions from its stored calculation record rather than requiring an operator to reconstruct the result from an old spreadsheet.


Comparing the Alternatives

CapabilitySpreadsheetInternal Tooleuets-calculator
Deterministic arithmeticPossibleUsuallyYes
Regulatory versioningOften manualDependsDesigned in
EU ETS calculationPossibleYesYes
FuelEU calculationComplexDependsModular engine
CII calculationComplexDependsModular engine
Historical CII stateManualDependsEngine capability
Charterparty scenariosManualCustomDedicated engine
Input integrityUsually manualDependsHash/provenance layer
Regulatory provenanceUsually weakDependsExplicit
Multi-voyage aggregationSpreadsheet-dependentUsuallyEngine capability
MRV validationManualDependsRoadmap
External verificationNot inherentNot inherentNot inherent
Regulatory authority determinationNoNoNo

The important comparison is not:

“our calculator is more accurate than Excel.”

Excel can perform extremely accurate arithmetic.

The stronger proposition is:

a domain-specific calculation engine can make the regulatory assumptions, calculation versions, data lineage and tests explicit.

That is what makes it operationally valuable.


Quick Start

# 1. Install
pip install -e .

# 2. Run an EU ETS scenario
euets-calc ets \
  --imo 9456789 \
  --voyage-id V001 \
  --fuel-type VLSFO \
  --quantity 800 \
  --phase-in-year 2025 \
  --eua-price 85

# 3. Run a FuelEU calculation
euets-calc fuel_eu \
  --imo 9456789 \
  --voyage-id V001 \
  --fuel-type VLSFO \
  --quantity 800 \
  --compliance-year 2030

# 4. Calculate an annual CII scenario
euets-calc cii \
  --imo 9456789 \
  --vessel-type Container \
  --co2 5000 \
  --cargo-capacity 10000 \
  --distance 50000 \
  --size medium

# 5. Run the test suite
python -m pytest tests/ -q

These commands should be understood as calculation examples, not as a substitute for the complete regulatory data and verification workflow required for an actual compliance submission.


What’s Next

The next stage of the project is not simply adding more formulas but strengthening the regulatory data model.

Regulatory versioning

Every regulatory parameter should have:

  • source;
  • effective date;
  • superseded date where applicable;
  • jurisdiction;
  • regulation/resolution identifier;
  • implementation notes;
  • tests.

MRV data validation

Operational data should be checked before calculation.

For example:

Fuel delivery record
        ↓
Consumption record
        ↓
Voyage record
        ↓
Consistency checks
        ↓
Calculation dataset

The calculator should distinguish:

calculated from supplied data

from

validated against an authoritative record.

Annual aggregation

EU ETS, FuelEU and CII all require period-aware aggregation, although the relevant periods and methodologies differ.

The system should therefore support annual and reporting-period datasets rather than treating every calculation as an isolated voyage.

Current CII methodology

The CII engine should be maintained against the latest applicable IMO resolutions and guidelines rather than treating a historical resolution as the permanent specification.

IMO’s own current documentation confirms that the CII/EEXI short-term measures are under continuing review.

FuelEU pooling and compliance mechanisms

Pooling, banking and borrowing should be implemented as explicit regulatory workflows with their applicable constraints, rather than generic arithmetic operations.

Independent test fixtures

The strongest test suite is not one containing hundreds of arbitrary assertions.

It is one containing:

  • primary-source regulatory examples;
  • boundary cases;
  • unit-conversion cases;
  • year-transition cases;
  • voyage-scope cases;
  • ship-type cases;
  • historical CII sequences;
  • FuelEU compliance-balance cases;
  • regression fixtures for amended regulations.

The Compliance Stack

The mature architecture ultimately looks like this:

                    ┌────────────────────────┐
                    │ Primary Regulations    │
                    │ EU / IMO sources       │
                    └───────────┬────────────┘
                                │
                                ▼
                    ┌────────────────────────┐
                    │ Regulatory Configuration│
                    │ versions / dates / rules│
                    └───────────┬────────────┘
                                │
                                ▼
┌────────────────┐    ┌────────────────────────┐
│ Operational    │───▶│ Canonical Data Model   │
│ Records        │    │ voyage / fuel / vessel │
└────────────────┘    └───────────┬────────────┘
                                  │
               ┌──────────────────┼──────────────────┐
               ▼                  ▼                  ▼
        ┌────────────┐     ┌────────────┐     ┌────────────┐
        │  EU ETS    │     │  FuelEU    │     │    CII     │
        │   Engine   │     │   Engine   │     │   Engine   │
        └─────┬──────┘     └─────┬──────┘     └─────┬──────┘
              │                  │                  │
              ▼                  ▼                  ▼
        ETS result         FuelEU balance       CII result
              │                  │                  │
              └──────────────────┼──────────────────┘
                                 ▼
                       ┌──────────────────┐
                       │ Provenance Layer │
                       │ hashes / versions│
                       │ inputs / outputs │
                       └──────────────────┘

That is the real opportunity for software.

Not one giant “carbon calculator.”

A regulatory calculation system with independent engines, shared operational data, explicit assumptions, versioned rules, and reproducible results.


The Bottom Line

Maritime carbon compliance is no longer a future problem.

EU ETS is already operating for maritime transport. FuelEU Maritime is already in force. IMO’s CII requirements are already part of the operational framework for applicable ships. The European and IMO regimes also continue to evolve, which means software that treats regulatory constants as permanent will eventually become wrong.

The software challenge is therefore larger than getting multiplication and division right.

A credible compliance calculation system needs to:

  1. Model the regulatory scope correctly.
  2. Keep EU ETS, FuelEU and CII methodologies separate.
  3. Use explicit, versioned regulatory parameters.
  4. Track the distinction between voyage data and annual compliance periods.
  5. Represent historical state where the regulation requires it.
  6. Treat fuel classification and emission factors as governed data.
  7. Keep contractual cost allocation separate from regulatory obligations.
  8. Provide deterministic calculations and explicit rounding.
  9. Maintain input and calculation provenance.
  10. Use hashes as integrity controls—not as a substitute for an audit trail.
  11. Test implementation against primary regulatory sources and boundary conditions.
  12. Make clear what the software calculates and what remains subject to verification, administration, or legal interpretation.

That’s the standard a maritime compliance calculator should aim for.

The product does not need to pretend to be an ERP, a SaaS platform, a verifier, or a regulator.

It needs to be something more specific:

a transparent, versioned, testable calculation engine for maritime carbon compliance.

Precise enough for operations.

Structured enough for audit.

Explicit enough for engineering.

And cautious enough not to confuse a software calculation with a regulatory determination.


MIT Licensed. Python ≥ 3.10. The examples above illustrate calculation workflows; production compliance use requires complete regulatory inputs, applicable data-validation processes, and appropriate verification.