package ac.ed.lurg.country; import java.io.Serializable; import ac.ed.lurg.ModelConfig; import ac.ed.lurg.Timestep; import ac.ed.lurg.types.Parameter; import ac.ed.lurg.utils.LogWriter; public class GlobalPrice implements Serializable { private static final long serialVersionUID = 2477952576838887039L; private int timestepId; private double exportPrice; private double importAmount; private double exportAmountBeforeLoss; private double transportLosses; private double stockLevel; private GlobalPrice(int timestepId, double exportPrice, double stockLevel, double importAmount, double exportAmountBeforeLoss, double transportLosses) { this.timestepId = timestepId; this.exportPrice = exportPrice; this.stockLevel = stockLevel; this.importAmount = importAmount; this.exportAmountBeforeLoss = exportAmountBeforeLoss; this.transportLosses = transportLosses; } public static GlobalPrice createInitial(double exportPrice, double intitalStock) { return new GlobalPrice(ModelConfig.START_TIMESTEP-1, exportPrice, intitalStock, Double.NaN, Double.NaN, Double.NaN); } public double getExportPrice(){ return exportPrice; } public double getStockLevel(){ return stockLevel; } public double getCountryImportPrice(double countryTradeBarrier, Timestep timestep) { int currentYear = timestep.getYear(); double tradeBarrierMultiplier = (!ModelConfig.SHOCKS_POSSIBLE)? ModelConfig.TRADE_BARRIER_MULTIPLIER: ModelConfig.getParameter(Parameter.TRADE_BARRIER_MULTIPLIER, currentYear); double transportLossesRate =(!ModelConfig.SHOCKS_POSSIBLE) ? ModelConfig.TRANSPORT_LOSSES : ModelConfig.getParameter(Parameter.TRANSPORT_LOSSES, currentYear); double transportCosts = (!ModelConfig.SHOCKS_POSSIBLE) ? ModelConfig.TRANSPORT_COST : ModelConfig.getParameter(Parameter.TRANSPORT_COST, currentYear); double importPrice = exportPrice * (1 + transportCosts) * (1.0 + countryTradeBarrier*tradeBarrierMultiplier) / (1.0 - transportLossesRate); return importPrice; } public double getImportAmount() { return importAmount; } public double getExportsAfterTransportLosses() { return exportAmountBeforeLoss - transportLosses; } public double getExportsBeforeTransportLoss() { return exportAmountBeforeLoss ; } public double getTransportLosses() { return transportLosses; } public GlobalPrice createWithUpdatedMarketPrices(double newImports, double newExportAmountBeforeLoss, Timestep timestep, double production) { if (newImports > 0 || newExportAmountBeforeLoss > 0) { double oldDiff = timestep.getTimestep() != timestepId ? 0.0 : exportAmountBeforeLoss - transportLosses - importAmount; // if recomputing for same year need to back our previous adjustment double transportLossRate = (!ModelConfig.SHOCKS_POSSIBLE) ? ModelConfig.TRANSPORT_LOSSES : ModelConfig.getParameter(Parameter.TRANSPORT_LOSSES, timestep.getYear()); double newTransportLosses = newExportAmountBeforeLoss * transportLossRate; double stockChange = newExportAmountBeforeLoss - newTransportLosses - newImports - oldDiff; double updatedStock; if (ModelConfig.IS_CALIBRATION_RUN && timestep.getTimestep() <= ModelConfig.END_FIRST_STAGE_CALIBRATION) updatedStock = stockLevel; // don't update stock in inital stage of calibration else updatedStock = stockLevel + stockChange; LogWriter.println(String.format(" imports %.2f, exports %.2f", newImports, newExportAmountBeforeLoss - newTransportLosses)); LogWriter.println(String.format(" updatedStock %.2f, previous %.2f (last timestep %.2f), stockChange %.2f, oldDiff %.2f", updatedStock, stockLevel, stockLevel-oldDiff, stockChange, oldDiff)); double adjustment; double financialSpeculationMultiplier = (!ModelConfig.SHOCKS_POSSIBLE)? 1.0 : ModelConfig.getParameter(Parameter.FINANCIAL_SPECULATION_MULTIPLIER,timestep.getYear()); if (!ModelConfig.MARKET_ADJ_PRICE || (ModelConfig.IS_CALIBRATION_RUN && timestep.getTimestep() <= ModelConfig.END_FIRST_STAGE_CALIBRATION)) { adjustment = 1; } else if (ModelConfig.PRICE_UPDATE_BY_MARKET_IMBALANCE) { double ratio = stockChange/(production-stockChange); adjustment = Math.exp(-ratio * ModelConfig.MARKET_LAMBA); LogWriter.println(String.format(" initally imbalance ratio= %.4f", ratio)); } else { if (stockChange == 0 && production == 0) adjustment=1; else if (stockChange >= 0 && production != 0) // stock increasing, so decrease price. stockChange is positive so adjustment < 1 adjustment = 1 - ModelConfig.MARKET_LAMBA * stockChange/production; else // stock decreasing, so increase price. stockChange is negative so adjustment > 1 adjustment = 1 - ModelConfig.MARKET_LAMBA * stockChange/Math.max(0, stockLevel); LogWriter.print(String.format(" initally adjustment= %.4f", adjustment)); } if (adjustment < ModelConfig.MAX_PRICE_DECREASE) adjustment = ModelConfig.MAX_PRICE_DECREASE; // default to max down change if (adjustment > ModelConfig.MAX_PRICE_INCREASE) adjustment = ModelConfig.MAX_PRICE_INCREASE; // default to max up change LogWriter.println(String.format(", after limit %.4f", adjustment)); double newPrice = exportPrice * adjustment * financialSpeculationMultiplier; return new GlobalPrice(timestep.getTimestep(), newPrice, updatedStock, newImports, newExportAmountBeforeLoss, newTransportLosses); } else { LogWriter.printlnError(String.format("Price for not updated (still %s), as no imports and no exports for it", exportPrice)); return this; } } @Override public String toString() { return String.format("exportPrice=%.6f", exportPrice); } public double getStockChange() { return exportAmountBeforeLoss - transportLosses - importAmount; } public GlobalPrice createPriceAdjustedByFactor(double factor) { return new GlobalPrice(timestepId, exportPrice * factor, stockLevel, importAmount, exportAmountBeforeLoss, transportLosses); } }