|
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.
Calling SMA, EMA and MA indicators with custom inputs return the same values - why? |
ChristianMEL
|
Post subject: Calling SMA, EMA and MA indicators with custom inputs return the same values - why? |
Post rating: 1
|
Posted: Tue 15 May, 2012, 06:57
|
|
User rating: 2
Joined: Sun 26 Jun, 2011, 07:05 Posts: 15 Location: Australia, Melbourne
|
Hello again, In my strategy I need to call SMA & EMA with custom input arrays, so I can not use simple IIndicators.calculateIndicator() method. This means I need to call the IIndicator.calculate() method of an indicator after manually populating it's inputs & outputs. Unfortunately this always seems to return the same values for SMA, EMA, MA(SMA) & MA(EMA) calls. I must be doing something fundamentally wrong. Please refer to the sample strategy below. When backtesting this over the last week it passes the same input arrays to the indicators, but they all return the same values - not different ones for different EMA & SMA calculations. package jforexStrategies;
import com.dukascopy.api.*; import com.dukascopy.api.indicators.*; import com.dukascopy.api.IIndicators.AppliedPrice;
public class MaTestStrategy implements IStrategy { double[][] price; int priceIndex = 0; @Configurable("Instrument") public com.dukascopy.api.Instrument instrument = Instrument.fromString("EUR/USD"); @Configurable("Period") public int maPeriod = 89; @Configurable("Price") public AppliedPrice appPrice = AppliedPrice.CLOSE; private IContext context; private IIndicators indicators; IIndicator ema = null; IIndicator sma = null; IIndicator ma = null; IIndicator ma2 = null; public void onStart(IContext context) throws JFException { this.context = context; this.indicators = context.getIndicators();
price = new double[AppliedPrice.values().length][maPeriod];
// get indicators ema = indicators.getIndicator("EMA"); sma = indicators.getIndicator("SMA"); ma = indicators.getIndicator("MA"); ma2 = indicators.getIndicator("MA"); // set optional input parameters of indicators ema.setOptInputParameter(0, maPeriod); sma.setOptInputParameter(0, maPeriod); ma.setOptInputParameter(0, maPeriod); ma.setOptInputParameter(1, IIndicators.MaType.SMA.ordinal()); ma2.setOptInputParameter(0, maPeriod); ma2.setOptInputParameter(1, IIndicators.MaType.EMA.ordinal());
}
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 (this.instrument == instrument && priceIndex < maPeriod && period == Period.ONE_HOUR) { context.getConsole().getOut().println("Storing values to use - priceIndex: " + priceIndex);
// store current bar's info for later indicator calls price[AppliedPrice.OPEN.ordinal()][priceIndex] = bidBar.getOpen(); price[AppliedPrice.CLOSE.ordinal()][priceIndex] = bidBar.getClose(); price[AppliedPrice.HIGH.ordinal()][priceIndex] = bidBar.getHigh(); price[AppliedPrice.LOW.ordinal()][priceIndex] = bidBar.getLow(); price[AppliedPrice.VOLUME.ordinal()][priceIndex] = bidBar.getVolume(); price[AppliedPrice.MEDIAN_PRICE.ordinal()][priceIndex] = (bidBar.getHigh()+bidBar.getLow())/2; price[AppliedPrice.TYPICAL_PRICE.ordinal()][priceIndex] = (bidBar.getHigh()+bidBar.getLow()+bidBar.getClose())/3; price[AppliedPrice.WEIGHTED_CLOSE.ordinal()][priceIndex] = (bidBar.getHigh()+bidBar.getLow()+2*bidBar.getClose())/4; price[AppliedPrice.TIMESTAMP.ordinal()][priceIndex] = bidBar.getTime(); priceIndex++; // do we have enough history to make the indicator calls? if (priceIndex == maPeriod) { // get indicator info's IndicatorInfo emaInfo = ema.getIndicatorInfo(); IndicatorInfo smaInfo = ema.getIndicatorInfo(); IndicatorInfo maInfo = ema.getIndicatorInfo(); IndicatorInfo ma2Info = ema.getIndicatorInfo(); // set output arrays double[][] emaOutputs = new double[emaInfo.getNumberOfOutputs()][]; for (int i = 0; i < emaOutputs.length; i++) { emaOutputs[i] = new double[1]; ema.setOutputParameter(i, emaOutputs[i]); } double[][] smaOutputs = new double[smaInfo.getNumberOfOutputs()][]; for (int i = 0; i < smaOutputs.length; i++) { smaOutputs[i] = new double[1]; sma.setOutputParameter(i, smaOutputs[i]); } double[][] maOutputs = new double[maInfo.getNumberOfOutputs()][]; for (int i = 0; i < maOutputs.length; i++) { maOutputs[i] = new double[1]; ma.setOutputParameter(i, maOutputs[i]); } double[][] ma2Outputs = new double[ma2Info.getNumberOfOutputs()][]; for (int i = 0; i < ma2Outputs.length; i++) { ma2Outputs[i] = new double[1]; ma2.setOutputParameter(i, ma2Outputs[i]); } // set input arrays ema.setInputParameter(0, price[appPrice.ordinal()]); sma.setInputParameter(0, price[appPrice.ordinal()]); ma.setInputParameter(0, price[appPrice.ordinal()]); ma2.setInputParameter(0, price[appPrice.ordinal()]); // calculate outputs int inputLength = price[0].length; int emaLB = ema.getLookback(); IndicatorResult emaResult = ema.calculate(emaLB, inputLength-1); // only calculate 1 value, so start & end indexes should be the same double emaRetval = emaOutputs[0][0]; int smaLB = sma.getLookback(); IndicatorResult smaResult = sma.calculate(smaLB, inputLength-1); // only calculate 1 value, so start & end indexes should be the same double smaRetval = smaOutputs[0][0]; int maLB = ma.getLookback(); IndicatorResult maResult = ma.calculate(maLB, inputLength-1); // only calculate 1 value, so start & end indexes should be the same double maRetval = maOutputs[0][0]; int ma2LB = ma2.getLookback(); IndicatorResult ma2Result = ma2.calculate(ma2LB, inputLength-1); // only calculate 1 value, so start & end indexes should be the same double ma2Retval = ma2Outputs[0][0]; // print values to console context.getConsole().getOut().println("The following values are passed as " + appPrice.toString() + " inputs to the indicators:"); for (int i = 0; i < maPeriod; i++) { context.getConsole().getOut().println("["+i+"]: " + price[appPrice.ordinal()][i]); } context.getConsole().getOut().println("emaRetval(" + maPeriod + "): " + emaRetval); context.getConsole().getOut().println("smaRetval(" + maPeriod + "): " + smaRetval); context.getConsole().getOut().println("maRetval(" + maPeriod + ", " + IIndicators.MaType.SMA.ordinal() + "): " + maRetval); context.getConsole().getOut().println("ma2Retval(" + maPeriod + ", " + IIndicators.MaType.EMA.ordinal() + "): " + ma2Retval); context.getConsole().getOut().println("Why are they all the same?"); } } } }
Can you please advise me what I must do to correctly calculate EMA and SMA values? thanks in advance, Christian
|
|
|
|
 |
API Support
|
Post subject: Re: Calling SMA, EMA and MA indicators with custom inputs return the same values - why? |
Post rating: 0
|
Posted: Tue 15 May, 2012, 07:56
|
|
User rating: ∞
Joined: Fri 31 Aug, 2007, 09:17 Posts: 6139
|
This is because EMA requires more inputs (this is indicated by unstable period property), hence, you need to pass more values to the indicator.
|
|
|
|
 |
ChristianMEL
|
Post subject: Re: Calling SMA, EMA and MA indicators with custom inputs return the same values - why? |
Post rating: 1
|
Posted: Tue 15 May, 2012, 11:50
|
|
User rating: 2
Joined: Sun 26 Jun, 2011, 07:05 Posts: 15 Location: Australia, Melbourne
|
Hi support, I have changed to code as per your advice and it now works. 2 quick follow up questions: 1. Do you have any advice as to how to estimate the extra input required for the EMA's unstable period? 2. Why isn't this taken into account in the IIndicator.getLookBack() call for each indicator? Fixed sample code: package jforexStrategies; import com.dukascopy.api.*; import com.dukascopy.api.indicators.*; import com.dukascopy.api.IIndicators.AppliedPrice; public class MaTestStrategy implements IStrategy { double[][] price; int priceIndex = 0; @Configurable("Instrument") public com.dukascopy.api.Instrument instrument = Instrument.fromString("EUR/USD"); @Configurable("Bar Period") public Period barPeriod = Period.FIVE_MINS; @Configurable("Moving Average Period") public int maPeriod = 89; @Configurable("Unstable Period Expansion") public int unstable = 1000; @Configurable("Price") public AppliedPrice appPrice = AppliedPrice.CLOSE; private IContext context; private IIndicators indicators; private IIndicator ema = null; private IIndicator sma = null; private IIndicator ma = null; private IIndicator ma2 = null; private IndicatorInfo emaInfo; private IndicatorInfo smaInfo; private IndicatorInfo maInfo; private IndicatorInfo ma2Info; private boolean unstableFlag = false; public void onStart(IContext context) throws JFException { this.context = context; this.indicators = context.getIndicators(); // get indicators ema = indicators.getIndicator("EMA"); sma = indicators.getIndicator("SMA"); ma = indicators.getIndicator("MA"); ma2 = indicators.getIndicator("MA"); // set optional input parameters of indicators ema.setOptInputParameter(0, maPeriod); sma.setOptInputParameter(0, maPeriod); ma.setOptInputParameter(0, maPeriod); ma.setOptInputParameter(1, IIndicators.MaType.SMA.ordinal()); ma2.setOptInputParameter(0, maPeriod); ma2.setOptInputParameter(1, IIndicators.MaType.EMA.ordinal()); // get indicator info's emaInfo = ema.getIndicatorInfo(); smaInfo = ema.getIndicatorInfo(); maInfo = ema.getIndicatorInfo(); ma2Info = ema.getIndicatorInfo();
// if any of the indicators have an unstable period, then add the user defined unstable period to the indicators' period if (emaInfo.isUnstablePeriod() || smaInfo.isUnstablePeriod() || maInfo.isUnstablePeriod() || ma2Info.isUnstablePeriod()) { unstableFlag = true; price = new double[AppliedPrice.values().length][maPeriod+unstable]; } else { price = new double[AppliedPrice.values().length][maPeriod]; } } 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 (this.instrument == instrument && period == barPeriod && ((unstableFlag == false && priceIndex < maPeriod) || (unstableFlag == true && priceIndex < maPeriod + unstable)) ) { context.getConsole().getOut().println("Storing values to use - priceIndex: " + priceIndex); // store current bar's info for later indicator calls price[AppliedPrice.OPEN.ordinal()][priceIndex] = bidBar.getOpen(); price[AppliedPrice.CLOSE.ordinal()][priceIndex] = bidBar.getClose(); price[AppliedPrice.HIGH.ordinal()][priceIndex] = bidBar.getHigh(); price[AppliedPrice.LOW.ordinal()][priceIndex] = bidBar.getLow(); price[AppliedPrice.VOLUME.ordinal()][priceIndex] = bidBar.getVolume(); price[AppliedPrice.MEDIAN_PRICE.ordinal()][priceIndex] = (bidBar.getHigh()+bidBar.getLow())/2; price[AppliedPrice.TYPICAL_PRICE.ordinal()][priceIndex] = (bidBar.getHigh()+bidBar.getLow()+bidBar.getClose())/3; price[AppliedPrice.WEIGHTED_CLOSE.ordinal()][priceIndex] = (bidBar.getHigh()+bidBar.getLow()+2*bidBar.getClose())/4; price[AppliedPrice.TIMESTAMP.ordinal()][priceIndex] = bidBar.getTime(); priceIndex++; // do we have enough history to make the indicator calls? if ((unstableFlag == false && priceIndex == maPeriod) || (unstableFlag == true && priceIndex == maPeriod + unstable)) {
// set output arrays double[][] emaOutputs = new double[emaInfo.getNumberOfOutputs()][]; for (int i = 0; i < emaOutputs.length; i++) { emaOutputs[i] = new double[unstableFlag ? unstable+1 : 1]; ema.setOutputParameter(i, emaOutputs[i]); } double[][] smaOutputs = new double[smaInfo.getNumberOfOutputs()][]; for (int i = 0; i < smaOutputs.length; i++) { smaOutputs[i] = new double[unstableFlag ? unstable+1 : 1]; sma.setOutputParameter(i, smaOutputs[i]); } double[][] maOutputs = new double[maInfo.getNumberOfOutputs()][]; for (int i = 0; i < maOutputs.length; i++) { maOutputs[i] = new double[unstableFlag ? unstable+1 : 1]; ma.setOutputParameter(i, maOutputs[i]); } double[][] ma2Outputs = new double[ma2Info.getNumberOfOutputs()][]; for (int i = 0; i < ma2Outputs.length; i++) { ma2Outputs[i] = new double[unstableFlag ? unstable+1 : 1]; ma2.setOutputParameter(i, ma2Outputs[i]); } // set input arrays ema.setInputParameter(0, price[appPrice.ordinal()]); sma.setInputParameter(0, price[appPrice.ordinal()]); ma.setInputParameter(0, price[appPrice.ordinal()]); ma2.setInputParameter(0, price[appPrice.ordinal()]); // calculate outputs int inputLength = price[0].length; IndicatorResult emaResult = ema.calculate(ema.getLookback(), inputLength-1); double emaRetval = emaOutputs[0][unstableFlag ? emaOutputs[0].length-1 : 0]; IndicatorResult smaResult = sma.calculate(sma.getLookback(), inputLength-1); double smaRetval = smaOutputs[0][unstableFlag ? smaOutputs[0].length-1 : 0]; IndicatorResult maResult = ma.calculate(ma.getLookback(), inputLength-1); double maRetval = maOutputs[0][unstableFlag ? maOutputs[0].length-1 : 0]; IndicatorResult ma2Result = ma2.calculate(ma2.getLookback(), inputLength-1); double ma2Retval = ma2Outputs[0][unstableFlag ? ma2Outputs[0].length-1 : 0]; // print values to console context.getConsole().getOut().println("The following values are passed as " + appPrice.toString() + " inputs to the indicators:"); for (int i = 0; i < price[0].length; i++) { context.getConsole().getOut().println("price["+appPrice.toString()+"]["+i+"]: " + price[appPrice.ordinal()][i]); } context.getConsole().getOut().println("emaRetval(" + maPeriod + "): " + emaRetval + ", emaOutput[0].length = " + emaOutputs[0].length); context.getConsole().getOut().println("smaRetval(" + maPeriod + "): " + smaRetval + ", smaOutput[0].length = " + smaOutputs[0].length); context.getConsole().getOut().println("maRetval(" + maPeriod + ", " + IIndicators.MaType.SMA.ordinal() + "): " + maRetval + ", maOutput[0].length = " + maOutputs[0].length); context.getConsole().getOut().println("ma2Retval(" + maPeriod + ", " + IIndicators.MaType.EMA.ordinal() + "): " + ma2Retval + ", ma2Output[0].length = " + ma2Outputs[0].length); context.getConsole().getOut().println("Why are they all the same?"); } } } }
thanks, Christian
|
|
|
|
 |
API Support
|
Post subject: Re: Calling SMA, EMA and MA indicators with custom inputs return the same values - why? |
Post rating: 0
|
Posted: Tue 15 May, 2012, 12:29
|
|
User rating: ∞
Joined: Fri 31 Aug, 2007, 09:17 Posts: 6139
|
ChristianMEL wrote: 1. Do you have any advice as to how to estimate the extra input required for the EMA's unstable period? The platform uses 100 extra inputs, however if you would compare the values yielded by using 10 and 100 extra outputs, the difference would be <0.1 pip, hence for the case of EMA, 10 extra inputs appear to be sufficient. ChristianMEL wrote: 2. Why isn't this taken into account in the IIndicator.getLookBack() call for each indicator? Because by API design lookback and unstablePeriod properties are treated separately. If you wish, you can create a custom indicator which in IIndicator.getLookBack() also considers unstablePeriod property.
|
|
|
|
 |
|
Pages: [
1
]
|
|
|
|
|