Dukascopy
 
 
Wiki JStore Search Login

Attention! Read the forum rules carefully before posting a topic.

    Try to find an answer in Wiki before asking a question.
    Submit programming questions in this forum only.
    Off topics are strictly forbidden.

Any topics which do not satisfy these rules will be deleted.

COPPOCK indicator
 Post subject: COPPOCK indicator Post rating: 0   Post Posted: Thu 08 Sep, 2011, 12:14 

User rating: 0
Joined: Wed 07 Sep, 2011, 12:10
Posts: 4
Location: DE
Hi,

I want a COPPOCK indicator, but i have problems with the code and need help.

I have used the formula: COP = WMA[20] of (ROC[8] + ROC[18])
(see: https://en.wikipedia.org/wiki/Coppock_curve).

Here is my code:

package jforex.indicators;
 
import com.dukascopy.api.indicators.*;
import com.dukascopy.api.indicators.OutputParameterInfo.DrawingStyle;
 
public class Coppock implements IIndicator {
   private IndicatorInfo indicatorInfo;
   private InputParameterInfo[] inputParameterInfos;
   private OptInputParameterInfo[] optInputParameterInfos;
   private OutputParameterInfo[] outputParameterInfos;
   private double[][][] rocInputs = new double[1][][];
   private double[][] wmaInputs = new double[1][];
   private double[][] outputs = new double[3][];
   private IIndicatorContext context;
   private IIndicator roc0, roc1, wma;
 
    public void onStart(IIndicatorContext context) {
        //getting interfaces of ROC and WMA indicators
        IIndicatorsProvider indicatorsProvider = context.getIndicatorsProvider();
        roc0 = indicatorsProvider.getIndicator("ROC");
        roc1 = indicatorsProvider.getIndicator("ROC");
        wma = indicatorsProvider.getIndicator("WMA");
 
        //inicator with one input, tree optional params and one output
        indicatorInfo = new IndicatorInfo("Coppock", "Coppock Indicator", "My indicators", false, false, true, 1, 3, 1);
 
        //one input array of doubles
        inputParameterInfos = new InputParameterInfo[] {
            new InputParameterInfo("first ROC Input", InputParameterInfo.Type.PRICE),
            new InputParameterInfo("secound ROC Input", InputParameterInfo.Type.PRICE),
            new InputParameterInfo("WMA Input", InputParameterInfo.Type.DOUBLE)
        };
 
        //tree optional params, one for every indicator
        optInputParameterInfos = new OptInputParameterInfo[] {
            new OptInputParameterInfo("WMA Time Period", OptInputParameterInfo.Type.OTHER, new IntegerRangeDescription(20, 1, 30, 20)),
            new OptInputParameterInfo("ROC_0 Time Period", OptInputParameterInfo.Type.OTHER, new IntegerRangeDescription(8, 1, 20, 8)),
            new OptInputParameterInfo("ROC_1 Time Period", OptInputParameterInfo.Type.OTHER, new IntegerRangeDescription(18, 1, 40, 18))
        };
 
        //one output arrays for COP
        outputParameterInfos = new OutputParameterInfo[] {
            new OutputParameterInfo("Coppock line", OutputParameterInfo.Type.DOUBLE, DrawingStyle.LINE),
        };
    }
 
    public IndicatorResult calculate(int startIndex, int endIndex) {
        if (startIndex - getLookback() < 0)
            startIndex -= startIndex - getLookback();
 
        //calculating roc
        int roc0Lookback = roc0.getLookback(), roc1Lookback = roc1.getLookback();
         
        //first alocate buffer for roc results
        double[] roc0Output, roc1Output, rocOutput;
        if (startIndex > endIndex || roc0Lookback > endIndex || roc1Lookback > endIndex)
            return new IndicatorResult(0, 0);
        else {
            roc0Output = new double[endIndex - (roc0Lookback > startIndex ? roc0Lookback : startIndex) + 1];
            roc1Output = new double[endIndex - (roc1Lookback > startIndex ? roc1Lookback : startIndex) + 1];
            rocOutput = new double[Math.max(roc0Output.length, roc1Output.length)];
        }
 
        //init roc indicatro with input data and array for output
        roc0.setInputParameter(0, rocInputs[0]);
        roc0.setOutputParameter(0, roc0Output);
        roc1.setInputParameter(0, wmaInputs[0]);
        roc1.setOutputParameter(0, roc1Output);
        IndicatorResult roc0Result = roc0.calculate(startIndex, endIndex);
        IndicatorResult roc1Result = roc1.calculate(startIndex, endIndex);
        if (roc0Result.getNumberOfElements() < wma.getLookback() || roc1Result.getNumberOfElements() < wma.getLookback())
            return new IndicatorResult(0, 0);
 
        //calculating cop
        for (int i = 0; i < rocOutput.length; i++)
            rocOutput[i] = roc0Output[i] + roc1Output[i];
 
        wma.setInputParameter(0, rocOutput);
        wma.setOutputParameter(0, outputs[0]);
        IndicatorResult wmaResult = wma.calculate(startIndex, endIndex);
 
        if (wmaResult.getNumberOfElements() == 0) {
            //wma returned 0 values
            return new IndicatorResult(0, 0);
        }
 
        IndicatorResult result = new IndicatorResult(roc0Result.getFirstValueIndex() + roc1Result.getFirstValueIndex() + wmaResult.getFirstValueIndex(), wmaResult.getNumberOfElements());
 
        return result;
    }
 
    public IndicatorInfo getIndicatorInfo() {
        return indicatorInfo;
    }
 
    public InputParameterInfo getInputParameterInfo(int index) {
        if (index <= inputParameterInfos.length) {
            return inputParameterInfos[index];
        }
        return null;
    }
 
    public int getLookback() {
        return (roc0.getLookback() + roc1.getLookback() + wma.getLookback());
    }
 
    public int getLookforward() {
        return 0;
   }
     
    public OptInputParameterInfo getOptInputParameterInfo(int index) {
        if (index <= optInputParameterInfos.length) {
            return optInputParameterInfos[index];
        }
        return null;
    }
 
    public OutputParameterInfo getOutputParameterInfo(int index) {
        if (index <= outputParameterInfos.length) {
            return outputParameterInfos[index];
        }
        return null;
    }
 
    public void setInputParameter(int index, Object array) {
        if (index == 0) rocInputs[0] = (double[][]) array;
        else if (index == 1) wmaInputs[0] = (double[]) array;
    }
 
    public void setOptInputParameter(int index, Object value) {
        //set optional params in indicators
        switch (index) {
        case 0:
            wma.setOptInputParameter(0, value);
            break;
        case 1:
            roc0.setOptInputParameter(0, value);
            break;
        case 2:
            roc1.setOptInputParameter(0, value);
            break;
        }
    }
 
    public void setOutputParameter(int index, Object array) {
        outputs[index] = (double[]) array;
    }
}


Thanks for any help.

regards


 
 Post subject: Re: COPPOCK indicator Post rating: 0   Post Posted: Thu 08 Sep, 2011, 15:45 
User avatar

User rating:
Joined: Fri 31 Aug, 2007, 09:17
Posts: 6139
Please see the comments in the source code:
package jforex.indicators;
 
import java.text.DecimalFormat;

import com.dukascopy.api.IConsole;
import com.dukascopy.api.indicators.*;
import com.dukascopy.api.indicators.OutputParameterInfo.DrawingStyle;
 
public class Coppock2 implements IIndicator {
   private IndicatorInfo indicatorInfo;
   private InputParameterInfo[] inputParameterInfos;
   private OptInputParameterInfo[] optInputParameterInfos;
   private OutputParameterInfo[] outputParameterInfos;
   private double[][][] rocInputs = new double[2][][];
   private double[][] wmaInputs = new double[1][];
   private double[][] outputs = new double[1][];
   private IIndicatorContext context;
   private IIndicator roc0, roc1, wma;
   private IConsole console;
   int lookback;
   boolean logInterValues = false;
 
    public void onStart(IIndicatorContext context) {
        //getting interfaces of ROC and WMA indicators
        IIndicatorsProvider indicatorsProvider = context.getIndicatorsProvider();
        roc0 = indicatorsProvider.getIndicator("ROC");
        roc1 = indicatorsProvider.getIndicator("ROC");
        wma = indicatorsProvider.getIndicator("WMA");
       
        //Support: the lookback was sum of all three which was incorrect - you just need max of the lookback values
        lookback = Math.max(Math.max(roc0.getLookback(), roc1.getLookback()),wma.getLookback());
 
        //Support: number of inputs was set to 1, which meant that you received only the first input
        //inicator with one input, tree optional params and one output
        indicatorInfo = new IndicatorInfo("Coppock", "Coppock Indicator", "My indicators", false, false, true, 3, 3, 1);
 
        //one input array of doubles
        inputParameterInfos = new InputParameterInfo[] {
            new InputParameterInfo("first ROC Input", InputParameterInfo.Type.PRICE),
            new InputParameterInfo("secound ROC Input", InputParameterInfo.Type.PRICE),
            new InputParameterInfo("WMA Input", InputParameterInfo.Type.DOUBLE)
        };
 
        //tree optional params, one for every indicator
        optInputParameterInfos = new OptInputParameterInfo[] {
            new OptInputParameterInfo("WMA Time Period", OptInputParameterInfo.Type.OTHER, new IntegerRangeDescription(20, 1, 30, 20)),
            new OptInputParameterInfo("ROC_0 Time Period", OptInputParameterInfo.Type.OTHER, new IntegerRangeDescription(8, 1, 20, 8)),
            new OptInputParameterInfo("ROC_1 Time Period", OptInputParameterInfo.Type.OTHER, new IntegerRangeDescription(18, 1, 40, 18))
        };
 
        //one output arrays for COP
        outputParameterInfos = new OutputParameterInfo[] {
            new OutputParameterInfo("Coppock line", OutputParameterInfo.Type.DOUBLE, DrawingStyle.LINE),
        };
       
        this.console = context.getConsole();
    }
 
    public IndicatorResult calculate(int startIndex, int endIndex) {
        if (startIndex - getLookback() < 0)
            startIndex -= startIndex - getLookback();
         
        //Support: loockback calculations got deleted, since we dealt with them already in onStart
        //first alocate buffer for roc results
        double[] roc0Output, roc1Output, rocOutput;
        if (startIndex > endIndex )
            return new IndicatorResult(0, 0);
        else {
            roc0Output = new double[endIndex - startIndex + 1];
            roc1Output = new double[endIndex - startIndex + 1];
            rocOutput = new double[endIndex + 1];
        }
 
        //init roc indicatro with input data and array for output
        //Support: here rocInputs[0][0] instead of rocInputs[0] needed to get passed
        roc0.setInputParameter(0, rocInputs[0][0]);
        roc0.setOutputParameter(0, roc0Output);
        roc1.setInputParameter(0, wmaInputs[0]);
        roc1.setOutputParameter(0, roc1Output);
       
        IndicatorResult roc0Result = roc0.calculate(startIndex, endIndex);
        IndicatorResult roc1Result = roc1.calculate(startIndex, endIndex);
       
        if (roc0Result.getNumberOfElements() < wma.getLookback() || roc1Result.getNumberOfElements() < wma.getLookback())
            return new IndicatorResult(0, 0);
 
       
        //Support: here you need additional index j since 0 of roc0Output and roc1Output maps to startIndex of rocOutput
        //calculating cop
        for (int i = startIndex, j=0; i < endIndex + 1; i++,j++)
            rocOutput[i] = roc0Output[j] + roc1Output[j];
       
        //Support: if you wish to log intermediary values, assign logInterValues=true
        if (logInterValues){
           print ("ROC startIndex="+ startIndex + " endIndex=" + endIndex
                 + " roc0Output: " + roc0Output.length + " " + arrayToString(roc0Output)
                 + " roc1Output: " + roc1Output.length + " " + arrayToString(roc1Output)
                 + " rocOutput: " + rocOutput.length + " " + arrayToString(rocOutput)
                 );
        }
 
        wma.setInputParameter(0, rocOutput);
        wma.setOutputParameter(0, outputs[0]);
       
        IndicatorResult wmaResult = wma.calculate(startIndex, endIndex);       
       
        //Support: if you wish to log intermediary values, assign logInterValues=true
        if (logInterValues){
           print ("WMA startIndex="+ startIndex + " endIndex=" + endIndex + " getLookback=" + wma.getLookback()
                 + " wma inputs: " + rocOutput.length + " " + arrayToString(rocOutput)
                 + " indicator outputs: "+ outputs[0].length + " " + arrayToString(outputs[0]));
        }
       
        if (wmaResult.getNumberOfElements() == 0) {
            //wma returned 0 values
            return new IndicatorResult(0, 0);
        }
 
        return new IndicatorResult(startIndex, outputs[0].length);
    }
   
    //Support: some helper functions
    public static String arrayToString(double [] arr){
        String str = "";
        for (int r=0; r<arr.length; r++) {
            str += "[" + r + "] "+ (new DecimalFormat("#.#######")).format(arr[r]) + "; ";
        }
        return str;
     }
   
   public static String arrayToString(double [][] arr){
      String str = "";
      for (int r=0; r<arr.length; r++) {
          for (int c=0; c<arr[r].length; c++) {
             str += " " + (new DecimalFormat("#.#######")).format(arr[r][c]);
          }
          str += "; ";
      }
      return str;
   }
   
   public static String arrayToString(double [][] arr, boolean isIndexed){
      String str = "";
      String indexStr = "";
      for (int r=0; r<arr.length; r++) {
          for (int c=0; c<arr[r].length; c++) {
             indexStr = isIndexed ? "[" + r + "][" + c + "] " : "";
             str += " " + indexStr + (new DecimalFormat("#.#######")).format(arr[r][c]);
          }
          str += "; ";
      }
      return str;
   }
   
    private void print(Object o){    this.console.getOut().println(o);   }
 
    public IndicatorInfo getIndicatorInfo() {
        return indicatorInfo;
    }
 
    public InputParameterInfo getInputParameterInfo(int index) {
        if (index <= inputParameterInfos.length) {
            return inputParameterInfos[index];
        }
        return null;
    }
 
    public int getLookback() {
        return lookback; //(roc0.getLookback() + roc1.getLookback() + wma.getLookback());
    }
 
    public int getLookforward() {
        return 0;
   }
     
    public OptInputParameterInfo getOptInputParameterInfo(int index) {
        if (index <= optInputParameterInfos.length) {
            return optInputParameterInfos[index];
        }
        return null;
    }
 
    public OutputParameterInfo getOutputParameterInfo(int index) {
        if (index <= outputParameterInfos.length) {
            return outputParameterInfos[index];
        }
        return null;
    }
 
    public void setInputParameter(int index, Object array) {
        if (index == 0)
           rocInputs[0] = (double[][]) array;
        if (index == 1)
           rocInputs[1] = (double[][]) array;
        if (index == 2)
           wmaInputs[0] = (double []) array;
        //else if (index == 1) wmaInputs[0] = (double[]) array;
    }
 
    public void setOptInputParameter(int index, Object value) {
        //set optional params in indicators
        switch (index) {
        case 0:
            wma.setOptInputParameter(0, value);
            break;
        case 1:
            roc0.setOptInputParameter(0, value);
            break;
        case 2:
            roc1.setOptInputParameter(0, value);
            break;
        }
    }
 
    public void setOutputParameter(int index, Object array) {
        outputs[index] = (double[]) array;
 }
}


 
 Post subject: Re: COPPOCK indicator Post rating: 0   Post Posted: Thu 08 Sep, 2011, 20:55 

User rating: 0
Joined: Wed 07 Sep, 2011, 12:10
Posts: 4
Location: DE
API Support wrote:
Please see the comments in the source code:
package jforex.indicators;
 
import java.text.DecimalFormat;

import com.dukascopy.api.IConsole;
import com.dukascopy.api.indicators.*;
import com.dukascopy.api.indicators.OutputParameterInfo.DrawingStyle;
 
public class Coppock2 implements IIndicator {
   private IndicatorInfo indicatorInfo;
   private InputParameterInfo[] inputParameterInfos;
   private OptInputParameterInfo[] optInputParameterInfos;
   private OutputParameterInfo[] outputParameterInfos;
   private double[][][] rocInputs = new double[2][][];
   private double[][] wmaInputs = new double[1][];
   private double[][] outputs = new double[1][];
   private IIndicatorContext context;
   private IIndicator roc0, roc1, wma;
   private IConsole console;
   int lookback;
   boolean logInterValues = false;
 
    public void onStart(IIndicatorContext context) {
        //getting interfaces of ROC and WMA indicators
        IIndicatorsProvider indicatorsProvider = context.getIndicatorsProvider();
        roc0 = indicatorsProvider.getIndicator("ROC");
        roc1 = indicatorsProvider.getIndicator("ROC");
        wma = indicatorsProvider.getIndicator("WMA");
       
        //Support: the lookback was sum of all three which was incorrect - you just need max of the lookback values
        lookback = Math.max(Math.max(roc0.getLookback(), roc1.getLookback()),wma.getLookback());
 
        //Support: number of inputs was set to 1, which meant that you received only the first input
        //inicator with one input, tree optional params and one output
        indicatorInfo = new IndicatorInfo("Coppock", "Coppock Indicator", "My indicators", false, false, true, 3, 3, 1);
 
        //one input array of doubles
        inputParameterInfos = new InputParameterInfo[] {
            new InputParameterInfo("first ROC Input", InputParameterInfo.Type.PRICE),
            new InputParameterInfo("secound ROC Input", InputParameterInfo.Type.PRICE),
            new InputParameterInfo("WMA Input", InputParameterInfo.Type.DOUBLE)
        };
 
        //tree optional params, one for every indicator
        optInputParameterInfos = new OptInputParameterInfo[] {
            new OptInputParameterInfo("WMA Time Period", OptInputParameterInfo.Type.OTHER, new IntegerRangeDescription(20, 1, 30, 20)),
            new OptInputParameterInfo("ROC_0 Time Period", OptInputParameterInfo.Type.OTHER, new IntegerRangeDescription(8, 1, 20, 8)),
            new OptInputParameterInfo("ROC_1 Time Period", OptInputParameterInfo.Type.OTHER, new IntegerRangeDescription(18, 1, 40, 18))
        };
 
        //one output arrays for COP
        outputParameterInfos = new OutputParameterInfo[] {
            new OutputParameterInfo("Coppock line", OutputParameterInfo.Type.DOUBLE, DrawingStyle.LINE),
        };
       
        this.console = context.getConsole();
    }
 
    public IndicatorResult calculate(int startIndex, int endIndex) {
        if (startIndex - getLookback() < 0)
            startIndex -= startIndex - getLookback();
         
        //Support: loockback calculations got deleted, since we dealt with them already in onStart
        //first alocate buffer for roc results
        double[] roc0Output, roc1Output, rocOutput;
        if (startIndex > endIndex )
            return new IndicatorResult(0, 0);
        else {
            roc0Output = new double[endIndex - startIndex + 1];
            roc1Output = new double[endIndex - startIndex + 1];
            rocOutput = new double[endIndex + 1];
        }
 
        //init roc indicatro with input data and array for output
        //Support: here rocInputs[0][0] instead of rocInputs[0] needed to get passed
        roc0.setInputParameter(0, rocInputs[0][0]);
        roc0.setOutputParameter(0, roc0Output);
        roc1.setInputParameter(0, wmaInputs[0]);
        roc1.setOutputParameter(0, roc1Output);
       
        IndicatorResult roc0Result = roc0.calculate(startIndex, endIndex);
        IndicatorResult roc1Result = roc1.calculate(startIndex, endIndex);
       
        if (roc0Result.getNumberOfElements() < wma.getLookback() || roc1Result.getNumberOfElements() < wma.getLookback())
            return new IndicatorResult(0, 0);
 
       
        //Support: here you need additional index j since 0 of roc0Output and roc1Output maps to startIndex of rocOutput
        //calculating cop
        for (int i = startIndex, j=0; i < endIndex + 1; i++,j++)
            rocOutput[i] = roc0Output[j] + roc1Output[j];
       
        //Support: if you wish to log intermediary values, assign logInterValues=true
        if (logInterValues){
           print ("ROC startIndex="+ startIndex + " endIndex=" + endIndex
                 + " roc0Output: " + roc0Output.length + " " + arrayToString(roc0Output)
                 + " roc1Output: " + roc1Output.length + " " + arrayToString(roc1Output)
                 + " rocOutput: " + rocOutput.length + " " + arrayToString(rocOutput)
                 );
        }
 
        wma.setInputParameter(0, rocOutput);
        wma.setOutputParameter(0, outputs[0]);
       
        IndicatorResult wmaResult = wma.calculate(startIndex, endIndex);       
       
        //Support: if you wish to log intermediary values, assign logInterValues=true
        if (logInterValues){
           print ("WMA startIndex="+ startIndex + " endIndex=" + endIndex + " getLookback=" + wma.getLookback()
                 + " wma inputs: " + rocOutput.length + " " + arrayToString(rocOutput)
                 + " indicator outputs: "+ outputs[0].length + " " + arrayToString(outputs[0]));
        }
       
        if (wmaResult.getNumberOfElements() == 0) {
            //wma returned 0 values
            return new IndicatorResult(0, 0);
        }
 
        return new IndicatorResult(startIndex, outputs[0].length);
    }
   
    //Support: some helper functions
    public static String arrayToString(double [] arr){
        String str = "";
        for (int r=0; r<arr.length; r++) {
            str += "[" + r + "] "+ (new DecimalFormat("#.#######")).format(arr[r]) + "; ";
        }
        return str;
     }
   
   public static String arrayToString(double [][] arr){
      String str = "";
      for (int r=0; r<arr.length; r++) {
          for (int c=0; c<arr[r].length; c++) {
             str += " " + (new DecimalFormat("#.#######")).format(arr[r][c]);
          }
          str += "; ";
      }
      return str;
   }
   
   public static String arrayToString(double [][] arr, boolean isIndexed){
      String str = "";
      String indexStr = "";
      for (int r=0; r<arr.length; r++) {
          for (int c=0; c<arr[r].length; c++) {
             indexStr = isIndexed ? "[" + r + "][" + c + "] " : "";
             str += " " + indexStr + (new DecimalFormat("#.#######")).format(arr[r][c]);
          }
          str += "; ";
      }
      return str;
   }
   
    private void print(Object o){    this.console.getOut().println(o);   }
 
    public IndicatorInfo getIndicatorInfo() {
        return indicatorInfo;
    }
 
    public InputParameterInfo getInputParameterInfo(int index) {
        if (index <= inputParameterInfos.length) {
            return inputParameterInfos[index];
        }
        return null;
    }
 
    public int getLookback() {
        return lookback; //(roc0.getLookback() + roc1.getLookback() + wma.getLookback());
    }
 
    public int getLookforward() {
        return 0;
   }
     
    public OptInputParameterInfo getOptInputParameterInfo(int index) {
        if (index <= optInputParameterInfos.length) {
            return optInputParameterInfos[index];
        }
        return null;
    }
 
    public OutputParameterInfo getOutputParameterInfo(int index) {
        if (index <= outputParameterInfos.length) {
            return outputParameterInfos[index];
        }
        return null;
    }
 
    public void setInputParameter(int index, Object array) {
        if (index == 0)
           rocInputs[0] = (double[][]) array;
        if (index == 1)
           rocInputs[1] = (double[][]) array;
        if (index == 2)
           wmaInputs[0] = (double []) array;
        //else if (index == 1) wmaInputs[0] = (double[]) array;
    }
 
    public void setOptInputParameter(int index, Object value) {
        //set optional params in indicators
        switch (index) {
        case 0:
            wma.setOptInputParameter(0, value);
            break;
        case 1:
            roc0.setOptInputParameter(0, value);
            break;
        case 2:
            roc1.setOptInputParameter(0, value);
            break;
        }
    }
 
    public void setOutputParameter(int index, Object array) {
        outputs[index] = (double[]) array;
 }
}



Dear Support,

I thank you very much for your help.

I still have some questions to understand the source code:

1) Is the difference between a 2-dimensional and 3-dimensional array, for example:

