Emission trading

Back to general structure

By default, every region has to pay for their own emission reductions. However, emission trading is a mechanism to allow regions to trade emission allowances with each other. This way, regions can pay for reductions in other regions if it is cheaper than reducing their own emissions or when following an effort-sharing regime.

The emission trading module can be chosen using the parameter emissiontrade module.

Note that emission trading is most often used in combination with an effort-sharing module.

Usage:

params = load_params()
params["model"]["emissiontrade module"] = "notrade"
model = MIMOSA(params)

Without emission trading, the import/export of emission reductions and mitigation costs is always zero:

\[ \text{import/export mitigation cost balance}_{t,r} = 0 \]

This means that the mitigation costs and the area under the MAC are exactly the same for each region (see Mitigation costs).

Source code in mimosa/components/emissiontrade/notrade.py
def get_constraints(m: AbstractModel) -> Sequence[GeneralConstraint]:
    """
    Without emission trading, the import/export of emission reductions and mitigation costs is always zero:

    $$
    \\text{import/export mitigation cost balance}_{t,r} = 0
    $$

    This means that the mitigation costs and the area under the MAC are exactly the same for each region (see [Mitigation costs](mitigation.md#mitigation-costs)).
    """
    constraints = []  # No constraints here

    m.import_export_emission_reduction_balance = Param(
        m.t, m.regions, units=quant.unit("emissionsrate_unit"), initialize=0
    )
    m.import_export_mitigation_cost_balance = Param(
        m.t, m.regions, units=quant.unit("currency_unit"), initialize=0
    )

    return constraints

Usage:

params = load_params()
params["model"]["emissiontrade module"] = "emissiontrade"
model = MIMOSA(params)

In MIMOSA, every region can reduce its own emissions. The price for this is determined by the area under the MAC (see Mitigation). On top of that, regions can trade emission reductions with each other. Regions can pay other regions to reduce their emissions, or receive payments for reducing their own emissions.

The financial transfers for this are captured in the variable \(\text{import/export mitigation cost balance}_{t,r}\). For every timestep, the sum of these transfers should be zero:

\[ \sum_r \text{import/export mitigation cost balance}_{t,r} = 0 \]

All emissions are traded at the global carbon price. Therefore, the financial flows (mitigation cost balance) is translated into emission flows (import/export emission reduction balance) using the global carbon price:

\[ \text{import/export emission reduction balance}_{t,r} = \frac{\text{import/export mitigation cost balance}_{t,r}}{\text{global carbon price}_{t}}, \]

where the global carbon price is the population weighted average of the regional carbon prices:

\[ \text{global carbon price}_{t} = \frac{\sum_r \text{carbon price}_{t,r} \cdot \text{population}_{t,r}}{\sum_r \text{population}_{t,r}}. \]

Finally, the emission reductions paid for by a region are calculated as the physical reductions in the region plus the import/export emission reduction balance:

\[ \text{paid for emission reductions}_{t,r} = \text{regional emission reduction}_{t,r} + \text{import/export emission reduction balance}_{t,r}. \]
Source code in mimosa/components/emissiontrade/emissiontrade.py
def get_constraints(m: AbstractModel) -> Sequence[GeneralConstraint]:
    """
    In MIMOSA, every region can reduce its own emissions. The price for this is determined
    by the area under the MAC (see [Mitigation](mitigation.md#mitigation-costs)). On top of that,
    regions can trade emission reductions with each other. Regions can pay other regions to reduce
    their emissions, or receive payments for reducing their own emissions.

    The financial transfers for
    this are captured in the variable $\\text{import/export mitigation cost balance}_{t,r}$. For every timestep,
    the sum of these transfers should be zero:

    $$
    \\sum_r \\text{import/export mitigation cost balance}_{t,r} = 0
    $$

    All emissions are traded at the global carbon price. Therefore, the financial flows (mitigation cost balance) is
    translated into emission flows (import/export emission reduction balance) using the global carbon price:

    $$
    \\text{import/export emission reduction balance}_{t,r} = \\frac{\\text{import/export mitigation cost balance}_{t,r}}{\\text{global carbon price}_{t}},
    $$

    where the global carbon price is the population weighted average of the regional carbon prices:

    $$
    \\text{global carbon price}_{t} = \\frac{\\sum_r \\text{carbon price}_{t,r} \\cdot \\text{population}_{t,r}}{\\sum_r \\text{population}_{t,r}}.
    $$

    Finally, the emission reductions paid for by a region are calculated as the physical reductions in the region plus the
    import/export emission reduction balance:

    $$
    \\text{paid for emission reductions}_{t,r} = \\text{regional emission reduction}_{t,r} + \\text{import/export emission reduction balance}_{t,r}.
    $$



    """
    constraints = []

    m.global_carbonprice = Var(m.t)

    # Emissions are traded at the global carbon price
    constraints.extend(
        [
            # Constraint that sets the global carbon price to the average of the regional carbon prices:
            GlobalConstraint(
                lambda m, t: m.global_carbonprice[t]
                == sum(m.carbonprice[t, r] * m.population[t, r] for r in m.regions)
                / sum(m.population[t, r] for r in m.regions),
                "global_carbonprice",
            ),
        ]
    )

    ## Extra reporting variables:

    m.paid_for_emission_reductions = Var(
        m.t, m.regions, units=quant.unit("emissionsrate_unit")
    )
    m.regional_emission_allowances = Var(
        m.t, m.regions, units=quant.unit("emissionsrate_unit")
    )
    m.import_export_emission_reduction_balance = Var(
        m.t, m.regions, units=quant.unit("emissionsrate_unit")
    )
    m.import_export_mitigation_cost_balance = Var(
        m.t, m.regions, units=quant.unit("currency_unit")
    )
    constraints.extend(
        [
            GlobalConstraint(
                lambda m, t: sum(
                    m.import_export_mitigation_cost_balance[t, r] for r in m.regions
                )
                == 0.0,
                "sum_mitigation_equals_sum_area_under_mac",
            ),
            # Constraint: from import/export mitigation costs to import/export of emissions using the global carbon price
            RegionalConstraint(
                lambda m, t, r: (
                    m.import_export_emission_reduction_balance[t, r]
                    == m.import_export_mitigation_cost_balance[t, r]
                    / soft_min(m.global_carbonprice[t])
                    if t > 0
                    else Constraint.Skip
                ),
                "import_export_emission_reduction_balance",
            ),
            # Constraint: paid for emission reductions
            RegionalConstraint(
                lambda m, t, r: (
                    m.paid_for_emission_reductions[t, r]
                    == (
                        m.regional_emission_reduction[t, r]
                        + m.import_export_emission_reduction_balance[t, r]
                    )
                    if t > 0
                    else Constraint.Skip
                ),
                "paid_for_emission_reductions",
            ),
            # Constraint: regional emission allowances, equal to baseline minus paid for emission reductions
            RegionalConstraint(
                lambda m, t, r: (
                    m.regional_emission_allowances[t, r]
                    == m.baseline[t, r] - m.paid_for_emission_reductions[t, r]
                    if t > 0
                    else Constraint.Skip
                )
            ),
        ]
    )

    return constraints