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.

Problems with a very simple renko strategy
 Post subject: Problems with a very simple renko strategy Post rating: 0   New post Posted: Tue 19 Feb, 2013, 08:37 

User rating: 0
Joined: Tue 23 Aug, 2011, 01:10
Posts: 7
Location: United States,
Very simple renko strategy:
- Open an order with no stop loss or take profit after two renko bars of the same color are filled.
- Close the order when a renko bar of the opposite color is filled.

The strategy is described in this youtube tutorial:
https://www.youtube.com/watch?v=vMCC9Ay5Cbw&t=28m18s

Here's a key section of the strategy:
    public void onBar(Instrument instrument, OfferSide offerSide, PriceRange brickSize, IRenkoBar bar) {
        try {
            // debug code begin
            IChart chart = context.getChart(instrument);
            IChartObject line = chart.getChartObjectFactory().createVerticalLine("" + renkoCount++, bar.getEndTime());
            line.setColor(isRedBar(bar)? Color.RED : Color.GREEN);
            chart.addToMainChart(line);
            log("-----------------------");
            log(new Date(bar.getEndTime()).toGMTString());
            log(new Date(history.getLastTick(instrument).getTime()).toGMTString());
            // debug code end
           
            bars.addFirst(bar);
            if (bars.size() < 2) {
                return;
            } else if (bars.size() > 2) {
                bars.removeLast();
            }
            if (!isActive(order)) {
                order = null;
            } else {
                if (isRedBar(bars.get(0)) != isRedBar(bars.get(1))) {
                    order.close();
                }
                return;
            }
            if (isRedBar(bars.get(0)) == isRedBar(bars.get(1))) {
                IEngine.OrderCommand orderCmd = !isRedBar(bars.get(0))? IEngine.OrderCommand.BUY : IEngine.OrderCommand.SELL;
                order = engine.submitOrder(getLabel(instrument), instrument, orderCmd, 0.1, 0.0, 0.0);
            }
        } catch (JFException e) {
            log(e.toString());
        }
    }
   
    private boolean isRedBar(IRenkoBar bar) {
        return bar.getOpen() > bar.getLow();
    }

In the above section of code, in the debug lines, why is it telling me that the last tick time is later than the end time of the bar passed to onBar?
There are large multi-minute gaps between the end time of the bar passed to onBar and the last tick time - why is this?
I would expect onBar to be called when the most current bar is filled, and that should happen at the time of the last tick, no?

Here's a chart showing back testing results with just a week's worth of data, illustrating the problems.
I don't understand why I'm getting these results.

Image


Attachments:
RenkoStrat1.java [3.83 KiB]
Downloaded 359 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: Problems with a very simple renko strategy Post rating: 0   New post Posted: Tue 19 Feb, 2013, 08:49 
User avatar

User rating:
Joined: Fri 31 Aug, 2007, 09:17
Posts: 6139
echomary wrote:
In the above section of code, in the debug lines, why is it telling me that the last tick time is later than the end time of the bar passed to onBar?
There are large multi-minute gaps between the end time of the bar passed to onBar and the last tick time - why is this?
I would expect onBar to be called when the most current bar is filled, and that should happen at the time of the last tick, no?
See IStrategy.onBar description:
https://www.dukascopy.com/wiki/#Strategy_API


 
 Post subject: Re: Problems with a very simple renko strategy Post rating: 0   New post Posted: Tue 19 Feb, 2013, 09:01 

User rating: 0
Joined: Tue 23 Aug, 2011, 01:10
Posts: 7
Location: United States,
I was referring to the onBar method of the IRenkoBarFeedListener, not the onBar method of IStrategy.
I don't see any documention for this on the page which you linked to.


 
 Post subject: Re: Problems with a very simple renko strategy Post rating: 0   New post Posted: Tue 19 Feb, 2013, 09:42 
User avatar

User rating:
Joined: Fri 31 Aug, 2007, 09:17
Posts: 6139
The principle is the same - you receive the renko bar in the listeners onBar call back method once it is finished, thus in the onBar method, the last tick time might be already greater than the finished renko's end time. If you wish to retrieve the currently-forming renko bar then use IHistory.getRenkoBar with shift=0.


 
 Post subject: Re: Problems with a very simple renko strategy Post rating: 0   New post Posted: Tue 19 Feb, 2013, 11:05 