private double [ ][ ][ ] rocInputs = new double [2][ ][ ];
private double [ ][ ] wmaInputs = new double [1][ ];

because, 'InputParameterInfo.Type type' is either 'DOUBLE' or 'PRICE' set?

DOUBLE = 2-dim; PRICE = 3-dim?

2) Why is the 'lookback' once the sum of each lookbacks and other times the maximum of the lookbacks?
What is the concrete functionality of the function 'getLookback ()'?

3) How do I program horizontal lines (to show constant values, e.g. extreme ranges) inside the indicator window? (e.g. STOCH: 80/20 - lines)

Thank you for your help in advance.

regards


 
 Post subject: Re: COPPOCK indicator Post rating: 0   Post Posted: Fri 09 Sep, 2011, 07:40 
User avatar

User rating:
Joined: Fri 31 Aug, 2007, 09:17
Posts: 6139
trader1389 wrote:
1) Is the difference between a 2-dimensional and 3-dimensional array, for example:

private double [ ][ ][ ] rocInputs = new double [2][ ][ ];
private double [ ][ ] wmaInputs = new double [1][ ];

because, 'InputParameterInfo.Type type' is either 'DOUBLE' or 'PRICE' set?

DOUBLE = 2-dim; PRICE = 3-dim?
No, DOUBLE is a 1-dim array of double values and PRICE is a 2-dim array, where one dimension Price values of open, close, high, low, volume and the other stands for price element. When you use these inputs in your indicator they add an additional dimension, because the first dimension stands for the input number, e.g. rocInputs[a][b][c]:
  1. Stands for input number - the first one rocInputs[0] you pass to the roc0 and the second rocInputs[1] - to roc1.
  2. Stands for price element, e.g., rocInputs[0][0] = {open=1.4, close=1.41, high=1.42, low=1.39, volume=1.0}.
  3. Stands for value in price, e.g. rocInputs[0][0][0] = {open=1.4}.
