Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package com.mycompany.supersimplestockmarket; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import org.apache.commons.math3.stat.StatUtils; /** * * @author mark.mcleod */ public class StockMarket { private final List<Trade> trades = new ArrayList<>(); private final HashMap<StockSymbol, AbstractStock> stocks = new HashMap<>(); private final HashMap<AbstractStock, Double> lastTradePrices = new HashMap<>(); public void recordTrade(Trade trade) throws Exception { if (trade.getStock() == null) throw new Exception("Cannot trade a null stock"); trades.add(trade); lastTradePrices.put(trade.getStock(), trade.getTradePrice()); } public void addStock(AbstractStock stock) { stocks.put(stock.getStockSymbol(), stock); lastTradePrices.put(stock, 0.0); } public AbstractStock[] getStocks() { AbstractStock[] stockArray = new AbstractStock[stocks.size()]; int i = 0; for (AbstractStock stock : stocks.values()) stockArray[i++] = stock; return stockArray; } public AbstractStock getStockByStockSymbol(StockSymbol stockSymbol) { return stocks.get(stockSymbol); } public double getLastTradePrice(AbstractStock stock) { return lastTradePrices.get(stock); } public double calculateDividendYield(StockSymbol symbol, double price) throws Exception { AbstractStock stock = getStockByStockSymbol(symbol); if (stock == null) throw new Exception(String.format("Unknown stock symbol: %s", symbol)); return stock.getDividendYield(price); } public double calculatePeRatio(StockSymbol symbol, double price) throws Exception { AbstractStock stock = getStockByStockSymbol(symbol); if (stock == null) throw new Exception(String.format("Unknown stock symbol: %s", symbol)); return stock.getPeRatio(price); } public double calculateVolumeWeightedStockPrice(StockSymbol symbol) throws Exception { AbstractStock stock = getStockByStockSymbol(symbol); if (stock == null) throw new Exception(String.format("Unknown stock symbols %s", symbol)); double totalTradedPriceXquantity = 0.0; double totalQuantity = 0.0; double volumeWeightedStockPrice = 0.0; // ugly - better to use JodaTime here, but lets stick to standard libraries for now Date fifteenMinutesAgo = new Date(System.currentTimeMillis() - (15 * 60 * 1000)); // this is pretty inefficient, however chose for simplicity for (Trade trade : trades) { if (!trade.getStock().equals(stock)) continue; if (trade.getTimestamp().after(fifteenMinutesAgo)) { totalTradedPriceXquantity += (trade.getTradePrice() * trade.getQuantity()); totalQuantity += trade.getQuantity(); } } if (totalQuantity > 0.0) { volumeWeightedStockPrice = totalTradedPriceXquantity / totalQuantity; } return volumeWeightedStockPrice; } public double calculateGBCEAllShareIndex() throws Exception { double allShareIndex = 0.0; // build list of all stock prices for stocks that had trades in last 15 minutes (i.e. non zero ones) ArrayList<Double> stockPrices = new ArrayList<>(); for (AbstractStock stock : stocks.values()) { double stockPrice = calculateVolumeWeightedStockPrice(stock.getStockSymbol()); if (stockPrice > 0.0) stockPrices.add(stockPrice); } // convert to array of double, and calculate geometric mean if (stockPrices.size() > 0) { double[] prices = new double[stockPrices.size()]; int i = 0; for (Double price : stockPrices) prices[i++] = price; allShareIndex = StatUtils.geometricMean(prices); } return allShareIndex; } }