User rating: 0
Joined: Tue 23 Aug, 2011, 01:10
Posts: 7
Location: United States,
To use IRenkoBarFeedListener in my strategy, I would need the onBar method to be invoked precisely when the current renko bar becomes fully filled and before any subsequent ticks arrive. Otherwise, the bar is essentially expired and my strategy is examing an old bar. The bar is filled when a tick arrives, so I don't understand why IRenkBarFeedListener.onBar isn't invoked then -- it seems like a useless method when it's invoked at a seemingly arbitrary time.

I've rewritten my strategy and placed the key bits in IStrategy.onTick. It calls history.getRenkoBar with shift=0 and compares the open price of the bar with the bid price of the current tick, and then it does its thing when the difference in pips is the size of a renko bar. This seems like an unintuitive way of accomplishing the goal when there's an IRenkoBarFeedListener that could do the job if the onBar invocation was at the time of the last tick that filled the bar.

Also I'm slightly perplexed why the renko bar passed to IRenkoBarFeedListener.onBar can return the same values for getOpen() and getClose(). I've heard other users describe this behavior as confusing as well, and I've seen no explanation that makes sense to me. If it's a bar in progress, I might expect open and close values to be the same, but more likely I would expect getClose() to return Double.NaN. For a filled renko bar, it seems logical that open and close would vary by the size of one renko bar, and high and low values would correspond with wicks.

Here's results from the modified strategy. There may still some problems with it.

Image

Here's the relevent section of code:
    public void onTick(Instrument instrument, ITick tick) throws JFException {
        if (!instrument.equals(this.instrument))
            return;
        IRenkoBar renkoBar0 = history.getRenkoBar(instrument, OfferSide.BID, PriceRange.valueOf(renkoSize), 0);
        IRenkoBar renkoBar1 = history.getRenkoBar(instrument, OfferSide.BID, PriceRange.valueOf(renkoSize), 1);
        if (renkoBar0 == null) {
            return;
        }
        double pipDiff = toPips(instrument, renkoBar0.getOpen() - tick.getBid());
        if (Math.abs(pipDiff) >= renkoSize) {
            if (!isActive(order)) {
                order = null;
            } else {
                if (isRedBar(renkoBar0) != isRedBar(renkoBar1)) {
                    order.close();
                }
                return;
            }
            if (isRedBar(renkoBar0) == isRedBar(renkoBar1)) {
                IEngine.OrderCommand orderCmd = !isRedBar(renkoBar0)? IEngine.OrderCommand.BUY : IEngine.OrderCommand.SELL;
                order = engine.submitOrder(getLabel(instrument), instrument, orderCmd, 0.1, 0.0, 0.0);
            }
        }
    }


Attachments:
RenkoStrat1.java [3.2 KiB]
Downloaded 302 times
RenkoStrat1.java [3.44 KiB]
Downloaded 304 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: Problems with a very simple renko strategy Post rating: 0   New post Posted: Tue 19 Feb, 2013, 14:15 
User avatar

User rating:
Joined: Fri 31 Aug, 2007, 09:17
Posts: 6139
echomary wrote:
To use IRenkoBarFeedListener in my strategy, I would need the onBar method to be invoked precisely when the current renko bar becomes fully filled and before any subsequent ticks arrive
IRenkoBarFeedListener.onBar gets fired exactly when the last tick breaches its range, thus the last tick will never be within the last finished renko.
echomary wrote:
Also I'm slightly perplexed why the renko bar passed to IRenkoBarFeedListener.onBar can return the same values for getOpen() and getClose().
Then you have misunderstood the renko algorithm. For all the "spike" renko bricks the close and open prices match - it's easy to check this on a chart which has an OHLC info object on it.


 
 Post subject: Re: Problems with a very simple renko strategy Post rating: 0   New post Posted: Thu 21 Feb, 2013, 02:03 

User rating: 0
Joined: Tue 23 Aug, 2011, 01:10
Posts: 7
Location: United States,
My code seems to be (mostly?) working now, but only after adding a couple tweaks which I don't fully understand why I need to add.

