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.

Accessing a Custom Indicator's Output Array
 Post subject: Accessing a Custom Indicator's Output Array Post rating: 0   New post Posted: Sun 12 Jun, 2011, 19:54 

User rating: 0
Joined: Sun 12 Jun, 2011, 04:31
Posts: 6
Location: United States,
I'm an experienced programmer, but new to java. In an old post (can't find it anymore, so this is posted as a New topic), Support suggested the use of an enhanced For loop to print each element of a custom indicator's output array. I adopted the recommended code which executed perfectly -- demonstrating that my custom indicator's output array is well-populated and in good order:

for (int i=0; i<sema.length; i++)
{
console.getOut().println("sema["+i+"] = "+sema[i]);
}

However, I don't want to print all elements. I want to reference just one element within some logic.
When I compile the following code, I get no error messages:

double sMA = (Double)sema[1];
context.getConsole().getOut().println("sMA = " + sMA);

But when I execute it, I get:
Strategy tester: java.lang.ArrayIndexOutOfBoundsException: 1 @... (the first of the two lines)

Can you please help me understand the proper way to access an individual element of a custom indicator's output array for use within logical comparisons, calculations, etc?


 
 Post subject: Re: Accessing a Custom Indicator's Output Array Post rating: 0   New post Posted: Mon 13 Jun, 2011, 14:55 
User avatar

User rating:
Joined: Fri 31 Aug, 2007, 09:17
Posts: 6139
You might consider checking array's length e.g.
if (sema.length>1)
    context.getConsole().getOut().println("sMA = " + sema[1]);
You might as well concatenate the whole array into one string before passing it to println:
   context.getConsole().getOut().println(arrayToString(sema));

   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 += "[" + r + "][" + c + "] " + (new DecimalFormat("#.#######")).format(arr[r][c]);
          }
          str += "; ";
      }
      return str;
   }
   
   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;
   }
Aprart from range checking you might consider exception handling, for example, if a particular array range violation
signals about some flawed behaviour.
      try{
         context.getConsole().getOut().println("sMA = " + sema[1]);
      } catch (ArrayIndexOutOfBoundsException e){
         context.getConsole().getErr().println(e);
      }


 
 Post subject: Re: Accessing a Custom Indicator's Output Array Post rating: 0   New post Posted: Tue 14 Jun, 2011, 12:59 

User rating: 0
Joined: Sun 12 Jun, 2011, 04:31
Posts: 6
Location: United States,
Thank you for the examples of printing the entire array. Please see the last sentence of my prior posting: my trouble is with accessing the first element of the array... [1]... when the length of the array is known to be 200. The following code explains with comments:

// this compiles without error and WORKS...
for (Object o3 : sema) {
for (double d3 : (double[])o3){
context.getConsole().getOut().println("sema = " + d3);
}
}
// immediately following, this compiles without error and DOES NOT WORK...
String s = sema[1].toString(); // <---- this is line 196 -- see error message below
double d = Double.valueOf(s).doubleValue();
context.getConsole().getOut().println("sema[1] = " + d);

// Historical Tester output look like this...

// 2011-06-14 11:45:33 Strategy tester: java.lang.ArrayIndexOutOfBoundsException: 1 @ jforex.flint05a.onStart(flint05a.java:196)
// 2011-06-14 11:45:33 sema = 1.362501256680309
// 2011-06-14 11:45:33 sema = 1.3623401491587086
// 2011-06-14 11:45:33 sema = 1.3624056556808117
// 2011-06-14 11:45:33 sema = 1.3628227781073985
// 2011-06-14 11:45:33 sema = 1.3625336265984176 (etc. all 200 elements of the custom indicator sema are printing, including [1].

Thank you for any insight you can provide.


 
 Post subject: Re: Accessing a Custom Indicator's Output Array Post rating: 0   New post Posted: Tue 14 Jun, 2011, 13:58 
User avatar