The syntax is sloppy, but hopefully this represents the idea well enough.
See all input types here:
https://www.dukascopy.com/client/javadoc ... .Type.html
trader1389 wrote:
2) Why is the 'lookback' once the sum of each lookbacks and other times the maximum of the lookbacks?
What is the concrete functionality of the function 'getLookback ()'?
The other approach was not hazardous, but these extra lookback values in this case were redundant and made more extracting the needed inputs and outputs more sophisticated, see:
https://www.dukascopy.com/wiki/index.php ... etLookback
trader1389 wrote:
3) How do I program horizontal lines (to show constant values, e.g. extreme ranges) inside the indicator window? (e.g. STOCH: 80/20 - lines)
This will be available with the next release of JForex client. Follow release information here: viewforum.php?f=71

After revisiting the indicator, we realized that there was an error in roc0 input passing and that actually the indicator needs just one input array, see the comments marked with "Support 2":
package jforex.indicators;
 
import java.text.DecimalFormat;

import com.dukascopy.api.IConsole;
import com.dukascopy.api.indicators.*;
import com.dukascopy.api.indicators.OutputParameterInfo.DrawingStyle;
 
public class Coppock2 implements IIndicator {
   private IndicatorInfo indicatorInfo;
   private InputParameterInfo[] inputParameterInfos;
   private OptInputParameterInfo[] optInputParameterInfos;
   private OutputParameterInfo[] outputParameterInfos;
   private double[][] inputs = new double[1][];
   private double[][] outputs = new double[1][];
   private IIndicatorContext context;
   private IIndicator roc0, roc1, wma;
   private IConsole console;
   int lookback;
   boolean logInterValues = false;
 
