diff --git a/src/ac/ed/lurg/InternationalMarket.java b/src/ac/ed/lurg/InternationalMarket.java
new file mode 100644
index 0000000000000000000000000000000000000000..d5a0a65deb0e8a059e374b841f70cbacd3c6cf5d
--- /dev/null
+++ b/src/ac/ed/lurg/InternationalMarket.java
@@ -0,0 +1,104 @@
+package ac.ed.lurg;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import ac.ed.lurg.country.CountryAgent;
+import ac.ed.lurg.country.GlobalPrice;
+import ac.ed.lurg.country.StockReader;
+import ac.ed.lurg.landuse.CropUsageData;
+import ac.ed.lurg.types.CropToDoubleMap;
+import ac.ed.lurg.types.CropType;
+import ac.ed.lurg.utils.LogWriter;
+
+public class InternationalMarket {
+
+	private Map<CropType, GlobalPrice> worldPrices;
+	private Map<CropType, Double> stockLevel;
+
+	public InternationalMarket() {
+		// in first timestep we don't have this info, but ok as constrained to
+		// import/export specified amount, values based on
+		// http://www.indexmundi.com/commodities/ for Jun 2010
+		worldPrices = new HashMap<CropType, GlobalPrice>();
+		worldPrices.put(CropType.WHEAT, GlobalPrice.createInitial(0.157 * ModelConfig.INITIAL_PRICE_SHIFT));
+		worldPrices.put(CropType.MAIZE, GlobalPrice.createInitial(0.152 * ModelConfig.INITIAL_PRICE_SHIFT));
+		worldPrices.put(CropType.RICE, GlobalPrice.createInitial(0.182 * ModelConfig.INITIAL_PRICE_SHIFT));
+		worldPrices.put(CropType.OILCROPS, GlobalPrice.createInitial((0.820 * .4 + 0.314 * .6) * 0.5 * ModelConfig.INITIAL_PRICE_SHIFT));
+
+		worldPrices.put(CropType.PULSES, GlobalPrice.createInitial(0.4 * ModelConfig.INITIAL_PRICE_SHIFT));
+		worldPrices.put(CropType.STARCHY_ROOTS, GlobalPrice.createInitial(0.1 * ModelConfig.INITIAL_PRICE_SHIFT));
+		worldPrices.put(CropType.MONOGASTRICS, GlobalPrice.createInitial(0.4 * 0.5 * ModelConfig.INITIAL_PRICE_SHIFT)); // quantities is in feed equivalent term (0.4 is weighted average price per feed, and 0.5 accounts for mark-up for additional processing)
+		worldPrices.put(CropType.RUMINANTS, GlobalPrice.createInitial(0.1 * 0.6 * ModelConfig.INITIAL_PRICE_SHIFT)); // quantities is in feed equivalent term
+		worldPrices.put(CropType.ENERGY_CROPS, GlobalPrice.createInitial(0.04 * ModelConfig.INITIAL_PRICE_SHIFT));
+		stockLevel = getInitialStockLevels();
+	}
+	
+	public  Map<CropType, GlobalPrice> getWorldPrices() {
+		return worldPrices;
+	}
+
+	private Map<CropType, Double> getInitialStockLevels() {
+		Map<CropType, Double> initialStockLevels = new StockReader().read();
+		initialStockLevels.put(CropType.ENERGY_CROPS, 0.0);
+		return initialStockLevels;
+	}
+
+	void determineInternationalTrade(Collection<CountryAgent> countryAgents, double gen2EcDDemand) {
+		CropToDoubleMap totalImportCommodities = new CropToDoubleMap();
+		CropToDoubleMap totalExportCommodities = new CropToDoubleMap();
+		for (CountryAgent ca : countryAgents) {
+
+			// Get values for world input costs
+			Map<CropType, CropUsageData> cropUsage = ca.getCropUsageData();
+			
+			for (Entry<CropType, CropUsageData> entry : cropUsage.entrySet()) {
+				CropType c = entry.getKey();
+				double countryNetImports = entry.getValue().getNetImports();
+
+				if (countryNetImports > 0)
+					totalImportCommodities.incrementValue(c, countryNetImports);
+				else
+					totalExportCommodities.incrementValue(c, -countryNetImports);
+			}
+		}
+
+		// energycrops are a special case where demand in global and exogenously specified
+		totalImportCommodities.incrementValue(CropType.ENERGY_CROPS, gen2EcDDemand);
+
+		// Look at trade balance and adjust appropriately
+		for (CropType crop : CropType.getImportedTypes()) {
+			GlobalPrice prevPrice = worldPrices.get(crop);
+			double imports = totalImportCommodities.containsKey(crop) ? totalImportCommodities.get(crop) : 0.0;
+			double exports = totalExportCommodities.containsKey(crop) ? totalExportCommodities.get(crop) * (1.0 - ModelConfig.TRANSPORT_LOSSES) : 0.0;
+
+			double previousStockLevel = stockLevel.get(crop);
+			GlobalPrice adjustedPrice = prevPrice.createWithUpdatedMarketPrices(imports, exports, (ModelConfig.MARKET_ADJ_PRICE));
+			LogWriter.println( String.format("Price for %s updated from %s (imports amount %.0f, exports amount %.0f) to %s ",
+							crop.getGamsName(), prevPrice, imports, exports, adjustedPrice));
+			worldPrices.put(crop, adjustedPrice);
+			double updatedStockLevel = previousStockLevel + exports - imports;
+			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));
+		}
+	}
+	
+	void writeGlobalMarketFile(Timestep timestep, BufferedWriter outputFile) throws IOException {
+		for (CropType crop : CropType.getImportedTypes()) {
+			StringBuffer sbData = new StringBuffer();
+			GlobalPrice priceQuantity = worldPrices.get(crop);
+			sbData.append(String.format("%d,%s", timestep.getYear(), crop.getGamsName()));
+			sbData.append(String.format(",%.1f,%.1f", priceQuantity.getImportAmount(), priceQuantity.getExportAmount()));
+			sbData.append(String.format(",%.3f,%.3f", priceQuantity.getExportPrice(), stockLevel.get(crop)));
+
+			outputFile.write(sbData.toString());
+			outputFile.newLine();
+		}
+	}
+}
diff --git a/src/ac/ed/lurg/ModelMain.java b/src/ac/ed/lurg/ModelMain.java
index 37dbdd75d13b438a23ac40197a4886e2213471d7..5b88ff3120bebc079bf130cf5533c68f8e571786 100644
--- a/src/ac/ed/lurg/ModelMain.java
+++ b/src/ac/ed/lurg/ModelMain.java
@@ -12,21 +12,16 @@ import java.nio.file.FileSystems;
 import java.nio.file.Files;
 import java.nio.file.StandardCopyOption;
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
 
 import ac.ed.lurg.country.CompositeCountry;
 import ac.ed.lurg.country.CompositeCountryManager;
 import ac.ed.lurg.country.CountryAgent;
 import ac.ed.lurg.country.CountryBoundaryRaster;
 import ac.ed.lurg.country.CountryBoundaryReader;
