package com.activequant.timeseries; import java.util.List; public class DoubleColumn extends TypedColumn<Double> { private static final long serialVersionUID = 1L; private double[] doubleCache = null; public DoubleColumn(List<Double> list) { super(list); } public DoubleColumn() { super(); } public double[] asDouble() { if (doubleCache == null || isDirty()) { doubleCache = new double[size()]; for (int i = 0; i < doubleCache.length; i++) { if (get(i) != null) doubleCache[i] = get(i); } setClean(); } return doubleCache; } /** * Calculates the cumulated sum. if a value is null, it is ignored and treated like 0.0. * * @return a new column with cumsums */ public DoubleColumn cumsum() { DoubleColumn ret = new DoubleColumn(); Double currentVal = null; for (int i = 0; i < super.size(); i++) { Double val = super.get(i); if (currentVal != null && val != null) { currentVal += val; } else if(currentVal == null) currentVal = val; else currentVal = currentVal; ret.add(currentVal); } return ret; } /** * Calculates the sum * * @return */ public Double sum() { Double currentVal = null; for (int i = 0; i < super.size(); i++) { if (currentVal == null) currentVal = super.get(i); if (currentVal != null && i > 0 && super.get(i) != null) { currentVal = currentVal + super.get(i); } } return currentVal; } /** * multiplies each data point by factor. used to scale a data series for * comparison purposes. * * @return */ public DoubleColumn multiply(Double value) { DoubleColumn ret = new DoubleColumn(); for (int i = 0; i < super.size(); i++) { ret.add(i, super.get(i) == null ? 0 : super.get(i) * value); } return ret; } /* * makes this + second doublecolumn */ public DoubleColumn add(DoubleColumn other) { if (super.size() != other.size()) { throw new IllegalArgumentException( "The columns sizes are different. They must be the same."); } DoubleColumn ret = new DoubleColumn(); for (int i = 0; i < super.size(); i++) { ret.add((super.get(i) == null ? 0 : super.get(i)) + (other.get(i) == null ? 0 : other.get(i))); } return ret; } public DoubleColumn returns() { DoubleColumn ret = new DoubleColumn(); ret.add(0, null); for (int i = 1; i < this.size(); i++) { Double currentVal = this.get(i); Double formerVal = this.get(i - 1); if (formerVal != null) { ret.add(i, (currentVal - formerVal) / formerVal); } } return ret; } // mean of returns public Double mean() { Double sum = 0.0; for (int i = 1; i < this.size(); i++) { sum = sum + (this.get(i) - this.get(i - 1)) / this.get(i - 1); } return sum / (this.size() - 1); } // standard deviation of returns public Double std() { Double sum1 = 0.0; Double sum2 = 0.0; for (int i = 1; i < this.size(); i++) { Double ret = (this.get(i) - this.get(i - 1)) / this.get(i - 1); sum1 = sum1 + ret; sum2 = sum2 + ret * ret; } Double var = sum2 / (this.size() - 1) - (sum1 / (this.size() - 1)) * (sum1 / (this.size() - 1)); Double std = Math.sqrt(var); return Math.sqrt(var); } // maximum drawdown // implementation is taken from // http://en.wikipedia.org/wiki/Drawdown_%28economics%29 // except multiplier 100 on dd calculation line - MATLAB does not use this // multiplier // test is taken from matlab public Double maxDrawdown() { Double mdd = 0.0; Double peak = -Double.MAX_VALUE; Double dd = 0.0; for (int i = 0; i < this.size(); i++) { if (this.get(i) > peak) { peak = this.get(i); } else { dd = (peak - this.get(i)) / peak; if (dd > mdd) { mdd = dd; } } } return mdd; } // can not have from/to timestamp parameters, // because there is no timestamps column public Integer maxRecoveryTime() { Integer maxPeriod = 0; Integer currentLength = 0; Double currentVal = Double.MIN_VALUE; for (int i = 0; i < this.size(); i++) { if (this.get(i) < currentVal) { currentLength = currentLength + 1; } if (this.get(i) > currentVal) { currentLength = 0; currentVal = this.get(i); } if (currentLength > maxPeriod) { maxPeriod = currentLength; } } return maxPeriod; } }