Here's the key section of code:
    public void onBar(Instrument instrument, OfferSide offerSide, PriceRange brickSize, IRenkoBar renkoBar1) {
        if (!instrument.equals(this.instrument))
            return;
        try {
            IRenkoBar renkoBar0 = history.getRenkoBar(instrument, OfferSide.BID, PriceRange.valueOf(renkoSize), 0);
            if (renkoBar0 == null) {
                return;
            }
            double pipDiff = toPips(instrument, history.getLastTick(instrument).getBid() - renkoBar0.getOpen());
            if (Math.abs(pipDiff) >= renkoSize) {
                if (!isActive(order)) {
                    order = null;
                } else {
                    if (isRedBar(renkoBar0) != lastBarRed) { //isRedBar(renkoBar1)) {
                        // debug code begin
                        log("----------------------");
                        log("Closing order " + order.getLabel());
                        log("renkoBar0: " + renkoBar0.toString());
                        log("renkoBar1: " + renkoBar1.toString());
                        // debug code end
                        order.close();
                    }
                    lastBarRed = isRedBar(renkoBar0);
                    return;
                }
                if (isRedBar(renkoBar0) == isRedBar(renkoBar1)) {
                    IEngine.OrderCommand orderCmd = !isRedBar(renkoBar0)? IEngine.OrderCommand.BUY : IEngine.OrderCommand.SELL;
                    order = engine.submitOrder(getLabel(instrument), instrument, orderCmd, 0.1, 0.0, 0.0);
                }
                lastBarRed = isRedBar(renkoBar0);
            }
        } catch (JFException e) {
            log(e.toString());
        }
    }

    private boolean isRedBar(IRenkoBar bar) {
        return bar.getOpen() > bar.getLow();
    }

