Conversation
lecfab
left a comment
There was a problem hiding this comment.
Thanks for all the dusting and testing that it takes to revive the permit trading!
I left comments here and there, mainly about aesthetics and documentation.
| cm_pemittraderatio "Percentage of restricted permit trading" | ||
| ; | ||
| cm_pemittraderatio = 0.2; !! def = 0.2 | ||
| *' |
There was a problem hiding this comment.
I find the existing names of "permit trades scenarios" a little confusing, in the sense that we would always need to refer to the main.gms to understand what they mean. The big undertaking of reactivating permit trade is possibly a good opportunity to simplify that. Two suggestions (either/or):
- simpler one: rename the "no permit trade" to
cm_permittradescen = 0 - nicer one: remove
cm_permittradescen, because it is redundant withcm_pemittraderatio(0% for no trade, 100% for full trade, and whatever in-between for limited trade)
| loop(ttot$(ttot.val ge 2005), | ||
| ***this is a 30$/tCo2eq in 2020 trajectory: | ||
| pm_pvp(ttot,"perm") = 0.11*1.05**(ttot.val-2020) * pm_pvp(ttot,"good"); | ||
| pm_pvp(ttot,"perm") = 0.18*1.05**(ttot.val-2020) * pm_pvp(ttot,"good"); |
There was a problem hiding this comment.
what does this change mean? can you add a comment explaining this number and the whole formula?
Is there a parameter that we can use instead of hard-coded 1.05 @fpiontek @johanneskoch94? I believe in some other places it was decided to use 1.045 instead (but I can't find where, pm_prtp is usually only 1.015)
There was a problem hiding this comment.
Isn't it just the initial guess for the permit price trajectory if no permit price exists in the input gdx?
Shouldn't we adjust the comment above to indicate " ~49$/tCO2eq" instead?
It is an increase in price level expected to reflect that we are moving more towards overshoot scenarios with end of period prices expected to be high?
| *' * (2): no permit trade (only domestic mitigation) | ||
| *' * (3): limited trade (certain percentage of regional allowances) | ||
| *' for limited trade use cm_pemittradefinalyr to set the final year until permit trading is allowed | ||
| *' with cm_pemittraderatio set the percentage of allowed trade |
There was a problem hiding this comment.
see comment for main.gms
https://github.com/remindmodel/remind/pull/2285/changes#r2799231804
| vm_Mport.up(t,regi,"perm")$(t.val gt cm_pemittradefinalyr)=0; | ||
| vm_Mport.up(t,regi,"perm")$(t.val le 2025)=0; | ||
| vm_Mport.lo(t,regi,"perm") = 0; | ||
| ); |
There was a problem hiding this comment.
What happens when cm_permittradescen is 1?
Also, should the cap be defined by gross emissions rather than abs(p41_co2eq(t,regi))?
Visual suggestions:
- disactivate
+ deactivate
- cm_pemittradefinalyr cm_pemittraderatio
+ cm_pemitTradeFinalYr cm_pemitTradeRatio
- ...)=0
+ ...) = 0
- vm_Xport.up(t,regi,"perm")$(t.val le cm_pemittradefinalyr)=abs(cm_pemittraderatio*(p41_co2eq(t,regi)));
- vm_Xport.up(t,regi,"perm")$(t.val gt cm_pemittradefinalyr)=0;
- vm_Xport.up(t,regi,"perm")$(t.val le 2025)=0;
- vm_Xport.lo(t,regi,"perm") = 0;
+ vm_Xport.fx(t,regi,"perm") = 0;
+ vm_Xport.up(t,regi,"perm") $ (t.val > 2025 and t.val <= cm_pemitTradeFinalYr) = cm_pemitTradeRatio * abs(p41_co2eq(t,regi));| *** initialization of pm_shPermit | ||
| pm_shPerm(t,regi) = p41_co2eq(t,regi)/sum(regi2, p41_co2eq(t,regi2)); | ||
| pm_emicapglob(t) = sum(regi, p41_co2eq(t,regi)); | ||
|
|
There was a problem hiding this comment.
Can you give more explanations about what is loaded, and what the ref and bau runs will mean in the calculation of permit allowances?
Also, I'm a bit worried about the shPerm values when a region has negative emissions (in which case I suppose p41_co2eq is negative).
Visual suggestion to avoid calculating the same thing twice:
- pm_shPerm(t,regi) = p41_co2eq(t,regi)/sum(regi2, p41_co2eq(t,regi2));
- pm_emicapglob(t) = sum(regi, p41_co2eq(t,regi));
+ pm_emicapglob(t) = sum(regi, p41_co2eq(t,regi));
+ pm_shPerm(t,regi) = p41_co2eq(t,regi) / pm_emicapglob(t);
benjaminpeeters
left a comment
There was a problem hiding this comment.
Hey @RahelMA
Thanks for the PR.
Added just a few comments from my side, notably on the changes for etaSL.
Not sure this is useful. Hope it is.
I just have another (small) question:
why cm_pemittradefinalyr and cm_pemittraderatio instead of cm_permittradefinalyr and cm_permittraderatio (with an 'r' in 'permit')?
| p80_etaST(tradePe) = 0.3; | ||
| p80_etaST("good") = 0.25; | ||
| p80_etaST("perm") = 0.3; | ||
| p80_etaST("perm") = 0.8; |
There was a problem hiding this comment.
As far as I understand these p.._etaST/LT haven't been changed since the codebase was open-sourced in December 2019 with the explicit indication "These parameters are pretty sensitive" :)
The permit market also does not "benefit" from the adaptive convergence boosting mechanism (the 4x/8x/16x escalation after iterations 15/20/25) -- only applies to tradePe and good if I'm not wrong (see https://github.com/remindmodel/remind/blob/develop/modules/80_optimization/nash/postsolve.gms#L139C1-L173C19).
I wonder:
- what motivate to such a big shift (from 0.3 to 0.8)?
- why
p80_etaST("pebiolc") = 0.8;was already fixed to 0.8 back then? @LaviniaBaumstark - have we try the "adaptative boosting"? wouldn't it be more consistent with the rest of the code? Are there good reasons to treat "perm" differently in that regard (e.g., much smaller fraction of the world exchanges wrt "good"? "pebiolc" does seem to have this boost as well)
- don't we need to be even more strict on
p80_etaSAfor "perm" given the fact that the inter iteration adjustment cost parameter is much lower than for other goods (https://github.com/remindmodel/remind/blob/develop/modules/80_optimization/nash/datainput.gms#L45-L48) and therefore has more risk of oscillation? (not sure) Likewise, wouldn't it lead to better convergence (less oscillation while adjustment) to decrease the adjustment cost even further to not be so aggressive aboutp80_etaST? In other words, instead of forcing the market with heavy-handed price corrections (high etaST), why not make the planners more responsive to prices (lower etaAdj) so the market clears more?
| *** | AGPL-3.0, you are granted additional permissions described in the | ||
| *** | REMIND License Exception, version 1.0 (see LICENSE file). | ||
| *** | Contact: remind@pik-potsdam.de | ||
| *** SOF ./modules/41_emicapregi/AbilityToPay/bounds.gms |
There was a problem hiding this comment.
new files reference AbilityToPay instead of TradingOnRef
| p41_co2eq(t, regi) = p41_co2eq_in(t,regi,"co2"); | ||
|
|
There was a problem hiding this comment.
Is it used anywhere or come from the copy paste from AbilityToPay?
| p80_surplusMaxTolerance(tradePe) = 2* 1.5 * sm_EJ_2_TWa; !! convert EJ/yr into internal unit TWa | ||
| p80_surplusMaxTolerance("good") = 2* 100/1000; !! in internal unit, trillion Dollar | ||
| p80_surplusMaxTolerance("perm") = 2* 300 * 12/44 / 1000; !! convert MtCO2eq into internal unit GtC | ||
| p80_surplusMaxTolerance("perm") = 3* 300 * 12/44 / 1000; !! convert MtCO2eq into internal unit GtC |
There was a problem hiding this comment.
What is the actual relative residual permit surplus at convergence in the test runs? Could you share the p80_surplusMaxRel values? do the iterations converge below the tolerance, or does it tend to stay blocked close to it?
| loop(ttot$(ttot.val ge 2005), | ||
| ***this is a 30$/tCo2eq in 2020 trajectory: | ||
| pm_pvp(ttot,"perm") = 0.11*1.05**(ttot.val-2020) * pm_pvp(ttot,"good"); | ||
| pm_pvp(ttot,"perm") = 0.18*1.05**(ttot.val-2020) * pm_pvp(ttot,"good"); |
There was a problem hiding this comment.
Isn't it just the initial guess for the permit price trajectory if no permit price exists in the input gdx?
Shouldn't we adjust the comment above to indicate " ~49$/tCO2eq" instead?
It is an increase in price level expected to reflect that we are moving more towards overshoot scenarios with end of period prices expected to be high?
Purpose of this PR
This PR tries to reactivate permit trading ;)
With the new realization
TradingOnRefin41_emicapregi, a reference run is used to allocate emission allowances for each region and timestep.Overall, there are three different types of permit trading:
(1): full permit trade (no restrictions)
(2): no permit trade (only domestic mitigation)
(3): limited trade (certain percentage of regional allowances)
for limited trade use
cm_pemittradefinalyrto set the final year until permit trading is allowedwith
cm_pemittraderatioset the percentage of allowed tradeIn these exemplary runs, I used 20% of permit allocation until 2060 and 2100:
Please note that I increased the surplus tolerance to also allow more aggressive trade patters like full trading or with a very short time frame. Honestly, it's hard for me to judge if it is a reasonable scale:
p80_surplusMaxTolerance("perm") = 2* 300 * 12/44 / 1000; to p80_surplusMaxTolerance("perm") = 3* 300 * 12/44 / 1000;
@LaviniaBaumstark what do you think?
Type of change
Indicate the items relevant for your PR by replacing ◻️ with ☑️.
Do not delete any lines. This makes it easier to understand which areas are affected by your changes and which are not.
Parts concerned
Impact
Checklist
Do not delete any line. Leave unfinished elements unchecked so others know how far along you are.
In the end all checkboxes must be ticked before you can merge.
make test) after my final commit and all tests pass (FAIL 0)remind2if and where it was neededforbiddenColumnNamesin readCheckScenarioConfig.R in case the PR leads to deprecated switchesCHANGELOG.mdcorrectly (added, changed, fixed, removed, input data/calibration)Further information (optional)
/p/tmp/rahelma/Committed/Equity/permTrading/p/tmp/rahelma/Committed/Equity/permTrading/compScen-tradingScen-2026-02-10_20.52.00-H12.pdf