-import ac.ed.lurg.country.GlobalPrice;
-import ac.ed.lurg.country.StockReader;
 import ac.ed.lurg.country.TradeManager;
-import ac.ed.lurg.country.gams.GamsRasterOutput;
 import ac.ed.lurg.demand.AbstractDemandManager;
 import ac.ed.lurg.demand.BaseConsumpManager;
 import ac.ed.lurg.demand.DemandManagerFromFile;
@@ -48,7 +43,6 @@ import ac.ed.lurg.landuse.RunOffReader;
 import ac.ed.lurg.output.LandUseOutputer;
 import ac.ed.lurg.output.LpjgOutputer;
 import ac.ed.lurg.types.CommodityType;
-import ac.ed.lurg.types.CropToDoubleMap;
 import ac.ed.lurg.types.CropType;
 import ac.ed.lurg.types.LandCoverType;
 import ac.ed.lurg.utils.LogWriter;
@@ -72,9 +66,7 @@ public class ModelMain {
 	private CompositeCountryManager compositeCountryManager;
 	private RasterHeaderDetails desiredProjection;
 
-	private Map<CropType, GlobalPrice> prevWorldPrices;
-	private Map<CropType, Double> prevStockLevel;
-	private RasterSet<LandUseItem> prevLandUseRaster;
+	private InternationalMarket internationalMarket;
 	private IrrigationRasterSet currentIrrigationData;
 	private RasterSet<LandUseItem> globalLandUseRaster;
 	private RasterSet<IntegerRasterItem> clusterIdRaster;
@@ -104,22 +96,7 @@ public class ModelMain {
 
 		countryAgents = createCountryAgents(compositeCountryManager.getAll());
 		globalLandUseRaster = new RasterSet<LandUseItem>(desiredProjection);
-
-		// in first timestep we don't have this info, but ok as constrained to
-		// import/export specified amount, values based on
-		// http://www.indexmundi.com/commodities/ for Jun 2010
-		prevWorldPrices = new HashMap<CropType, GlobalPrice>();
-		prevWorldPrices.put(CropType.WHEAT, GlobalPrice.createInitial(0.157 * ModelConfig.INITIAL_PRICE_SHIFT));
-		prevWorldPrices.put(CropType.MAIZE, GlobalPrice.createInitial(0.152 * ModelConfig.INITIAL_PRICE_SHIFT));
-		prevWorldPrices.put(CropType.RICE, GlobalPrice.createInitial(0.182 * ModelConfig.INITIAL_PRICE_SHIFT));
-		prevWorldPrices.put(CropType.OILCROPS, GlobalPrice.createInitial((0.820 * .4 + 0.314 * .6) * 0.5 * ModelConfig.INITIAL_PRICE_SHIFT));
-
-		prevWorldPrices.put(CropType.PULSES, GlobalPrice.createInitial(0.4 * ModelConfig.INITIAL_PRICE_SHIFT));
-		prevWorldPrices.put(CropType.STARCHY_ROOTS, GlobalPrice.createInitial(0.1 * ModelConfig.INITIAL_PRICE_SHIFT));
-		prevWorldPrices.put(CropType.MONOGASTRICS, GlobalPrice.createInitial(0.4 * 0.5 * ModelConfig.INITIAL_PRICE_SHIFT)); // quantities is in feed equivalent term (0.4 is weighted average price per feed, and 0.5 accounts for mark-up for additional processing)
-		prevWorldPrices.put(CropType.RUMINANTS, GlobalPrice.createInitial(0.1 * 0.6 * ModelConfig.INITIAL_PRICE_SHIFT)); // quantities is in feed equivalent term
-		prevWorldPrices.put(CropType.ENERGY_CROPS, GlobalPrice.createInitial(0.04 * ModelConfig.INITIAL_PRICE_SHIFT));
-		prevStockLevel = getInitialStockLevels();
+		internationalMarket = new InternationalMarket();
 	}
 
 	/* run the model */
@@ -148,8 +125,6 @@ public class ModelMain {
 		double previousGen2EcDDemand = (timestep.isInitialTimestep() || ModelConfig.IS_CALIBRATION_RUN ) ? 0: demandManager.getSecondGenBioenergyDemand(timestep.getPreviousTimestep());
 		double gen2EcDDemand = demandManager.getSecondGenBioenergyDemand(ModelConfig.IS_CALIBRATION_RUN ? new Timestep(1) : timestep);
 		double gen2Increase = (gen2EcDDemand>previousGen2EcDDemand) ? gen2EcDDemand - previousGen2EcDDemand : 0.0;
-		CropToDoubleMap totalImportCommodities = new CropToDoubleMap();
-		CropToDoubleMap totalExportCommodities = new CropToDoubleMap();
 
 		for (CountryAgent ca : countryAgents) {
 
@@ -157,19 +132,13 @@ public class ModelMain {
 			Collection<RasterKey> countryKeys = countryBoundaryRaster.getKeysFor(ca.getCountry());
 			YieldRaster countryYieldSurfaces = yieldSurfaces.createSubsetForKeys(countryKeys);
 			RasterSet<IrrigationItem> irrigData = currentIrrigationData.createSubsetForKeys(countryKeys);
-
-			GamsRasterOutput result = null;
-
+			
 			// do the optimization
 			try {
-				result = ca.determineProduction(timestep, countryYieldSurfaces, irrigData, prevWorldPrices, gen2Increase);
+				ca.determineProduction(timestep, countryYieldSurfaces, irrigData, internationalMarket.getWorldPrices(), gen2Increase);
 			} catch (Exception e) {
 				LogWriter.printlnError("Exception processing " + ca.getCountry() + " will continue with other countries");
 				LogWriter.print(e);
-			}
-
-			if (result == null) {
-				LogWriter.printlnError("No results for " + ca.getCountry());
 				continue;
 			}
 
@@ -187,55 +156,21 @@ public class ModelMain {
 			}
 
 			// update global rasters
-			globalLandUseRaster.putAll(result.getLandUses());
+			globalLandUseRaster.putAll(ca.getLandUses());
 
 			// if first timestep and calibration get the clustering info, which
 			// doesn't change through time
 			if (ModelConfig.GENERATE_NEW_YIELD_CLUSTERS && timestep.isInitialTimestep())
 				clusterIdRaster.putAll(ca.getYieldClusters());
-
-			// Get values for world input costs
-			Map<CropType, CropUsageData> cropUsage = result.getCropUsageData();
-
-			for (Entry<CropType, CropUsageData> entry : cropUsage.entrySet()) {
-				CropType c = entry.getKey();
-				double countryNetImports = entry.getValue().getNetImports();
-
-				if (countryNetImports > 0)
-					totalImportCommodities.incrementValue(c, countryNetImports);
-				else
-					totalExportCommodities.incrementValue(c, -countryNetImports);
-			}
-		}
-
-		// energycrops are a special case where demand in global and exogenously specified
-		totalImportCommodities.incrementValue(CropType.ENERGY_CROPS, gen2EcDDemand);
-
-		// Look at trade balance and adjust appropriately
-		for (CropType crop : CropType.getImportedTypes()) {
-			GlobalPrice prevPrice = prevWorldPrices.get(crop);
-			double imports = totalImportCommodities.containsKey(crop) ? totalImportCommodities.get(crop) : 0.0;
-			double exports = totalExportCommodities.containsKey(crop) ? totalExportCommodities.get(crop) * (1.0 - ModelConfig.TRANSPORT_LOSSES) : 0.0;
-
-			double previousStockLevel = prevStockLevel.get(crop);
-			GlobalPrice adjustedPrice = prevPrice.createWithUpdatedMarketPrices(imports, exports, (ModelConfig.MARKET_ADJ_PRICE));
-			LogWriter.println( String.format("Price for %s updated from %s (imports amount %.0f, exports amount %.0f) to %s ",
-							crop.getGamsName(), prevPrice, imports, exports, adjustedPrice));
-			prevWorldPrices.put(crop, adjustedPrice);
-			double updatedStockLevel = previousStockLevel + exports - imports;
-			prevStockLevel.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));
 		}
+		
+		internationalMarket.determineInternationalTrade(countryAgents, gen2EcDDemand);
 
 		// output results
 		outputTimestepResults(timestep, globalLandUseRaster, yieldSurfaces);
-
-		// keep last to allow interpolation
-		prevLandUseRaster = globalLandUseRaster;
 	}
 
