Skip to content
Snippets Groups Projects
Commit 56d3ce3f authored by Peter Alexander's avatar Peter Alexander
Browse files

Allow price to be adjusted from stock levels

parent 16b9b617
No related branches found
No related tags found
No related merge requests found
...@@ -9,34 +9,33 @@ import java.util.Map.Entry; ...@@ -9,34 +9,33 @@ import java.util.Map.Entry;
import ac.ed.lurg.country.AbstractCountryAgent; import ac.ed.lurg.country.AbstractCountryAgent;
import ac.ed.lurg.country.GlobalPrice; import ac.ed.lurg.country.GlobalPrice;
import ac.ed.lurg.country.StockReader;
import ac.ed.lurg.landuse.CropUsageData; import ac.ed.lurg.landuse.CropUsageData;
import ac.ed.lurg.types.CropToDoubleMap; import ac.ed.lurg.types.CropToDoubleMap;
import ac.ed.lurg.types.CropType; import ac.ed.lurg.types.CropType;
import ac.ed.lurg.types.Parameter;
import ac.ed.lurg.utils.LogWriter; import ac.ed.lurg.utils.LogWriter;
public class InternationalMarket { public class InternationalMarket {
private Map<CropType, GlobalPrice> worldPrices = new HashMap<CropType, GlobalPrice>(); private Map<CropType, GlobalPrice> worldPrices = new HashMap<CropType, GlobalPrice>();
private Map<CropType, Double> stockLevel;
public InternationalMarket() { public InternationalMarket() {
for (CropType crop : CropType.getImportedTypes()) //Map<CropType, Double> stockLevel = getInitialStockLevels();
for (CropType crop : CropType.getImportedTypes()) {
//Double stock = stockLevel.get(crop);
worldPrices.put(crop, GlobalPrice.createInitial(crop.getInitialPrice())); worldPrices.put(crop, GlobalPrice.createInitial(crop.getInitialPrice()));
}
stockLevel = getInitialStockLevels();
} }
public Map<CropType, GlobalPrice> getWorldPrices() { public Map<CropType, GlobalPrice> getWorldPrices() {
return worldPrices; return worldPrices;
} }
private Map<CropType, Double> getInitialStockLevels() { /* private Map<CropType, Double> getInitialStockLevels() {
Map<CropType, Double> initialStockLevels = new StockReader().read(); Map<CropType, Double> initialStockLevels = new StockReader().read();
initialStockLevels.put(CropType.ENERGY_CROPS, 0.0); initialStockLevels.put(CropType.ENERGY_CROPS, 0.0);
return initialStockLevels; return initialStockLevels;
} } */
void determineInternationalTrade(Collection<AbstractCountryAgent> countryAgents, double gen2EcDDemand, Timestep timestep) { void determineInternationalTrade(Collection<AbstractCountryAgent> countryAgents, double gen2EcDDemand, Timestep timestep) {
CropToDoubleMap totalImportCommodities = new CropToDoubleMap(); CropToDoubleMap totalImportCommodities = new CropToDoubleMap();
...@@ -69,17 +68,10 @@ public class InternationalMarket { ...@@ -69,17 +68,10 @@ public class InternationalMarket {
GlobalPrice prevPrice = worldPrices.get(crop); GlobalPrice prevPrice = worldPrices.get(crop);
double imports = totalImportCommodities.containsKey(crop) ? totalImportCommodities.get(crop) : 0.0; double imports = totalImportCommodities.containsKey(crop) ? totalImportCommodities.get(crop) : 0.0;
double exportsBeforeTransportLosses = totalExportCommodities.containsKey(crop) ? totalExportCommodities.get(crop) : 0.0; double exportsBeforeTransportLosses = totalExportCommodities.containsKey(crop) ? totalExportCommodities.get(crop) : 0.0;
double previousStockLevel = stockLevel.get(crop); LogWriter.print("Updating " + crop.getGamsName() + " prices : ");
double transportLossRate=(!ModelConfig.SHOCKS_POSSIBLE) ? ModelConfig.TRANSPORT_LOSSES : ModelConfig.getParameter(Parameter.TRANSPORT_LOSSES, timestep.getYear()); GlobalPrice adjustedPrice = prevPrice.createWithUpdatedMarketPrices(imports, exportsBeforeTransportLosses, timestep, totalProduction.get(crop));
GlobalPrice adjustedPrice = prevPrice.createWithUpdatedMarketPrices(imports, exportsBeforeTransportLosses, exportsBeforeTransportLosses * transportLossRate, (ModelConfig.MARKET_ADJ_PRICE), timestep, totalProduction.get(crop)); LogWriter.println( String.format("Price for %s updated from %s to %s \n", crop.getGamsName(), prevPrice, adjustedPrice));
LogWriter.println( String.format("Price for %s updated from %s (imports amount %.1f, exports amount %.1f) to %s ",
crop.getGamsName(), prevPrice, imports, adjustedPrice.getExportsAfterTransportLosses(), adjustedPrice));
worldPrices.put(crop, adjustedPrice); worldPrices.put(crop, adjustedPrice);
double updatedStockLevel = previousStockLevel + adjustedPrice.getStockChange();
stockLevel.put(crop, updatedStockLevel);
LogWriter.println(String.format("Global stocks for %s updated from %s to %s ", crop.getGamsName(), previousStockLevel, updatedStockLevel));
if (updatedStockLevel < 0)
LogWriter.println(String.format("Global stocks for %s is below zero ", crop.getGamsName(), previousStockLevel));
} }
} }
...@@ -89,7 +81,7 @@ public class InternationalMarket { ...@@ -89,7 +81,7 @@ public class InternationalMarket {
GlobalPrice priceQuantity = worldPrices.get(crop); GlobalPrice priceQuantity = worldPrices.get(crop);
sbData.append(String.format("%d,%s", timestep.getYear(), crop.getGamsName())); sbData.append(String.format("%d,%s", timestep.getYear(), crop.getGamsName()));
sbData.append(String.format(",%.1f,%.1f", priceQuantity.getImportAmount(), priceQuantity.getExportsAfterTransportLosses())); sbData.append(String.format(",%.1f,%.1f", priceQuantity.getImportAmount(), priceQuantity.getExportsAfterTransportLosses()));
sbData.append(String.format(",%.8f,%.3f", priceQuantity.getExportPrice(), stockLevel.get(crop))); sbData.append(String.format(",%.8f,%.3f", priceQuantity.getExportPrice(), priceQuantity.getStockLevel()));
outputFile.write(sbData.toString()); outputFile.write(sbData.toString());
outputFile.newLine(); outputFile.newLine();
......
...@@ -342,6 +342,8 @@ public class ModelConfig { ...@@ -342,6 +342,8 @@ public class ModelConfig {
public static final double SUGAR_SUB_PROPORTION = getDoubleProperty("SUGAR_SUB_PROPORTION", 0.1); public static final double SUGAR_SUB_PROPORTION = getDoubleProperty("SUGAR_SUB_PROPORTION", 0.1);
public static final double MARKET_LAMBA = getDoubleProperty("MARKET_LAMBA", 0.4); // controls international market price adjustment rate public static final double MARKET_LAMBA = getDoubleProperty("MARKET_LAMBA", 0.4); // controls international market price adjustment rate
public static final boolean PRICE_UPDATE_BY_MARKET_IMBALANCE = getBooleanProperty("PRICE_UPDATE_BY_MARKET_IMBALANCE", false);;
public static final double STOCK_TARGET_RATE = getDoubleProperty("STOCK_TARGET_RATE", 0.05);
public static final int DEMAND_RECALC_MAX_ITERATIONS = getIntProperty("DEMAND_RECALC_MAX_ITERATIONS", 0); // 0 is original behaviour public static final int DEMAND_RECALC_MAX_ITERATIONS = getIntProperty("DEMAND_RECALC_MAX_ITERATIONS", 0); // 0 is original behaviour
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 double POPULATION_AGGREG_LIMIT = getDoubleProperty("POPULATION_AGGREG_LIMIT", 30.0); // in millions, smaller countries are aggregated on a regional basis
...@@ -395,5 +397,5 @@ public class ModelConfig { ...@@ -395,5 +397,5 @@ public class ModelConfig {
public static final double CONSTANT_PROTECTED_AREA_RATE = getDoubleProperty("CONSTANT_PROTECTED_AREA_RATE", Double.NaN); public static final double CONSTANT_PROTECTED_AREA_RATE = getDoubleProperty("CONSTANT_PROTECTED_AREA_RATE", Double.NaN);
public static final boolean USE_CRAFTY_COUNTRIES = getBooleanProperty("USE_CRAFTY_COUNTRIES", false); public static final boolean USE_CRAFTY_COUNTRIES = getBooleanProperty("USE_CRAFTY_COUNTRIES", false);
public static final String CRAFTY_PRODUCTION_DIR = getProperty("CRAFTY_PRODUCTION_DIR", OUTPUT_DIR + File.separator + "crafty"); public static final String CRAFTY_PRODUCTION_DIR = getProperty("CRAFTY_PRODUCTION_DIR", OUTPUT_DIR + File.separator + "crafty");
} }
...@@ -10,21 +10,27 @@ public class GlobalPrice { ...@@ -10,21 +10,27 @@ public class GlobalPrice {
private double importAmount; private double importAmount;
private double exportAmountBeforeLoss; private double exportAmountBeforeLoss;
private double transportLosses; private double transportLosses;
private double stockLevel;
public GlobalPrice(double exportPrice, double importAmount, double exportAmountBeforeLoss, double transportLosses) { private GlobalPrice(double exportPrice, double stockLevel, double importAmount, double exportAmountBeforeLoss, double transportLosses) {
this.exportPrice = exportPrice; this.exportPrice = exportPrice;
this.stockLevel = stockLevel;
this.importAmount = importAmount; this.importAmount = importAmount;
this.exportAmountBeforeLoss = exportAmountBeforeLoss; this.exportAmountBeforeLoss = exportAmountBeforeLoss;
this.transportLosses = transportLosses; this.transportLosses = transportLosses;
} }
public static GlobalPrice createInitial(double exportPrice) { public static GlobalPrice createInitial(double exportPrice) {
return new GlobalPrice(exportPrice, Double.NaN, Double.NaN, Double.NaN); return new GlobalPrice(exportPrice, Double.NaN, Double.NaN, Double.NaN, Double.NaN);
} }
public double getExportPrice(){ public double getExportPrice(){
return exportPrice; return exportPrice;
} }
public double getStockLevel(){
return stockLevel;
}
public double getCountryImportPrice(double countryTradeBarrier, Timestep timestep) { public double getCountryImportPrice(double countryTradeBarrier, Timestep timestep) {
...@@ -55,19 +61,46 @@ public class GlobalPrice { ...@@ -55,19 +61,46 @@ public class GlobalPrice {
return transportLosses; return transportLosses;
} }
public GlobalPrice createWithUpdatedMarketPrices(double imports, double exportsBeforeTransportLosses, double transportLosses, boolean adjustPrice, Timestep timestep, double production) { public GlobalPrice createWithUpdatedMarketPrices(double imports, double exportsBeforeTransportLosses, Timestep timestep, double production) {
if (Double.isNaN(stockLevel))
stockLevel = ModelConfig.STOCK_TARGET_RATE * production; // set stock initially to target level, this is pretty horrible and should really be done on construction but don't easily have production value at that point
double transportLossRate = (!ModelConfig.SHOCKS_POSSIBLE) ? ModelConfig.TRANSPORT_LOSSES : ModelConfig.getParameter(Parameter.TRANSPORT_LOSSES, timestep.getYear());
double transportLosses = exportsBeforeTransportLosses * transportLossRate;
double exportsAfterTransportLosses = exportsBeforeTransportLosses - transportLosses; double exportsAfterTransportLosses = exportsBeforeTransportLosses - transportLosses;
if (imports > 0 || exportsAfterTransportLosses > 0) { if (imports > 0 || exportsAfterTransportLosses > 0) {
double ratio; double updatedStock = stockLevel + exportsBeforeTransportLosses - transportLosses - imports;
LogWriter.println(String.format(" global stocks from %.2f to %.2f", stockLevel, updatedStock));
ratio = (imports-exportsAfterTransportLosses)/(imports-exportsAfterTransportLosses+production); if (updatedStock < 0)
double adjustment = adjustPrice ? Math.exp(ratio * ModelConfig.MARKET_LAMBA) : 1.0; LogWriter.println(String.format("Global stocks are below zero"));
//adjustment = Math.min(adjustment, 2.0); // can only double in a time step
//adjustment = Math.max(adjustment, 0.5); // can only half in a time step
double financialSpeculationMultiplier = (!ModelConfig.SHOCKS_POSSIBLE)? 1.0 : ModelConfig.getParameter(Parameter.FINANCIAL_SPECULATION_MULTIPLIER,timestep.getYear());
return new GlobalPrice(exportPrice * adjustment *financialSpeculationMultiplier, imports, exportsBeforeTransportLosses, transportLosses); double newPrice, adjustment;
double financialSpeculationMultiplier = (!ModelConfig.SHOCKS_POSSIBLE)? 1.0 : ModelConfig.getParameter(Parameter.FINANCIAL_SPECULATION_MULTIPLIER,timestep.getYear());
if (!ModelConfig.MARKET_ADJ_PRICE) {
adjustment = 1;
}
else if (ModelConfig.PRICE_UPDATE_BY_MARKET_IMBALANCE) {
double ratio = (imports-exportsAfterTransportLosses)/(imports-exportsAfterTransportLosses+production);
adjustment = Math.exp(ratio * ModelConfig.MARKET_LAMBA);
LogWriter.println(String.format("Price update market imbalance: adjustment= %s, imports %.1f, exports %.1f", adjustment, imports, getExportsAfterTransportLosses()));
}
else {
double stockTarget = ModelConfig.STOCK_TARGET_RATE * production;
double ratio = (stockTarget - updatedStock) / stockTarget;
if (Math.abs(ratio) >= 1)
adjustment = 10; // default to max change
else
adjustment = 1 + ModelConfig.MARKET_LAMBA * ratio/(1 - ratio*ratio);
LogWriter.println(String.format("Price update from stock target: adjustment= %s, ratio= %s", adjustment, ratio));
}
newPrice = exportPrice * adjustment * financialSpeculationMultiplier;
return new GlobalPrice(newPrice, updatedStock, imports, exportsBeforeTransportLosses, transportLosses);
} }
else { else {
LogWriter.printlnError(String.format("Price for not updated (still %s), as no imports and no exports for it", exportPrice)); LogWriter.printlnError(String.format("Price for not updated (still %s), as no imports and no exports for it", exportPrice));
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment