Dukascopy
 
 
Wiki JStore Search Login

APICLIENT-2 ATR indicator over a moving daily timespan
 Post subject: APICLIENT-2 ATR indicator over a moving daily timespan Post rating: 0   New post Posted: Wed 20 Jun, 2012, 21:38 

User rating: 1
Joined: Tue 12 Jul, 2011, 20:43
Posts: 51
Location: Germany,
Hello,

I created an indicator which provides an Average Daily TrueRange (ADTR) for TIME_PERIOD_AGGREGATION charts (possible periods between 30 seconds and 12 hours) and TICK_BAR charts. The timespan for ATR calculation is moving 24 hours back from last period, whereat time gaps over weekends and periods with ATR = 0 are filtered. The intention is to compensate lower ATRs (during night sessions, lunch times and so on) and higher ATRs (during main trading sessions).

Here is the source code of the ADTR indicator:
package jForex;

import com.dukascopy.api.indicators.*;
import com.dukascopy.api.IBar;
import java.awt.Color;

public class ADTR implements IIndicator
{
    private IndicatorInfo clsIndicatorInfo;
    private IIndicatorContext clsIndicatorContext;
    private InputParameterInfo[] clsInputParameterInfos;
    private OutputParameterInfo[] clsOutputParameterInfos;
    private IBar[][] clsBarInputs = new IBar[1][];
    private double[][] clsdOutputs = new double[1][];
   
    public void onStart(IIndicatorContext context)
    {
        clsIndicatorContext = context;
        clsIndicatorInfo = new IndicatorInfo("ADTR", "Average Daily TrueRange", "My Indicators", false, false, true, 1, 0, 1);
        clsIndicatorInfo.setUnstablePeriod(true);
        clsIndicatorInfo.setRecalculateOnNewCandleOnly(true);
        clsInputParameterInfos = new InputParameterInfo[] { new InputParameterInfo("Inputs", InputParameterInfo.Type.BAR) };
        clsOutputParameterInfos = new OutputParameterInfo[] { new OutputParameterInfo("ADTR", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.LINE) {{ setColor(Color.gray); }} };
    }
   
    public IndicatorResult calculate(int iStartIndex, int iEndIndex)
    {
        int iInIndex = 0, iOutIndex = 0, iIndex = 0, iPeriodsCount = 0;
        long lIntervalOnePeriod = clsIndicatorContext.getFeedDescriptor().getPeriod().getInterval(),
             lInterval30Seconds = 30 * 1000L, lIntervalOneHour = 2 * 60 * lInterval30Seconds, lIntervalOneDay = 24 * lIntervalOneHour,
             lLastInterval = 0L, lIntervalSum = 0L;
        double dLastAvgDailyTrueRange = Double.NaN, dLastTrueRange = 0.0, dTrueRangeSum = 0.0;
       
        if (iStartIndex - getLookback() < 0)
            iStartIndex = getLookback();
        if (iStartIndex > iEndIndex)
            return new IndicatorResult(0, 0);
       
        for (iInIndex = iStartIndex, iOutIndex = 0 ; iInIndex <= iEndIndex ; iInIndex++, iOutIndex++)
        {
            if (lIntervalOneDay / Math.abs(lIntervalOnePeriod) > 1)
            {
                for (lIntervalSum = 0L, iPeriodsCount = 0, dTrueRangeSum = 0.0, iIndex = iInIndex ; iIndex >= iStartIndex && lIntervalSum < lIntervalOneDay; iIndex--)
                {
                    lLastInterval = ((IBar)clsBarInputs[0][iIndex]).getTime() - ((IBar)clsBarInputs[0][iIndex-1]).getTime();
                    if ((lIntervalOnePeriod >= lInterval30Seconds && lLastInterval == lIntervalOnePeriod) || (lIntervalOnePeriod == -1 && lLastInterval < lIntervalOneHour))
                    {
                        lIntervalSum += lLastInterval;
                        dLastTrueRange = Math.max(((IBar)clsBarInputs[0][iIndex-1]).getHigh(), ((IBar)clsBarInputs[0][iIndex]).getOpen()) - Math.min(((IBar)clsBarInputs[0][iIndex-1]).getLow(), ((IBar)clsBarInputs[0][iIndex]).getOpen());
                        if (dLastTrueRange > 0.0)
                        {
                            iPeriodsCount++;
                            dTrueRangeSum += dLastTrueRange;
                        }
                    }
                }
                if (iPeriodsCount > 0 && dTrueRangeSum > 0.0)
                    dLastAvgDailyTrueRange = dTrueRangeSum / iPeriodsCount;
            }
            else
            {
                dLastTrueRange = Math.max(((IBar)clsBarInputs[0][iInIndex-1]).getHigh(), ((IBar)clsBarInputs[0][iInIndex]).getOpen()) - Math.min(((IBar)clsBarInputs[0][iInIndex-1]).getLow(), ((IBar)clsBarInputs[0][iInIndex]).getOpen());
                if (dLastTrueRange > 0.0)
                    dLastAvgDailyTrueRange = dLastTrueRange;
            }
            clsdOutputs[0][iOutIndex] = dLastAvgDailyTrueRange;
        }
       
        return new IndicatorResult(iStartIndex, iOutIndex);
    }
   