+
 	private BufferedWriter getFileWriter(Timestep timestep, String file, String columnHeadings) throws IOException {
 		if (timestep.isInitialTimestep()) {
 			FileWriter fstream = new FileWriter(file, false);
@@ -276,20 +211,8 @@ public class ModelMain {
 
 	private void writeGlobalMarketFile(Timestep timestep) {
 		try {
-			StringBuffer sbHeadings = new StringBuffer(
-					"Year,Crop,Imports (Mt),Exports (Mt),New export price, Stock Levels (Mt)");
-			BufferedWriter outputFile = getFileWriter(timestep, ModelConfig.PRICES_OUTPUT_FILE, sbHeadings.toString());
-
-			for (CropType crop : CropType.getImportedTypes()) {
-				StringBuffer sbData = new StringBuffer();
-				sbData.append(String.format("%d,%s", timestep.getYear(), crop.getGamsName()));
-				sbData.append(String.format(",%.1f,%.1f", prevWorldPrices.get(crop).getImportAmount(), prevWorldPrices.get(crop).getExportAmount()));
-				sbData.append(String.format(",%.3f,%.3f", prevWorldPrices.get(crop).getExportPrice(), prevStockLevel.get(crop)));
-
-				outputFile.write(sbData.toString());
-				outputFile.newLine();
-			}
-
+			BufferedWriter outputFile = getFileWriter(timestep, ModelConfig.PRICES_OUTPUT_FILE, "Year,Crop,Imports (Mt),Exports (Mt),New export price, Stock Levels (Mt)");
+			internationalMarket.writeGlobalMarketFile(timestep, outputFile);
 			outputFile.close();
 		} catch (IOException e) {
 			LogWriter.print(e);
@@ -298,8 +221,7 @@ public class ModelMain {
 
 	private void writeDemandFile(Timestep timestep) {
 		try {
-			StringBuffer sbHeadings = new StringBuffer("Year,Commodity,Amount (Mt)");
-			BufferedWriter outputFile = getFileWriter(timestep, ModelConfig.DEMAND_OUTPUT_FILE, sbHeadings.toString());
+			BufferedWriter outputFile = getFileWriter(timestep, ModelConfig.DEMAND_OUTPUT_FILE, "Year,Commodity,Amount (Mt)");
 
 			for (CommodityType comm : CommodityType.getAllItems()) {
 				double demandAmount = 0;
@@ -346,7 +268,7 @@ public class ModelMain {
 							return new LandUseItem();
 						}
 					};
-					intermediateLandUse.setup(prevLandUseRaster, landUseRaster, timestep.getPreviousTimestep().getYear(), timestep.getYear(), outputYear);
+					intermediateLandUse.setup(globalLandUseRaster, landUseRaster, timestep.getPreviousTimestep().getYear(), timestep.getYear(), outputYear);
 					landUseToOutput = intermediateLandUse;
 				}
 
@@ -560,10 +482,4 @@ public class ModelMain {
 			currentIrrigationData.updateIrrigConstraints(timestep);
 		}
 	}
-
-	private Map<CropType, Double> getInitialStockLevels() {
-		Map<CropType, Double> initialStockLevels = new StockReader().read();
-		initialStockLevels.put(CropType.ENERGY_CROPS, 0.0);
-		return initialStockLevels;
-	}
 }
diff --git a/src/ac/ed/lurg/country/CountryAgent.java b/src/ac/ed/lurg/country/CountryAgent.java
index f91e507a73f4fc23fe0dbf0440a82c20a29a4ae2..541ff4abcba9283810062fde74c737e47d928237 100644
--- a/src/ac/ed/lurg/country/CountryAgent.java
+++ b/src/ac/ed/lurg/country/CountryAgent.java
@@ -129,7 +129,7 @@ public class CountryAgent {
 			return result;
 		}
 		
-		return null;
+		throw new RuntimeException("Skipping optimisation of country " + country);
 	}
 	
 	public Map<CommodityType, Double> getCurrentProjectedDemand() {
@@ -206,4 +206,12 @@ public class CountryAgent {
 	
 		return countryPrices;
 	}
+
+	public RasterSet<LandUseItem> getLandUses() {
+		return previousGamsRasterOutput.getLandUses();
+	}
+
+	public Map<CropType, CropUsageData> getCropUsageData() {
+		return previousGamsRasterOutput.getCropUsageData();
+	}
 }