Add Indicators on Chart

The IChartPanel.add methods get used to plot an indicator on chart. One can retrieve parameters and appearance information of already plotted indicators by calling the IChartPanel.getIndicatorApperanceInfos method. One can also plot another indicator or chart objects on the same indicator panel.
IChartPanel.add
法用于在图表上绘制一个指示器。您可以通过调用 IChartPanel.getIndicatorApperanceInfos 来检索已经绘制的指示器的参数和外观信息。你也可以在同一个指示器面板上绘制另一个指示器或图表对象。

Use optional parameters

The following methods may be used to add indicators on chart. The latter method lets you specify values for indicator optional parameters.
下列方法可用于在图表上添加指标。后一种方法允许您为指示器可选参数指定值。

chart.add(indicators.getIndicator("ZIGZAG"));
chart.add(indicators.getIndicator("ET_Nico"), new Object[]{15});

Specify output style

Use the following code to specify the applied price, drawing style, colors, etc for the indicator you add:
使用以下代码来指定您所添加的指示器的应用价格、绘图样式、颜色等:

IChart chart = context.getChart(Instrument.EURUSD);
IIndicator indCOG = indicators.getIndicator("COG");
for (int i = 0; i < indCOG.getIndicatorInfo().getNumberOfInputs(); i++) {
  InputParameterInfo inputParameterInfo = indCOG.getInputParameterInfo(i);
  inputParameterInfo.setAppliedPrice(AppliedPrice.LOW);
}                                                   

chart.add(indCOG, 
  new Object[]{5, 6, MaType.SMA.ordinal()}, 
  new Color[]{Color.RED, Color.GREEN},
  new DrawingStyle[]{DrawingStyle.DASHDOT_LINE, DrawingStyle.LINE}, 
  new int[]{1, 2});        

Object array optParams, the second parameter of chart.addIndicator, stands for indicator-specific parameters whose info can be retrieved from indicator metadata.
chart.add 的第二个参数,对象数组 optParams。代表特定指标的参数,其信息可以从指示器 metadata 中检索。

Use on-chart indicator parameters

As mentioned above, one can retrieve parameters and appearance information of already plotted indicators by calling the IChartPanel.getIndicatorApperanceInfos method. Consider a strategy which calculates indicators with the same parameters as they appear on the last selected chart:
如上所述,可以通过调用 IChartPanel.getIndicatorApperanceInfos 来检索已经绘制的指示器的参数和外观信息。考虑一种策略,该策略使用与最后一个选定图表上相同的参数来计算指标:

private IIndicators indicators;
private IHistory history;
private IConsole console;
private IChart chart;

private int dataCount = 3;

@Override
public void onStart(IContext context) throws JFException {
    indicators = context.getIndicators();
    history = context.getHistory();
    console = context.getConsole();
    chart = context.getLastActiveChart();
    if (chart == null) {
        console.getErr().println("No chart opened!");
        return;
    }
    IFeedDescriptor feedDescriptor = chart.getFeedDescriptor();
    if(feedDescriptor.getDataType() == DataType.TICKS){
        console.getWarn().println("Tick charts need to get calculate with from-to method");
        return;
    }

    for (IIndicatorAppearanceInfo info : chart.getIndicatorApperanceInfos()) {
        AppliedPrice[] appliedPrices = new AppliedPrice[info.getDrawingStyles().length];
        Arrays.fill(appliedPrices, AppliedPrice.CLOSE);
        OfferSide[] offerSides = new OfferSide[info.getDrawingStyles().length];
        Arrays.fill(offerSides, chart.getSelectedOfferSide());
        IIndicator indicator = indicators.getIndicator(info.getName());
        ITimedData feedData = history.getFeedData(feedDescriptor, 0);
        Object[] result = indicators.calculateIndicator(
                feedDescriptor, offerSides, info.getName(), appliedPrices, info.getOptParams(),
                dataCount, feedData.getTime(), 0);
        for (int i = 0; i < indicator.getIndicatorInfo().getNumberOfOutputs(); i++) {
            OutputParameterInfo.Type outputType = indicator.getOutputParameterInfo(i).getType();
            String resultStr = 
                    outputType == OutputParameterInfo.Type.DOUBLE ? Arrays.toString((double[]) result[i])
                    : outputType == OutputParameterInfo.Type.INT ? Arrays.toString((int[]) result[i])
                    : "object outputs need special processing";
            console.getOut().format(
                "%s %s last %s values: %s", 
                info.getName(), indicator.getOutputParameterInfo(i).getName(), dataCount, resultStr).println();
        }

    }
    context.stop();
}

