EMlab-generation Documentation  1.0
Documentation of the EMLab-Generation model.
InvestInPowerGenerationTechnologiesWithCO2ForecastRole.java
1 /*******************************************************************************
2  * Copyright 2013 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  ******************************************************************************/
16 package emlab.gen.role.investment;
17 
18 import java.util.HashMap;
19 import java.util.Map;
20 import java.util.Map.Entry;
21 import java.util.Set;
22 import java.util.TreeMap;
23 
24 import org.apache.commons.math.stat.regression.SimpleRegression;
25 import org.springframework.beans.factory.annotation.Autowired;
26 import org.springframework.beans.factory.annotation.Configurable;
27 import org.springframework.data.annotation.Transient;
28 import org.springframework.data.neo4j.annotation.NodeEntity;
29 import org.springframework.data.neo4j.aspects.core.NodeBacked;
30 import org.springframework.data.neo4j.support.Neo4jTemplate;
31 import org.springframework.transaction.annotation.Transactional;
32 
33 import agentspring.role.Role;
59 
66 @Configurable
67 @NodeEntity
68 public class InvestInPowerGenerationTechnologiesWithCO2ForecastRole<T extends EnergyProducer> extends GenericInvestmentRole<T>
69 implements
70 Role<T>,
71 NodeBacked {
72 
73  @Transient
74  @Autowired
75  Reps reps;
76 
77  @Transient
78  @Autowired
79  Neo4jTemplate template;
80 
81  @Transient
82  @Autowired
83  StrategicReserveOperatorRepository strategicReserveOperatorRepository;
84 
85  // market expectations
86  @Transient
87  Map<ElectricitySpotMarket, MarketInformation> marketInfoMap = new HashMap<ElectricitySpotMarket, MarketInformation>();
88 
89  @Override
90  public void act(T agent) {
91 
92  long futureTimePoint = getCurrentTick() + agent.getInvestmentFutureTimeHorizon();
93  // logger.warn(agent + " is looking at timepoint " + futureTimePoint);
94 
95  // ==== Expectations ===
96 
97  Map<Substance, Double> expectedFuelPrices = predictFuelPrices(agent, futureTimePoint);
98 
99  // CO2
100  Map<ElectricitySpotMarket, Double> expectedCO2Price = determineExpectedCO2PriceInclTaxAndFundamentalForecast(
101  futureTimePoint,
102  agent.getNumberOfYearsBacklookingForForecasting(), 0, getCurrentTick());
103 
104  // logger.warn("{} expects CO2 prices {}", agent.getName(),
105  // expectedCO2Price);
106 
107  Map<ElectricitySpotMarket, Double> expectedCO2PriceOld = determineExpectedCO2PriceInclTax(futureTimePoint,
108  agent.getNumberOfYearsBacklookingForForecasting(), getCurrentTick());
109  // logger.warn("{} used to expect CO2 prices {}", agent.getName(),
110  // expectedCO2PriceOld);
111 
112  // logger.warn(expectedCO2Price.toString());
113 
114  //Demand
115  Map<ElectricitySpotMarket, Double> expectedDemand = new HashMap<ElectricitySpotMarket, Double>();
116  for(ElectricitySpotMarket elm : reps.template.findAll(ElectricitySpotMarket.class)){
118  for(long time = getCurrentTick(); time>getCurrentTick()-agent.getNumberOfYearsBacklookingForForecasting() && time>=0; time=time-1){
119  gtr.addData(time, elm.getDemandGrowthTrend().getValue(time));
120  }
121  expectedDemand.put(elm, gtr.predict(futureTimePoint));
122  }
123 
124 
125 
126  // Investment decision
127  // for (ElectricitySpotMarket market :
128  // reps.genericRepository.findAllAtRandom(ElectricitySpotMarket.class))
129  // {
130  ElectricitySpotMarket market = agent.getInvestorMarket();
131  MarketInformation marketInformation = new MarketInformation(market, expectedDemand, expectedFuelPrices, expectedCO2Price.get(market)
132  .doubleValue(), futureTimePoint);
133  /*
134  * if (marketInfoMap.containsKey(market) && marketInfoMap.get(market).time == futureTimePoint) { marketInformation = marketInfoMap.get(market); } else { marketInformation = new
135  * MarketInformation(market, expectedFuelPrices, expectedCO2Price, futureTimePoint); marketInfoMap.put(market, marketInformation); }
136  */
137 
138  // logger.warn(agent + " is expecting a CO2 price of " +
139  // expectedCO2Price.get(market) + " Euro/MWh at timepoint "
140  // + futureTimePoint + " in Market " + market);
141 
142  // logger.warn("Agent {} found the expected prices to be {}", agent,
143  // marketInformation.expectedElectricityPricesPerSegment);
144 
145  // logger.warn("Agent {} found that the installed capacity in the market {} in future to be "
146  // + marketInformation.capacitySum +
147  // "and expectde maximum demand to be "
148  // + marketInformation.maxExpectedLoad, agent, market);
149 
150  double highestValue = Double.MIN_VALUE;
151  PowerGeneratingTechnology bestTechnology = null;
152 
153  for (PowerGeneratingTechnology technology : reps.genericRepository.findAll(PowerGeneratingTechnology.class)) {
154 
155  PowerPlant plant = new PowerPlant();
156  plant.specifyNotPersist(getCurrentTick(), agent, getNodeForZone(market.getZone()), technology);
157  // if too much capacity of this technology in the pipeline (not
158  // limited to the 5 years)
159  double expectedInstalledCapacityOfTechnology = reps.powerPlantRepository
160  .calculateCapacityOfExpectedOperationalPowerPlantsInMarketAndTechnology(market, technology, futureTimePoint);
161  PowerGeneratingTechnologyTarget technologyTarget = reps.powerGenerationTechnologyTargetRepository.findOneByTechnologyAndMarket(technology, market);
162  if(technologyTarget!=null){
163  double technologyTargetCapacity = technologyTarget.getTrend().getValue(futureTimePoint);
164  expectedInstalledCapacityOfTechnology = (technologyTargetCapacity > expectedInstalledCapacityOfTechnology) ? technologyTargetCapacity : expectedInstalledCapacityOfTechnology;
165  }
166  double pgtNodeLimit = Double.MAX_VALUE;
167  PowerGeneratingTechnologyNodeLimit pgtLimit = reps.powerGeneratingTechnologyNodeLimitRepository
168  .findOneByTechnologyAndNode(technology, plant.getLocation());
169  if (pgtLimit != null) {
170  pgtNodeLimit = pgtLimit.getUpperCapacityLimit(futureTimePoint);
171  }
172  double expectedInstalledCapacityOfTechnologyInNode = reps.powerPlantRepository
173  .calculateCapacityOfExpectedOperationalPowerPlantsByNodeAndTechnology(plant.getLocation(),
174  technology, futureTimePoint);
175  double expectedOwnedTotalCapacityInMarket = reps.powerPlantRepository
176  .calculateCapacityOfExpectedOperationalPowerPlantsInMarketByOwner(market, futureTimePoint, agent);
177  double expectedOwnedCapacityInMarketOfThisTechnology = reps.powerPlantRepository
178  .calculateCapacityOfExpectedOperationalPowerPlantsInMarketByOwnerAndTechnology(market, technology, futureTimePoint,
179  agent);
180  double capacityOfTechnologyInPipeline = reps.powerPlantRepository.calculateCapacityOfPowerPlantsByTechnologyInPipeline(
181  technology, getCurrentTick());
182  double operationalCapacityOfTechnology = reps.powerPlantRepository.calculateCapacityOfOperationalPowerPlantsByTechnology(
183  technology, getCurrentTick());
184  double capacityInPipelineInMarket = reps.powerPlantRepository
185  .calculateCapacityOfPowerPlantsByMarketInPipeline(market, getCurrentTick());
186 
187  if ((expectedInstalledCapacityOfTechnology + plant.getActualNominalCapacity())
188  / (marketInformation.maxExpectedLoad + plant.getActualNominalCapacity()) > technology
189  .getMaximumInstalledCapacityFractionInCountry()) {
190  // logger.warn(agent +
191  // " will not invest in {} technology because there's too much of this type in the market",
192  // technology);
193  } else if ((expectedInstalledCapacityOfTechnologyInNode + plant.getActualNominalCapacity()) > pgtNodeLimit) {
194 
195  } else if (expectedOwnedCapacityInMarketOfThisTechnology > expectedOwnedTotalCapacityInMarket
196  * technology.getMaximumInstalledCapacityFractionPerAgent()) {
197  // logger.warn(agent +
198  // " will not invest in {} technology because there's too much capacity planned by him",
199  // technology);
200  } else if (capacityInPipelineInMarket > 0.2 * marketInformation.maxExpectedLoad) {
201  // logger.warn("Not investing because more than 20% of demand in pipeline.");
202 
203  } else if ((capacityOfTechnologyInPipeline > 2.0 * operationalCapacityOfTechnology)
204  && capacityOfTechnologyInPipeline > 9000) { // TODO:
205  // reflects that you cannot expand a technology out of zero.
206  // logger.warn(agent +
207  // " will not invest in {} technology because there's too much capacity in the pipeline",
208  // technology);
209  } else if (plant.getActualInvestedCapital() * (1 - agent.getDebtRatioOfInvestments()) > agent
210  .getDownpaymentFractionOfCash() * agent.getCash()) {
211  // logger.warn(agent +
212  // " will not invest in {} technology as he does not have enough money for downpayment",
213  // technology);
214  } else {
215 
216  Map<Substance, Double> myFuelPrices = new HashMap<Substance, Double>();
217  for (Substance fuel : technology.getFuels()) {
218  myFuelPrices.put(fuel, expectedFuelPrices.get(fuel));
219  }
220  Set<SubstanceShareInFuelMix> fuelMix = calculateFuelMix(plant, myFuelPrices, expectedCO2Price.get(market));
221  plant.setFuelMix(fuelMix);
222 
223  double expectedMarginalCost = determineExpectedMarginalCost(plant, expectedFuelPrices, expectedCO2Price.get(market));
224  double runningHours = 0d;
225  double expectedGrossProfit = 0d;
226 
227  long numberOfSegments = reps.segmentRepository.count();
228 
229  // TODO somehow the prices of long-term contracts could also
230  // be used here to determine the expected profit. Maybe not
231  // though...
232  for (SegmentLoad segmentLoad : market.getLoadDurationCurve()) {
233  double expectedElectricityPrice = marketInformation.expectedElectricityPricesPerSegment.get(segmentLoad
234  .getSegment());
235  double hours = segmentLoad.getSegment().getLengthInHours();
236  if (expectedMarginalCost <= expectedElectricityPrice) {
237  runningHours += hours;
238  expectedGrossProfit += (expectedElectricityPrice - expectedMarginalCost) * hours
239  * plant.getAvailableCapacity(futureTimePoint, segmentLoad.getSegment(), numberOfSegments);
240  }
241  }
242 
243  // logger.warn(agent +
244  // "expects technology {} to have {} running", technology,
245  // runningHours);
246  // expect to meet minimum running hours?
247  if (runningHours < plant.getTechnology().getMinimumRunningHours()) {
248  // logger.warn(agent+
249  // " will not invest in {} technology as he expect to have {} running, which is lower then required",
250  // technology, runningHours);
251  } else {
252 
253  double fixedOMCost = calculateFixedOperatingCost(plant, getCurrentTick());// /
254  // plant.getActualNominalCapacity();
255 
256  double operatingProfit = expectedGrossProfit - fixedOMCost;
257 
258  // TODO Alter discount rate on the basis of the amount
259  // in long-term contracts?
260  // TODO Alter discount rate on the basis of other stuff,
261  // such as amount of money, market share, portfolio
262  // size.
263 
264  // Calculation of weighted average cost of capital,
265  // based on the companies debt-ratio
266  double wacc = (1 - agent.getDebtRatioOfInvestments()) * agent.getEquityInterestRate()
267  + agent.getDebtRatioOfInvestments() * agent.getLoanInterestRate();
268 
269  // Creation of out cash-flow during power plant building
270  // phase (note that the cash-flow is negative!)
271  TreeMap<Integer, Double> discountedProjectCapitalOutflow = calculateSimplePowerPlantInvestmentCashFlow(
272  technology.getDepreciationTime(), (int) plant.getActualLeadtime(),
273  plant.getActualInvestedCapital(), 0);
274  // Creation of in cashflow during operation
275  TreeMap<Integer, Double> discountedProjectCashInflow = calculateSimplePowerPlantInvestmentCashFlow(
276  technology.getDepreciationTime(), (int) plant.getActualLeadtime(), 0, operatingProfit);
277 
278  double discountedCapitalCosts = npv(discountedProjectCapitalOutflow, wacc);// are
279  // defined
280  // negative!!
281  // plant.getActualNominalCapacity();
282 
283  // logger.warn("Agent {} found that the discounted capital for technology {} to be "
284  // + discountedCapitalCosts, agent,
285  // technology);
286 
287  double discountedOpProfit = npv(discountedProjectCashInflow, wacc);
288 
289  // logger.warn("Agent {} found that the projected discounted inflows for technology {} to be "
290  // + discountedOpProfit,
291  // agent, technology);
292 
293  double projectValue = discountedOpProfit + discountedCapitalCosts;
294 
295  // logger.warn(
296  // "Agent {} found the project value for technology {} to be "
297  // + Math.round(projectValue /
298  // plant.getActualNominalCapacity()) +
299  // " EUR/kW (running hours: "
300  // + runningHours + "", agent, technology);
301 
302  // double projectTotalValue = projectValuePerMW *
303  // plant.getActualNominalCapacity();
304 
305  // double projectReturnOnInvestment = discountedOpProfit
306  // / (-discountedCapitalCosts);
307 
308  /*
309  * Divide by capacity, in order not to favour large power plants (which have the single largest NPV
310  */
311 
312  if (projectValue > 0 && projectValue / plant.getActualNominalCapacity() > highestValue) {
313  highestValue = projectValue / plant.getActualNominalCapacity();
314  bestTechnology = plant.getTechnology();
315  }
316  }
317 
318  }
319  }
320 
321  if (bestTechnology != null) {
322  // logger.warn("Agent {} invested in technology {} at tick " + getCurrentTick(), agent, bestTechnology);
323 
324  PowerPlant plant = new PowerPlant();
325  plant.specifyAndPersist(getCurrentTick(), agent, getNodeForZone(market.getZone()), bestTechnology);
326  PowerPlantManufacturer manufacturer = reps.genericRepository.findFirst(PowerPlantManufacturer.class);
327  BigBank bigbank = reps.genericRepository.findFirst(BigBank.class);
328 
329  double investmentCostPayedByEquity = plant.getActualInvestedCapital() * (1 - agent.getDebtRatioOfInvestments());
330  double investmentCostPayedByDebt = plant.getActualInvestedCapital() * agent.getDebtRatioOfInvestments();
331  double downPayment = investmentCostPayedByEquity;
332  createSpreadOutDownPayments(agent, manufacturer, downPayment, plant);
333 
334  double amount = determineLoanAnnuities(investmentCostPayedByDebt, plant.getTechnology().getDepreciationTime(),
335  agent.getLoanInterestRate());
336  // logger.warn("Loan amount is: " + amount);
337  Loan loan = reps.loanRepository.createLoan(agent, bigbank, amount, plant.getTechnology().getDepreciationTime(),
338  getCurrentTick(), plant);
339  // Create the loan
340  plant.createOrUpdateLoan(loan);
341 
342  } else {
343  // logger.warn("{} found no suitable technology anymore to invest in at tick "
344  // + getCurrentTick(), agent);
345  // agent will not participate in the next round of investment if
346  // he does not invest now
347  setNotWillingToInvest(agent);
348  }
349  }
350 
351  // }
352 
353  // Creates n downpayments of equal size in each of the n building years of a
354  // power plant
355  @Transactional
356  private void createSpreadOutDownPayments(EnergyProducer agent, PowerPlantManufacturer manufacturer, double totalDownPayment,
357  PowerPlant plant) {
358  int buildingTime = (int) plant.getActualLeadtime();
359  reps.nonTransactionalCreateRepository.createCashFlow(agent, manufacturer, totalDownPayment / buildingTime,
360  CashFlow.DOWNPAYMENT, getCurrentTick(), plant);
361  Loan downpayment = reps.loanRepository.createLoan(agent, manufacturer, totalDownPayment / buildingTime,
362  buildingTime - 1, getCurrentTick(), plant);
363  plant.createOrUpdateDownPayment(downpayment);
364  }
365 
366  @Transactional
367  private void setNotWillingToInvest(EnergyProducer agent) {
368  agent.setWillingToInvest(false);
369  }
370 
378  public Map<Substance, Double> predictFuelPrices(EnergyProducer agent, long futureTimePoint){
379  // Fuel Prices
380  Map<Substance, Double> expectedFuelPrices = new HashMap<Substance, Double>();
381  for (Substance substance : reps.substanceRepository.findAllSubstancesTradedOnCommodityMarkets()) {
382  //Find Clearing Points for the last 5 years (counting current year as one of the last 5 years).
383  Iterable<ClearingPoint> cps = reps.clearingPointRepository
384  .findAllClearingPointsForSubstanceTradedOnCommodityMarkesAndTimeRange(substance, getCurrentTick()
385  - (agent.getNumberOfYearsBacklookingForForecasting() - 1), getCurrentTick(), false);
386  //logger.warn("{}, {}", getCurrentTick()-(agent.getNumberOfYearsBacklookingForForecasting()-1), getCurrentTick());
387  //Create regression object
388  SimpleRegression gtr = new SimpleRegression();
389  for (ClearingPoint clearingPoint : cps) {
390  //logger.warn("CP {}: {} , in" + clearingPoint.getTime(), substance.getName(), clearingPoint.getPrice());
391  gtr.addData(clearingPoint.getTime(), clearingPoint.getPrice());
392  }
393  gtr.addData(getCurrentTick(), findLastKnownPriceForSubstance(substance, getCurrentTick()));
394  expectedFuelPrices.put(substance, gtr.predict(futureTimePoint));
395  //logger.warn("Forecast {}: {}, in Step " + futureTimePoint, substance, expectedFuelPrices.get(substance));
396  }
397  return expectedFuelPrices;
398  }
399 
400  // Create a powerplant investment and operation cash-flow in the form of a
401  // map. If only investment, or operation costs should be considered set
402  // totalInvestment or operatingProfit to 0
403  private TreeMap<Integer, Double> calculateSimplePowerPlantInvestmentCashFlow(int depriacationTime, int buildingTime,
404  double totalInvestment, double operatingProfit) {
405  TreeMap<Integer, Double> investmentCashFlow = new TreeMap<Integer, Double>();
406  double equalTotalDownPaymentInstallement = totalInvestment / buildingTime;
407  for (int i = 0; i < buildingTime; i++) {
408  investmentCashFlow.put(new Integer(i), -equalTotalDownPaymentInstallement);
409  }
410  for (int i = buildingTime; i < depriacationTime + buildingTime; i++) {
411  investmentCashFlow.put(new Integer(i), operatingProfit);
412  }
413 
414  return investmentCashFlow;
415  }
416 
417  private double npv(TreeMap<Integer, Double> netCashFlow, double wacc) {
418  double npv = 0;
419  for (Integer iterator : netCashFlow.keySet()) {
420  npv += netCashFlow.get(iterator).doubleValue() / Math.pow(1 + wacc, iterator.intValue());
421  }
422  return npv;
423  }
424 
425  public double determineExpectedMarginalCost(PowerPlant plant, Map<Substance, Double> expectedFuelPrices, double expectedCO2Price) {
426  double mc = determineExpectedMarginalFuelCost(plant, expectedFuelPrices);
427  double co2Intensity = plant.calculateEmissionIntensity();
428  mc += co2Intensity * expectedCO2Price;
429  return mc;
430  }
431 
432  public double determineExpectedMarginalFuelCost(PowerPlant powerPlant, Map<Substance, Double> expectedFuelPrices) {
433  double fc = 0d;
434  for (SubstanceShareInFuelMix mix : powerPlant.getFuelMix()) {
435  double amount = mix.getShare();
436  double fuelPrice = expectedFuelPrices.get(mix.getSubstance());
437  fc += amount * fuelPrice;
438  }
439  return fc;
440  }
441 
442  private PowerGridNode getNodeForZone(Zone zone) {
443  for (PowerGridNode node : reps.genericRepository.findAll(PowerGridNode.class)) {
444  if (node.getZone().equals(zone)) {
445  return node;
446  }
447  }
448  return null;
449  }
450 
451  private class MarketInformation {
452 
453  Map<Segment, Double> expectedElectricityPricesPerSegment;
454  double maxExpectedLoad = 0d;
455  Map<PowerPlant, Double> meritOrder;
456  double capacitySum;
457 
458  MarketInformation(ElectricitySpotMarket market, Map<ElectricitySpotMarket, Double> expectedDemand, Map<Substance, Double> fuelPrices, double co2price, long time) {
459  // determine expected power prices
460  expectedElectricityPricesPerSegment = new HashMap<Segment, Double>();
461  Map<PowerPlant, Double> marginalCostMap = new HashMap<PowerPlant, Double>();
462  capacitySum = 0d;
463 
464  // get merit order for this market
465  for (PowerPlant plant : reps.powerPlantRepository.findExpectedOperationalPowerPlantsInMarket(market, time)) {
466 
467  double plantMarginalCost = determineExpectedMarginalCost(plant, fuelPrices, co2price);
468  marginalCostMap.put(plant, plantMarginalCost);
469  capacitySum += plant.getActualNominalCapacity();
470  }
471 
472  //get difference between technology target and expected operational capacity
473  for(PowerGeneratingTechnologyTarget pggt : reps.powerGenerationTechnologyTargetRepository.findAllByMarket(market)){
474  double expectedTechnologyCapacity = reps.powerPlantRepository.calculateCapacityOfExpectedOperationalPowerPlantsInMarketAndTechnology(market, pggt.getPowerGeneratingTechnology(), time);
475  double targetDifference = pggt.getTrend().getValue(time) - expectedTechnologyCapacity;
476  if(targetDifference > 0){
477  PowerPlant plant = new PowerPlant();
478  plant.specifyNotPersist(getCurrentTick(), new EnergyProducer(), reps.powerGridNodeRepository.findFirstPowerGridNodeByElectricitySpotMarket(market), pggt.getPowerGeneratingTechnology());
479  plant.setActualNominalCapacity(targetDifference);
480  double plantMarginalCost = determineExpectedMarginalCost(plant, fuelPrices, co2price);
481  marginalCostMap.put(plant, plantMarginalCost);
482  capacitySum += targetDifference;
483  }
484  }
485 
486  MapValueComparator comp = new MapValueComparator(marginalCostMap);
487  meritOrder = new TreeMap<PowerPlant, Double>(comp);
488  meritOrder.putAll(marginalCostMap);
489 
490  long numberOfSegments = reps.segmentRepository.count();
491 
492  double demandFactor = expectedDemand.get(market).doubleValue();
493 
494  // find expected prices per segment given merit order
495  for (SegmentLoad segmentLoad : market.getLoadDurationCurve()) {
496 
497  double expectedSegmentLoad = segmentLoad.getBaseLoad() * demandFactor;
498 
499  if (expectedSegmentLoad > maxExpectedLoad) {
500  maxExpectedLoad = expectedSegmentLoad;
501  }
502 
503  double segmentSupply = 0d;
504  double segmentPrice = 0d;
505  double totalCapacityAvailable = 0d;
506 
507  for (Entry<PowerPlant, Double> plantCost : meritOrder.entrySet()) {
508  PowerPlant plant = plantCost.getKey();
509  double plantCapacity = 0d;
510  // Determine available capacity in the future in this
511  // segment
512  plantCapacity = plant.getExpectedAvailableCapacity(time, segmentLoad.getSegment(), numberOfSegments);
513  totalCapacityAvailable += plantCapacity;
514  // logger.warn("Capacity of plant " + plant.toString() +
515  // " is " +
516  // plantCapacity/plant.getActualNominalCapacity());
517  if (segmentSupply < expectedSegmentLoad) {
518  segmentSupply += plantCapacity;
519  segmentPrice = plantCost.getValue();
520  }
521 
522  }
523 
524  // logger.warn("Segment " +
525  // segmentLoad.getSegment().getSegmentID() + " supply equals " +
526  // segmentSupply + " and segment demand equals " +
527  // expectedSegmentLoad);
528 
529  // Find strategic reserve operator for the market.
530  double reservePrice = 0;
531  double reserveVolume = 0;
532  for (StrategicReserveOperator operator : strategicReserveOperatorRepository.findAll()) {
533  ElectricitySpotMarket market1 = reps.marketRepository.findElectricitySpotMarketForZone(operator
534  .getZone());
535  if (market.getNodeId().intValue() == market1.getNodeId().intValue()) {
536  reservePrice = operator.getReservePriceSR();
537  reserveVolume = operator.getReserveVolume();
538  }
539  }
540 
541  if (segmentSupply >= expectedSegmentLoad
542  && ((totalCapacityAvailable - expectedSegmentLoad) <= (reserveVolume))) {
543  expectedElectricityPricesPerSegment.put(segmentLoad.getSegment(), reservePrice);
544  // logger.warn("Price: "+
545  // expectedElectricityPricesPerSegment);
546  } else if (segmentSupply >= expectedSegmentLoad
547  && ((totalCapacityAvailable - expectedSegmentLoad) > (reserveVolume))) {
548  expectedElectricityPricesPerSegment.put(segmentLoad.getSegment(), segmentPrice);
549  // logger.warn("Price: "+
550  // expectedElectricityPricesPerSegment);
551  } else {
552  expectedElectricityPricesPerSegment.put(segmentLoad.getSegment(), market.getValueOfLostLoad());
553  }
554 
555  }
556  }
557  }
558 
571  protected HashMap<ElectricitySpotMarket, Double> determineExpectedCO2PriceInclTaxAndFundamentalForecast(
572  long futureTimePoint, long yearsLookingBackForRegression, int adjustmentForDetermineFuelMix,
573  long clearingTick) {
574  HashMap<ElectricitySpotMarket, Double> co2Prices = new HashMap<ElectricitySpotMarket, Double>();
575  CO2Auction co2Auction = reps.genericRepository.findFirst(CO2Auction.class);
576  Iterable<ClearingPoint> cps = reps.clearingPointRepository.findAllClearingPointsForMarketAndTimeRange(
577  co2Auction, clearingTick - yearsLookingBackForRegression + 1 - adjustmentForDetermineFuelMix,
578  clearingTick - adjustmentForDetermineFuelMix, false);
579  // Create regression object and calculate average
580  SimpleRegression sr = new SimpleRegression();
581  Government government = reps.template.findAll(Government.class).iterator().next();
582  double lastPrice = 0;
583  double averagePrice = 0;
584  int i = 0;
585  for (ClearingPoint clearingPoint : cps) {
586  sr.addData(clearingPoint.getTime(), clearingPoint.getPrice());
587  lastPrice = clearingPoint.getPrice();
588  averagePrice += lastPrice;
589  i++;
590  }
591  averagePrice = averagePrice / i;
592  double expectedCO2Price;
593  double expectedRegressionCO2Price;
594  if (i > 1) {
595  expectedRegressionCO2Price = sr.predict(futureTimePoint);
596  expectedRegressionCO2Price = Math.max(0, expectedRegressionCO2Price);
597  expectedRegressionCO2Price = Math
598  .min(expectedRegressionCO2Price, government.getCo2Penalty(futureTimePoint));
599  } else {
600  expectedRegressionCO2Price = lastPrice;
601  }
602  ClearingPoint expectedCO2ClearingPoint = reps.clearingPointRepository.findClearingPointForMarketAndTime(
603  co2Auction,
604  getCurrentTick()
605  + reps.genericRepository.findFirst(DecarbonizationModel.class).getCentralForecastingYear(),
606  true);
607  expectedCO2Price = (expectedCO2ClearingPoint == null) ? 0 : expectedCO2ClearingPoint.getPrice();
608  expectedCO2Price = (expectedCO2Price + expectedRegressionCO2Price) / 2;
609  for (ElectricitySpotMarket esm : reps.marketRepository.findAllElectricitySpotMarkets()) {
610  double nationalCo2MinPriceinFutureTick = reps.nationalGovernmentRepository
611  .findNationalGovernmentByElectricitySpotMarket(esm).getMinNationalCo2PriceTrend()
612  .getValue(futureTimePoint);
613  double co2PriceInCountry = 0d;
614  if (expectedCO2Price > nationalCo2MinPriceinFutureTick) {
615  co2PriceInCountry = expectedCO2Price;
616  } else {
617  co2PriceInCountry = nationalCo2MinPriceinFutureTick;
618  }
619  co2PriceInCountry += reps.genericRepository.findFirst(Government.class).getCO2Tax(futureTimePoint);
620  co2Prices.put(esm, Double.valueOf(co2PriceInCountry));
621  }
622  return co2Prices;
623  }
624 
625 }
HashMap< ElectricitySpotMarket, Double > determineExpectedCO2PriceInclTaxAndFundamentalForecast(long futureTimePoint, long yearsLookingBackForRegression, int adjustmentForDetermineFuelMix, long clearingTick)