User rating:
Joined: Fri 31 Aug, 2007, 09:17
Posts: 6139
Could you please tell what is the type of sema? Is it a list of arrays or list of object or an array? I ask this because if it's an array then you can't do this: for (Object o3 : sema), but if it's a list then you can't do this: sema[1]
Assuming that you print your values in setOutputParameter, the printing approach could be the following:
    public void setOutputParameter(int index, Object array) {
       List<Object> semaList = new ArrayList<Object>();
       semaList.add(array);
       Object[] semaArr = {(double[]) array};

       //output for a list
       print("first output: " + ((double[]) semaList.get(0))[0]);
       //output for an array
       print("first output: " + ((double[]) semaArr[0])[0]);
       
        outputs[index] = (double[]) array;
    }

    private void print(Object o){    this.console.getOut().println(o);   }


 
 Post subject: Re: Accessing a Custom Indicator's Output Array Post rating: 0   New post Posted: Wed 15 Jun, 2011, 02:40 

User rating: 0
Joined: Sun 12 Jun, 2011, 04:31
Posts: 6
Location: United States,
Thank you for your answers, but each one presents methods of printing all elements of a list or array. I'm sorry for not being clear with my request. Here is the question from my original posting:

Can you please help me understand the proper way to access an individual element of a custom indicator's output array for use within logical comparisons, calculations, etc?

I confused the issue by not realizing there are differences between lists and arrays (and I still don't know what I've got in this case).