CalculateIndicatorsFromChart.java

Include in OHLC

Consider a strategy which plots EMA and MACD indicators on chart and adds an OHLC informer with indicator showing option. The strategy also calculates the indicators on every bar, such that one can verify that the values match:

ChartAndStrategy.jpg

The function that adds the indicators and the OHLC informer:

    public void onStart(IContext context) throws JFException {
        this.console = context.getConsole();
        this.indicators = context.getIndicators();

        IChart chart = null;
        for(IChart c : context.getCharts(instrument)){
            if(c.getSelectedOfferSide() == this.side
                    && c.getSelectedPeriod() == this.period
                    && c.getFilter() == this.filter){
                chart = c;
                break;
            }
            if(c.getFilter() != this.filter){
                console.getErr().println(
                    "Filter dismatch! Change in platform settings the filter " +
                            "to the same one that the strategy is using!");
                context.stop();
            }
        }
        if(chart == null){
            chart = context.openChart(new TimePeriodAggregationFeedDescriptor(instrument, period, side, filter));
        }

        chart.add(indicators.getIndicator("EMA"), 
                  new Object[] { emaTimePeriod });
        chart.add(indicators.getIndicator("MACD"), 
                  new Object[] { macdFastPeriod, macdSlowPeriod, macdSignalPeriod });

        IOhlcChartObject ohlc = null;
        for (IChartObject obj : chart.getAll()) {
            if (obj instanceof IOhlcChartObject) {
                ohlc = (IOhlcChartObject) obj;
            }
        }
        if (ohlc == null) {
            ohlc = chart.getChartObjectFactory().createOhlcInformer();
            chart.add(ohlc);
        }
        ohlc.setShowIndicatorInfo(true);

        //calculate on the previous bar over candle interval such that the filters get used
        long time = context.getHistory().getBar(instrument, period, side, 1).getTime();
        double[][] macd = indicators.macd(instrument, period, side, AppliedPrice.CLOSE, 
            macdFastPeriod, macdSlowPeriod, macdSignalPeriod, filter, 1, time, 0);

        double[] ema = indicators.ema(instrument, period, side, AppliedPrice.CLOSE, 
            emaTimePeriod, filter, 1, time, 0);

        console.getOut().format("%s - ema=%s, macd=%s (by candle interval)", 
            DateUtils.format(time), arrayToString(ema), arrayToString(macd)).println();
    }

PlotEmaMacdWithOhlc.java

Also consider a generalized version that works with any feed:

PlotEmaMacdWithOhlcFeed.java

Plot on newly opened chart

