[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[amibroker] problems with AmiBroker built-in stop capabilities



PureBytes Links

Trading Reference Links

Hi,

I think there are some slight but serious problems with how AB deals
with implementing built-in stops (at least for trailing mode type of
stops) via the ApplyStops function when used within the context of
backtesting and/or visually charting the buy/sell arrows on a chart.

I've included sample code (at bottom in "Code Below" section) to help
illustrate this problem.

There are 2 fundamental problems I see with it.  I welcome discussion
regarding this topic.  I see that its been brought before by "dbirru"
but I don't see how it really is even related to ATR
(http://finance.groups.yahoo.com/group/amibroker-beta/message/2177).

My hypothesis is that the root of the stop problem is that ApplyStops
itself uses current bar High (when in Long position) which can lead to
situations where that is indeed future information (e.g., Low of day
triggered the stop but the Low happened hours before the High of the
day happened and thus it should not have been triggered).

*****
Problem 1: ApplyStop with stopTypeTrailing mode references current bar
High.
*****

First of all, there seems to be a postdictive error problem with
ApplyStop with regards to backtesting.  It appears that ApplyStop
utilizes current bar's High value instead of referencing previous
bar's High value.  Also, ApplyStop should not be able to exit the same
bar for trailing stops when that bar is an entry bar.  This can happen
however because ApplyStop uses current bar high including current bar
that is an entry bar.  Instead, the trailing stop calculation for a
day of entry should evaluate its trail stop calculation to NULL for
that day in my opinion.

Examples of incorrect stops because not referencing previous day's High:
  * EBAY 3/13/2000 sold @ 22.75 but should have sold 3/16/2000 @ 23.06
  * GOOG 12/30/2004 sold @ 193.23 but should have sold 12/31/2004 @ 193.23
  * GOOG 5/23/2005 sold @ 253.10 but should have sold 5/25/2005 @
252.73 (Open gap)

Examples of incorrect stops because referencing today's High on day of
Entry, when in fact should not allow to exit on same day as entry when
stop mode is trailing:
  * GOOG 1/19/2005 sold @ 200.30 but should have sold 1/20/2005 @
192.5 (Open gap)
  * GOOG 2/3/2005 sold @ 208.37 but should have sold 2/4/2005 @ 206.47
(Open gap)
  * GOOG 7/21/2005 sold @ 312.80 but should have sold 7/22/2005 @
306.56 (Open gap)

*****
Problem 2: Backtester doesn't always respect open gaps.
*****

Also, when backtesting with AA, you'll notice problem with handling
some gaps properly.  It will not respect open gaps down and give them
precedence for trailing stops all the time.  It seems to be a bug with
partial gaps only instead of full gaps.

Examples of incorrect stop values due to partial gaps with
ActivateStopsImmediately is set to True:
  * EBAY 1/21/1999 sold @ 8.37 but should have sold 1/21/1999 @ 8.21
(Open gap)

*****
How to see the stop problems..
*****
To Illustrate the stop problems, do the following inside AB after
copying below code (see "Code Below" section):

1. Add Custom Layers (after the Monthly layer) 5, 6, 7, 8 to your
layers tab if not already have them.  Name them as such if you prefer:
    Layer 5 - Buy/Sells
    Layer 6 - Short/Covers
    Layer 7 - Sell Stops
    Layer 8 - Cover Stops
2. Turn on all these layers (checkmarked)
3. Open new trading window
4. Insert this chart code via "Insert Linked" to a chart pane.
5. Insert this chart code a second time via "Insert Linked" to a chart
pane.
6. On above chart pane, make sure "Show Postdictive?" setting is set
to "Yes"
7. On below chart pane, make sure "Show Postdictive?" setting is set
to "No"
8. Optionally turn on debug enabled flags to see bar by bar
calculations of
trailing stop figure
9. Leave all Long and Short Trail amounts to default value of 5.
10. Set symbol to EBAY or GOOG and take note of above examples when
exit arrows happen even though they do not cross the blue line (bottom
pane's better trail calculations) vs. the red line (above pane's
ApplyStop trail calculations).  There are many more examples I can
give as well.

*****
Code Below
*****
/*
This code should illustrate 2 problems with built-in stops with AmiBroker.

First of all, there is a postdictive error problem with ApplyStop with
regards to backtesting.  It appears that ApplyStop utilizes current bar's
High value instead of referencing previous bar's High value.  Also,
ApplyStop
should not be able to exit the same bar for trailing stops when that
bar is
an entry bar.  This can happen however.  Instead, the trailing stop
calculation
for a day of entry should evaluate to NULL in my opinion.

Examples of incorrect stops because not referencing previous day's High:
  * EBAY 3/13/2000 sold @ 22.75 but should have sold 3/16/2000 @ 23.06
  * GOOG 12/30/2004 sold @ 193.23 but should have sold 12/31/2004 @ 193.23
  * GOOG 5/23/2005 sold @ 253.10 but should have sold 5/25/2005 @
252.73 (Open gap)

Examples of incorrect stops because referencing today's High on day of
Entry, when
in fact should not allow to exit on same day as entry when stop mode
is trailing:
  * GOOG 1/19/2005 sold @ 200.30 but should have sold 1/20/2005 @
192.5 (Open gap)
  * GOOG 2/3/2005 sold @ 208.37 but should have sold 2/4/2005 @ 206.47
(Open gap)
  * GOOG 7/21/2005 sold @ 312.80 but should have sold 7/22/2005 @
306.56 (Open gap)

Also, when backtesting with AA, you'll notice problem with handling
some gaps
properly.  It will not respect open gaps down and give them precedence for
trailing stops all the time.  It seems to be a bug with partial gaps only
instead of full gaps.

Examples of incorrect stop values due to partial gaps with
ActivateStopsImmediately
is set to True:
  * EBAY 1/21/1999 sold @ 8.37 but should have sold 1/21/1999 @ 8.21
(Open gap)

To Illustrate the stop problems, do the following inside AB:

1. Add Custom Layers (after the Monthly layer) 5, 6, 7, 8 to your
layers tab if
not already have them.  Name them as such if you prefer:
    Layer 5 - Buy/Sells
    Layer 6 - Short/Covers
    Layer 7 - Sell Stops
    Layer 8 - Cover Stops
2. Turn on all these layers (checkmarked)
3. Open new trading window
4. Insert this chart code via "Insert Linked" to a chart pane.
5. Insert this chart code a second time via "Insert Linked" to a chart
pane.
6. On above chart pane, make sure "Show Postdictive?" setting is set
to "Yes"
7. On below chart pane, make sure "Show Postdictive?" setting is set
to "No"
8. Optionally turn on debug enabled flags to see bar by bar
calculations of
trailing stop figure
9. Leave all Long and Short Trail amounts to default value of 5.
10. Set symbol to EBAY or GOOG and take note of above examples when
exit arrows happen
even though they do not cross the blue line (bottom pane's better
trail calculations)
vs. the red line (above pane's ApplyStop trail calculations).
*/

#pragma nocache
#include <Basic Charts/Price.afl>

//
//A simply buy/short system that relies on ApplyStop to exit
//
Buy = Cross(MACD(), Signal());
Sell = False;
Short = MACD() < Signal() AND Volume > 2 * WMA(Volume, 10) AND
ROC(Close, 10) < 0;
Cover = False;

//
//Lets make our trail system very simple - hard coded constants set to
5.0 points by default
//
trailLongPoint = Param("Long Trail Amount", 5.0, 0.1, 100.0, 0.1);
trailShortPoint = Param("Short Trail Amount", 5.0, 0.1, 100.0, 0.1);
drawStops = ParamToggle("Draw Stops?", "No|Yes", True);
debugEnabled = ParamToggle("Debug Enabled?", "No|Yes", False);
debugBetterEnabled = ParamToggle("Debug Better Enabled?", "No|Yes",
False);
showPostdictive = ParamToggle("Show Postdictive?", "No|Yes", True);

//
//Some options and parameters to use
//
SetOption("NoDefaultColumns", False);
SetOption("InitialEquity", 30000);

SetOption("AllowSameBarExit", True);
SetOption("ActivateStopsImmediately", True);

SetOption("AllowPositionShrinking", True);
SetOption("FuturesMode", False);
SetOption("InterestRate", 0);
SetOption("MaxOpenPositions", 5);
SetOption("WorstRankHeld", 5);
SetOption("MinShares", 10);

SetOption("PriceBoundChecking", True);

SetOption("CommissionMode", 2);             //0 (table), 1 (% of
trade), 2 ($ per trade), 3 ($ per share/contract)
SetOption("CommissionAmount", 0);
SetOption("MarginRequirement", 100);
SetOption("ReverseSignalForcesExit", False);
SetOption("UsePrevBarEquityForPosSizing", False);
SetOption("PortfolioReportMode", 0);        //0 (trade list), 1
(detailed log), 2 (summary), 3 (no output - custom only)
SetOption("UseCustomBacktestProc", False);

/**
You trade on next bar OPEN and want to exit intraday on stop price
Correct settings:
ActivateStopsImmediately turned ON
ExitAtStop = 1
Trade delays set to one
Trade price set to open
*/
//Trade delays offset by 1 bar
//***IMPORTANT - set delays in GUI to 0 since this code deals with it
//***See Equity notes for reason why code preferred over GUI for this
value
exitAtStop = 1;
SetTradeDelays(1, 1, 1, 1);
reEntryDelay = 1;       //Wait 1 bar before allowing same stock to be
entered into again

//
//Trail Calculations  -- calculations that ApplyStop seems to use
//
stopLongTrailBasis = High;
trailLongPeriod = BarsSince(Buy);
stopLongTrail = HHV(stopLongTrailBasis - trailLongPoint, trailLongPeriod);

stopShortTrailBasis = Low;
trailShortPeriod = BarsSince(Short);
stopShortTrail = LLV(stopShortTrailBasis + trailShortPoint,
trailShortPeriod);

//
//Better Trail Calculations  -- ones that eliminate postdictive errors
by not referencing potential future data
//
betterStopLongTrailBasis = Ref(High, -1);
betterTrailLongPeriod = BarsSince(Buy) - 1;
betterStopLongTrail = HHV(betterStopLongTrailBasis - trailLongPoint,
betterTrailLongPeriod);

betterStopShortTrailBasis = Ref(Low, -1);
betterTrailShortPeriod = BarsSince(Short) - 1;
betterStopShortTrail = LLV(betterStopShortTrailBasis +
trailShortPoint, betterTrailShortPeriod);

//
//Lets just use a simple trailing stop via ApplyStop function
//
ApplyStop(stopTypeTrailing, stopModePoint, trailLongPoint, exitAtStop,
volatile=False, reEntryDelay);

//
//Re-calculate sell/cover arrays from application of stops
//
if (Status("action") != actionBacktest)      //Don't use Equity(2) for
Backtest mode
    Equity(2);

//
//Re-Calculate calculations used for visual display of trail code
//
trailLongPeriod = BarsSince(Buy) + 1;
stopLongTrail = HHV(stopLongTrailBasis - trailLongPoint, trailLongPeriod);
trailShortPeriod = BarsSince(Short) + 1;
stopShortTrail = LLV(stopShortTrailBasis + trailShortPoint,
trailShortPeriod);

//
//Re-Calculate Better calculations used for visual display of trail code
//
betterTrailLongPeriod = BarsSince(Buy);
betterStopLongTrail = IIf(Buy, Null, HHV(betterStopLongTrailBasis -
trailLongPoint, betterTrailLongPeriod));
betterTrailShortPeriod = BarsSince(Short);
betterStopShortTrail = IIf(Short, Null, LLV(betterStopShortTrailBasis
+ trailShortPoint, betterTrailShortPeriod));

//
//Exploration of Trail Stops
//
Filter = 1; //Buy OR (Sell >= 1) OR Short OR (Cover >= 1);
AddColumn(MACD(), "MACD()");
AddColumn(Signal(), "Signal()");
AddColumn(BarsSince(Buy), "Bars in Buy", 1, colorDefault,
        IIf(Buy, colorGreen, colorDefault));
AddColumn(BarsSince(Short), "Bars in Short", 1, colorDefault,
        IIf(Short, colorGreen, colorDefault));
AddColumn(Open, "Open");
AddColumn(High, "High");
AddColumn(Low, "Low", 1.4);
AddColumn(Close, "Close");
AddColumn(Avg, "Avg");
AddColumn(stopLongTrail, "Trail Long Stop", 1.4);
AddColumn(stopShortTrail, "Trail Short Stop", 1.4);
AddColumn(trailLongPeriod, "Trail Long Period", 1);
AddColumn(trailShortPeriod, "Trail Short Period", 1);
AddColumn(BuyPrice, "BuyPrice");
AddColumn(SellPrice, "SellPrice");
AddColumn(ShortPrice, "ShortPrice");
AddColumn(CoverPrice, "CoverPrice");

//
//Graphics
//
buySellLayer = 5;
shortCoverLayer = 6;
sellStopLayer = 7;
coverStopLayer = 8;

if (drawStops) {
    //Plot Buy/Sells on Layer 5, Short/Covers on Layer 6, Stops on 7 and 8
    PlotShapes(Buy * shapeUpArrow, colorLime, buySellLayer, Low);
    PlotShapes((Sell >= 1) * shapeDownArrow, colorRed, sellStopLayer,
High);
    PlotShapes(Cross(stopLongTrail, Low) * shapeStar, colorRed,
sellStopLayer, Low - 1);

    PlotShapes(Short * shapeDownArrow, colorGreen, shortCoverLayer,
High + 2);
    PlotShapes((Cover >= 1) * shapeUpArrow, colorBrown,
coverStopLayer, Low - 2);
    PlotShapes(Cross(High, stopShortTrail) * shapeStar, colorBrown,
coverStopLayer, High + 3);

    //
    //Plot ApplyStop style visuals
    //
    if (showPostdictive) {
        if (debugEnabled) {
            Plot(stopLongTrailBasis - trailLongPoint, "TrailL Calc",
colorRed,
                    styleDots | styleNoLine);
            Plot(stopShortTrailBasis + trailShortPoint, "TrailS Calc",
colorBrown,
                    styleDots | styleNoLine);
        }
        Plot(stopLongTrail, "TrailL", colorRed, styleStaircase);
        Plot(stopShortTrail, "TrailS", colorBrown, styleStaircase);
    }

    //
    //Plot my own custom stop trail style visuals that eliminate
postdictive errors
    //
    if (!showPostdictive) {
        if (debugBetterEnabled) {
            Plot(betterStopLongTrailBasis - trailLongPoint, "Better
TrailL Calc", colorBlue,
                    styleDots | styleNoLine);
            Plot(betterStopShortTrailBasis + trailShortPoint, "Better
TrailS Calc", colorBlueGrey,
                    styleDots | styleNoLine);
        }
        Plot(betterStopLongTrail, "BetterTrailL", colorBlue,
styleStaircase);
        Plot(betterStopShortTrail, "BetterTrailS", colorBlueGrey,
styleStaircase);
    }
}

//
//Interpretation
//
if(Status("action") == actionCommentary) {
    printf(WriteIf(Buy, "\nLE (Long Entry) @ " + BuyPrice, ""));
    printf(WriteIf(Short, "\nSE (Short Entry) @ " + ShortPrice, ""));

    printf(WriteIf(Sell == 6, "\nRX (Ruin Long Stop) @ " + SellPrice,
""));
    printf(WriteIf(Sell == 2, "\n-- (Max Loss Long Stop) @ " +
SellPrice, ""));
    printf(WriteIf(Sell == 3, "\n+ (Profit Target Long Stop) @ " +
SellPrice, ""));
    printf(WriteIf(Sell == 4, "\n- (Trailing Long Stop) @ " +
SellPrice, ""));
    printf(WriteIf(Sell == 5, "\nNX - N-Bar Long Stop @ " + SellPrice,
""));
    printf(WriteIf(Sell == 1, "\nLX - Regular Long Exit @ " +
SellPrice, ""));

    printf(WriteIf(Cover == 6, "\nRX (Ruin Short Stop) @ " +
CoverPrice, ""));
    printf(WriteIf(Cover == 2, "\n-- (Max Loss Short Stop) @ " +
CoverPrice, ""));
    printf(WriteIf(Cover == 3, "\n+ (Profit Target Short Stop) @ " +
CoverPrice, ""));
    printf(WriteIf(Cover == 4, "\n- (Trailing Short Stop) @ " +
CoverPrice, ""));
    printf(WriteIf(Cover == 5, "\nNX - N-Bar Short Stop @ " +
CoverPrice, ""));
    printf(WriteIf(Cover == 1, "\nSX - Regular Short Exit @ " +
CoverPrice, ""));

    if (debugEnabled) {
        printf("\n\nBarsSince(Buy) = " + BarsSince(Buy));
        printf("\nBuy = " + Buy);
        printf("\nShort = " + Short);

        printf("\n\nAA.NoDefaultColumns = " +
GetOption("NoDefaultColumns"));
        printf("\nAA.InitialEquity = " + GetOption("InitialEquity"));
        printf("\nAA.AllowSameBarExit = " +
GetOption("AllowSameBarExit"));
        printf("\nAA.ActivateStopsImmediately = " +
GetOption("ActivateStopsImmediately"));
        printf("\nAA.AllowPositionShrinking = " +
GetOption("AllowPositionShrinking"));
        printf("\nAA.FuturesMode = " + GetOption("FuturesMode"));
        printf("\nAA.InterestRate = " + GetOption("InterestRate"));
        printf("\nAA.MaxOpenPositions = " +
GetOption("MaxOpenPositions"));
        printf("\nAA.WorstRankHeld = " + GetOption("WorstRankHeld"));
        printf("\nAA.MinShares = " + GetOption("MinShares"));
        printf("\nAA.PriceBoundChecking = " +
GetOption("PriceBoundChecking"));
        printf("\nAA.CommissionMode = " + GetOption("CommissionMode"));
        printf("\nAA.CommissionAmount = " +
GetOption("CommissionAmount"));
        printf("\nAA.MarginRequirement = " +
GetOption("MarginRequirement"));
        printf("\nAA.ReverseSignalForcesExit = " +
GetOption("ReverseSignalForcesExit"));
        printf("\nAA.UsePrevBarEquityForPosSizing = " +
GetOption("UsePrevBarEquityForPosSizing"));
   }
}





------------------------ Yahoo! Groups Sponsor --------------------~--> 
Put more honey in your pocket. (money matters made easy).
http://us.click.yahoo.com/r7D80C/dlQLAA/cosFAA/GHeqlB/TM
--------------------------------------------------------------------~-> 

Please note that this group is for discussion between users only.

To get support from AmiBroker please send an e-mail directly to 
SUPPORT {at} amibroker.com

For other support material please check also:
http://www.amibroker.com/support.html

 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/amibroker/

<*> To unsubscribe from this group, send an email to:
    amibroker-unsubscribe@xxxxxxxxxxxxxxx

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/