I have created a custom indicator and I'm trying to use it in a strategy as follows:

    public void onStart(IContext context) throws JFException {
        this.engine = context.getEngine();       
        this.console = context.getConsole();
        this.history = context.getHistory();
        this.context = context;
        this.indicators = context.getIndicators();
     
        indicators.registerCustomIndicator(new File(context.getFilesDir() + System.getProperty("file.separator") + "sema.jfx"));
                             
    Object[] sema = indicators.calculateIndicator(selectedInstrument, selectedPeriod, new  OfferSide[] {OfferSide.BID},
        "sema", new AppliedPrice[]{AppliedPrice.CLOSE}, new Object[]{0.62, 0.72},
        Filter.WEEKENDS, 200, context.getHistory().getLastTick(selectedInstrument).getTime(), 0);       



Here is my question explicitly: When I get to "onBar", how do I test the 4th element of the indicator (index=3) to see if it is greater than 2.15? I know the following doesn't work, but it expresses what I am trying to do:

if (sema[3] > 2.15) {
// do something when true
}

It is the individual elements of my custom indicator which I am trying to access for tests and calculations, one at a time. My problem is that I don't know how to convert the array or list or cast types or whatever... because I am still very new to java.

Thank you for your patience.

UPDATE!! ... through trial and error, I've made some progress. I now have 2 questions (at the end)... here is the background:

// this code works when index = 0 only. Any other index gives an out of bounds error.
Object[] semaArr = {(double[])sema[0]};
sMA = ((double[]) semaArr[0])[0];
context.getConsole().getOut().println("***************************");
context.getConsole().getOut().println("sema[0] = " + sMA);
context.getConsole().getOut().println("***************************");

// however, this code shows that the indicator is populating data for indexes 0 through 199 (200 elements).
for (Object o3 : sema) {
for (double d3 : (double[])o3){
context.getConsole().getOut().println("sema = " + d3);
}
}

Historical Tester output looks like this (note that the line labeled sema[0] matches the first sema printed out immediately above it.

2011-06-15 04:08:13 sema = 1.3648239441128291
2011-06-15 04:08:13 sema = 1.3650261687179712 etc.
2011-06-15 04:08:13 sema = 1.3648241282051874 index=2
2011-06-15 04:08:13 sema = 1.3647003373820723 index=1
2011-06-15 04:08:13 sema = 1.365108782584401.......................<----\
2011-06-15 04:08:13 ***************************.....................------- these match, index=0
2011-06-15 04:08:13 sema[0] = 1.365108782584401...................<----/
2011-06-15 04:08:13 ***************************

// 2 Questions:
// Why does the data in positions 1 thru 199 seem to "go away / not be accessible" when the loop logic shows they are there?
// Is the data at index=0 the most recently closed bar? (during onBar processing)? I thought 0 = the in-progress/unfinished bar and 1 = most recent close?

Thanks!


 
 Post subject: Re: Accessing a Custom Indicator's Output Array Post rating: 0   New post Posted: Wed 15 Jun, 2011, 08:53 
User avatar

User rating:
Joined: Fri 31 Aug, 2007, 09:17
Posts: 6139
rimrock wrote:
                              
    Object[] sema = indicators.calculateIndicator(selectedInstrument, selectedPeriod, new  OfferSide[] {OfferSide.BID},
        "sema", new AppliedPrice[]{AppliedPrice.CLOSE}, new Object[]{0.62, 0.72},
        Filter.WEEKENDS, 200, context.getHistory().getLastTick(selectedInstrument).getTime(), 0);   
Since, apparently, your indicator has just one output, for simplicity consider:
                              
    double[] semaArray = (double[]) indicators.calculateIndicator(selectedInstrument, selectedPeriod, new  OfferSide[] {OfferSide.BID},
        "sema", new AppliedPrice[]{AppliedPrice.CLOSE}, new Object[]{0.62, 0.72},
        Filter.WEEKENDS, 200, context.getHistory().getLastTick(selectedInstrument).getTime(), 0)[0];     
rimrock wrote:
Here is my question explicitly: When I get to "onBar", how do I test the 4th element of the indicator (index=3) to see if it is greater than 2.15? I know the following doesn't work, but it expresses what I am trying to do:

if (sema[3] > 2.15) {
// do something when true
}
Try:
(double[]) sema[0])[3]
Quote:
// Why does the data in positions 1 thru 199 seem to "go away / not be accessible" when the loop logic shows they are there?
Because sema is an array of double arrays, but the example you showed iterates trough the first of those double arrays (though still it is an open question how did you assign the value of sema that you could use iterator).
Quote:
// Is the data at index=0 the most recently closed bar? (during onBar processing)? I thought 0 = the in-progress/unfinished bar and 1 = most recent close?
The most recent one is the last value in the array.

For your convenience, consider the following strategy which prints output values of an indicator.
package jforex.strategies.indicators;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.TimeZone;

import com.dukascopy.api.*;
import com.dukascopy.api.IIndicators.AppliedPrice;

public class UniversalIndChart implements IStrategy {
   private IConsole console;
   private IHistory history;
   private IIndicators indicators;
   
   private SimpleDateFormat sdf;
   private DecimalFormat df;

   public Instrument instrument = Instrument.EURUSD;
   public Period selectedPeriod = Period.FIVE_MINS;
   public Filter indicatorFilter = Filter.NO_FILTER;

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

      String DATE_FORMAT_NOW = "yyyy-MM-dd HH:mm:ss";
      sdf = new SimpleDateFormat(DATE_FORMAT_NOW);
      sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
      
      df = new DecimalFormat("0.00000");
   }

   public void onAccount(IAccount account) throws JFException {   }

   public void onMessage(IMessage message) throws JFException {   }

   public void onStop() throws JFException {   }

   public void onTick(Instrument instrument, ITick tick) throws JFException {
   }

   public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {

      if (!instrument.equals(instrument) || !period.equals(selectedPeriod))
         return;

      IBar prevBar = history.getBar(instrument, selectedPeriod, OfferSide.BID, 1);

      String indName = "sma".toUpperCase(); //can change to EMA, SMA, smma, hma, etc.
      int indTimePeriod = 50;
      int candlesBefore = 10;
      int candlesAfter = 0;

      
      double [] valueArray = (double[]) indicators.calculateIndicator(
            instrument,
            period,
            new OfferSide[] {OfferSide.BID},
            indName,
            new AppliedPrice[] {AppliedPrice.CLOSE},
            new Object[] {indTimePeriod},
            indicatorFilter,
            candlesBefore,
            prevBar.getTime(),
            candlesAfter)[0];
      
      print( sdf.format(bidBar.getTime()) + " Indicator: "+indName+", last value: "
            + df.format(valueArray[valueArray.length - 1]) + ", array: " + arrayToString(valueArray));
   }
   
   public String arrayToString(double [] arr){
      String str = "";
      for (int r=0; r<arr.length; r++) {
          str += " " + df.format(arr[r]) + "; ";
      }
      return str;
   }

   private void print(Object message) {
      console.getOut().println(message);
   }
}


 

Jump to:  

  © 1998-2026 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