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.

Simple SMA Cross Backtest problem
 Post subject: Simple SMA Cross Backtest problem Post rating: 0   New post Posted: Fri 10 Jun, 2011, 18:50 

User rating: -
Hello everyone, :)

I am currently working at a strategy and found a problem with the backtesting. I took the SMA Crossover strategy, that is downloadable in the Wiki, and changed the fast MA from a SMA to an EMA:

Original:
      filteredSma10 = indicators.[b][u]sma[/u][/b](instrument, selectedPeriod, OfferSide.BID, AppliedPrice.CLOSE, 10,
            indicatorFilter, 2, prevBar.getTime(), 0)


Changed to:
      filteredSma10 = indicators.[u][b]ema[/b][/u](instrument, selectedPeriod, OfferSide.BID, AppliedPrice.CLOSE, 10,
            indicatorFilter, 2, prevBar.getTime(), 0)


In the backtest the strategy did exactly what it was supposed to do: opening and closing trades when the EMA and the SMA crossed. As the backtest passed approximately 30% of the tested 3 month period, the strategy stopped trading entirely. Anyone know a solution to that?

Screenshots:

Screen 1
Screen 2


 
 Post subject: Re: Simple SMA Cross Backtest problem Post rating: 0   New post Posted: Mon 13 Jun, 2011, 15:12 
User avatar

User rating:
Joined: Fri 31 Aug, 2007, 09:17
Posts: 6139
We couldn't reproduce this. The modified SMA crossover strategy (SMA substituted with EMA) successfully completed running over periods of 3 and 6 months.
barrett wrote:
As the backtest passed approximately 30% of the tested 3 month period, the strategy stopped trading entirely. Anyone know a solution to that?
Could you please elaborate on this? Did the progress bar get stuck or did it the test run complete but after 30% progress no trades were made?


 
 Post subject: Re: Simple SMA Cross Backtest problem Post rating: 0   New post Posted: Mon 13 Jun, 2011, 17:48 

User rating: -
Hello,
thanks for the quick reply :)

I just checked again, and at approximately 16% no trades are opened eventhough the MAs cross.
What I did:

1. I downloaded the strtegy from the wiki here