    public void onStart(IIndicatorContext context) {
        //getting interfaces of ROC and WMA indicators
        IIndicatorsProvider indicatorsProvider = context.getIndicatorsProvider();
        roc0 = indicatorsProvider.getIndicator("ROC");
        roc1 = indicatorsProvider.getIndicator("ROC");
        wma = indicatorsProvider.getIndicator("WMA");
       
        this.console = context.getConsole();
       
        //Support 2: print indicator infos, so that you know what inputs to pass and what outputs to expect
        if (logInterValues){
           printIndicatorInfos(roc0);
           printIndicatorInfos(wma);
        }
       
        //Support: the lookback was sum of all three which was incorrect - you just need max of the looback values
        lookback = Math.max(Math.max(roc0.getLookback(), roc1.getLookback()),wma.getLookback());
 
        //Support: number of inputs was set to 1, which meant that you received only the first input
        //inicator with one input, tree optional params and one output
        indicatorInfo = new IndicatorInfo("Coppock", "Coppock Indicator", "My indicators", false, false, true, 1, 3, 1);
 
        //Support 2: we actually need just one input - DOUBLE by default is an array of close prices, this can be modified, by using the objects setters
        //one input array of doubles
        inputParameterInfos = new InputParameterInfo[] {
            new InputParameterInfo("ROC input", InputParameterInfo.Type.DOUBLE)
        };
 
        //tree optional params, one for every indicator
        optInputParameterInfos = new OptInputParameterInfo[] {
            new OptInputParameterInfo("WMA Time Period", OptInputParameterInfo.Type.OTHER, new IntegerRangeDescription(20, 1, 30, 20)),
            new OptInputParameterInfo("ROC_0 Time Period", OptInputParameterInfo.Type.OTHER, new IntegerRangeDescription(8, 1, 20, 8)),
            new OptInputParameterInfo("ROC_1 Time Period", OptInputParameterInfo.Type.OTHER, new IntegerRangeDescription(18, 1, 40, 18))
        };
 
        //one output arrays for COP
        outputParameterInfos = new OutputParameterInfo[] {
            new OutputParameterInfo("Coppock line", OutputParameterInfo.Type.DOUBLE, DrawingStyle.LINE),
        };
       

    }
 
