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.

Linear Regression/volume
 Post subject: Linear Regression/volume Post rating: 0   New post Posted: Tue 12 Jul, 2011, 01:04 

User rating: -
Hi,
i've been trying to make an indicator that would calculate the quotient of the linear regression and the volume, presenting it as a line. This is the first time i am messing with indicators. I have taken the SMAoverRSI indicator from the wiki and tried to adapt it, but i get the following error message, when running it:
23:58:59 Error in indicator: java.lang.ClassCastException: [D cannot be cast to [[D @ jforex.SMAOverRSIIndicator.calculate(SMAOverRSIIndicator.java:54)

Since the compilation was successful, I hope that the problem can easily be fixed.
Can anyone help?
Thanks in advance!

package jforex;

import com.dukascopy.api.indicators.*;

public class SMAOverRSIIndicator 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[2][];
    private IIndicatorContext context;
    private IIndicator linreg;
    private IIndicator volume;
   
    public void onStart(IIndicatorContext context) {           
       
        IIndicatorsProvider indicatorsProvider = context.getIndicatorsProvider();
        linreg = indicatorsProvider.getIndicator("linearreg");
        volume = indicatorsProvider.getIndicator("volume");

        indicatorInfo = new IndicatorInfo("linreg/volume", "linearreg over volume", "My indicators",
                false, false, false, false, 1, 1, 1);

        inputParameterInfos = new InputParameterInfo[] {new InputParameterInfo("Input data", InputParameterInfo.Type.DOUBLE)};

        optInputParameterInfos = new OptInputParameterInfo[] {new OptInputParameterInfo("Linear Regression Time Period", OptInputParameterInfo.Type.OTHER,
                new IntegerRangeDescription(14, 2, 100, 1))};

        outputParameterInfos = new OutputParameterInfo[] {new OutputParameterInfo("Linreg line", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.LINE), new OutputParameterInfo("volumes", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.HISTOGRAM)};
    }

    public IndicatorResult calculate(int startIndex, int endIndex) {       
        //calculating rsi
        int linregLookback = linreg.getLookback();
        //first alocate buffer for rsi results
        double[] linregOutput;
        if (startIndex > endIndex || linregLookback > endIndex) {   
            return new IndicatorResult(0, 0);
        } else {
            //take the greater value (startindex/ lookback)
            linregOutput = new double[endIndex - (linregLookback > startIndex ? linregLookback : startIndex) + 1];
        }
        //init rsi indicator with input data and array for output
        linreg.setInputParameter(0, inputs[0]);
        linreg.setOutputParameter(0, linregOutput);
        IndicatorResult linregResult = linreg.calculate(startIndex, endIndex);
        if (linregResult.getNumberOfElements() < volume.getLookback()) {
            //not enough data to calculate sma
            return new IndicatorResult(0, 0);
        }
       
        //calculating sma
        volume.setInputParameter(0, inputs[0]);
        volume.setOutputParameter(0, outputs[1]);
        IndicatorResult volumeResult = volume.calculate(0, linregResult.getNumberOfElements() - 1);
        if (volumeResult.getNumberOfElements() == 0) {
            //sma returned 0 values
            return new IndicatorResult(0, 0);
        }
        //copy rsi values to output excluding first values used for sma lookback
        System.arraycopy(linregOutput, volumeResult.getFirstValueIndex(), outputs[0], 0, volumeResult.getNumberOfElements());
        //creating result, first value index for our input is FVI for rsi + FVI for sma, because we calculated sma starting from 0 element
        IndicatorResult result = new IndicatorResult(linregResult.getFirstValueIndex() + volumeResult.getFirstValueIndex(), volumeResult.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 linreg.getLookback() + volume.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) {
        inputs[index] = (double[]) array;
    }

    public void setOptInputParameter(int index, Object value) {
        //set optional params in indicators
        switch (index) {
            case 0:
                linreg.setOptInputParameter(0, value);
                break;
            case 1:
                volume.setOptInputParameter(0, value);
                break;
        }
    }

    public void setOutputParameter(int index, Object array) {
        outputs[index] = (double[]) array;
    }
}


 
 Post subject: Re: Linear Regression/volume Post rating: 0   New post Posted: Tue 12 Jul, 2011, 13:36 
User avatar

User rating:
Joined: Fri 31 Aug, 2007, 09:17
Posts: 6139
There were multiple issues, like incompatibility between parameter types and incorrect parameter counts at indicator info declaration. See our comments in the modified indicator:
package jforex.indicators;

 
import java.text.DecimalFormat;

import com.dukascopy.api.IConsole;
import com.dukascopy.api.indicators.*;
 
public class SMAOverRSIIndicator implements IIndicator {
    private IndicatorInfo indicatorInfo;
    private InputParameterInfo[] inputParameterInfos;
    private OptInputParameterInfo[] optInputParameterInfos;
    private OutputParameterInfo[] outputParameterInfos;
    private double[][] inputDouble = new double[1][];
    private double[][][] inputPrice = new double[1][][];
    private double[][] outputs = new double[2][];
    private IIndicatorContext context;
    private IIndicator linreg;
    private IIndicator volume;
   
    private IConsole console;
     
    public void onStart(IIndicatorContext context) {           
         
        IIndicatorsProvider indicatorsProvider = context.getIndicatorsProvider();
        linreg = indicatorsProvider.getIndicator("linearreg");
        volume = indicatorsProvider.getIndicator("volume");
 
        //Support: you had number of outputs set to 1, although they were 2 - make sure that the parameter counts match
        //the ones that you pass later on in onStart method
        indicatorInfo = new IndicatorInfo("linreg volume", "linearreg over volume", "My indicators", false, false, false, 2, 1, 2);
 
        inputParameterInfos = new InputParameterInfo[] {
              new InputParameterInfo("Input data double", InputParameterInfo.Type.DOUBLE),
              new InputParameterInfo("Input data price", InputParameterInfo.Type.PRICE)
        };
 
        optInputParameterInfos = new OptInputParameterInfo[] {
              new OptInputParameterInfo("Linear Regression Time Period", OptInputParameterInfo.Type.OTHER,
                new IntegerRangeDescription(14, 2, 100, 1))};
 
        outputParameterInfos = new OutputParameterInfo[] {
              new OutputParameterInfo("Linreg line", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.LINE),
              new OutputParameterInfo("volumes", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.HISTOGRAM)};

        //Support: print parameter infos - so that you see what types of inputs and outputs you need to pass.
        //Comment this out when you don't need it no more
        this.console = context.getConsole();
        printIndicatorInfos(linreg);
        printIndicatorInfos(volume);
    }
 
    public IndicatorResult calculate(int startIndex, int endIndex) {       
        //calculating rsi
        int linregLookback = linreg.getLookback();
        //first alocate buffer for rsi results
        double[] linregOutput;
        if (startIndex > endIndex || linregLookback > endIndex) {   
            return new IndicatorResult(0, 0);
        } else {
            //take the greater value (startindex/ lookback)
            linregOutput = new double[endIndex - (linregLookback > startIndex ? linregLookback : startIndex) + 1];
        }
        //Support: comment this out once you don't need to know what inputs  you pass to the indicators
        print ("received inputs onCalculate - inputsDouble: " + arrayToString(inputDouble[0]) + " inputPrice: " + arrayToString(inputPrice[0]));
       
        //init rsi indicator with input data and array for output
        linreg.setInputParameter(0, inputDouble[0]);
        linreg.setOutputParameter(0, linregOutput);
        IndicatorResult linregResult = linreg.calculate(startIndex, endIndex);
        if (linregResult.getNumberOfElements() < volume.getLookback() || linregResult.getNumberOfElements() == 0) {
            //not enough data to calculate sma
            return new IndicatorResult(0, 0);
        }
         
        //calculating sma
        //Support: here you got exception because volume input parameter was of type PRICE, but you passed to it DOUBLE
        volume.setInputParameter(0, inputPrice[0]);
        volume.setOutputParameter(0, outputs[1]);
        //Support: here you had not received outputs[1] since in indicatorInfo declaration you had set output size to 1.

        IndicatorResult volumeResult = volume.calculate(0, linregResult.getNumberOfElements() - 1);
        if (volumeResult.getNumberOfElements() == 0) {
            //sma returned 0 values
            return new IndicatorResult(0, 0);
        }
        //copy rsi values to output excluding first values used for sma lookback
        System.arraycopy(linregOutput, volumeResult.getFirstValueIndex(), outputs[0], 0, volumeResult.getNumberOfElements());
        //creating result, first value index for our input is FVI for rsi + FVI for sma, because we calculated sma starting from 0 element
        IndicatorResult result = new IndicatorResult(linregResult.getFirstValueIndex() + volumeResult.getFirstValueIndex(), volumeResult.getNumberOfElements());
        return result;
    }
   
    //________________________________
    //Support: Some helper methods for printing
    private void print(Object o){
       console.getOut().println(o);
    }
   
    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 = "";
      if(arr == null)
         return "null";
      for (int r=0; r<arr.length; r++) {
          for (int c=0; c<arr[r].length; c++) {
             str += "[" + r + "][" + c + "] " + (new DecimalFormat("#.#######")).format(arr[r][c]);
          }
          str += "; ";
      }
      return str;
   }
   //________________________________
 
    public IndicatorInfo getIndicatorInfo() {
        return indicatorInfo;
    }
 
    public InputParameterInfo getInputParameterInfo(int index) {
        if (index <= inputParameterInfos.length) {
            return inputParameterInfos[index];
        }
        return null;
    }
 
    public int getLookback() {
        return linreg.getLookback() + volume.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;
    }
 
    //Support: if you have inputs of different types, it is more convenient to keep them in separate variables
    public void setInputParameter(int index, Object array) {
       if (index == 0){
          inputDouble[0] = (double[]) array;
       } else {
          inputPrice[0] = (double[][]) array;
       }
    }
 
    public void setOptInputParameter(int index, Object value) {
        //set optional params in indicators
        switch (index) {
            case 0:
                linreg.setOptInputParameter(0, value);
                break;
            case 1:
                volume.setOptInputParameter(0, value);
                break;
        }
    }
 
    public void setOutputParameter(int index, Object array) {
        outputs[index] = (double[]) array;
    }
}



 
 Post subject: Re: Linear Regression/volume Post rating: 0   New post Posted: Tue 12 Jul, 2011, 13:40 

User rating: -
Quote:
There were multiple issues, like incompatibility between parameter types and incorrect parameter counts at indicator info declaration.


Sorry about that. :roll:
Thanks a lot!


 

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