/* * Licensed Materials - Property of Perforce Software, Inc. * © Copyright Perforce Software, Inc. 2014, 2021 * © Copyright IBM Corp. 2009, 2014 * © Copyright ILOG 1996, 2009 * All Rights Reserved. * * Note to U.S. Government Users Restricted Rights: * The Software and Documentation were developed at private expense and * are "Commercial Items" as that term is defined at 48 CFR 2.101, * consisting of "Commercial Computer Software" and * "Commercial Computer Software Documentation", as such terms are * used in 48 CFR 12.212 or 48 CFR 227.7202-1 through 227.7202-4, * as applicable. */ package thinstock; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Font; import java.awt.event.ActionEvent; import java.net.MalformedURLException; import java.net.URL; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.Iterator; import java.util.List; import javax.servlet.ServletConfig; import javax.swing.AbstractAction; import javax.swing.BorderFactory; import com.ibm.icu.text.DecimalFormat; import com.ibm.icu.text.NumberFormat; import ilog.views.chart.IlvAxis; import ilog.views.chart.IlvChart; import ilog.views.chart.IlvChartLayout; import ilog.views.chart.IlvChartRenderer; import ilog.views.chart.IlvColor; import ilog.views.chart.IlvDataInterval; import ilog.views.chart.IlvDefaultStepsDefinition; import ilog.views.chart.IlvLegend; import ilog.views.chart.IlvStyle; import ilog.views.chart.IlvTimeUnit; import ilog.views.chart.data.IlvDataSet; import ilog.views.chart.data.IlvDefaultDataSet; import ilog.views.chart.data.IlvDefaultDataSource; import ilog.views.chart.event.AxisChangeEvent; import ilog.views.chart.event.AxisListener; import ilog.views.chart.event.AxisRangeEvent; import ilog.views.chart.renderer.IlvHiLoChartRenderer; import ilog.views.chart.renderer.IlvPolylineChartRenderer; import ilog.views.chart.renderer.IlvSingleAreaRenderer; import ilog.views.chart.renderer.IlvSingleBarRenderer; import ilog.views.chart.renderer.IlvSinglePolylineRenderer; import ilog.views.chart.renderer.IlvSingleStairRenderer; import ilog.views.chart.util.IlvDoubleArray; import ilog.views.util.IlvLocaleUtil; import ilog.views.util.IlvResourceUtil; import ilog.views.util.time.IlvCalendarFactory; import stock.CategoryTimeSteps; import stock.SharedGrid; import stock.StockColors; import stock.StockDataSource; import stock.StockUtil; import stock.Stripes; import stock.ThresholdLines; import stock.indicator.BollingerBandsIndicator; import stock.indicator.MACDIndicator; import stock.indicator.MovingAverageIndicator; import stock.indicator.PriceChannelIndicator; import stock.indicator.RSIIndicator; import stock.indicator.StochasticIndicator; import stock.indicator.TechnicalIndicator; import stock.indicator.VolumeIndicator; import stock.indicator.WilliamsRIndicator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class StockDemoApp implements StockColors { private static final Logger LOGGER = LoggerFactory.getLogger(StockDemoApp.class); /** The number of lower charts. */ private static final int LOWER_CHART_COUNT = 2; private static final int RIGHT_MARGIN = 6; private static final Font DEFAULT_FONT = new Font("Dialog", Font.PLAIN, 10); public static final int LINE = 0; public static final int AREA = 1; public static final int BAR = 2; public static final int STAIR = 3; public static final int HLOC = 4; public static final int CANDLE = 5; /** * The threshold beyond which quotes are displayed with an overview * representation mode. This constant is equal to the approximate duration of * 3 months for daily data and one year for weekly data. */ public static final double OVERVIEW_THRESHOLD = 65; static { List<Color> colorList = IlvColor.getDefaultColors(); colorList.clear(); colorList.addAll(Arrays.asList(DEFAULT_COLORS)); } // == Chart related data members StockDataSource stockDS; IlvChart mainChart; IlvChart[] lowerCharts; List<TechnicalIndicator> upperIndicators = new ArrayList<TechnicalIndicator>(); TechnicalIndicator[] lowerIndicators; /** The overview renderer for the primary symbol. */ IlvChartRenderer overviewRenderer; /** The detailed renderer for the primary symbol. */ IlvChartRenderer detailedRenderer; /** The renderer for the seconary symbols. */ IlvChartRenderer secondaryRenderer; boolean antiAliasing = false; // == UI related data members private List<UpperIndicatorAction> upperIndicatorActions; private List<LowerIndicatorAction>[] lowerIndicatorActions; private NumberFormat numFmt = new DecimalFormat(".###"); private ThresholdLines threshold; /** Creates a new instance of StockDemoApp */ public StockDemoApp(ServletConfig config) { initDemo(config); } private void initDemo(ServletConfig config) { numFmt = NumberFormat.getNumberInstance(); numFmt.setMaximumFractionDigits(3); // Create the stock data source to read the result of the query. URL defaultDataURL = null; try { defaultDataURL = config.getServletContext().getResource("/data/default.csv"); } catch (Exception x) { x.printStackTrace(); } stockDS = new StockDataSource(defaultDataURL); // == Create the main chart. mainChart = createMainChart(); setOverviewRepresentation(LINE); setDetailedRepresentation(CANDLE); secondaryRenderer = new IlvPolylineChartRenderer(); mainChart.addRenderer(secondaryRenderer); // == Create indicator charts. lowerCharts = createLowerCharts(); lowerIndicators = new TechnicalIndicator[lowerCharts.length]; initIndicatorActions(); setLowerIndicator(0, ((IndicatorAction) lowerIndicatorActions[0].get(0)).getIndicator()); setLowerIndicator(1, ((IndicatorAction) lowerIndicatorActions[1].get(1)).getIndicator()); setAntiAliasing(true); // Load the default data. loadDefaultData(config); } /** * Returns the data source that holds the stock data. */ public StockDataSource getStockDataSource() { return stockDS; } /** * Returns the main chart. */ public IlvChart getMainChart() { return mainChart; } /** * Returns the lower chart of the specified index. */ public IlvChart getLowerChart(int idx) { return lowerCharts[idx]; } public boolean isOverviewVisible() { return overviewRenderer.isVisible(); } public IlvChartRenderer getOverviewRenderer() { return overviewRenderer; } public IlvDataSet getDetailedDataSet() { return detailedRenderer.getDataSource().getDataSet(2); } public IlvDataSet getLowerIndicatorDataSet(int chartIdx) { return lowerIndicators[chartIdx].getMainDataSet(); } // -------------------------------------------------------------------------- // - Indicators public String getLowerIndicatorName(int chartIdx) { return lowerIndicators[chartIdx].getName(); } public void setLowerIndicator(int chartIdx, int indicatorIdx) { ((IndicatorAction) lowerIndicatorActions[chartIdx].get(indicatorIdx)).actionPerformed(null); } /** Sets a lower indicator. */ protected void setLowerIndicator(int idx, TechnicalIndicator indicator) { if (lowerIndicators[idx] == indicator) return; if (lowerIndicators[idx] != null) lowerIndicators[idx].detach(); if (indicator != null) indicator.attach(lowerCharts[idx]); lowerIndicators[idx] = indicator; } public void setUpperIndicators(int[] indicators) { for (int i = 0; i < upperIndicatorActions.size(); ++i) { UpperIndicatorAction action = (UpperIndicatorAction) upperIndicatorActions.get(i); removeUpperIndicator(action.getIndicator()); action.reset(); } for (int i = 0; i < indicators.length; ++i) ((IndicatorAction) upperIndicatorActions.get(indicators[i])).actionPerformed(null); } /** Adds an upper indicator. */ protected void addUpperIndicator(TechnicalIndicator indicator) { if (indicator != null) indicator.attach(mainChart); upperIndicators.add(indicator); } /** Removes an upper indicator. */ protected void removeUpperIndicator(TechnicalIndicator indicator) { if (!upperIndicators.contains(indicator)) return; if (indicator != null) indicator.detach(); upperIndicators.remove(indicator); } /** * Creates the main chart. This chart displays the stock data and the upper * indicators. */ protected IlvChart createMainChart() { IlvChart chart = createChart(); chart.setBorder(BorderFactory.createEmptyBorder(0, 0, 4, 0)); setMargins(chart); chart.getXAxis().setVisibleRange(0, 10); chart.getYScale(0).setTitle("Share price ($)", 270); chart.getYScale(0).getTitleRenderer().setFont(new Font("Dialog", Font.PLAIN, 12)); Stripes stripes = new Stripes(chart.getYScale(0), STRIPES_COLOR); stripes.setDrawOrder(-3); chart.addDecoration(stripes); chart.getYAxis(0).setVisibleRange(0, 100); chart.getXScale().setMajorTickVisible(false); chart.getXScale().setVisible(false); chart.getChartArea().setRightMargin(RIGHT_MARGIN); // Add an axis listener to toggle the visibility of the // quote renderers/quote overview. chart.getXAxis().addAxisListener(new AxisListener() { double oldLen = 0; boolean oldAntiAliasing; Override public void axisRangeChanged(AxisRangeEvent evt) { if (evt.isChangedEvent() && !evt.isAdjusting() && evt.isVisibleRangeEvent()) { updateDisplay(evt.getAxis()); } else if (!evt.isChangedEvent()) { double min = evt.getNewMin(); double max = evt.getNewMax(); if (max - min < StockUtil.MIN_XLEN) { double mid = (max + min) / 2; evt.setNewMax(mid + StockUtil.MIN_XLEN / 2); evt.setNewMin(mid - StockUtil.MIN_XLEN / 2); } } } Override public void axisChanged(AxisChangeEvent evt) { if (evt.getType() == AxisChangeEvent.ADJUSTMENT_CHANGE) { if (evt.isAdjusting()) { if (StockDemoApp.this.antiAliasing) { StockDemoApp.this.setAntiAliasing(false); oldAntiAliasing = true; } } else { if (oldAntiAliasing) { StockDemoApp.this.setAntiAliasing(true); oldAntiAliasing = false; } updateDisplay(evt.getAxis()); } } else if (evt.getType() == AxisChangeEvent.TRANSFORMER_CHANGE) { // LocalZoomHandler lzh = LocalZoomHandler.get(mainChart, -1); // if (lzh == null) return; // if (oldZoomfactor != lzh.getTransformer().getZoomFactor()) { // zoomInAction.computeEnabled(); // zoomOutAction.computeEnabled(); // oldZoomfactor = lzh.getTransformer().getZoomFactor(); // } } } private void updateDisplay(IlvAxis axis) { // Check if the zoom level has changed and call the // xRangeChanged() method. IlvDataInterval xRange = mainChart.getXAxis().getVisibleRange(); double newLen = xRange.getLength(); boolean zoom = (oldLen == 0) || (Math.abs(newLen - oldLen) / oldLen > .01); StockDemoApp.this.xRangeChanged(zoom); oldLen = newLen; } }); chart.getYAxis(0).addAxisListener(new AxisListener() { Override public void axisRangeChanged(AxisRangeEvent evt) { if (evt.isAboutToChangeEvent()) { IlvDataInterval range = StockUtil.getYDataRange(mainChart, 0, mainChart.getXAxis().getVisibleRange()); if (!range.isEmpty()) { evt.setNewMin(range.min); evt.setNewMax(range.max); } } } Override public void axisChanged(AxisChangeEvent evt) { } }); // == Add the quote display panel and the legend as a header. // JPanel header = new JPanel(new GridLayout(0,1,0,4)); // header.setBorder(BorderFactory.createEmptyBorder(4, 0, 0, 8)); // header.setBackground(HEADER_COLOR); IlvLegend legend = createLegend(); // chart.setLegend(legend); // header.add(legend); // chart.setHeader(header); chart.addLegend(legend, IlvChartLayout.NORTH_BOTTOM); return chart; } /** Creates the charts displaying lower indicators. */ protected IlvChart[] createLowerCharts() { IlvChart[] charts = new IlvChart[LOWER_CHART_COUNT]; for (int i = 0; i < LOWER_CHART_COUNT; ++i) { charts[i] = createLowerChart(); } return charts; } /** Creates a lower chart. */ private IlvChart createLowerChart() { IlvChart chart = createChart(); chart.synchronizeAxis(mainChart, IlvAxis.X_AXIS, false); chart.setXScale(null); chart.setXGrid(new SharedGrid(mainChart.getXScale(), GRID_COLOR)); setMargins(chart); // JPanel header = new JPanel(new GridLayout(0,1,0,4)); // header.setBorder(BorderFactory.createEmptyBorder(4, 0, 0, 8)); // header.setBackground(HEADER_COLOR); IlvLegend legend = createLegend(); // chart.setLegend(legend); // header.add(legend); // chart.setHeader(header); chart.addLegend(legend, IlvChartLayout.NORTH_BOTTOM); return chart; } private void setMargins(IlvChart chart) { chart.getChartArea().setHorizontalMargins(50, 3); } /** Creates the list of upper indicators. */ protected List<TechnicalIndicator> createUpperIndicators() { List<TechnicalIndicator> list = new ArrayList<TechnicalIndicator>(); list.add(new BollingerBandsIndicator(stockDS)); list.add(new PriceChannelIndicator(stockDS)); list.add(MovingAverageIndicator.createSMA(stockDS, 20)); list.add(MovingAverageIndicator.createSMA(stockDS, 40)); list.add(MovingAverageIndicator.createEMA(stockDS, 20)); list.add(MovingAverageIndicator.createEMA(stockDS, 40)); return list; } /** Creates the list of lower indicators. */ protected List<TechnicalIndicator> createLowerIndicators() { List<TechnicalIndicator> list = new ArrayList<TechnicalIndicator>(); list.add(new VolumeIndicator(stockDS)); list.add(new RSIIndicator(stockDS, 14)); list.add(MACDIndicator.createMACD(stockDS)); list.add(new WilliamsRIndicator(stockDS, 14)); list.add(StochasticIndicator.createFastStochastic(stockDS)); list.add(StochasticIndicator.createSlowStochastic(stockDS)); return list; } /** Initializes the actions associated with indicators. */ SuppressWarnings("unchecked") private void initIndicatorActions() { List<TechnicalIndicator> list = createUpperIndicators(); Iterator<TechnicalIndicator> ite = list.iterator(); upperIndicatorActions = new ArrayList<StockDemoApp.UpperIndicatorAction>(list.size()); while (ite.hasNext()) { TechnicalIndicator indicator = (TechnicalIndicator) ite.next(); UpperIndicatorAction action = new UpperIndicatorAction(indicator); action.updateEnabled(); upperIndicatorActions.add(action); } lowerIndicatorActions = new ArrayList[lowerCharts.length]; for (int i = 0; i < lowerIndicatorActions.length; ++i) { lowerIndicatorActions[i] = new ArrayList<LowerIndicatorAction>(); ite = createLowerIndicators().iterator(); while (ite.hasNext()) { TechnicalIndicator indicator = (TechnicalIndicator) ite.next(); LowerIndicatorAction action = new LowerIndicatorAction(indicator, i); action.updateEnabled(); lowerIndicatorActions[i].add(action); } } } /** Toggles the price threshold. */ public void setThreshold(boolean set) { if (set) { if (threshold == null) { Color upperColor = new Color(120, 220, 120); Color midColor = new Color(233, 150, 122); Color lowerColor = IlvColor.indianRed; threshold = new ThresholdLines(FOREGROUND, BACKGROUND, lowerColor, midColor, upperColor); ThresholdLines.set(threshold, mainChart, 0); threshold.setThresholds(mainChart.getYAxis(0).getDataRange()); } else { ThresholdLines.set(threshold, mainChart, 0); } overviewRenderer.setRenderingHint(threshold); detailedRenderer.setRenderingHint(threshold); } else { ThresholdLines.remove(mainChart, 0); overviewRenderer.setRenderingHint(null); detailedRenderer.setRenderingHint(null); } } /** Toggles anti-aliasing for the charts. */ public void setAntiAliasing(boolean b) { if (antiAliasing == b) return; mainChart.setAntiAliasing(b); mainChart.getChartArea().repaint(); for (int i = 0; i < lowerCharts.length; ++i) { lowerCharts[i].setAntiAliasing(b); lowerCharts[i].getChartArea().repaint(); } antiAliasing = b; } /** * Sets the input API key on the StockDataSource instance. */ public void setAPIKey(String apiKey) { stockDS.setAPIKey(apiKey); } /** * Loads the quotes. */ public boolean loadQuotes(final String symbol, Date startDate, Date endDate, int frequency, String[] secsymbols) { boolean retVal = false; if (symbol == null || symbol.length() == 0) LOGGER.warn("Missing ticker symbol!"); else if (stockDS == null || stockDS.getAPIKey().isEmpty()) LOGGER.warn("Missing API key!"); else { // == Reset all data overviewRenderer.getDataSource().setDataSets(null); detailedRenderer.getDataSource().setDataSets(null); secondaryRenderer.getDataSource().setDataSets(null); // == Workaround BUG IlvHiLoChartRenderer (setDataSets(null)) int mode = ((IlvHiLoChartRenderer) detailedRenderer).getMode(); if (mode == IlvHiLoChartRenderer.CANDLE) setDetailedRepresentation(CANDLE); else setDetailedRepresentation(HLOC); // == End Workaround stockDS.reset(); updateIndicators(); stockDS.loadData(symbol, startDate, endDate, frequency, null); // primaryDataLoaded(symbol, secsymbols); retVal = true; } return retVal; } private void loadDefaultData(ServletConfig config) { URL dataFile = null; try { dataFile = config.getServletContext().getResource("/data/default.csv"); } catch (MalformedURLException e) { e.printStackTrace(); } stockDS.loadDefaultData(dataFile); primaryDataLoaded(StockDataSource.DEFAULT_SYMBOL, null); setThreshold(true); threshold.setThresholds(new IlvDataInterval(25, 45)); } public void primaryDataLoaded(String expectedSymbol, String[] secsymbols) { if (stockDS.getDataSetCount() > 0) { if (threshold != null && ThresholdLines.get(mainChart, 0) == null) // i.e. // Threshold // has // been // hidden threshold = null; String symbol = stockDS.getSymbol().toUpperCase(); if (!symbol.equalsIgnoreCase(expectedSymbol)) { String msg = IlvResourceUtil.getServerLocaleString(StockDemoApp.class, "PrimarySymbolNotFound"); System.err.println(MessageFormat.format(msg, expectedSymbol)); } // == Update overview Renderer overviewRenderer.getDataSource().addDataSet(stockDS.getCloseDataSet()); overviewRenderer.setName(symbol); // == Update detailed renderer IlvDataSet[] quotes = { stockDS.getLowDataSet(), // low stockDS.getHighDataSet(), // high stockDS.getOpenDataSet(), // open stockDS.getCloseDataSet() // close }; detailedRenderer.getDataSource().setDataSets(quotes); detailedRenderer.setName(symbol); Color c = PRIMARY_COLOR; IlvStyle style1 = IlvStyle.createStroked(c); IlvStyle style2 = new IlvStyle(c, IlvColor.brighter(c)); IlvStyle style3 = new IlvStyle(c, IlvColor.darker(c)); detailedRenderer.setStyles(new IlvStyle[] { style1, style1, style2, style3 }); // == Load data for secondary symbols // final String[] secondarySymbols = queryPanel.getSecondarySymbols(); if (secsymbols != null && secsymbols.length > 0) { IlvDoubleArray[] data = stockDS.loadData(secsymbols, null); secondaryDataLoaded(secsymbols, data); } } // == Update indicators updateIndicators(); // == Reset visible range and history. resetVisibleRange(); // == Update the x-scale updateXScale(); // Adjust existing threshold if (threshold != null) { threshold.setThresholds(mainChart.getYAxis(0).getVisibleRange()); } } private void secondaryDataLoaded(String[] symbols, IlvDoubleArray[] data) { IlvDefaultDataSource dataSource = new IlvDefaultDataSource(); if (data != null) { // else loading was interrupted by another request // Update the renderer for the secondary symbols. String error = null; for (int i = 0; i < data.length; ++i) { if (data[i] == null) { if (error == null) error = symbols[i]; else error += ", " + symbols[i]; continue; } String name = symbols[i].toUpperCase(); data[i].trim(); dataSource.addDataSet(new IlvDefaultDataSet(name, data[i].data())); } if (error != null) { String msg = IlvResourceUtil.getServerLocaleString(StockDemoApp.class, "secondSymbolNotFound"); System.out.println(msg + error); } } secondaryRenderer.setDataSource(dataSource); } /** * Invoked when quotes are loaded for the primary symbol. This method updates * the steps definition of the x-scale. */ private void updateXScale() { Date[] dates = stockDS.getDates(); if (dates == null) { mainChart.getXScale().setVisible(false); mainChart.getXScale().setStepsDefinition(new IlvDefaultStepsDefinition()); } else { IlvTimeUnit unit = null; switch (stockDS.getFrequency()) { case StockDataSource.MONTHLY: unit = IlvTimeUnit.MONTH; break; case StockDataSource.WEEKLY: unit = IlvTimeUnit.WEEK; break; case StockDataSource.DAILY: default: unit = IlvTimeUnit.DAY; break; } CategoryTimeSteps def; def = new CategoryTimeSteps(dates, unit); mainChart.getXScale().setStepsDefinition(def); mainChart.getXScale().setVisible(true); } } /** * Invoked when quotes are loaded for the primary symbol. This method updates * the indicators and the enabled state of their associated actions */ private void updateIndicators() { // Refresh indicators. for (int i = 0; i < lowerIndicators.length; ++i) { if (lowerIndicators[i] != null) lowerIndicators[i].refresh(); } Iterator<TechnicalIndicator> ite = upperIndicators.iterator(); while (ite.hasNext()) ((TechnicalIndicator) ite.next()).refresh(); // Update the enabled state of actions. Iterator<UpperIndicatorAction> ite2 = upperIndicatorActions.iterator(); while (ite2.hasNext()) { ((UpperIndicatorAction) ite2.next()).updateEnabled(); } Iterator<LowerIndicatorAction> ite3; for (int i = 0; i < lowerIndicatorActions.length; ++i) { ite3 = lowerIndicatorActions[i].iterator(); while (ite3.hasNext()) { ((LowerIndicatorAction) ite3.next()).updateEnabled(); } } } private void resetVisibleRange() { mainChart.getXAxis().setAutoVisibleRange(true); mainChart.getYAxis(0).setAutoVisibleRange(true); } /** * Creates a legend for the charts. */ protected IlvLegend createLegend() { IlvLegend legend = new IlvLegend(); legend.setLayout(new FlowLayout(FlowLayout.LEFT, 12, 2)); legend.setPaintingBackground(false); legend.setBorder(null); legend.setForeground(FOREGROUND); legend.setMovable(false); legend.setFont(DEFAULT_FONT); legend.setSymbolSize(new Dimension(16, 12)); return legend; } /** * Creates a new <code>IlvChart</code> and sets common properties. */ protected IlvChart createChart() { IlvChart chart = new IlvChart(); chart.getXGrid().setMajorPaint(GRID_COLOR); chart.getYGrid(0).setMajorPaint(GRID_COLOR); chart.getXGrid().setDrawOrder(-2); chart.getYGrid(0).setDrawOrder(-2); chart.setForeground(FOREGROUND); chart.setBackground(BACKGROUND); chart.setOpaque(true); chart.setFont(DEFAULT_FONT); IlvStyle style = chart.getChartArea().getPlotStyle(); if (style != null) chart.getChartArea().setPlotStyle(style.setFillOn(false)); return chart; } /** * Invoked when the visible time range changes. * <p> * This method toggles the visibility of the quote overview/quote renderers * according to the visible time range. */ private void xRangeChanged(boolean zoom) { IlvDataInterval xRange = mainChart.getXAxis().getVisibleRange(); if (xRange.isEmpty()) return; IlvDataInterval yRange = StockUtil.getYDataRange(mainChart, 0, xRange); if (!yRange.isEmpty()) mainChart.getYAxis(0).setVisibleRange(yRange); if (zoom) { boolean hideOverview = (xRange.getLength() < OVERVIEW_THRESHOLD); mainChart.getYAxis(0).setAutoDataRange(false); overviewRenderer.setVisible(!hideOverview); detailedRenderer.setVisible(hideOverview); mainChart.getYAxis(0).setAutoDataRange(true); } } /** * Specifies the stock overview representation. * * @param representation * The desired representation. * @see #BAR * @see #LINE * @see #AREA * @see #STAIR */ public void setOverviewRepresentation(int representation) { int idx = mainChart.getRenderers().indexOf(overviewRenderer); IlvChartRenderer r = null; Color c = DEFAULT_COLORS[0]; IlvStyle filledStyle = new IlvStyle(c, IlvColor.setAlpha(c, .45f)); IlvStyle strokedStyle = new IlvStyle(2.f, c); switch (representation) { case BAR: r = new IlvSingleBarRenderer(filledStyle, 100.); break; case STAIR: r = new IlvSingleStairRenderer(filledStyle); break; case AREA: r = new IlvSingleAreaRenderer(filledStyle); break; case LINE: default: r = new IlvSinglePolylineRenderer(strokedStyle); break; } if (idx == -1) { mainChart.addRenderer(r); } else { r.setVisible(overviewRenderer.isVisible()); r.setName(overviewRenderer.getName()); mainChart.setRenderer(idx, r); // Update y-range explicitly since the setRenderer can modify // the x-range before the new renderer is added. xRangeChanged(false); } overviewRenderer = r; } /** * Specifies the stock overview representation. * * @param representation * The desired representation. * @see #HLOC * @see #CANDLE */ public void setDetailedRepresentation(int representation) { int idx = mainChart.getRenderers().indexOf(detailedRenderer); IlvChartRenderer r = null; switch (representation) { case HLOC: r = new IlvHiLoChartRenderer(IlvHiLoChartRenderer.OPENCLOSE, 0, 80); break; case CANDLE: default: r = new IlvHiLoChartRenderer(IlvHiLoChartRenderer.CANDLE, 0, 80); break; } if (idx == -1) mainChart.addRenderer(r); else { r.setVisible(detailedRenderer.isVisible()); r.setName(detailedRenderer.getName()); IlvStyle[] styles = detailedRenderer.getStyles(); mainChart.setRenderer(idx, r); r.setStyles(styles); xRangeChanged(false); } detailedRenderer = r; } /** * Returns the default start date for quote queries. * * @return One year before the current date. */ static final Date getDefaultStartDate() { Calendar cal = IlvCalendarFactory.createInstance(IlvLocaleUtil.getCurrentULocale()); cal.setTime(new Date()); cal.add(Calendar.YEAR, -1); return cal.getTime(); } // -------------------------------------------------------------------------- /** * The base action class for setting indicators. */ abstract class IndicatorAction extends AbstractAction { private TechnicalIndicator indicator; /** * Creates a new <code>UpperIndicatorAction</code> that references the * specified indicator. */ public IndicatorAction(TechnicalIndicator indicator) { super(indicator.getName()); this.indicator = indicator; } /** * Computes the enable state of the action. */ public void updateEnabled() { boolean enabled = (stockDS.getDataSetCount() > 0); setEnabled(enabled); } /** * Returns the indicator associated with this action. */ public final TechnicalIndicator getIndicator() { return indicator; } } /** * An action class used to add upper indicators. */ class UpperIndicatorAction extends IndicatorAction { private boolean added; /** * Creates a new <code>UpperIndicatorAction</code> that references the * specified indicator. */ public UpperIndicatorAction(TechnicalIndicator indicator) { super(indicator); } /** Invoked when an action occurs. */ Override public void actionPerformed(ActionEvent evt) { if (!isEnabled()) return; if (added) { removeUpperIndicator(getIndicator()); added = false; } else { addUpperIndicator(getIndicator()); added = true; } } public void reset() { added = false; } } /** * An action class used to set lower indicators. */ class LowerIndicatorAction extends IndicatorAction { private int chartIdx; /** * Creates a new <code>LowerIndicatorAction</code> that references the * specified indicator. */ public LowerIndicatorAction(TechnicalIndicator indicator, int chartIdx) { super(indicator); this.chartIdx = chartIdx; } /** Invoked when an action occurs. */ Override public void actionPerformed(ActionEvent evt) { if (!isEnabled()) return; setLowerIndicator(chartIdx, getIndicator()); } } }