    public IndicatorResult calculate(int startIndex, int endIndex) {
        if (startIndex - getLookback() < 0)
            startIndex -= startIndex - getLookback();
         
        //Support: loockback calculations got deleted, since we dealt with them already in onStart
        //first alocate buffer for roc results
        double[] roc0Output, roc1Output, rocOutput;
        if (startIndex > endIndex )
            return new IndicatorResult(0, 0);
        else {
            roc0Output = new double[endIndex - startIndex + 1];
            roc1Output = new double[endIndex - startIndex + 1];
            rocOutput = new double[endIndex + 1];
        }
 
        //init roc indicator with input data and array for output
        //Support: for both the input type is the same so we can use the same variable - inputs[0]
        roc0.setInputParameter(0, inputs[0]);
        roc0.setOutputParameter(0, roc0Output);
        roc1.setInputParameter(0, inputs[0]);
        roc1.setOutputParameter(0, roc1Output);
       
        IndicatorResult roc0Result = roc0.calculate(startIndex, endIndex);
        IndicatorResult roc1Result = roc1.calculate(startIndex, endIndex);
       
        if (roc0Result.getNumberOfElements() < wma.getLookback() || roc1Result.getNumberOfElements() < wma.getLookback())
            return new IndicatorResult(0, 0);
 
       
        //Support 2: here you need additional index j since 0 of roc0Output and roc1Output maps to startIndex of rocOutput
        //calculating cop
        for (int i = startIndex, j=0; i < endIndex + 1; i++,j++)
            rocOutput[i] = roc0Output[j] + roc1Output[j];
       
        //Support: if you wish to log intermediary values, assign logInterValues=true
        if (logInterValues){
           print ("ROC startIndex="+ startIndex + " endIndex=" + endIndex
                 + " roc0Output: " + roc0Output.length + " " + arrayToString(roc0Output)
                 + " roc1Output: " + roc1Output.length + " " + arrayToString(roc1Output)
                 + " rocOutput: " + rocOutput.length + " " + arrayToString(rocOutput)
                 );
        }
 
        wma.setInputParameter(0, rocOutput);
        wma.setOutputParameter(0, outputs[0]);
       
        IndicatorResult wmaResult = wma.calculate(startIndex, endIndex);       
       
        //Support: if you wish to log intermediary values, assign logInterValues=true
        if (logInterValues){
           print ("WMA startIndex="+ startIndex + " endIndex=" + endIndex + " getLookback=" + wma.getLookback()
                 + " wma inputs: " + rocOutput.length + " " + arrayToString(rocOutput)
                 + " indicator outputs: "+ outputs[0].length + " " + arrayToString(outputs[0]));
        }
       
        if (wmaResult.getNumberOfElements() == 0) {
            //wma returned 0 values
            return new IndicatorResult(0, 0);
        }
 
        return new IndicatorResult(startIndex, outputs[0].length);
    }
   