Consider creating a wrapper class which describes both the indicator data and the feed it is supposed to be calculated on:

    class IndDataAndFeed{

        private IFeedDescriptor feedDescriptor;
        private String indicatorName;
        private Object[] optionalInputs;
        private int outputIndex;
        private IIndicator indicator;
        private IChart chart;

        public IndDataAndFeed(
                String indicatorName, Object[] optionalInputs, int outputIndex, IFeedDescriptor feedDescriptor) {
            this.feedDescriptor = feedDescriptor;
            this.indicatorName = indicatorName;
            this.optionalInputs = optionalInputs;
            this.outputIndex = outputIndex;
        }

        public void openChartAddIndicator(){
            for(IChart openedChart : context.getCharts(feedDescriptor.getInstrument())){
                IFeedDescriptor chartFeed = openedChart.getFeedDescriptor();
                if(chartFeed.getPeriod() == feedDescriptor.getPeriod() 
                        && chartFeed.getOfferSide() == feedDescriptor.getOfferSide()){
                    chart = openedChart;
                }
            }
            if(chart == null){
                chart = context.openChart(feedDescriptor);
            }
            if(chart.getFeedDescriptor().getFilter() != feedDescriptor.getFilter()){
                console.getErr().println("Chart filter " + chart.getFeedDescriptor().getFilter() + 
                    " does not match indicator feed filter " + feedDescriptor.getFilter() +
                    " please adjust the platform settings");
                context.stop();
            }
            indicator = indicators.getIndicator(indicatorName);

            int outputCount = indicator.getIndicatorInfo().getNumberOfOutputs();
            Color[] colors = new Color[outputCount];
            DrawingStyle[] styles = new DrawingStyle[outputCount];
            int[] widths = new int[outputCount];
            for(int outIdx = 0; outIdx< outputCount; outIdx++){
                OutputParameterInfo outInfo = indicator.getOutputParameterInfo(outIdx);
                if(outInfo == null){
                    console.getErr().println(indicatorName + " "  + outIdx + "is null");
                    continue;
                }
                //make colors darker
                colors[outIdx] = new Color(new Random().nextInt(256 * 256 * 256));
                //make solid-line inputs dashed
                styles[outIdx] = outInfo.getDrawingStyle() == DrawingStyle.LINE ?
                        DrawingStyle.DASH_LINE : 
                        outInfo.getDrawingStyle();
                //thicken the 1-width lines
                widths[outIdx] = 2;
            }

            chart.add(indicator, optionalInputs, colors, styles, widths);

            //show indicator values in ohlc
            IOhlcChartObject ohlc = null;
            for (IChartObject obj : chart.getAll()) {
                if (obj instanceof IOhlcChartObject) {
                    ohlc = (IOhlcChartObject) obj;
                }
            }
            if (ohlc == null) {
                ohlc = chart.getChartObjectFactory().createOhlcInformer();
                chart.add(ohlc);
            }
            ohlc.setShowIndicatorInfo(true);
        }

        public double getCurrentValue() throws JFException{
            Object[] outputs = indicators.calculateIndicator(
                    feedDescriptor, 
                    new OfferSide[] { feedDescriptor.getOfferSide() }, 
                    indicatorName,
                    new AppliedPrice[] { AppliedPrice.CLOSE }, 
                    optionalInputs, 
                    0);
            double value = (Double) outputs[outputIndex];
            return value;
        }

        public void removeFromChart(){
            if(chart != null && indicator != null){
                chart.removeIndicator(indicator);
            }
        }

        @Override 
        public String toString(){
            return String.format("%s %s on %s %s feed",
                indicatorName, 
                Arrays.toString(optionalInputs), 
                feedDescriptor.getOfferSide(),
                feedDescriptor.getPeriod());
        }

    }

Then add a list of indicators which you wish to calculate and plot on respective chart:

    private List<IndDataAndFeed> calculatableIndicators = new ArrayList<>(Arrays.asList(new IndDataAndFeed[]{
            new IndDataAndFeed("MACD", new Object[] {12,26,9}, 0,
                               new TimePeriodAggregationFeedDescriptor(
                                       instrument, Period.FIVE_MINS, OfferSide.BID, Filter.WEEKENDS)),
            new IndDataAndFeed("RSI", new Object[] {50}, 0,
                               new TimePeriodAggregationFeedDescriptor(
                                       instrument, Period.FIVE_MINS, OfferSide.BID, Filter.WEEKENDS)),
            new IndDataAndFeed("RSI", new Object[] {50}, 0,
                               new TimePeriodAggregationFeedDescriptor(
                                       instrument, Period.ONE_HOUR, OfferSide.BID, Filter.WEEKENDS)),
            new IndDataAndFeed("CCI", new Object[] {14}, 0,
                               new TimePeriodAggregationFeedDescriptor(
                                       instrument, Period.FIFTEEN_MINS, OfferSide.BID, Filter.WEEKENDS)),
            new IndDataAndFeed("CCI", new Object[] {14}, 0,
                               new TimePeriodAggregationFeedDescriptor(
                                       instrument, Period.ONE_HOUR, OfferSide.BID, Filter.WEEKENDS))
    }));

