From fcfefffa7492e1852899132bfe89baef7e0b1990 Mon Sep 17 00:00:00 2001
From: Bart Arendarczyk <s1924442@ed.ac.uk>
Date: Sat, 1 Apr 2023 14:50:06 +0100
Subject: [PATCH] Improved handling of trade constraints and price adjustment.

---
 GAMS/IntExtOpt.gms                            |  32 +-
 data/price_caps.csv                           |  26 +-
 data/wood_demand_adj.csv                      | 363 ++++++++++++++++++
 src/ac/ed/lurg/ModelConfig.java               |  21 +-
 src/ac/ed/lurg/country/CountryAgent.java      |  38 +-
 src/ac/ed/lurg/country/GlobalPrice.java       |  62 +--
 src/ac/ed/lurg/country/TradeConstraint.java   |  10 +
 .../country/gams/GamsLocationOptimiser.java   |  10 +-
 src/ac/ed/lurg/landuse/WoodUsageData.java     |   4 +
 src/ac/ed/lurg/types/CropType.java            |  20 +-
 src/ac/ed/lurg/yield/YieldResponsesItem.java  |   2 +-
 11 files changed, 465 insertions(+), 123 deletions(-)
 create mode 100644 data/wood_demand_adj.csv

diff --git a/GAMS/IntExtOpt.gms b/GAMS/IntExtOpt.gms
index f487da0a..0b41b15f 100644
--- a/GAMS/IntExtOpt.gms
+++ b/GAMS/IntExtOpt.gms
@@ -70,7 +70,7 @@
  SCALAR maxGrossLccRate                      max rate of gross land cover change;
  SCALAR maxFertChange                        max increase in total fertilizer use;
  SCALAR maxIrrigChange                       max increase in total irrigation use;
- SCALAR tradeAdjustmentCostRate
+ SCALAR tradeAdjustmentCostRate;
 
  SCALAR forestManagementCost    cost $1000 per ha;
  SCALAR vegClearingCostRate     cost of clearing vegetation $1000 per tC;
@@ -122,9 +122,12 @@ $gdxin
  baseCost('pasture') = 0.04;
  otherIntCost('pasture') = 0.8 + otherICost;
  
- PARAMETER animalProdCost(animal);
- animalProdCost('ruminants') = 0.28;
- animalProdCost('monogastrics') = 0.24;
+ PARAMETER animalProdCost(animal)
+          /   ruminants       0.20
+              monogastrics    0.14  /;
+
+ PARAMETER previousNetImport(import_types);
+ previousNetImport(import_types) = previousImportAmount(import_types) - previousExportAmount(import_types);
  
 
  VARIABLES
@@ -140,6 +143,7 @@ $gdxin
        importAmount(all_types)            imports of crops and meat - Mt
        exportAmount(all_types)            exports of crops and meat - Mt
        animalProd(animal)                 animal production
+       netImportAmount(import_types)
        tradeAdjustmentCost(import_types)
        
        totalFeedDM                        total feed dry matter
@@ -153,7 +157,6 @@ $gdxin
        forestryCost(location)               total cost in 1000$
 
        carbonCredits(location)
-       totalLandValue
 *       A                                  "artificial variable for debugging https://www.gams.com/blog/2017/07/misbehaving-model-infeasible/"
        total_cost                         total cost of domestic supply including net imports;
 
@@ -184,6 +187,7 @@ $gdxin
        RUM_PROD_CALC                                  ruminants production
        MON_PROD_CALC                                  monogastrics production
 
+       NET_IMPORT_CALC(import_types)
        MAX_NET_IMPORT_CONSTRAINT(import_types)           constraint on max net imports
        MIN_NET_IMPORT_CONSTRAINT(import_types)           constraint on min net imports
        PASTURE_IMPORT_CONSTRAINT                        constraint to not import pasture
@@ -284,7 +288,7 @@ $gdxin
                                                                      landCoverChange(land_cover_before, land_cover_after, location) * conversionCost(land_cover_before, land_cover_after, location));
                                                                      
 * MIN_LAND_COVER_AREA_CONSTRAINT(land_cover, location) .. landCoverArea(land_cover, location) =G= minLandCoverArea(land_cover, location);
- 
+
 ************* Forestry ***********************************
  
  WOOD_YIELD_CALC(location) .. woodYieldRota(location) =E= woodYieldMax(location) * (1 - exp(-woodYieldParam(location) / rotationIntensity(location)));
@@ -302,8 +306,8 @@ $gdxin
                                                             
  FORESTRY_COST_CALC(location) .. forestryCost(location) =E= sum(managed_forest, landCoverArea(managed_forest, location) * forestBaseCost(managed_forest))
                                                             + forestManagementCost * rotationIntensity(location) * landCoverArea('timberForest', location)
-                                                            + sum(land_cover$[not sameAs(land_cover, 'carbonForest')], landCoverChange(land_cover, 'carbonForest', location) * forestManagementCost);
-*                                                            + sum(wood_type, 0.005 * (exp((exportAmount(wood_type) - previousExportAmount(wood_type))) - 1) * exportAmount(wood_type));
+                                                            + sum(land_cover$[not sameAs(land_cover, 'carbonForest')], landCoverChange(land_cover, 'carbonForest', location) * forestManagementCost)
+                                                            + woodSupply(location) * vegClearingCostRate;
 
 *********** Carbon ***********************************
                                        
@@ -315,13 +319,15 @@ $gdxin
 
 *************** Trade *******************************
 
- MAX_NET_IMPORT_CONSTRAINT(import_types) .. importAmount(import_types) - exportAmount(import_types) =L= maxNetImport(import_types);
- MIN_NET_IMPORT_CONSTRAINT(import_types) .. importAmount(import_types) - exportAmount(import_types) =G= minNetImport(import_types);
+ NET_IMPORT_CALC(import_types) .. netImportAmount(import_types) =E= importAmount(import_types) - exportAmount(import_types);
+
+ MAX_NET_IMPORT_CONSTRAINT(import_types) .. netImportAmount(import_types) =L= maxNetImport(import_types);
+ MIN_NET_IMPORT_CONSTRAINT(import_types) .. netImportAmount(import_types) =G= minNetImport(import_types);
  
  PASTURE_IMPORT_CONSTRAINT .. importAmount('pasture') =E= 0;
  PASTURE_EXPORT_CONSTRAINT .. exportAmount('pasture') =E= 0;
- 
- TRADE_ADJUSTMENT_COST_CALC(import_types) .. tradeAdjustmentCost(import_types) =E= tradeAdjustmentCostRate * power((importAmount(import_types) - exportAmount(import_types)) - (previousImportAmount(import_types) - previousExportAmount(import_types)), 2);
+
+ TRADE_ADJUSTMENT_COST_CALC(import_types) .. tradeAdjustmentCost(import_types) =E= power(netImportAmount(import_types) - previousNetImport(import_types), 2) * tradeAdjustmentCostRate;
 
 ************ Total cost ******************************
 
@@ -367,7 +373,6 @@ $gdxin
  parameter totalProdCost(all_types);
  parameter totalArea(crop);
  parameter totalCropland(location);
- parameter netImportAmount(all_types);
  parameter netImportCost(all_types);
  parameter feedCostRate(feed_crop);
  parameter productionShock(all_types);
@@ -392,7 +397,6 @@ $gdxin
  totalProdCost('ruminants') = sum(feed_crop, ruminantFeed.l(feed_crop) * feedCostRate(feed_crop)) + animalProd.l('ruminants') * animalProdCost('ruminants');
  totalProdCost('monogastrics') = sum(feed_crop, monogastricFeed.l(feed_crop) * feedCostRate(feed_crop)) + animalProd.l('monogastrics') * animalProdCost('monogastrics');
 
- netImportAmount(import_types) = importAmount.l(import_types) - exportAmount.l(import_types);
  netImportCost(import_types) = importAmount.l(import_types) * importPrices(import_types) - exportAmount.l(import_types) * exportPrices(import_types);
  
  netCarbonCredits = SUM(location, carbonCredits.L(location));