    public int getLookback()
    {
        return 1;
    }
   
    public int getLookforward()
    {
        return 0;
    }
   
    public IndicatorInfo getIndicatorInfo()
    {
        return clsIndicatorInfo;
    }
   
    public InputParameterInfo getInputParameterInfo(int iIndex)
    {
        return (iIndex <= clsInputParameterInfos.length ? clsInputParameterInfos[iIndex] : null);
    }
   
    public OptInputParameterInfo getOptInputParameterInfo(int iIndex)
    {
        return null;
    }
   
    public OutputParameterInfo getOutputParameterInfo(int iIndex)
    {
        return (iIndex <= clsOutputParameterInfos.length ? clsOutputParameterInfos[iIndex] : null);
    }
   
    public void setInputParameter(int iIndex, Object oArray)
    {
        clsBarInputs[iIndex] = (IBar[]) oArray;
    }
   
    public void setOptInputParameter(int iIndex, Object oValue)
    {
        return;
    }
   
    public void setOutputParameter(int iIndex, Object oArray)
    {
        clsdOutputs[iIndex] = (double[]) oArray;
    }
}


Hint to support:
I tried to filter the chart DataType using "IIndicatorContext.getFeedDescriptor().getDataType()". But this method provides "TICKS" instead of "TICK_BAR" applied to a 100 Ticks TickBar chart. This seems to be an error, please correct it with next API version.

Because of this getDataType() problem my only indication for chart type is "IIndicatorContext.getFeedDescriptor().getPeriod().getInterval()" at line 29 which provides -1 for TickBar charts.

If the timespan between two TickBar period start times is one hour or more, then I assume that a weekend is between theese two periods.

Question:
Because I want to use this indicator inside other indicators I tried to encode a test indicator ADTRTest.java.
But I get a NullPointerException in the calculate method at line 39. I need help to find out and eliminate the reason of this error. I don't know if the root cause is in ADTR indicator (although standalone ADTR works fine without exception) or in calling ADTRTest indicator.

package jForex;

import com.dukascopy.api.indicators.*;
import com.dukascopy.api.IBar;

public class ADTRTest implements IIndicator
{
    private IndicatorInfo clsIndicatorInfo;
    private IIndicatorContext clsIndicatorContext;
    private InputParameterInfo[] clsInputParameterInfos;
    private OutputParameterInfo[] clsOutputParameterInfos;
    private IIndicator clsIndicatorADTR;
    private IBar[][] clsBarInputs = new IBar[1][];
    private double[][] clsdOutputs = new double[1][];
   