2. Line 53 looks as follows:
Quote:
filteredSma10 = indicators.sma(instrument, selectedPeriod, OfferSide.BID, AppliedPrice.CLOSE, 10,

I changed "indicators.sma" to "indicators.ema"

3. Compiled the strategy

4. Tested the strategy with the following test settings:

Historical data:
EUR/USD
Last 3 months
5 minutes
4 Ticks at OHLC
Bid

The parameters for the strategy were:

Istrument: EUR/USD
Period: 5 minutes
SMA Filter: No Filter
_____

I hope these informations are going to allow you to reproduce the problem. Below is another Screenshot of the Result. I had to zoom out pretty far and change to the 4 hour chart to make the whole 3 month period visible.

Klick


 
 Post subject: Re: Simple SMA Cross Backtest problem Post rating: 0   New post Posted: Tue 14 Jun, 2011, 09:21 
User avatar

User rating:
Joined: Fri 31 Aug, 2007, 09:17
Posts: 6139
Unfortunately we were not able to reproduce the same behavior (see the attached printcreen) - the strategy didn't stop trading at any point.
The result in the printscreen was achieved by using your settings, both for historical tester and the strategy.
Here is the strategy which was used (only change from wiki is changing SMA to EMA):

package jforex.bugtests;

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

public class EMACrossover  implements IStrategy {
   private IEngine engine;
   private IConsole console;
   private IHistory history;
   private IIndicators indicators;
   private int counter =0;
   private double [] filteredSma90;
   private double [] filteredSma10;
   private IOrder order = null;

   @Configurable("Instrument")
   public Instrument selectedInstrument = Instrument.EURUSD;
   @Configurable("Period")
   public Period selectedPeriod = Period.THIRTY_MINS;
   @Configurable("SMA filter")
   public Filter indicatorFilter = Filter.NO_FILTER;
   

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

   public void onAccount(IAccount account) throws JFException {
   }

   public void onMessage(IMessage message) throws JFException {
   }

   public void onStop() throws JFException {
      for (IOrder order : engine.getOrders()) {
         engine.getOrder(order.getLabel()).close();
      }
   }

   public void onTick(Instrument instrument, ITick tick) throws JFException {
      if (!instrument.equals(selectedInstrument)) {
         return;
      }
      IBar prevBar = history.getBar(instrument, selectedPeriod, OfferSide.BID, 1);
      filteredSma90 = indicators.ema(instrument, selectedPeriod, OfferSide.BID, AppliedPrice.CLOSE, 90,
            indicatorFilter, 2, prevBar.getTime(), 0);
      filteredSma10 = indicators.ema(instrument, selectedPeriod, OfferSide.BID, AppliedPrice.CLOSE, 10,
            indicatorFilter, 2, prevBar.getTime(), 0);

      // SMA10 crossover SMA90 from UP to DOWN
      if ((filteredSma10[1] < filteredSma10[0]) && (filteredSma10[1] < filteredSma90[1]) && (filteredSma10[0] >= filteredSma90[0])) {
         if (engine.getOrders().size() > 0) {
            for (IOrder orderInMarket : engine.getOrders()) {
               if (orderInMarket.isLong()) {
                  print("Closing Long position");
                  orderInMarket.close();
               }
            }
         }
         if ((order == null) || (order.isLong() && order.getState().equals(IOrder.State.CLOSED)) ) {
            print("Create SELL");
            order = engine.submitOrder(getLabel(instrument), instrument, OrderCommand.SELL, 0.01);
         }
      }
      // SMA10 crossover SMA90 from DOWN to UP
      if ((filteredSma10[1] > filteredSma10[0]) && (filteredSma10[1] > filteredSma90[1]) && (filteredSma10[0] <= filteredSma90[0])) {
         if (engine.getOrders().size() > 0) {
            for (IOrder orderInMarket : engine.getOrders()) {
               if (!orderInMarket.isLong()) {
                  print("Closing Short position");
                  orderInMarket.close();
               }
            }
         }
         if ((order == null) || (!order.isLong() && order.getState().equals(IOrder.State.CLOSED)) ) {
            order = engine.submitOrder(getLabel(instrument), instrument, OrderCommand.BUY, 0.01);
         }
      }
   }   

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

   protected String getLabel(Instrument instrument) {
      String label = instrument.name();
      label = label + (counter++);
      label = label.toUpperCase();
      return label;
   }

   public void print(String message) {
      console.getOut().println(message);
   }
}


Attachments:
EMAcrossover5Mins.png [237.05 KiB]
Downloaded 466 times
DISCLAIMER: Dukascopy Bank SA's waiver of responsability - Documents, data or information available on this webpage may be posted by third parties without Dukascopy Bank SA being obliged to make any control on their content. Anyone accessing this webpage and downloading or otherwise making use of any document, data or information found on this webpage shall do it on his/her own risks without any recourse against Dukascopy Bank SA in relation thereto or for any consequences arising to him/her or any third party from the use and/or reliance on any document, data or information found on this webpage.
 
 Post subject: Re: Simple SMA Cross Backtest problem Post rating: 0   New post Posted: Wed 15 Jun, 2011, 16:19 

User rating: -
Sorry i'm causing so much trouble :oops:

With the code that you posted i got good results, but you changed both indicators to EMA's. Only change the "sma" in line 51 to "ema" and keep the "sma" in line 49. In the code that you posted you changed both SMA's to EMA's. Having one of each gives the following code:

package jforex.bugtests;
 
import com.dukascopy.api.*;
import com.dukascopy.api.IEngine.OrderCommand;
import com.dukascopy.api.IIndicators.AppliedPrice;
 
public class EMACrossover  implements IStrategy {
   private IEngine engine;
   private IConsole console;
   private IHistory history;
   private IIndicators indicators;
   private int counter =0;
   private double [] filteredSma90;
   private double [] filteredSma10;
   private IOrder order = null;
 
   @Configurable("Instrument")
   public Instrument selectedInstrument = Instrument.EURUSD;
   @Configurable("Period")
   public Period selectedPeriod = Period.THIRTY_MINS;
   @Configurable("SMA filter")
   public Filter indicatorFilter = Filter.NO_FILTER;
   
 
   public void onStart(IContext context) throws JFException {
      this.engine = context.getEngine();
      this.console = context.getConsole();
      this.history = context.getHistory();
      this.indicators = context.getIndicators();
   }
 
   public void onAccount(IAccount account) throws JFException {
   }
 
   public void onMessage(IMessage message) throws JFException {
   }
 
   public void onStop() throws JFException {
      for (IOrder order : engine.getOrders()) {
         engine.getOrder(order.getLabel()).close();
      }
   }
 
   public void onTick(Instrument instrument, ITick tick) throws JFException {
      if (!instrument.equals(selectedInstrument)) {
         return;
      }
      IBar prevBar = history.getBar(instrument, selectedPeriod, OfferSide.BID, 1);
      filteredSma90 = indicators.sma(instrument, selectedPeriod, OfferSide.BID, AppliedPrice.CLOSE, 90,
            indicatorFilter, 2, prevBar.getTime(), 0);
      filteredSma10 = indicators.ema(instrument, selectedPeriod, OfferSide.BID, AppliedPrice.CLOSE, 10,
            indicatorFilter, 2, prevBar.getTime(), 0);
 
      // SMA10 crossover SMA90 from UP to DOWN
      if ((filteredSma10[1] < filteredSma10[0]) && (filteredSma10[1] < filteredSma90[1]) && (filteredSma10[0] >= filteredSma90[0])) {
         if (engine.getOrders().size() > 0) {
            for (IOrder orderInMarket : engine.getOrders()) {
               if (orderInMarket.isLong()) {
                  print("Closing Long position");
                  orderInMarket.close();
               }
            }
         }
         if ((order == null) || (order.isLong() && order.getState().equals(IOrder.State.CLOSED)) ) {
            print("Create SELL");
            order = engine.submitOrder(getLabel(instrument), instrument, OrderCommand.SELL, 0.01);
         }
      }
      // SMA10 crossover SMA90 from DOWN to UP
      if ((filteredSma10[1] > filteredSma10[0]) && (filteredSma10[1] > filteredSma90[1]) && (filteredSma10[0] <= filteredSma90[0])) {
         if (engine.getOrders().size() > 0) {
            for (IOrder orderInMarket : engine.getOrders()) {
               if (!orderInMarket.isLong()) {
                  print("Closing Short position");
                  orderInMarket.close();
               }
            }
         }
         if ((order == null) || (!order.isLong() && order.getState().equals(IOrder.State.CLOSED)) ) {
            order = engine.submitOrder(getLabel(instrument), instrument, OrderCommand.BUY, 0.01);
         }
      }
   }   
 
   public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {
    }
 
   protected String getLabel(Instrument instrument) {
      String label = instrument.name();
      label = label + (counter++);
      label = label.toUpperCase();
      return label;
   }
 
   public void print(String message) {
      console.getOut().println(message);
   }
}


That code stops trading on the 11th of march in the 3 month period.

Thanks a lot!


 
 Post subject: Re: Simple SMA Cross Backtest problem Post rating: 0   New post Posted: Thu 16 Jun, 2011, 10:57 
User avatar

User rating:
Joined: Fri 31 Aug, 2007, 09:17
Posts: 6139
Since the order processing logic gets executed in onTick method, for all ticks to get considered in historical testing, select Tick instead of 5 minutes in Historical Data panel. Alternatively you might consider moving the logic to onBar method with filter at the start of the method:
if (!instrument.equals(selectedInstrument) || !period.equals(this.selectedPeriod)) 
    return;


 

Jump to:  

  © 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