diff --git a/data/price_caps.csv b/data/price_caps.csv
index af8165a7..7bc18965 100644
--- a/data/price_caps.csv
+++ b/data/price_caps.csv
@@ -1,14 +1,14 @@
 Category,Item,MinPrice,MaxPrice
-crop,monogastrics,0.005,1
-crop,ruminants,0.005,1
-crop,wheat,0.005,1
-crop,maize,0.005,1
-crop,rice,0.005,1
-crop,oilcrops,0.005,1
-crop,pulses,0.005,1
-crop,starchyRoots,0.005,1
-crop,fruitveg,0.005,1
-crop,sugar,0.005,1
-crop,energycrops,0.005,1
-wood,wood,0.005,1
-carbon,carbon,0.005,1
+crop,monogastrics,0.0001,5
+crop,ruminants,0.0001,5
+crop,wheat,0.0001,5
+crop,maize,0.0001,5
+crop,rice,0.0001,5
+crop,oilcrops,0.0001,5
+crop,pulses,0.0001,5
+crop,starchyRoots,0.0001,5
+crop,fruitveg,0.0001,5
+crop,sugar,0.0001,5
+crop,energycrops,0.0001,5
+wood,wood,0.0001,5
+carbon,carbon,0.0001,5
\ No newline at end of file
diff --git a/data/wood_demand_adj.csv b/data/wood_demand_adj.csv
new file mode 100644
index 00000000..20b2d76d
--- /dev/null
+++ b/data/wood_demand_adj.csv
@@ -0,0 +1,363 @@
+Iso3,Type,Production,Demand,NetImports
+AFG,roundwood,1.76,1.760609667,0.000609667
+AFG,fuelwood,1.890300667,1.890468667,0.000168
+ALB,roundwood,0.097208333,0.108182667,0.010974333
+ALB,fuelwood,1.028746667,1.017354,-0.011392667
+DZA,roundwood,0.1386,0.178031,0.039431
+DZA,fuelwood,8.686460667,8.686460667,0
+AGO,roundwood,1.25,1.164618333,-0.085381667
+AGO,fuelwood,4.773993,4.773993,0
+ARG,roundwood,13.20259867,13.09079467,-0.111804
+ARG,fuelwood,4.076543667,4.076453667,-9.00E-05
+ARM,roundwood,0.001693667,0.002870333,0.001176667
+ARM,fuelwood,1.546,1.546014,1.40E-05
+AUS,roundwood,32.97932033,28.00568233,-4.973638
+AUS,fuelwood,4.108786,4.033908667,-0.074877333
+AUT,roundwood,13.33730833,22.27463967,8.937331333
+AUT,fuelwood,5.243656,5.679198667,0.435542667
+AZE,roundwood,0.0033,0.004935333,0.001635333
+AZE,fuelwood,0.422,0.422001,1.00E-06
+BHS,roundwood,0.017,0.029723667,0.012723667
+BHS,fuelwood,0.033818667,0.033819,3.33E-07
+BHR,roundwood,0,0.003009667,0.003009667
+BHR,fuelwood,0.007253667,0.007605,0.000351333
+BGD,roundwood,0.217071668,0.302692335,0.085620667
+BGD,fuelwood,13.84515643,13.84502676,-0.000129667
+BRB,roundwood,0.006,0.00703,0.00103
+BRB,fuelwood,0.004742333,0.004742333,0
+BLR,roundwood,15.43957167,14.73271733,-0.706854333
+BLR,fuelwood,11.02323333,10.96296667,-0.060266667
+BEL,roundwood,3.782298866,5.8310872,2.048788333
+BEL,fuelwood,0.769859482,0.885607815,0.115748333
+BLZ,roundwood,0.041,0.047361,0.006361
+BLZ,fuelwood,0.126,0.126,0
+BEN,roundwood,0.384656,0.337515667,-0.047140333
+BEN,fuelwood,6.600257667,6.600257667,0
+BTN,roundwood,0.125168,0.125172,4.00E-06
+BTN,fuelwood,5.236146333,5.236146333,0
+BOL,roundwood,1.315666667,1.303423,-0.012243667
+BOL,fuelwood,2.479089667,2.479089667,0
+BIH,roundwood,2.950468667,2.978938667,0.02847
+BIH,fuelwood,1.531766667,0.73802,-0.793746667
+BWA,roundwood,0.105,0.152695333,0.047695333
+BWA,fuelwood,0.699385667,0.699448333,6.27E-05
+BRA,roundwood,150.6666667,150.1932567,-0.47341
+BRA,fuelwood,122.5866667,122.5699563,-0.016710333
+BRN,roundwood,0.077776667,0.077798667,2.20E-05
+BRN,fuelwood,0.011643667,0.011650667,7.00E-06
+BGR,roundwood,3.516785667,3.284521667,-0.232264
+BGR,fuelwood,2.849241667,2.665237667,-0.184004
+BFA,roundwood,1.171,1.171388,0.000388
+BFA,fuelwood,14.19381233,14.19381233,0
+BDI,roundwood,0.440082908,0.440155241,7.23E-05
+BDI,fuelwood,4.224091784,4.224091784,0
+CPV,roundwood,0,0.000853,0.000853
+CPV,fuelwood,0.186,0.186,0
+KHM,roundwood,0.322,0.292383,-0.029617
+KHM,fuelwood,7.369578667,7.369372,-0.000206667
+CMR,roundwood,3.831865,2.615151333,-1.216713667
+CMR,fuelwood,10.57166567,10.57166567,0
+CAN,roundwood,150.2097817,147.11891,-3.090871667
+CAN,fuelwood,1.486046333,1.411855667,-0.074190667
+CAF,roundwood,0.844713,0.640019667,-0.204693333
+CAF,fuelwood,2,2,0
+TCD,roundwood,0.761,0.760977333,-2.27E-05
+TCD,fuelwood,7.982273,7.982273,0
+CHL,roundwood,46.29762967,46.05308333,-0.244546333
+CHL,fuelwood,16.121789,16.12179167,2.67E-06
+CHN,roundwood,175.5271153,234.379758,58.85264267
+CHN,fuelwood,163.0260283,163.0286893,0.002661
+COL,roundwood,2.666166333,2.589068667,-0.077097667
+COL,fuelwood,6.519973333,6.519968667,-4.67E-06
+COM,roundwood,0.02465,0.024810667,0.000160667
+COM,fuelwood,0.321685667,0.32183,0.000144333
+COG,roundwood,2.369456333,1.468768,-0.900688333
+COG,fuelwood,1.507886667,1.507886667,0
+CRI,roundwood,1.286713667,1.137161333,-0.149552333
+CRI,fuelwood,3.272391667,3.272399667,8.00E-06
+CIV,roundwood,2.4,2.387988333,-0.012011667
+CIV,fuelwood,9.226079,9.226069333,-9.67E-06
+HRV,roundwood,3.131572667,3.009152667,-0.12242
+HRV,fuelwood,2.256533333,1.690524333,-0.566009
+CUB,roundwood,0.611,0.618024,0.007024
+CUB,fuelwood,1.141,1.141,0
+CYP,roundwood,0.002001,0.00609,0.004089
+CYP,fuelwood,0.009947667,0.011530667,0.001583
+CZE,roundwood,12.05542176,3.933860764,-8.121561
+CZE,fuelwood,2.322295074,2.142197407,-0.180097667
+PRK,roundwood,1.5,1.483337,-0.016663
+PRK,fuelwood,6.235740333,6.235727,-1.33E-05
+COD,roundwood,4.611013,4.558086,-0.052927
+COD,fuelwood,85.63231767,85.63231567,-2.00E-06
+DNK,roundwood,1.781,1.698104,-0.082896
+DNK,fuelwood,2.0611,2.135235667,0.074135667
+DJI,roundwood,0,0.000183667,0.000183667
+DJI,fuelwood,0.399619,0.399619,0
+DOM,roundwood,0.078003333,0.122837,0.044833667
+DOM,fuelwood,0.967961333,0.967961333,0
+ECU,roundwood,2.44,2.169531667,-0.270468333
+ECU,fuelwood,5.037486333,5.0375,1.37E-05
+EGY,roundwood,0,0.137141784,0.137141784
+EGY,fuelwood,0,1.524929143,1.524929143
+SLV,roundwood,0.682,0.670865,-0.011135
+SLV,fuelwood,4.133777333,4.133777333,0
+GNQ,roundwood,1.266666667,0.265714,-1.000952667
+GNQ,fuelwood,0.447,0.447,0
+ERI,roundwood,0.022495,0.0225,5.00E-06
+ERI,fuelwood,1.000536,1.000536,0
+EST,roundwood,6.127567537,3.768639203,-2.358928333
+EST,fuelwood,3.899880828,3.646980828,-0.2529
+SWZ,roundwood,0.521415582,0.496981249,-0.024434333
+SWZ,fuelwood,1.025868038,0.456938038,-0.56893
+ETH,roundwood,2.935,2.934981,-1.90E-05
+ETH,fuelwood,111.8815183,111.8815183,0
+FJI,roundwood,0.8,0.798907333,-0.001092667
+FJI,fuelwood,0.037,0.036942,-5.80E-05
+FIN,roundwood,29.48393523,34.23556223,4.751627
+FIN,fuelwood,4.077734732,4.026342065,-0.051392667
+FRA,roundwood,25.50871967,22.70654333,-2.802176333
+FRA,fuelwood,24.41010167,24.06707067,-0.343031
+PYF,roundwood,0.001,0.002688667,0.001688667
+PYF,fuelwood,0.004644,0.004645,1.00E-06
+GAB,roundwood,2.157666667,2.117734667,-0.039932
+GAB,fuelwood,1.07,1.07,0
+GMB,roundwood,0.154166667,0.042185333,-0.111981333
+GMB,fuelwood,0.765960667,0.765960667,0
+GEO,roundwood,0.169483,0.198123333,0.028640333
+GEO,fuelwood,0.405099333,0.397191667,-0.007907667
+DEU,roundwood,46.16455765,48.32213698,2.157579333
+DEU,fuelwood,21.01938124,21.27516358,0.255782333
+GHA,roundwood,2.430555667,2.078253,-0.352302667
+GHA,fuelwood,47.22927,47.226388,-0.002882
+GRC,roundwood,0.479673333,0.495795667,0.016122333
+GRC,fuelwood,1.003137333,1.159827333,0.15669
+GRD,roundwood,0,0.000642667,0.000642667
+GRD,fuelwood,0,0,0
+GTM,roundwood,0.653804,0.626832333,-0.026971667
+GTM,fuelwood,20.908489,20.90847133,-1.77E-05
+GIN,roundwood,0.651,0.642553,-0.008447
+GIN,fuelwood,12.34088267,12.34088267,0
+GNB,roundwood,0.13191,0.125225667,-0.006684333
+GNB,fuelwood,2.882234333,2.882234333,0
+GUY,roundwood,0.311762333,0.187762667,-0.123999667
+GUY,fuelwood,0.823948,0.818361,-0.005587
+HTI,roundwood,0.239,0.240356667,0.001356667
+HTI,fuelwood,2.119133667,2.119133667,0
+HND,roundwood,0.981062,0.972730667,-0.008331333
+HND,fuelwood,8.23591,8.232712667,-0.003197333
+HUN,roundwood,2.930692667,2.613198333,-0.317494333
+HUN,fuelwood,2.776239667,2.751587,-0.024652667
+ISL,roundwood,0.001666667,0.004139,0.002472333
+ISL,fuelwood,0.001333333,0.001227667,-0.000105667
+IND,roundwood,49.517,53.794734,4.277734
+IND,fuelwood,303.339636,303.3447007,0.005064667
+IDN,roundwood,79.38933333,80.205874,0.816540667
+IDN,fuelwood,42.30000967,42.29690033,-0.003109333
+IRN,roundwood,0.416,0.435980667,0.019980667
+IRN,fuelwood,0.03,0.030063667,6.37E-05
+IRQ,roundwood,0.059,0.088999667,0.029999667
+IRQ,fuelwood,0.118,0.118009667,9.67E-06
+IRL,roundwood,3.589333333,3.871886,0.282552667
+IRL,fuelwood,0.212666667,0.223793,0.011126333
+ISR,roundwood,0.025,0.039261667,0.014261667
+ISR,fuelwood,0.002,0.014996,0.012996
+ITA,roundwood,3.982316,6.963112667,2.980796667
+ITA,fuelwood,10.839,11.85788733,1.018887333
+JAM,roundwood,0.152349333,0.156162667,0.003813333
+JAM,fuelwood,0.509008667,0.509008667,0
+JPN,roundwood,23.07933333,25.19033467,2.111001333
+JPN,fuelwood,6.405666667,6.411855,0.006188333
+JOR,roundwood,0.004,0.004826667,0.000826667
+JOR,fuelwood,0.364387,0.364993667,0.000606667
+KAZ,roundwood,0.148333333,0.230896333,0.082563
+KAZ,fuelwood,0.228333333,0.231526667,0.003193333
+KEN,roundwood,1.032,1.02962,-0.00238
+KEN,fuelwood,26.4,26.40000967,9.67E-06
+KWT,roundwood,0,0.007041667,0.007041667
+KWT,fuelwood,0.020447667,0.021229,0.000781333
+KGZ,roundwood,0.00932,0.051386667,0.042066667
+KGZ,fuelwood,0.0366,0.036567,-3.30E-05
+LAO,roundwood,1.432,1.325165,-0.106835
+LAO,fuelwood,5.770353667,5.769886333,-0.000467333
+LVA,roundwood,10.1991231,8.515890435,-1.683232667
+LVA,fuelwood,2.10455698,1.830953647,-0.273603333
+LBN,roundwood,0.00715,0.011868667,0.004718667
+LBN,fuelwood,0.018609,0.019169,0.00056
+LSO,roundwood,0.012666667,0.049391,0.036724333
+LSO,fuelwood,2.139851,2.140261333,0.000410333
+LBR,roundwood,0.46343,0.331720333,-0.131709667
+LBR,fuelwood,9.169455667,9.169455667,0
+LBY,roundwood,0.116,0.130988,0.014988
+LBY,fuelwood,1.041532,1.041601,6.90E-05
+LTU,roundwood,4.95,3.358847667,-1.591152333
+LTU,fuelwood,1.871666667,1.694826667,-0.17684
+LUX,roundwood,0.28300617,0.57429617,0.29129
+LUX,fuelwood,0.063332796,0.076008796,0.012676
+MDG,roundwood,0.17393,0.175286333,0.001356333
+MDG,fuelwood,14.68201467,14.681773,-0.000241667
+MWI,roundwood,1.43,1.433014333,0.003014333
+MWI,fuelwood,5.913169,5.913169,0
+MYS,roundwood,14.49014967,12.75565533,-1.734494333
+MYS,fuelwood,2.455313,2.448034667,-0.007278333
+MDV,roundwood,0,0.003682667,0.003682667
+MDV,fuelwood,0.016437667,0.017669333,0.001231667
+MLI,roundwood,0.817,0.763762,-0.053238
+MLI,fuelwood,5.783094333,5.783094333,0
+MLT,roundwood,0,5.63E-05,5.63E-05
+MLT,fuelwood,0,0.001238,0.001238
+MRT,roundwood,0.032,0.037719333,0.005719333
+MRT,fuelwood,2.168979333,2.168955333,-2.40E-05
+MUS,roundwood,0.000521425,0.026659425,0.026138
+MUS,fuelwood,0.002021237,0.002197237,0.000176
+MEX,roundwood,7.752333333,7.754599667,0.002266333
+MEX,fuelwood,38.605443,38.586746,-0.018697
+MNG,roundwood,0.162,0.164886333,0.002886333
+MNG,fuelwood,0.6,0.600109667,0.000109667
+MNE,roundwood,0.751338333,0.751781333,0.000443
+MNE,fuelwood,0.35662,0.354181333,-0.002438667
+MAR,roundwood,0.298333333,0.424320667,0.125987333
+MAR,fuelwood,6.616582333,6.616612667,3.03E-05
+MOZ,roundwood,1.984,1.282292,-0.701708
+MOZ,fuelwood,16.724,16.72406167,6.17E-05
+MMR,roundwood,4.36,4.326867,-0.033133
+MMR,fuelwood,38.28655733,38.28659667,3.93E-05
+NAM,roundwood,0,0.01365,0.01365
+NAM,fuelwood,1.632811667,1.627289333,-0.005522333
+NPL,roundwood,1.3,1.302659667,0.002659667
+NPL,fuelwood,11.87636667,11.876367,3.33E-07
+NLD,roundwood,0.775764,0.541152,-0.234612
+NLD,fuelwood,2.345233333,2.047625333,-0.297608
+NCL,roundwood,0.0147,0.015176333,0.000476333
+NCL,fuelwood,0.012855333,0.012855333,0
+NZL,roundwood,35.45066667,14.720892,-20.72977467
+NZL,fuelwood,0,8.50E-05,8.50E-05
+NIC,roundwood,0.130104667,0.129353667,-0.000751
+NIC,fuelwood,6.168661667,6.168661667,0
+NER,roundwood,0.701,0.700366333,-0.000633667
+NER,fuelwood,11.65273467,11.65273467,0
+NGA,roundwood,10.022,9.581148333,-0.440851667
+NGA,fuelwood,66.213834,66.21224467,-0.001589333
+MKD,roundwood,0.117,0.158541,0.041541
+MKD,fuelwood,0.672333333,0.687934333,0.015601
+NOR,roundwood,10.78854,7.667534333,-3.121005667
+NOR,fuelwood,1.639671333,1.759432333,0.119761
+OMN,roundwood,0,0.019557667,0.019557667
+OMN,fuelwood,0.048892,0.049096,0.000204
+PAK,roundwood,2.417459011,2.582250678,0.164791667
+PAK,fuelwood,17.5851381,17.58464043,-0.000497667
+PAN,roundwood,0.397696667,0.257536333,-0.140160333
+PAN,fuelwood,1.005105667,1.005105667,0
+PNG,roundwood,4.072,0.501659667,-3.570340333
+PNG,fuelwood,5.533,5.533,0
+PRY,roundwood,4.044,4.029523,-0.014477
+PRY,fuelwood,7.469185,7.469063333,-0.000121667
+PER,roundwood,1.125863333,1.155319,0.029455667
+PER,fuelwood,7.240179,7.240167,-1.20E-05
+PHL,roundwood,3.890466,3.949002667,0.058536667
+PHL,fuelwood,11.489433,11.48549767,-0.003935333
+POL,roundwood,39.87205667,37.152746,-2.719310667
+POL,fuelwood,5.225207,5.079971,-0.145236
+PRT,roundwood,6.470583864,8.02512153,1.554537667
+PRT,fuelwood,0.628597354,0.614416021,-0.014181333
+QAT,roundwood,0,0.001529,0.001529
+QAT,fuelwood,0.005116,0.011,0.005884
+KOR,roundwood,4.272666667,9.583414333,5.310747667
+KOR,fuelwood,0.292333333,0.292653667,0.000320333
+MDA,roundwood,0.045,0.045315333,0.000315333
+MDA,fuelwood,1.219978333,1.219981,2.67E-06
+ROU,roundwood,10.06658567,11.204917,1.138331333
+ROU,fuelwood,5.369443,5.591606333,0.222163333
+RUS,roundwood,206.791394,188.6343767,-18.15701733
+RUS,fuelwood,15.47527233,15.33109267,-0.144179667
+RWA,roundwood,1.013574141,1.016177475,0.002603333
+RWA,fuelwood,4.181663341,4.181663341,0
+LCA,roundwood,0,0.000368667,0.000368667
+LCA,fuelwood,0.009492,0.009492,0
+VCT,roundwood,0,0.000595333,0.000595333
+VCT,fuelwood,0.007106,0.007106,0
+WSM,roundwood,0.0057,0.006466667,0.000766667
+WSM,fuelwood,0.07,0.07,0
+STP,roundwood,0.0272,0.027245,4.50E-05
+STP,fuelwood,0.113544,0.113544,0
+SAU,roundwood,0,0.024284333,0.024284333
+SAU,fuelwood,0.301267667,0.313421667,0.012154
+SEN,roundwood,0.816,0.824499,0.008499
+SEN,fuelwood,5.598048333,5.595732,-0.002316333
+SRB,roundwood,1.514,1.511333333,-0.002666667
+SRB,fuelwood,6.439666667,6.409666667,-0.03
+SLE,roundwood,0.257866667,0.139872667,-0.117994
+SLE,fuelwood,5.927444667,5.927403667,-4.10E-05
+SGP,roundwood,0,0.031815,0.031815
+SGP,fuelwood,0.028732333,0.027356,-0.001376333
+SVK,roundwood,8.735620333,8.021461,-0.714159333
+SVK,fuelwood,0.571453,0.644598667,0.073145667
+SVN,roundwood,3.630870667,1.927916,-1.702954667
+SVN,fuelwood,1.091295333,0.903115667,-0.188179667
+SLB,roundwood,3.202,0.252728333,-2.949271667
+SLB,fuelwood,0.134754,0.134754,0
+SOM,roundwood,0.11,0.110926667,0.000926667
+SOM,fuelwood,15.60759267,15.60759267,0
+ZAF,roundwood,14.99697567,14.45323533,-0.543740333
+ZAF,fuelwood,12.02560733,12.61095567,0.585348333
+SSD,roundwood,0,0,-0.010986
+SSD,fuelwood,4.716333333,4.716333333,0
+ESP,roundwood,15.16807033,14.154257,-1.013813333
+ESP,fuelwood,2.908704333,2.863029667,-0.045674667
+LKA,roundwood,0.7028,0.704197333,0.001397333
+LKA,fuelwood,4.60367,4.60367,0
+SDN,roundwood,1.157,1.142306667,-0.014693333
+SDN,fuelwood,15.50879767,15.50879767,0
+SUR,roundwood,1.006862667,0.518723667,-0.488139
+SUR,fuelwood,0.088,0.088019333,1.93E-05
+SWE,roundwood,46.19464132,53.65073666,7.456095333
+SWE,fuelwood,3.943455967,4.024326967,0.080871
+CHE,roundwood,2.910666667,2.414162333,-0.496504333
+CHE,fuelwood,1.708176667,1.715751,0.007574333
+SYR,roundwood,0.0398,0.048706,0.008906
+SYR,fuelwood,0.034790667,0.034790667,0
+TWN,roundwood,1.459448667,1.900008333,0.440559667
+TWN,fuelwood,0.005495667,0.007134,0.001638333
+TJK,roundwood,0,0.011085667,0.011085667
+TJK,fuelwood,3.674,3.673969333,-3.07E-05
+THA,roundwood,14.6,14.61619333,0.016193333
+THA,fuelwood,18.518049,18.523733,0.005684
+TLS,roundwood,0,0,-1.17E-05
+TLS,fuelwood,0.085032,0.085032,0
+TGO,roundwood,0.206003,0.172215333,-0.033787667
+TGO,fuelwood,4.424,4.423988,-1.20E-05
+TTO,roundwood,0.1668,0.166106333,-0.000693667
+TTO,fuelwood,0.030460667,0.030461,3.33E-07
+TUN,roundwood,0.084519823,0.096815823,0.012296
+TUN,fuelwood,1.003672897,1.003591231,-8.17E-05
+TUR,roundwood,21.54266667,21.58823333,0.045566667
+TUR,fuelwood,5.593666667,5.620589333,0.026922667
+TKM,roundwood,0,0.004609667,0.004609667
+TKM,fuelwood,0.006666667,0.032,0.025333333
+UGA,roundwood,5.33,5.310808333,-0.019191667
+UGA,fuelwood,43.73351467,43.73351467,0
+UKR,roundwood,8.525466667,8.532739,0.007272333
+UKR,fuelwood,10.30696667,9.117434333,-1.189532333
+ARE,roundwood,0,0.081065,0.081065
+ARE,fuelwood,0.018847,0.024242,0.005395
+GBR,roundwood,8.600561,9.039714333,0.439153333
+GBR,fuelwood,2.350933333,2.495227667,0.144294333
+TZA,roundwood,2.838079,2.835825667,-0.002253333
+TZA,fuelwood,24.820354,24.81902333,-0.001330667
+USA,roundwood,385.542306,376.036402,-9.505904
+USA,fuelwood,69.13516433,68.992805,-0.142359333
+URY,roundwood,7.506575953,6.029059619,-1.477516333
+URY,fuelwood,1.415608914,1.415610914,2.00E-06
+UZB,roundwood,0.0092,0.257660333,0.248460333
+UZB,fuelwood,0.020166667,0.020120333,-4.63E-05
+VUT,roundwood,0.038,0.034559667,-0.003440333
+VUT,fuelwood,0.091,0.091,0
+VEN,roundwood,1.317,1.310759333,-0.006240667
+VEN,fuelwood,4.304446,4.304446,0
+VNM,roundwood,36.16875333,38.70161033,2.532857
+VNM,fuelwood,20,19.98639467,-0.013605333
+YEM,roundwood,0.002556667,0.003327,0.000770333
+YEM,fuelwood,0.574145667,0.574783,0.000637333
+ZMB,roundwood,2.674666667,2.629792,-0.044874667
+ZMB,fuelwood,23.033,23.03300133,1.33E-06
+ZWE,roundwood,0.60448,0.585449667,-0.019030333
+ZWE,fuelwood,9.296991667,9.296991667,0
\ No newline at end of file
diff --git a/src/ac/ed/lurg/ModelConfig.java b/src/ac/ed/lurg/ModelConfig.java
index 35e5760c..51f8d80c 100755
--- a/src/ac/ed/lurg/ModelConfig.java
+++ b/src/ac/ed/lurg/ModelConfig.java
@@ -228,7 +228,7 @@ public class ModelConfig {
 	public static final double INITAL_PRICE_MAIZE = getDoubleProperty("INITAL_PRICE_MAIZE", 0.132 * ModelConfig.INITIAL_PRICE_SHIFT);
 	public static final double INITAL_PRICE_RICE = getDoubleProperty("INITAL_PRICE_RICE", 0.142 * ModelConfig.INITIAL_PRICE_SHIFT);
 	public static final double INITAL_PRICE_OILCROPS = getDoubleProperty("INITAL_PRICE_OILCROPS", 0.13 * ModelConfig.INITIAL_PRICE_SHIFT);
-	public static final double INITAL_PRICE_PULSES = getDoubleProperty("INITAL_PRICE_PULSES", 0.3 * ModelConfig.INITIAL_PRICE_SHIFT);
+	public static final double INITAL_PRICE_PULSES = getDoubleProperty("INITAL_PRICE_PULSES", 0.40 * ModelConfig.INITIAL_PRICE_SHIFT);
 	public static final double INITAL_PRICE_STARCHYROOTS = getDoubleProperty("INITAL_PRICE_STARCHYROOTS", 0.07 * ModelConfig.INITIAL_PRICE_SHIFT);
 	public static final double INITAL_PRICE_MONOGASTRICS = getDoubleProperty("INITAL_PRICE_MONOGASTRICS", 0.27 * ModelConfig.INITIAL_PRICE_SHIFT); // value from calibration
 	public static final double INITAL_PRICE_RUMINANTS = getDoubleProperty("INITAL_PRICE_RUMINANTS", 0.25 * ModelConfig.INITIAL_PRICE_SHIFT); // value from calibration
@@ -363,10 +363,9 @@ public class ModelConfig {
 	public static final int BASE_YEAR = getIntProperty("BASE_YEAR", 2019);
 
 	// Import export limits
-	public static final double ANNUAL_MAX_IMPORT_CHANGE = getDoubleProperty("ANNUAL_MAX_IMPORT_CHANGE", 0.05);
+	public static final double ANNUAL_MAX_IMPORT_CHANGE = getDoubleProperty("ANNUAL_MAX_IMPORT_CHANGE", 0.5);
 	public static final double MAX_IMPORT_CHANGE = getDoubleProperty("MAX_IMPORT_CHANGE", ANNUAL_MAX_IMPORT_CHANGE*TIMESTEP_SIZE);
-	public static final double IMPORT_CHANGE_ELASTICITY = getDoubleProperty("IMPORT_CHANGE_ELASTICITY", 3.0); // higher value = steeper trade imbalance adjustment
-	public static final double TRADE_ADJUSTMENT_COST_RATE = getDoubleProperty("TRADE_ADJUSTMENT_COST_RATE", 0.05);
+	public static final double TRADE_ADJUSTMENT_COST_RATE = getDoubleProperty("TRADE_ADJUSTMENT_COST_RATE", 0.02);
 	
 	// Price caps
 	public static final String PRICE_CAP_FILE = DATA_DIR + File.separator + "price_caps.csv";
@@ -426,14 +425,14 @@ public class ModelConfig {
 	public static final boolean RESET_ENERGYCROP_PRICE = getBooleanProperty("RESET_ENERGYCROP_PRICE", true); // Resets price after calibration to avoid problems due to low initial demand
 	//	public static final double BIOENERGY_HEATING_VALUE_GJ_PER_T = getDoubleProperty("BIOENERGY_HEATING_VALUE_GJ_PER_T", 17.5); // GJ per t DM
 
-	public static final double MARKET_LAMBDA = getDoubleProperty("MARKET_LAMBDA", 0.04); // controls international market price adjustment rate
-	public static final double MARKET_DAMPING = getDoubleProperty("MARKET_DAMPING", 1.0); // controls international market price adjustment rate
+	public static final double MARKET_BETA = getDoubleProperty("MARKET_BETA", 0.015); // controls international market price adjustment rate
+	public static final double MARKET_LAMBDA = getDoubleProperty("MARKET_LAMBDA", 0.4); // controls international market price adjustment rate
 
 	public static final String PRICE_UPDATE_METHOD = getProperty("PRICE_UPDATE_METHOD", "StockUseRatio"); // Options: StockUseRatio, MarketImbalance, StockChange
 	public static final double MAX_PRICE_INCREASE = getDoubleProperty("MAX_PRICE_INCREASE", 1.5);
 	public static final double MAX_PRICE_DECREASE = getDoubleProperty("MAX_PRICE_DECREASE", .75);
-	public static final int DEMAND_RECALC_MAX_ITERATIONS = IS_CALIBRATION_RUN ? 0 : getIntProperty("DEMAND_RECALC_MAX_ITERATIONS", 1);  // 0 is original behaviour
-	public static final boolean DEMAND_RECALC_ON_NEGATIVE_STOCK = IS_CALIBRATION_RUN ? false : getBooleanProperty("DEMAND_RECALC_ON_NEGATIVE_STOCK", false); 
+	public static final int DEMAND_RECALC_MAX_ITERATIONS = IS_CALIBRATION_RUN ? 0 : getIntProperty("DEMAND_RECALC_MAX_ITERATIONS", 0);  // 0 is original behaviour
+	public static final boolean DEMAND_RECALC_ON_NEGATIVE_STOCK = IS_CALIBRATION_RUN ? false : getBooleanProperty("DEMAND_RECALC_ON_NEGATIVE_STOCK", false);
 
 	public static final double POPULATION_AGGREG_LIMIT = getDoubleProperty("POPULATION_AGGREG_LIMIT", 30.0);  // in millions, smaller countries are aggregated on a regional basis
 	public static final boolean PREDEFINED_COUNTRY_GROUPING = getBooleanProperty("PREDEFINED_COUNTRY_GROUPING", true);
@@ -451,7 +450,7 @@ public class ModelConfig {
 
 	public static final double IRRIG_COST_SCALE_FACTOR = getDoubleProperty("IRRIG_COST_SCALE_FACTOR", 0.00035);
 	public static final double IRRIG_COST_MULTIPLIER = getDoubleProperty("IRRIG_COST_MULTIPLIER", 1.0);
-	public static final double FERTILISER_COST_PER_T = getDoubleProperty("FERTILISER_COST_PER_T", 1.6); // $500/t, 18% N/t
+	public static final double FERTILISER_COST_PER_T = getDoubleProperty("FERTILISER_COST_PER_T", 1.4); // $500/t, 18% N/t
 	public static final double FERTILISER_MAX_COST = FERTILISER_COST_PER_T * MAX_FERT_AMOUNT/1000;
 
 	public static final double DOMESTIC_PRICE_MARKUP = getDoubleProperty("DOMESTIC_PRICE_MARKUP", 1.0);
@@ -482,7 +481,7 @@ public class ModelConfig {
 	
 	public static final double PASTURE_MAX_IRRIGATION_RATE = getDoubleProperty("DEFAULT_MAX_IRRIGATION_RATE", 50.0); // shouldn't need this but some areas crops don't have a value, but was causing them to be selected
 	public static final int LPJG_TIMESTEP_SIZE = getIntProperty("LPJG_TIMESTEP_SIZE", 5);
-	public static final int LPJ_YEAR_OFFSET = getIntProperty("LPJ_YEAR_OFFSET", -1);;
+	public static final int LPJ_YEAR_OFFSET = getIntProperty("LPJ_YEAR_OFFSET", -1);
 	
 	public static final int NUM_YIELD_CLUSTERS = getIntProperty("NUM_YIELD_CLUSTERS", 5000);
 	public static final long RANDOM_SEED = getIntProperty("RANDOM_SEED", 1974329);  // any number will do
@@ -526,7 +525,7 @@ public class ModelConfig {
 	public static final double VEGETATION_CLEARING_COST = getDoubleProperty("VEGETATION_CLEARING_COST", 0.08); //$1000/tC
 	public static final double FOREST_MANAGEMENT_COST = IS_FORESTRY_ON ? getDoubleProperty("FOREST_MANAGEMENT_COST", 2.5) : 0.0; // establishment, management etc. $1000/ha
 	public static final double FOREST_BASE_COST = getDoubleProperty("FOREST_BASE_COST", 0.3); // $1000/ha
-	public static final double WOOD_TRADE_BARRIER = getDoubleProperty("WOOD_TRADE_BARRIER", 0.2); //$1000/tC
+	public static final double WOOD_TRADE_BARRIER = getDoubleProperty("WOOD_TRADE_BARRIER", 0.3); //$1000/tC
 	public static final double INIT_ROUNDWOOD_PRICE = IS_FORESTRY_ON ? getDoubleProperty("INIT_ROUNDWOOD_PRICE", 0.1) : 0.0; // $1000/tC-eq
 	public static final double INIT_FUELWOOD_PRICE = IS_FORESTRY_ON ? getDoubleProperty("INIT_FUELWOOD_PRICE", 0.08) : 0.0; // $1000/tC-eq
 	public static final int CARBON_WOOD_MAX_TIME = getIntProperty("CARBON_WOOD_MAX_TIME", 160); // upper data limit, years
diff --git a/src/ac/ed/lurg/country/CountryAgent.java b/src/ac/ed/lurg/country/CountryAgent.java
index 2f66cef1..f870f431 100644
--- a/src/ac/ed/lurg/country/CountryAgent.java
+++ b/src/ac/ed/lurg/country/CountryAgent.java
@@ -169,30 +169,13 @@ public class CountryAgent extends AbstractCountryAgent {
 			double changeDown = 0;
 			
 			// max of supply overall, needed for when imports are supplying feed and change is zero to allow for production to replace imports
-			double maxOfProdOrSupply = cropUsage.getProductionExpected() + Math.max(baseTrade, 0);  //max of supply for food
-			double production = cropUsage.getProductionExpected();
-			double netSupply = getCropUsageData().get(crop).getNetSupply();
-			GlobalPrice cropPrice = currentWorldPrices.get(crop);
+			// minimum 1 so trade balance can still change when supply is 0
+			double maxOfProdOrSupply = Math.max(cropUsage.getProductionExpected() + Math.max(baseTrade, 0), 1);
 
 			if (ModelConfig.IS_CALIBRATION_RUN && currentTimestep.getTimestep() <= ModelConfig.END_FIRST_STAGE_CALIBRATION) {
 				changeUp = changeDown = 0;
 			} else {
-				if (crop.isImportedCrop()) {
-					// exporter or not fully reliant on exports. Avoid forcing import reliant countries to reduce imports
-					if (baseTrade < 0 || production > baseTrade) {
-						double tradeImbalanceFract = cropPrice.getTradeImbalanceFraction();
-						// If in danger of stocks becoming negative, shift towards more exports
-						if (cropPrice.isStockCritical()) {
-							baseTrade = baseTrade - Math.abs(baseTrade) * tradeImbalanceFract * 1.1;
-							changeUp = 0;
-						} else {
-							changeUp = maxOfProdOrSupply * ModelConfig.MAX_IMPORT_CHANGE;
-						}
-					} else {
-						changeUp = maxOfProdOrSupply * ModelConfig.MAX_IMPORT_CHANGE;
-					}
-					changeDown = maxOfProdOrSupply * ModelConfig.MAX_IMPORT_CHANGE;
-				}
+				changeDown = changeUp = maxOfProdOrSupply * ModelConfig.MAX_IMPORT_CHANGE;
 			}
 			
 			if (CropType.ENERGY_CROPS.equals(crop) && baseTrade == 0) { // could apply this logic for all crops?
@@ -212,8 +195,11 @@ public class CountryAgent extends AbstractCountryAgent {
 				minLimit = minMaxLimits.get(MinMaxNetImportManager.LimitType.MIN_LIMIT_TYPE).get(crop);
 				maxLimit = minMaxLimits.get(MinMaxNetImportManager.LimitType.MAX_LIMIT_TYPE).get(crop);
 			}
+
 			LogWriter.print(crop.toString(), 3);
-			importConstraints.put(crop, new TradeConstraint(baseTrade - changeDown, baseTrade + changeUp, restiction, minLimit, maxLimit));
+			TradeConstraint tradeConstraint = new TradeConstraint(baseTrade - changeDown, baseTrade + changeUp, restiction, minLimit, maxLimit);
+
+			importConstraints.put(crop, tradeConstraint);
 		}
 		
 		TradeConstraint carbonTradeConstraint;
@@ -226,10 +212,9 @@ public class CountryAgent extends AbstractCountryAgent {
 			if (Math.abs(baseTrade) < 1e-3) { // to set initial trade when starting from zero
 				changeUp = changeDown = getCurrentCarbonDemand();
 			} else {
-				double maxOfProdOrSupply = carbonUsageData.getCarbonCredits() + Math.max(baseTrade, 0);
+				double maxOfProdOrSupply = Math.max(carbonUsageData.getCarbonCredits() + Math.max(baseTrade, 0), 1);
 				// double change otherwise we run into issues as not all countries can meet demand with domestic production
-				changeUp = maxOfProdOrSupply * globalCarbonPrice.getMaxImportChange() * 2;
-				changeDown = maxOfProdOrSupply * globalCarbonPrice.getMaxExportChange() * 2;
+				changeUp = changeDown = maxOfProdOrSupply * ModelConfig.MAX_IMPORT_CHANGE;
 			}
 
 			carbonTradeConstraint = new TradeConstraint(baseTrade - changeDown, baseTrade + changeUp);
@@ -253,15 +238,12 @@ public class CountryAgent extends AbstractCountryAgent {
 			double changeUp;
 			double changeDown;
 
-			double demand = currentWoodDemand.get(woodType);
-			double maxOfProdOrSupply = woodUsage.getProduction() + Math.max(baseTrade, 0);
-			//double baseTrade = demand * woodUsage.getBaseImportDemandRatio();
+			double maxOfProdOrSupply = Math.max(woodUsage.getProduction() + Math.max(baseTrade, 0), 1);
 
 			if (ModelConfig.IS_CALIBRATION_RUN && currentTimestep.getTimestep() <= ModelConfig.END_FIRST_STAGE_CALIBRATION) {
 				changeUp = changeDown = 0.0;
 			} else {
 				changeUp = changeDown = maxOfProdOrSupply * ModelConfig.MAX_IMPORT_CHANGE;
-				//changeUp = changeDown = demand * 0.04;
 			}
 
 			woodTradeConstraints.put(woodType, new TradeConstraint(baseTrade - changeDown, baseTrade + changeUp));
diff --git a/src/ac/ed/lurg/country/GlobalPrice.java b/src/ac/ed/lurg/country/GlobalPrice.java
index dd5174b6..fa1ea9f5 100644
--- a/src/ac/ed/lurg/country/GlobalPrice.java
+++ b/src/ac/ed/lurg/country/GlobalPrice.java
@@ -18,9 +18,10 @@ public class GlobalPrice implements Serializable {
 	private double stockLevel;
 	private double stockUseRatio;
 	private double referencePrice;
+	private double prevStockChange;
 
 	private GlobalPrice(Timestep timestep, double exportPrice, double stockLevel, double importAmount, double exportAmountBeforeLoss,
-						double transportLosses, double referencePrice, double stockUseRatio) {
+						double transportLosses, double referencePrice, double stockUseRatio, double prevStockChange) {
 		this.timestep = timestep;
 		this.exportPrice = exportPrice;
 		this.stockLevel = stockLevel;
@@ -29,12 +30,13 @@ public class GlobalPrice implements Serializable {
 		this.exportAmountBeforeLoss = exportAmountBeforeLoss;
 		this.transportLosses = transportLosses;
 		this.referencePrice = referencePrice;
+		this.prevStockChange = prevStockChange;
 		LogWriter.println("Created " + this, 3);
 	}
 	
 	public static GlobalPrice createInitial(double exportPrice, double intitalStock) {
 		return new GlobalPrice(new Timestep(ModelConfig.START_TIMESTEP-1), exportPrice, intitalStock, Double.NaN,
-				Double.NaN, Double.NaN, Double.NaN, Double.NaN);
+				Double.NaN, Double.NaN, Double.NaN, Double.NaN, 0.0);
 	}
 	
 	public double getExportPrice(){
@@ -99,9 +101,20 @@ public class GlobalPrice implements Serializable {
 				adjustment = 1;
 			}
 			else if (ModelConfig.PRICE_UPDATE_METHOD.equals("StockUseRatio")) {
-				// MARKET_LAMBDA controls how strongly prices adjust to stock imbalance
-				// MARKET_DAMPING controls how quickly prices reach equilibrium
-				adjustment = 1 - (ModelConfig.MARKET_LAMBDA * (updatedStock - targetStock) + ModelConfig.MARKET_DAMPING * stockChange) / production;
+				// MARKET_BETA controls how strongly prices adjust to stock imbalance
+				// MARKET_LAMBDA controls how quickly prices reach equilibrium
+				//adjustment = 1 - (ModelConfig.MARKET_BETA * (updatedStock - targetStock) + ModelConfig.MARKET_LAMBDA * stockChange) / production;
+				// Sum of target stock and trade flow volume. Trying to avoid large swings in prices when stocks low
+				double stockAndFlow = stockLevel + Math.max(newImports, newExportAmountBeforeLoss);
+				adjustment = 1 - (ModelConfig.MARKET_LAMBDA * stockChange / stockAndFlow
+						+ ModelConfig.MARKET_LAMBDA  * (stockChange - prevStockChange) / stockAndFlow
+						+ ModelConfig.MARKET_BETA * (updatedStock - targetStock) / targetStock );
+
+				// Maximum price increase if projected stock below zero
+				if (updatedStock + stockChange + (stockChange - prevStockChange) <= 0) {
+					adjustment = ModelConfig.MAX_PRICE_INCREASE;
+				}
+
 			}
 			else if (ModelConfig.PRICE_UPDATE_METHOD.equals("MarketImbalance")) {
 				double ratio = stockChange/(production-stockChange);
@@ -131,9 +144,9 @@ public class GlobalPrice implements Serializable {
 
 			double newPrice = exportPrice * adjustment;
 			double refPrice = ModelConfig.IS_CALIBRATION_RUN ? exportPrice : referencePrice;  // during calibration reference price isn't fixed, but it is after that
-			
+
 			return new GlobalPrice(thisTimeStep, newPrice, updatedStock, newImports, newExportAmountBeforeLoss,
-					newTransportLosses, refPrice, updatedStockUseRatio);
+					newTransportLosses, refPrice, updatedStockUseRatio, stockChange);
 		}
 		else {
 			LogWriter.printlnWarning(String.format("Price for not updated (still %s), as no imports and no exports for it", exportPrice));
@@ -157,45 +170,12 @@ public class GlobalPrice implements Serializable {
 	
 	public GlobalPrice createPriceAdjustedByFactor(double factor) {
 		return new GlobalPrice(timestep, exportPrice * factor, stockLevel, importAmount, exportAmountBeforeLoss,
-				transportLosses, referencePrice, stockUseRatio);
+				transportLosses, referencePrice, stockUseRatio, prevStockChange);
 	}
 
 	public void resetStock(Double stock) {
 		this.stockLevel = stock;
 	}
-	
-	public double calcTradeMaxChange(double ratio) {
-		if (Double.isNaN(ratio)) {
-			return ModelConfig.MAX_IMPORT_CHANGE;
-		} else {
-			// allowed change decreases as trade imbalance increases
-			double change = Math.exp(-(ratio - 1) * ModelConfig.IMPORT_CHANGE_ELASTICITY) * ModelConfig.MAX_IMPORT_CHANGE;
-			return Math.min(change, ModelConfig.MAX_IMPORT_CHANGE); // cap at max change
-		}
-	}
-	
-	public double getMaxImportChange() {
-		//return calcTradeMaxChange(importAmount / exportAmountBeforeLoss);
-		return stockLevel > importAmount ? Math.min(stockLevel / importAmount - 1, ModelConfig.MAX_IMPORT_CHANGE) : 0;
-	}
-	
-	public double getMaxExportChange() {
-		//return calcTradeMaxChange(exportAmountBeforeLoss/ importAmount);
-		return (exportAmountBeforeLoss > 1.2 * importAmount) ? 0 : ModelConfig.MAX_IMPORT_CHANGE;
-	}
-
-	public boolean isStockCritical() {
-		return (stockLevel < importAmount && exportAmountBeforeLoss < importAmount * 1.2) || stockLevel < 0;
-	}
 
-	public double getTradeImbalanceFraction() {
-		double netImports = importAmount - exportAmountBeforeLoss;
-		double tradeVolume = importAmount + exportAmountBeforeLoss;
-		return netImports / tradeVolume;
-	}
-
-	public double getImportToExportRatio() {
-		return exportAmountBeforeLoss > 0 ? importAmount / exportAmountBeforeLoss : 0;
-	}
 
 }
\ No newline at end of file
diff --git a/src/ac/ed/lurg/country/TradeConstraint.java b/src/ac/ed/lurg/country/TradeConstraint.java
index e90e2ce5..ffa912c0 100644
--- a/src/ac/ed/lurg/country/TradeConstraint.java
+++ b/src/ac/ed/lurg/country/TradeConstraint.java
@@ -1,10 +1,12 @@
 package ac.ed.lurg.country;
 
+import ac.ed.lurg.ModelConfig;
 import ac.ed.lurg.utils.LogWriter;
 
 public class TradeConstraint {
 	private double minValue;
 	private double maxValue;
+	private double tradeAdjustmentCost = ModelConfig.TRADE_ADJUSTMENT_COST_RATE;
 
 	public TradeConstraint(double min, double max) {
 		minValue = min;
@@ -47,6 +49,14 @@ public class TradeConstraint {
 		return maxValue;
 	}
 
+	public void setTradeAdjustmentCost(double cost) {
+		tradeAdjustmentCost = cost;
+	}
+
+	public double getTradeAdjustmentCost() {
+		return tradeAdjustmentCost;
+	}
+
 	@Override
 	public String toString() {
 		return "TradeConstraint [minValue=" + minValue + ", maxValue=" + maxValue + "]";
diff --git a/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java b/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java
index 24311649..99f5c442 100644
--- a/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java
+++ b/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java
@@ -520,7 +520,7 @@ public class GamsLocationOptimiser {
 		GAMSVariable varOtherIntensities = outDB.getVariable("otherIntensity");
 		GAMSVariable varRuminantFeed = outDB.getVariable("ruminantFeed");
 		GAMSVariable varMonogastricFeed = outDB.getVariable("monogastricFeed");
-		GAMSParameter parmNetImports = outDB.getParameter("netImportAmount");
+		GAMSVariable varNetImports = outDB.getVariable("netImportAmount");
 		GAMSParameter parmNetImportCost = outDB.getParameter("netImportCost");
 		GAMSVariable varYields = outDB.getVariable("yield");
 		GAMSVariable varUnitEnergies = outDB.getVariable("unitCost");
@@ -558,7 +558,7 @@ public class GamsLocationOptimiser {
 			if (!cropUsageData.containsKey(cropType)) {  // then we must not have seen this crop type before, so need to do all non location specific stuff
 				ruminantFeed = varRuminantFeed.findRecord(itemName).getLevel();
 				monogastricFeed = varMonogastricFeed.findRecord(itemName).getLevel();
-				netImport = cropType.isImportedCrop() ? getParmValue(parmNetImports, itemName) : 0;
+				netImport = cropType.isImportedCrop() ? varNetImports.findRecord(itemName).getLevel() : 0;
 				netImportCost = cropType.isImportedCrop() ? getParmValue(parmNetImportCost, itemName) : 0;
 				prod =  getParmValue(parmProd, itemName);
 				prodCost = getParmValue(parmProdCost, itemName);
@@ -587,7 +587,7 @@ public class GamsLocationOptimiser {
 		}
 
 		for (CropType meatTypes : CropType.getMeatTypes()) {
-			netImport = getParmValue(parmNetImports, meatTypes.getGamsName());
+			netImport = varNetImports.findRecord(meatTypes.getGamsName()).getLevel();
 			netImportCost= getParmValue(parmNetImportCost, meatTypes.getGamsName());
 			prod = getParmValue(parmProd, meatTypes.getGamsName());
 			prodCost = getParmValue(parmProdCost, meatTypes.getGamsName());
@@ -634,7 +634,7 @@ public class GamsLocationOptimiser {
 		 */
 		GAMSParameter woodSupplyP = outDB.getParameter("woodSupplyP");
 		for (WoodType wType : WoodType.values()) {
-			double netImports = getParmValue(parmNetImports, wType.getName());
+			double netImports = varNetImports.findRecord(wType.getName()).getLevel();
 			double supply = getParmValue(woodSupplyP, wType.getName());
 			WoodUsageData woodUsageData = inputData.getCountryInput().getPreviousWoodUsageData().get(wType);
 			woodUsageData.setProduction(supply);
@@ -653,7 +653,7 @@ public class GamsLocationOptimiser {
 		
 		// Carbon
 		double carbonSequestered = outDB.getParameter("netCarbonCredits").getFirstRecord().getValue();
-		double netCarbonImport = getParmValue(parmNetImports, "carbonCredits");
+		double netCarbonImport = varNetImports.findRecord("carbonCredits").getLevel();
 		CarbonUsageData carbonUsageData = new CarbonUsageData(carbonSequestered, netCarbonImport, 0.0);
 
 		return new GamsLocationOutput(modelStatus, landUses, cropUsageData, landCoverChanges, carbonUsageData,
diff --git a/src/ac/ed/lurg/landuse/WoodUsageData.java b/src/ac/ed/lurg/landuse/WoodUsageData.java
index 3771e670..4d803430 100644
--- a/src/ac/ed/lurg/landuse/WoodUsageData.java
+++ b/src/ac/ed/lurg/landuse/WoodUsageData.java
@@ -41,4 +41,8 @@ public class WoodUsageData implements Serializable {
 	public double getBaseImportDemandRatio() {
 		return baseImportDemandRatio;
 	}
+
+	public double getNetSupply() {
+		return expectedProduction + netImport;
+	}
 }
diff --git a/src/ac/ed/lurg/types/CropType.java b/src/ac/ed/lurg/types/CropType.java
index 06457535..47a13ab1 100644
--- a/src/ac/ed/lurg/types/CropType.java
+++ b/src/ac/ed/lurg/types/CropType.java
@@ -11,18 +11,18 @@ import ac.ed.lurg.utils.LogWriter;
 
 public enum CropType {
 
-	WHEAT("WheatBarleyOats", "wheat", true, false, 9.5, ModelConfig.INITAL_PRICE_WHEAT, 0.4),
-	MAIZE("MaizeMilletSorghum", "maize", true, false, 5.1, ModelConfig.INITAL_PRICE_MAIZE, 0.4),
-	RICE("Rice (Paddy Equivalent)", "rice", true, false, 8.3, ModelConfig.INITAL_PRICE_RICE, 0.4),
-	OILCROPS("Oilcrops", "oilcrops", true, false, 4.4, ModelConfig.INITAL_PRICE_OILCROPS, 0.3),
-	PULSES("Pulses", "pulses", true, false, 10.8, ModelConfig.INITAL_PRICE_PULSES, 0.5),
-	STARCHY_ROOTS("Starchy Roots", "starchyRoots", true, false, 14.3, ModelConfig.INITAL_PRICE_STARCHYROOTS, 0.2),
+	WHEAT("WheatBarleyOats", "wheat", true, false, 9.5, ModelConfig.INITAL_PRICE_WHEAT, 0.45),
+	MAIZE("MaizeMilletSorghum", "maize", true, false, 5.1, ModelConfig.INITAL_PRICE_MAIZE, 0.35),
+	RICE("Rice (Paddy Equivalent)", "rice", true, false, 8.3, ModelConfig.INITAL_PRICE_RICE, 0.50),
+	OILCROPS("Oilcrops", "oilcrops", true, false, 4.4, ModelConfig.INITAL_PRICE_OILCROPS, 0.25),
+	PULSES("Pulses", "pulses", true, false, 10.8, ModelConfig.INITAL_PRICE_PULSES, 0.45),
+	STARCHY_ROOTS("Starchy Roots", "starchyRoots", true, false, 14.3, ModelConfig.INITAL_PRICE_STARCHYROOTS, 0.10),
 	ENERGY_CROPS("Energy crops", "energycrops", true, false, 5, ModelConfig.INITAL_PRICE_ENERGYCROPS, 0.2),
 	SETASIDE("setaside", "setaside", false, false, 0, 0, 0),
-	MONOGASTRICS("Monogastrics", "monogastrics", true, true, 3.1, ModelConfig.INITAL_PRICE_MONOGASTRICS, 0.2),
-	RUMINANTS("Ruminants", "ruminants", true, true, 2.2, ModelConfig.INITAL_PRICE_RUMINANTS, 0.2),
-	FRUITVEG("FruitVeg", "fruitveg", true, false, 8.9, ModelConfig.INITAL_PRICE_FRUITVEG, 0.2),
-	SUGAR("Sugar", "sugar", true, false, 0.1, ModelConfig.INITAL_PRICE_SUGAR, 0.5),
+	MONOGASTRICS("Monogastrics", "monogastrics", true, true, 3.1, ModelConfig.INITAL_PRICE_MONOGASTRICS, 0.35),
+	RUMINANTS("Ruminants", "ruminants", true, true, 2.2, ModelConfig.INITAL_PRICE_RUMINANTS, 0.10),
+	FRUITVEG("FruitVeg", "fruitveg", true, false, 8.9, ModelConfig.INITAL_PRICE_FRUITVEG, 0.10),
+	SUGAR("Sugar", "sugar", true, false, 0.1, ModelConfig.INITAL_PRICE_SUGAR, 0.40),
 	PASTURE("pasture", "pasture", false, false, 0, 0, 0);  // confusing having a land cover and a crop type.  Needed here for yields (but not used for cropland area fractions).
 
 	private String faoName;
diff --git a/src/ac/ed/lurg/yield/YieldResponsesItem.java b/src/ac/ed/lurg/yield/YieldResponsesItem.java
index 95aece9d..f36251d7 100644
--- a/src/ac/ed/lurg/yield/YieldResponsesItem.java
+++ b/src/ac/ed/lurg/yield/YieldResponsesItem.java
@@ -54,7 +54,7 @@ public class YieldResponsesItem implements RasterItem {
 		YieldResponsesItem item = new YieldResponsesItem();
 		for (CropType crop : CropType.values()) {
 			for (YieldType yieldType : YieldType.values()) {
-				item.setYield(yieldType, crop, 0.0);
+				item.setYield(yieldType, crop, 0.001); // Needs to be non-zero otherwise GAMS will fail
 			}
 		}
 		return item;
-- 
GitLab