    public void onStart(IIndicatorContext context)
    {
        clsIndicatorContext = context;
        IIndicatorsProvider indicatorsProvider = clsIndicatorContext.getIndicatorsProvider();
        clsIndicatorADTR = indicatorsProvider.getIndicator("ADTR");
        clsIndicatorInfo = new IndicatorInfo("ADTRTest", "Average Daily TrueRange Test", "My Indicators", false, false, true, 1, 0, 1);
        clsInputParameterInfos = new InputParameterInfo[] { new InputParameterInfo("Inputs", InputParameterInfo.Type.BAR) };
        clsOutputParameterInfos = new OutputParameterInfo[] { new OutputParameterInfo("ADTRTest", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.LINE) };
    }
   
    public IndicatorResult calculate(int iStartIndex, int iEndIndex)
    {
        int iLookback = getLookback(), iInIndex = 0, iOutIndex = 0, iIndex = 0;
        double[] dIndicatorADTROutputs;
       
        if (iStartIndex - iLookback < 0)
            iStartIndex = iLookback;
        if (iStartIndex > iEndIndex)
            return new IndicatorResult(0, 0);
       
        dIndicatorADTROutputs = new double[iEndIndex - iStartIndex + 1];
        clsIndicatorADTR.setInputParameter(0, clsBarInputs[0]);
        clsIndicatorADTR.setOutputParameter(0, dIndicatorADTROutputs);
        IndicatorResult indicatorADTRResult = clsIndicatorADTR.calculate(iStartIndex, iEndIndex);
       
        for (iInIndex = iStartIndex, iOutIndex = 0 ; iInIndex <= iEndIndex ; iInIndex++, iOutIndex++)
        {
            clsdOutputs[0][iOutIndex] = dIndicatorADTROutputs[iOutIndex];
        }
       
        return new IndicatorResult(iStartIndex, iOutIndex);
    }
   
    public int getLookback()
    {
        return clsIndicatorADTR.getLookback();
    }
   
    public int getLookforward()
    {
        return 0;
    }
   
    public IndicatorInfo getIndicatorInfo()
    {
        return clsIndicatorInfo;
    }
   
    public InputParameterInfo getInputParameterInfo(int iIndex)
    {
        return (iIndex <= clsInputParameterInfos.length ? clsInputParameterInfos[iIndex] : null);
    }
   
    public OptInputParameterInfo getOptInputParameterInfo(int iIndex)
    {
        return null;
    }
   
    public OutputParameterInfo getOutputParameterInfo(int iIndex)
    {
        return (iIndex <= clsOutputParameterInfos.length ? clsOutputParameterInfos[iIndex] : null);
    }
   
    public void setInputParameter(int iIndex, Object oArray)
    {
        clsBarInputs[iIndex] = (IBar[]) oArray;
    }
   
    public void setOptInputParameter(int iIndex, Object oValue)
    {
        return;
    }
   
    public void setOutputParameter(int iIndex, Object oArray)
    {
        clsdOutputs[iIndex] = (double[]) oArray;
    }
}


Regards
AbsoluteReturner


 
 Post subject: Re: ATR indicator over a moving daily timespan Post rating: 0   New post Posted: Thu 21 Jun, 2012, 11:34 
User avatar