    //Support 2: helper functions
    /**
     * print all input, output, opt input names and types
     */
    private void printIndicatorInfos(IIndicator ind){
        for (int i = 0; i < ind.getIndicatorInfo().getNumberOfInputs(); i++){
           print(ind.getIndicatorInfo().getName() +" Input " + ind.getInputParameterInfo(i).getName() +" " + ind.getInputParameterInfo(i).getType());
        }
        for (int i = 0; i < ind.getIndicatorInfo().getNumberOfOptionalInputs(); i++){
           print(ind.getIndicatorInfo().getName() +" Opt Input " + ind.getOptInputParameterInfo(i).getName() +" " + ind.getOptInputParameterInfo(i).getType());
        }
        for (int i = 0; i < ind.getIndicatorInfo().getNumberOfOutputs(); i++){
           print(ind.getIndicatorInfo().getName() +" Output " + ind.getOutputParameterInfo(i).getName() +" " + ind.getOutputParameterInfo(i).getType());
        }
    }
   
    public static String arrayToString(double [] arr){
        String str = "";
        for (int r=0; r<arr.length; r++) {
            str += "[" + r + "] "+ (new DecimalFormat("#.#######")).format(arr[r]) + "; ";
        }
        return str;
     }
   
   public static String arrayToString(double [][] arr){
      String str = "";
      for (int r=0; r<arr.length; r++) {
          for (int c=0; c<arr[r].length; c++) {
             str += " " + (new DecimalFormat("#.#######")).format(arr[r][c]);
          }
          str += "; ";
      }
      return str;
   }
   
