/** * Adds a data item to the series. * * @param notify the notify listeners. * @param dataItem MACDItem */ public void add(MACDItem dataItem, boolean notify) { if (!this.isEmpty()) { MACDItem item0 = (MACDItem) this.getDataItem(0); if (!dataItem.getPeriod().getClass().equals(item0.getPeriod().getClass())) { throw new IllegalArgumentException("Can't mix RegularTimePeriod class types."); } } super.add(dataItem, notify); }
/** * Adds a data item to the series. * * @param period the period. * @param MACD the MACD. */ public void add( RegularTimePeriod period, BigDecimal MACD, BigDecimal signalLine, BigDecimal MACDHistogram) { if (!this.isEmpty()) { MACDItem item0 = (MACDItem) this.getDataItem(0); if (!period.getClass().equals(item0.getPeriod().getClass())) { throw new IllegalArgumentException("Can't mix RegularTimePeriod class types."); } } super.add(new MACDItem(period, MACD, signalLine, MACDHistogram), true); }
/** Method printSeries. */ public void printSeries() { for (int i = 0; i < this.getItemCount(); i++) { MACDItem dataItem = (MACDItem) this.getDataItem(i); _log.debug( "Type: " + this.getType() + " Time: " + dataItem.getPeriod().getStart() + " Value: " + dataItem.getMACD()); } }
/** * Returns the true/false if the date falls within a period. * * @param date the date for which we want a period. * @return exists */ public int indexOf(Date date) { for (int i = this.data.size(); i > 0; i--) { MACDItem item = (MACDItem) this.data.get(i - 1); if (date.getTime() > item.getPeriod().getLastMillisecond()) { break; } if ((date.getTime() >= item.getPeriod().getFirstMillisecond()) && (date.getTime() <= item.getPeriod().getLastMillisecond())) { return i - 1; } } return -1; }
/** * Method updateSeries. * * @param source CandleSeries * @param skip int * @param newBar boolean */ public void updateSeries(CandleSeries source, int skip, boolean newBar) { if (source == null) { throw new IllegalArgumentException("Null source (CandleSeries)."); } if (getFastLength() == null || getFastLength() < 1) { throw new IllegalArgumentException("Fast MA must be greater than zero."); } if (getSlowLength() == null || getSlowLength() < 1) { throw new IllegalArgumentException("Slow MA must be greater than zero."); } if (getSignalSmoothing() == null || getSignalSmoothing() < 1) { throw new IllegalArgumentException("Signal Smoothing must be greater than zero."); } if (getSlowLength() < getFastLength()) { throw new IllegalArgumentException("Fast MA must be greater than Slow MA."); } if (source.getItemCount() > skip) { // get the current data item... CandleItem candleItem = (CandleItem) source.getDataItem(skip); // work out the average for the earlier values... Number yy = candleItem.getY(); if (null != yy) { if (this.fastYYValues.size() == getFastLength()) { /* * If the item does not exist in the series then this is a * new time period and so we need to remove the last in the * set and add the new periods values. Otherwise we just * update the last value in the set. Sum is just used for * performance save having to sum the last set of values * each time. */ if (newBar) { fastSum = fastSum - this.fastYYValues.getLast() + yy.doubleValue(); this.fastYYValues.removeLast(); this.fastYYValues.addFirst(yy.doubleValue()); } else { fastSum = fastSum - this.fastYYValues.getFirst() + yy.doubleValue(); this.fastYYValues.removeFirst(); this.fastYYValues.addFirst(yy.doubleValue()); } } else { if (newBar) { fastSum = fastSum + yy.doubleValue(); this.fastYYValues.addFirst(yy.doubleValue()); } else { fastSum = fastSum + yy.doubleValue() - this.fastYYValues.getFirst(); this.fastYYValues.removeFirst(); this.fastYYValues.addFirst(yy.doubleValue()); } } if (this.slowYYValues.size() == getSlowLength()) { /* * If the item does not exist in the series then this is a * new time period and so we need to remove the last in the * set and add the new periods values. Otherwise we just * update the last value in the set. Sum is just used for * performance save having to sum the last set of values * each time. */ if (newBar) { slowSum = slowSum - this.slowYYValues.getLast() + yy.doubleValue(); this.slowYYValues.removeLast(); this.slowYYValues.addFirst(yy.doubleValue()); } else { slowSum = slowSum - this.slowYYValues.getFirst() + yy.doubleValue(); this.slowYYValues.removeFirst(); this.slowYYValues.addFirst(yy.doubleValue()); } } else { if (newBar) { slowSum = slowSum + yy.doubleValue(); this.slowYYValues.addFirst(yy.doubleValue()); } else { slowSum = slowSum + yy.doubleValue() - this.slowYYValues.getFirst(); this.slowYYValues.removeFirst(); this.slowYYValues.addFirst(yy.doubleValue()); } } if (this.slowYYValues.size() == getSlowLength()) { double fastEMA = 0; if (fastMultiplyer == Double.MAX_VALUE) { fastEMA = fastSum / this.getFastLength(); fastMultiplyer = 2 / (this.getFastLength() + 1.0d); } else { fastEMA = ((this.fastYYValues.getFirst() - prevFastEMA) * fastMultiplyer) + prevFastEMA; } prevFastEMA = fastEMA; double slowEMA = 0; if (slowMultiplyer == Double.MAX_VALUE) { slowEMA = slowSum / this.getSlowLength(); slowMultiplyer = 2 / (this.getSlowLength() + 1.0d); } else { slowEMA = ((this.slowYYValues.getFirst() - prevSlowEMA) * slowMultiplyer) + prevSlowEMA; } prevSlowEMA = slowEMA; double MACD = fastEMA - slowEMA; if (this.signalSmoothingYYValues.size() == this.getSignalSmoothing()) { /* * If the item does not exist in the series then this is * a new time period and so we need to remove the last * in the set and add the new periods values. Otherwise * we just update the last value in the set. Sum is just * used for performance save having to sum the last set * of values each time. */ if (newBar) { signalSmoothingSum = signalSmoothingSum - this.signalSmoothingYYValues.getLast() + MACD; this.signalSmoothingYYValues.removeLast(); this.signalSmoothingYYValues.addFirst(MACD); } else { signalSmoothingSum = signalSmoothingSum - this.signalSmoothingYYValues.getFirst() + MACD; this.signalSmoothingYYValues.removeFirst(); this.signalSmoothingYYValues.addFirst(MACD); } } else { if (newBar) { signalSmoothingSum = signalSmoothingSum + MACD; this.signalSmoothingYYValues.addFirst(MACD); } else { signalSmoothingSum = signalSmoothingSum + MACD - this.signalSmoothingYYValues.getFirst(); this.signalSmoothingYYValues.removeFirst(); this.signalSmoothingYYValues.addFirst(MACD); } } double signalLine = Double.MAX_VALUE; if (this.signalSmoothingYYValues.size() == getSignalSmoothing()) { signalLine = calculateSmoothingMA( this.signalSmoothingYYValues.getFirst(), this.prevSignalSmoothingEMA, this.signalSmoothingSum); this.prevSignalSmoothingEMA = signalLine; } if (newBar) { MACDItem dataItem = new MACDItem( candleItem.getPeriod(), new BigDecimal(MACD), (signalLine == Double.MAX_VALUE ? null : new BigDecimal(signalLine)), (signalLine == Double.MAX_VALUE ? null : new BigDecimal(MACD - signalLine))); this.add(dataItem, false); } else { MACDItem dataItem = (MACDItem) this.getDataItem(this.getItemCount() - 1); dataItem.setMACD(MACD); if (signalLine == Double.MAX_VALUE) { dataItem.setSignalLine(signalLine); dataItem.setMACDHistogram(MACD - signalLine); } } } } } }
/** * Returns the time period for the specified item. * * @param index the item index. * @return The time period. */ public RegularTimePeriod getPeriod(int index) { final MACDItem item = (MACDItem) getDataItem(index); return item.getPeriod(); }