|
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 |
barrett
|
Post subject: Simple SMA Cross Backtest problem |
Post rating: 0
|
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 1Screen 2
|
|
|
|
 |
API Support
|
Post subject: Re: Simple SMA Cross Backtest problem |
Post rating: 0
|
Posted: Mon 13 Jun, 2011, 15:12
|
|
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?
|
|
|
|
 |
barrett
|
Post subject: Re: Simple SMA Cross Backtest problem |
Post rating: 0
|
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 here2. 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
|
|
|
|
 |
API Support
|
Post subject: Re: Simple SMA Cross Backtest problem |
Post rating: 0
|
Posted: Tue 14 Jun, 2011, 09:21
|
|
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.
|
|
|
|
|
 |
Guest
|
Post subject: Re: Simple SMA Cross Backtest problem |
Post rating: 0
|
Posted: Wed 15 Jun, 2011, 16:19
|
|
User rating: -
|
Sorry i'm causing so much trouble 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!
|
|
|
|
 |
API Support
|
Post subject: Re: Simple SMA Cross Backtest problem |
Post rating: 0
|
Posted: Thu 16 Jun, 2011, 10:57
|
|
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;
|
|
|
|
 |
|
Pages: [
1
]
|
|
|
|
|