User rating:
Joined: Fri 31 Aug, 2007, 09:17
Posts: 6139
AbsoluteReturner wrote:
I tried to filter the chart DataType using "IIndicatorContext.getFeedDescriptor().getDataType()". But this method provides "TICKS" instead of "TICK_BAR" applied to a 100 Ticks TickBar chart. This seems to be an error, please correct it with next API version.
This will get fixed with next API versions.
AbsoluteReturner wrote:
Because of this getDataType() problem my only indication for chart type is "IIndicatorContext.getFeedDescriptor().getPeriod().getInterval()" at line 29 which provides -1 for TickBar charts.
FeedDescriptor.getPeriod() is not applicable to tick bar feed, because it is not an tick aggregation over a time interval, rather count. For applicable arguments see the constructor:
https://www.dukascopy.com/client/javadoc/com/dukascopy/api/feed/util/TickBarFeedDescriptor.html
AbsoluteReturner wrote:
Question:
Because I want to use this indicator inside other indicators I tried to encode a test indicator ADTRTest.java.
But I get a NullPointerException in the calculate method at line 39. I need help to find out and eliminate the reason of this error. I don't know if the root cause is in ADTR indicator (although standalone ADTR works fine without exception) or in calling ADTRTest indicator.
You need to register your custom indicator. This can be done from calculate method (but not from onStart):
    public IndicatorResult calculate(int iStartIndex, int iEndIndex)
    {
        if(clsIndicatorADTR == null){
            try {
                indicatorsProvider.registerUserIndicator(new File("C:\\temp\\indicators\\ADTR.jfx"));
                clsIndicatorADTR = indicatorsProvider.getIndicator("ADTR");
            } catch (JFException e) {
                clsIndicatorContext.getConsole().getErr().println(e);
                e.printStackTrace();
            }
        }
//...
At the moment the FeedDescriptor within a registered custom indicator is always null, so currently you won't be able to use expressions like this:
clsIndicatorContext.getFeedDescriptor().getPeriod().getInterval()
As a workaround, consider subtracting the IBar.getTime of to adjacent input bars.


 
 Post subject: Re: APICLIENT-2 ATR indicator over a moving daily timespan Post rating: 0   New post Posted: Thu 21 Jun, 2012, 19:30 

User rating: 1
Joined: Tue 12 Jul, 2011, 20:43
Posts: 51
Location: Germany,
Quote:
At the moment the FeedDescriptor within a registered custom indicator is always null ...

What is about using "IIndicatorContext.getPeriod().getInterval()" instead to find out if the chart is a TickBar chart (result = -1) or not ?
IIndicatorContext.getPeriod() is marked as depricated. Is it usable anyway, also with further API versions ?


 
 Post subject: Re: APICLIENT-2 ATR indicator over a moving daily timespan Post rating: 0   New post Posted: Fri 22 Jun, 2012, 11:41 
User avatar

User rating:
Joined: Fri 31 Aug, 2007, 09:17
Posts: 6139
Please do not use the deprecated methods.


 
 Post subject: Re: APICLIENT-2 ATR indicator over a moving daily timespan Post rating: 0   New post Posted: Thu 28 Jun, 2012, 13:33 

User rating: 1
Joined: Tue 12 Jul, 2011, 20:43
Posts: 51
Location: Germany,
I think that the workaround you suggested is not fully reliable. It's possible that for a TimePeriodAggregation chart for two consecutive periods the timespans between bar start times are different when a weekend or holiday time gap or also a data feed gap occurs. It's also possible that for a TickBar chart for two consecutive periods the timespans between bar start times are equal by chance.
Furthermore for TickBar charts I noticed that there is no weekend gap. This means that the last TickBar on Friday spans over the whole weekend, and if there is a huge price gap because of significant news during weekend, this candle also has a huge range wich can distort average range TickBar calculation. Therefore it's important for me to distinguish between TimePeriodAggregation and TickBar chart type.

So I ask you when FeedDescriptor functionality will be provided within a registered custom indicator. I'm not sure if the APICLIENT-2 bug includes incorrect "IIndicatorContext.getFeedDescriptor().getDataType()" result only or also FeedDescriptor NullPointerException within a registered custom indicator.

I also request you to provide current functionality for "IIndicatorContext.getPeriod().getInterval()" furthermore (it provides -1 for TickBar charts) although it's deprecated, at least while FeedDescriptor functionality is not yet usable within registered custom indicators.


 
 Post subject: Re: APICLIENT-2 ATR indicator over a moving daily timespan Post rating: 0   New post Posted: Thu 28 Jun, 2012, 14:39 
User avatar

User rating:
Joined: Fri 31 Aug, 2007, 09:17
Posts: 6139
AbsoluteReturner wrote:
It's possible that for a TimePeriodAggregation chart for two consecutive periods the timespans between bar start times are different when a weekend or holiday time gap or also a data feed gap occurs.
If you use filter, then just take 3 bars for comparison and take the smallest interval as result - there won't be 2 gaps in a row (unless, of course you use FILTER_FLATS).
AbsoluteReturner wrote:
It's also possible that for a TickBar chart for two consecutive periods the timespans between bar start times are equal by chance.
For tickbars the interval does not get applied.


 

Jump to:  

cron
  © 1998-2024 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