   public static String arrayToString(double [][] arr, boolean isIndexed){
      String str = "";
      String indexStr = "";
      for (int r=0; r<arr.length; r++) {
          for (int c=0; c<arr[r].length; c++) {
             indexStr = isIndexed ? "[" + r + "][" + c + "] " : "";
             str += " " + indexStr + (new DecimalFormat("#.#######")).format(arr[r][c]);
          }
          str += "; ";
      }
      return str;
   }
   
    private void print(Object o){    this.console.getOut().println(o);   }
 
    public IndicatorInfo getIndicatorInfo() {
        return indicatorInfo;
    }
 
    public InputParameterInfo getInputParameterInfo(int index) {
        if (index <= inputParameterInfos.length) {
            return inputParameterInfos[index];
        }
        return null;
    }
 
    public int getLookback() {
        return lookback;
    }
 
    public int getLookforward() {
        return 0;
   }
     
    public OptInputParameterInfo getOptInputParameterInfo(int index) {
        if (index <= optInputParameterInfos.length) {
            return optInputParameterInfos[index];
        }
        return null;
    }
 
    public OutputParameterInfo getOutputParameterInfo(int index) {
        if (index <= outputParameterInfos.length) {
            return outputParameterInfos[index];
        }
        return null;
    }
 
    public void setInputParameter(int index, Object array) {
        inputs[index] = (double []) array;
    }
 
    public void setOptInputParameter(int index, Object value) {
        //set optional params in indicators
        switch (index) {
        case 0:
            wma.setOptInputParameter(0, value);
            break;
        case 1:
            roc0.setOptInputParameter(0, value);
            break;
        case 2:
            roc1.setOptInputParameter(0, value);
            break;
        }
    }
 
    public void setOutputParameter(int index, Object array) {
        outputs[index] = (double[]) array;
 }
}


 

Jump to:  

cron
  © 1998-2025 Dukascopy® Bank SA
On-line Currency forex trading with Swiss Forex Broker - ECN Forex Brokerage,
Managed Forex Accounts, introducing forex brokers, Currency Forex Data Feed and News
Currency Forex Trading Platform provided on-line by Dukascopy.com