package org.chartsy.main.data; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * * @author Viorel */ public final class DatasetUtilities { public static final int OPEN_PRICE = 0; public static final int HIGH_PRICE = 1; public static final int LOW_PRICE = 2; public static final int CLOSE_PRICE = 3; public static final int VOLUME_PRICE = 4; public static final String OPEN = "Open"; public static final String HIGH = "High"; public static final String LOW = "Low"; public static final String CLOSE = "Close"; public static final String VOLUME = "Volume"; public static final String[] LIST = new String[] { OPEN, HIGH, LOW, CLOSE }; private DatasetUtilities() { } public static int getPrice(String price) { for (int i = 0; i < LIST.length; i++) if (price.equals(LIST[i])) return i; return 3; // Default Close } public static Dataset getVisibleDataset(Dataset dataset, int period, int end) { return new Dataset(getVisibleItems(dataset, period, end)); } public static List<DataItem> getVisibleItems(Dataset dataset, int period, int end) { List<DataItem> list = new ArrayList<DataItem>(); for (int i = 0; i < period; i++) { int j = end - period + i; if (j < dataset.getItemsCount() && j >= 0) { list.add(dataset.getDataItem(j)); } } return list; } public static DataItem[] getVisibleItemsArray(Dataset dataset, int period, int end) { DataItem[] list = new DataItem[period]; for (int i = 0; i < period; i++) { int j = end - period + i; if (j < dataset.getItemsCount() && j >= 0) list[i] = dataset.getDataItem(j); } return list; } public static Dataset EMPTY(int count) { List<DataItem> items = new ArrayList<DataItem>(count); Collections.fill(items, null); return new Dataset(items); } public static Dataset CONST(Dataset dataset, double ct) { if (dataset == null) return null; int count = dataset.getItemsCount(); Dataset result = EMPTY(count); for (int i = 0; i < count; i++) { long time = dataset.getTimeAt(i); DataItem item = new DataItem(time, ct); result.setDataItem(i, item); } return result; } public static Dataset LOG(Dataset dataset) { if (dataset == null) return null; int count = dataset.getItemsCount(); Dataset result = EMPTY(count); for (int i = 0; i < count; i++) { if (dataset.getDataItem(i) != null) { long time = dataset.getTimeAt(i); double open = Math.log10(dataset.getOpenAt(i)); double high = Math.log10(dataset.getHighAt(i)); double low = Math.log10(dataset.getLowAt(i)); double close = Math.log10(dataset.getCloseAt(i)); double volume = Math.log10(dataset.getVolumeAt(i)); DataItem item = new DataItem(time, open, high, low, close, volume); result.setDataItem(i, item); } } return result; } public static Dataset SUM(Dataset dataset1, Dataset dataset2) { if (dataset1 == null) { return dataset2; } else { if (dataset2 == null) { return dataset1; } } int count1 = dataset1.getItemsCount(); int count2 = dataset2.getItemsCount(); int count = Math.min(count1, count2); Dataset result = EMPTY(count); for (int i = 0; i < count; i++) { long time = dataset1.getTimeAt(i); double open = dataset1.getOpenAt(i) + dataset2.getOpenAt(i); double high = dataset1.getHighAt(i) + dataset2.getHighAt(i); double low = dataset1.getLowAt(i) + dataset2.getLowAt(i); double close = dataset1.getCloseAt(i) + dataset2.getCloseAt(i); double volume = dataset1.getVolumeAt(i) + dataset2.getVolumeAt(i); DataItem item = new DataItem(time, open, high, low, close, volume); result.setDataItem(i, item); } return result; } public static Dataset DIFF(Dataset dataset1, Dataset dataset2) { if (dataset1 == null) { return dataset2; } else { if (dataset2 == null) { return dataset1; } } int count1 = dataset1.getItemsCount(); int count2 = dataset2.getItemsCount(); int count = Math.min(count1, count2); Dataset result = EMPTY(count); for (int i = 0; i < count; i++) { long time = dataset1.getTimeAt(i); double open = dataset1.getOpenAt(i) - dataset2.getOpenAt(i); double high = dataset1.getHighAt(i) - dataset2.getHighAt(i); double low = dataset1.getLowAt(i) - dataset2.getLowAt(i); double close = dataset1.getCloseAt(i) - dataset2.getCloseAt(i); double volume = dataset1.getVolumeAt(i) - dataset2.getVolumeAt(i); DataItem item = new DataItem(time, open, high, low, close, volume); result.setDataItem(i, item); } return result; } public static Dataset MULTIPLY(Dataset dataset, double value) { if (dataset == null) return null; int count = dataset.getItemsCount(); Dataset result = EMPTY(count); for (int i = 0; i < count; i++) { long time = dataset.getTimeAt(i); double open = dataset.getOpenAt(i) * value; double high = dataset.getHighAt(i) * value; double low = dataset.getLowAt(i) * value; double close = dataset.getCloseAt(i) * value; double volume = dataset.getVolumeAt(i) * value; DataItem item = new DataItem(time, open, high, low, close, volume); result.setDataItem(i, item); } return result; } public static Dataset DIV(Dataset dataset, double value) { if (dataset == null) return null; int count = dataset.getItemsCount(); Dataset result = EMPTY(count); for (int i = 0; i < count; i++) { long time = dataset.getTimeAt(i); double open = dataset.getOpenAt(i) / value; double high = dataset.getHighAt(i) / value; double low = dataset.getLowAt(i) / value; double close = dataset.getCloseAt(i) / value; double volume = dataset.getVolumeAt(i) / value; DataItem item = new DataItem(time, open, high, low, close, volume); result.setDataItem(i, item); } return result; } public static Dataset HMA(Dataset dataset, int period) { if (dataset == null) return null; Dataset wma_n2 = WMA(dataset, period / 2); Dataset wma_n = WMA(dataset, period); Dataset two_wma_n2 = MULTIPLY(wma_n2, 2); Dataset diff = DIFF(two_wma_n2, wma_n); Dataset result = WMA(diff, (int) Math.sqrt(period)); return result; } public static Dataset SMA(Dataset dataset, int period) { if (dataset == null) return null; int count = dataset.getItemsCount(); Dataset result = EMPTY(count); int j = 0; for (j = 0; j < count && (dataset.getDataItem(j) == null); j++) result.setDataItem(j, null); for (int i = j + period - 1; i < count; i++) { long time = dataset.getTimeAt(i); double open = 0; double high = 0; double low = 0; double close = 0; double volume = 0; for (int k = 0; k < period; k++) { open += dataset.getOpenAt(i - k); high += dataset.getHighAt(i - k); low += dataset.getLowAt(i - k); close += dataset.getCloseAt(i - k); volume += dataset.getVolumeAt(i - k); } open /= (double) period; high /= (double) period; low /= (double) period; close /= (double) period; volume /= (double) period; DataItem item = new DataItem(time, open, high, low, close, volume); result.setDataItem(i, item); } return result; } public static Dataset EMA(Dataset dataset, int period) { if (dataset == null) return null; int count = dataset.getItemsCount(); Dataset result = EMPTY(count); int j = 0; for (j = 0; j < count && (dataset.getDataItem(j) == null); j++) result.setDataItem(j, null); double open = 0; double high = 0; double low = 0; double close = 0; double volume = 0; for (int i = j; i < period + j && i < count; i++) { long time = dataset.getTimeAt(i); open += dataset.getOpenAt(i); high += dataset.getHighAt(i); low += dataset.getLowAt(i); close += dataset.getCloseAt(i); volume += dataset.getVolumeAt(i); if (i == period + j - 1) { open /= (double) period; high /= (double) period; low /= (double) period; close /= (double) period; volume /= (double) period; DataItem item = new DataItem(time, open, high, low, close, volume); result.setDataItem(i, item); } else { result.setDataItem(i, null); } } double k = 2 / ((double) (period + 1)); for (int i = period + j; i < count; i++) { long time = dataset.getTimeAt(i); open = (dataset.getOpenAt(i) - open) * k + open; high = (dataset.getHighAt(i) - high) * k + high; low = (dataset.getLowAt(i) - low) * k + low; close = (dataset.getCloseAt(i) - close) * k + close; volume = (dataset.getVolumeAt(i) - volume) * k + volume; DataItem item = new DataItem(time, open, high, low, close, volume); result.setDataItem(i, item); } return result; } /* * Wilder does not use the standard exponential moving average formula. * * Indicators affected are: * Average True Range * Directional Movement System * Relative Strength Index * Twiggs Money Flow developed by Colin Twiggs using Wilder's moving average formula. * * http://www.incrediblecharts.com/indicators/wilder_moving_average.php * http://user42.tuxfamily.org/chart/manual/Exponential-Moving-Average.html */ public static Dataset EMAWilder(Dataset dataset, int period) { int classic_ema_period = 2 * period - 1; return EMA(dataset, classic_ema_period); } public static Dataset WMA(Dataset dataset, int period) { if (dataset == null) return null; int count = dataset.getItemsCount(); Dataset result = EMPTY(count); double denominator = ((double) period * ((double) period + 1)) / 2; int j = 0; for (j = 0; j < count && (dataset.getDataItem(j) == null); j++) result.setDataItem(j, null); for (int i = j; i < period + j; i++) result.setDataItem(i, null); for (int i = period + j; i < count; i++) { long time = dataset.getTimeAt(i); double open = 0; double high = 0; double low = 0; double close = 0; double volume = 0; for (int k = i - period; k < i; k++) { open += (period - i + k + 1) * dataset.getOpenAt(k); high += (period - i + k + 1) * dataset.getHighAt(k); low += (period - i + k + 1) * dataset.getLowAt(k); close += (period - i + k + 1) * dataset.getCloseAt(k); volume += (period - i + k + 1) * dataset.getVolumeAt(k); } open /= denominator; high /= denominator; low /= denominator; close /= denominator; volume /= denominator; DataItem item = new DataItem(time, open, high, low, close, volume); result.setDataItem(i, item); } return result; } public static Dataset TEMA(Dataset dataset, int period) { if (dataset == null) return null; int count = dataset.getItemsCount(); Dataset result = EMPTY(count); Dataset ema1 = EMA(dataset, period); Dataset ema2 = EMA(ema1, period); Dataset ema3 = EMA(ema2, period); int j = 0; for (j = 0; j < count && (dataset.getDataItem(j) == null || ema1.getDataItem(j) == null || ema2.getDataItem(j) == null || ema3.getDataItem(j) == null); j++) result.setDataItem(j, null); for (int i = j; i < count; i++) { long time = dataset.getTimeAt(i); double open = 0; double high = 0; double low = 0; double close = 0; double volume = 0; if (ema1.getCloseAt(i) != 0 && ema2.getCloseAt(i) != 0 && ema3.getCloseAt(i) != 0) { open = 3 * ema1.getOpenAt(i) - 3 * ema2.getOpenAt(i) + ema3.getOpenAt(i); high = 3 * ema1.getHighAt(i) - 3 * ema2.getHighAt(i) + ema3.getHighAt(i); low = 3 * ema1.getLowAt(i) - 3 * ema2.getLowAt(i) + ema3.getLowAt(i); close = 3 * ema1.getCloseAt(i) - 3 * ema2.getCloseAt(i) + ema3.getCloseAt(i); volume = 3 * ema1.getVolumeAt(i) - 3 * ema2.getVolumeAt(i) + ema3.getVolumeAt(i); } DataItem item = new DataItem(time, open, high, low, close, volume); result.setDataItem(i, item); } return result; } public static Dataset[] ADX(Dataset dataset, int period) { if (dataset == null) return null; int count = dataset.getItemsCount(); Dataset pdi = EMPTY(count); Dataset mdi = EMPTY(count); Dataset dx = EMPTY(count); Dataset tr = EMPTY(count); Dataset hmhp = EMPTY(count); Dataset lmlp = EMPTY(count); for (int i = 1; i < count; i++) { long time = dataset.getTimeAt(i); double tr0 = dataset.getHighAt(i) - dataset.getCloseAt(i - 1); double tr1 = Math.abs(dataset.getHighAt(i) - dataset.getCloseAt(i - 1)); tr0 = Math.max(tr0, tr1); tr1 = Math.abs(dataset.getLowAt(i) - dataset.getCloseAt(i - 1)); tr.setDataItem(i, new DataItem(time, Math.max(tr0, tr1))); if (dataset.getHighAt(i) <= dataset.getHighAt(i - 1) && dataset.getLowAt(i) < dataset.getLowAt(i - 1)) { lmlp.setDataItem(i, new DataItem(time, dataset.getLowAt(i - 1) - dataset.getLowAt(i))); } else if (dataset.getHighAt(i) > dataset.getHighAt(i - 1) && dataset.getLowAt(i) >= dataset.getLowAt(i - 1)) { hmhp.setDataItem(i, new DataItem(time, dataset.getHighAt(i) - dataset.getHighAt(i - 1))); } else { double tempH = Math.abs(dataset.getHighAt(i) - dataset.getHighAt(i - 1)); double tempL = Math.abs(dataset.getLowAt(i) - dataset.getLowAt(i - 1)); if (tempH > tempL) { DataItem item = new DataItem(time, tempH); hmhp.setDataItem(i, item); } else { DataItem item = new DataItem(time, tempL); lmlp.setDataItem(i, item); } } } Dataset strDS = EMA(tr, period); Dataset shmhpDS = EMA(hmhp, period); Dataset slmlpDS = EMA(lmlp, period); for (int i = period; i < count; i++) { DataItem item = null; long time = dataset.getTimeAt(i); double curPDI = 0; double curMDI = 0; if (strDS.getDataItem(i) != null) { if (strDS.getCloseAt(i) != 0) { curPDI = (shmhpDS.getCloseAt(i) / strDS.getCloseAt(i)) * 100; curMDI = (slmlpDS.getCloseAt(i) / strDS.getCloseAt(i)) * 100; } } item = new DataItem(time, curPDI); pdi.setDataItem(i, new DataItem(time, curPDI)); item = new DataItem(time, curMDI); mdi.setDataItem(i, new DataItem(time, curMDI)); if (curPDI + curMDI != 0) { double value = Math.abs(curPDI - curMDI) / (curPDI + curMDI) * 100; item = new DataItem(time, value); dx.setDataItem(i, item); } } Dataset adx = EMA(dx, period); Dataset[] result = new Dataset[3]; result[0] = pdi; result[1] = mdi; result[2] = adx; return result; } }