And finally make calls from the strategy:

    @Override
    public void onStart(IContext context) throws JFException {

        if(!context.getSubscribedInstruments().contains(instrument)){
            context.setSubscribedInstruments(
                    new HashSet<Instrument>(
                            Arrays.asList(new Instrument [] {instrument})), true);
        }

        this.context = context;
        console = context.getConsole();
        indicators = context.getIndicators();

        for(IndDataAndFeed indDataAndFeed : calculatableIndicators){
            indDataAndFeed.openChartAddIndicator();
        }
    }

    @Override
    public void onTick(Instrument instrument, ITick tick) throws JFException {
        if (instrument != this.instrument) {
            return;
        }
        for (IndDataAndFeed indDataAndFeed : calculatableIndicators) {
            double value = indDataAndFeed.getCurrentValue();
            print("%s current value=%.5f", indDataAndFeed, value);
        }
    }

    @Override
    public void onStop() throws JFException {
        for(IndDataAndFeed indDataAndFeed : calculatableIndicators){
            indDataAndFeed.removeFromChart();
        }
    }

FeedMultiIndOpenChartsOhlc.java

Randomize output style and include in OHLC

Consider modifying the previous example, by modifying the indicator ouput styles and including the indicator values in the OHLC information object:

public void openChartAddIndicator(){
    for(IChart openedChart : context.getCharts(feedDescriptor.getInstrument())){
        IFeedDescriptor chartFeed = openedChart.getFeedDescriptor();
        if(chartFeed.getPeriod() == feedDescriptor.getPeriod() && 
                        chartFeed.getOfferSide() == feedDescriptor.getOfferSide()){
            chart = openedChart;
        }
    }
    if(chart == null){
        chart = context.openChart(feedDescriptor);
    }
    if(chart.getFeedDescriptor().getFilter() != feedDescriptor.getFilter()){
        console.getErr().println(
                "Chart filter " + chart.getFeedDescriptor().getFilter() + 
                                " does not match indicator feed filter " +
                                feedDescriptor.getFilter() + " please adjust the platform settings");
        context.stop();
    }
    indicator = indicators.getIndicator(indicatorName);

    int outputCount = indicator.getIndicatorInfo().getNumberOfOutputs();
    Color[] colors = new Color[outputCount];
    DrawingStyle[] styles = new DrawingStyle[outputCount];
    int[] widths = new int[outputCount];
    for(int outIdx = 0; outIdx< outputCount; outIdx++){
        OutputParameterInfo outInfo = indicator.getOutputParameterInfo(outIdx);
        if(outInfo == null){
            console.getErr().println(indicatorName + " "  + outIdx + "is null");
            continue;
        }
        //make colors darker
        colors[outIdx] = new Color(new Random().nextInt(256 * 256 * 256));
        //make solid-line inputs dashed
        styles[outIdx] = outInfo.getDrawingStyle() == DrawingStyle.LINE ? 
                    DrawingStyle.DASH_LINE : 
                        outInfo.getDrawingStyle();
        //thicken the 1-width lines
        widths[outIdx] = 2;
    }

    chart.add(indicator, optionalInputs, colors, styles, widths);

    //show indicator values in ohlc
    IOhlcChartObject ohlc = null;
    for (IChartObject obj : chart.getAll()) {
        if (obj instanceof IOhlcChartObject) {
            ohlc = (IOhlcChartObject) obj;
        }
    }
    if (ohlc == null) {
        ohlc = chart.getChartObjectFactory().createOhlcInformer();
        chart.add(ohlc);
    }
    ohlc.setShowIndicatorInfo(true);
}

FeedMultiIndOpenChartsOhlc.java

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • rljs by sennchi Timeline of History Part One The Cognitiv...
    sennchi阅读 7,499评论 0 10
  • 《金文诚〈论语〉学习笔记463尧曰第二十1》 【尧曰:"咨,尔舜,天之历数在尔躬,允执其中。四海穷困,天禄永终。"...
    金吾生阅读 449评论 1 1
  • 我出生在一个破旧落后的小城镇,很小的时候爸爸还用粮票买食物,零花钱经常是零或者几毛钱,上小学爸爸给我两块钱那次是我...
    夕屿Nicole阅读 503评论 0 2
  • 郭芳艳 焦点网络初级五期 坚持原创分享第157天 感觉很惭愧,大家可能都已经报过讲课的名字了,可是我却...
    冰山蓝鹰阅读 180评论 0 0
  • 我们从小在她的臂弯里初生,跌倒,受伤,长大,当我们能用肩膀拥抱她时,她已悄然走远,岁月带走了她曾经如花的笑颜和被我...
    我有一把刀阅读 327评论 0 0