Take this line:
                  if (isRedBar(renkoBar0) != lastBarRed) { //isRedBar(renkoBar1)) {

If I remove the lastBarRed variable and call isRedBar(renkoBar1) instead, I get this:
Image

Quote:
The principle is the same - you receive the renko bar in the listeners onBar call back method once it is finished, thus in the onBar method, the last tick time might be already greater than the finished renko's end time. If you wish to retrieve the currently-forming renko bar then use IHistory.getRenkoBar with shift=0.

So shouldn't the bar returned by history.getRenkoBar with shift=0 be at least one renko in size when IRenkoBarFeedListener.onBar is called? What exactly do you mean when you say "once it is finished"? I would think it's when the currently forming bar has met or exceeded the size of one renko that the previous bar is finished. I must not be understanding something. Why do I need to perform a check with the lines:
            double pipDiff = toPips(instrument, history.getLastTick(instrument).getBid() - renkoBar0.getOpen());
            if (Math.abs(pipDiff) >= renkoSize) {
            ...


If I don't add these lines, I get:
Image

With the tweaks added, I'm getting closer to the right results, but there still appears to be errors in the timing of entering and exiting some trades (the highlighted part is not an example of an error though - that's a section where i was getting wrong results before):
Image

Subtracting a small fraction from the expected renkoSize seems to fix the occassionally seen problem of missing a bar that would close an open order (order 23-EURUSD22 to be specific):
            if (Math.abs(pipDiff) >= renkoSize - 0.001) {
            ...

That doesn't seem like the truly correct way of fixing the problem though.

Is this a bug in the platform - shouldn't that be a blue bar?
Image

Isn't this also a platform bug - shouldn't those two bars be consolidated into one bar?
Image

Sorry to be so general, but is there a more correct way of writing this strategy?


Attachments:
RenkoStrat2.java [4 KiB]
Downloaded 310 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.
 
The Best Answer  Post subject: Re: Problems with a very simple renko strategy Post rating: 0   New post Posted: Fri 22 Feb, 2013, 13:00 
User avatar

User rating:
Joined: Fri 31 Aug, 2007, 09:17
Posts: 6139
echomary wrote:
If I remove the lastBarRed variable and call isRedBar(renkoBar1) instead, I get this:
Image
What do you find being wrong there? The renkoBar0 is null-brick, as there are no ticks within its range.
echomary wrote:
So shouldn't the bar returned by history.getRenkoBar with shift=0 be at least one renko in size when IRenkoBarFeedListener.onBar is called?
What do you mean by "least one renko in size"? If you mean tick, then a renko brick can also contain 0 ticks, if there are no ticks within its range, say one tick is at 1.3001 and the next 1.3101 then the listener will receive 4 renko bricks in a row:
  • 1.3000 - 1.3025 (includes tick 1.3001)
  • 1.3025 - 1.3050 (empty: endTime - startTime = 1ms)
  • 1.3050 - 1.3075 (empty: endTime - startTime = 1ms)
  • 1.3075 - 1.3100 (empty: endTime - startTime = 1ms)
and the currently forming renko bar will include the tick with price 1.3101.

echomary wrote:
Sorry to be so general, but is there a more correct way of writing this strategy?
From api standpoint, working with IFeedListener gives you more flexibility in switching between different feeds and feed types, see:
https://www.dukascopy.com/wiki/#Chart_feeds/Subscribe_to_a_feed
From business logic standpoint, you just need to make sure that your assumptions about the renko-generation logic are correct.

Quote:
Is this a bug in the platform - shouldn't that be a blue bar?
Image
Isn't this also a platform bug - shouldn't those two bars be consolidated into one bar?
Image
This is under investigation.


 
 Post subject: Re: Problems with a very simple renko strategy Post rating: 0   New post Posted: Sat 23 Feb, 2013, 07:12 

User rating: 0
Joined: Tue 23 Aug, 2011, 01:10
Posts: 7
Location: United States,
Quote:
What do you find being wrong there? The renkoBar0 is null-brick, as there are no ticks within its range.

Zooming in on a one min chart, I see now that there's a gap in the price that was created over a weekend.
For renkoBar1, the open price is 1.23962, whereas all the other open prices are even renko values (divisible by 25 pips).
This makes sense though - I just wasn't accounting for gaps.
Image

I think this is the fix:
    public void onBar(Instrument instrument, OfferSide offerSide, PriceRange brickSize, IRenkoBar renkoBar1) {
        if (!instrument.equals(this.instrument))
            return;
        try {
            IRenkoBar renkoBar0 = history.getRenkoBar(instrument, OfferSide.BID, PriceRange.valueOf(renkoSize), 0);
            if (isFirstBarOfWeek(renkoBar0)) {
                return;
            }
            if (isFirstBarOfWeek(renkoBar1)) {
                renkoBar1 = history.getRenkoBars(instrument, OfferSide.BID, PriceRange.valueOf(renkoSize), 2, renkoBar1.getTime(), 0).get(0);
            }
            if (!isActive(order)) {
                order = null;
            } else {
                if (isRedBar(renkoBar0) != isRedBar(renkoBar1)) {
                    order.close();
                }
                return;
            }
            if (isRedBar(renkoBar0) == isRedBar(renkoBar1)) {
                IEngine.OrderCommand orderCmd = !isRedBar(renkoBar0)? IEngine.OrderCommand.BUY : IEngine.OrderCommand.SELL;
                order = engine.submitOrder(getLabel(instrument), instrument, orderCmd, 0.1, 0.0, 0.0);
            }
        } catch (JFException e) {
            log(e.toString());
        }
    }
   
    private boolean isFirstBarOfWeek(IRenkoBar renkoBar) throws JFException {
        IRenkoBar previousBar = history.getRenkoBars(instrument, OfferSide.BID, PriceRange.valueOf(renkoSize), 2, renkoBar.getTime(), 0).get(0);
        Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
        cal.setTime(new Date(renkoBar.getTime()));
        return cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY
                    && cal.get(Calendar.HOUR_OF_DAY) == 21
                    && cal.get(Calendar.MINUTE) == 0
                    && renkoBar.getOpen() != previousBar.getClose();
    }

Oddly, incidentally, the strategy seems to work infinitely better (on last year of EUR/USD) with trend detection reversed, replacing
        IEngine.OrderCommand orderCmd = !isRedBar(renkoBar0)? IEngine.OrderCommand.BUY : IEngine.OrderCommand.SELL; 

with
         IEngine.OrderCommand orderCmd = isRedBar(renkoBar0)? IEngine.OrderCommand.BUY : IEngine.OrderCommand.SELL;

Thanks for your assistance.


Attachments:
RenkoStrat1.java [4.03 KiB]
Downloaded 375 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.
 

Jump to:  

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