Low level CBI and ApplyStop

The following code works when CBI is NOT used, but crashes when CBI is used

type or paste
case 1:   // Profit Target OK
    Profit = "1-ATR";
//
    ATR_ProfitMult_   = 40;
	//ATR_ProfitMult_   = Optimize("ProfitMult",20,2,40,2);
    ATR_ProfitMult    = ATR_ProfitMult_ / 10;
    ATR_ProfitPercent = ATR_ProfitMult * ATR( 14 ) / Close * 100;
    ApplyStop( stopTypeProfit, stopModePercent, ATR_ProfitPercent, 1, False, 1 ) ;
	_TRACE("CBI-ApplyStop - Symbol " + Name() + "  Close " + WriteVal(Close,1.2) + "  ATR " + WriteVal(ATR(14),1.2) + "  ATR_Profitperc " + WriteVal(ATR_ProfitPercent,1.2));
	break;
// code here

The offending line is the ApplyStop() line. When I comment out this line, CBI code

for( sig = bo.GetFirstSignal( i ); sig; sig = bo.GetNextSignal( i ) )

produces the following 4 lines inDebugView:
image

When the ApplyStop() line is not commented out and I backtest for selected period, I get Access Violation error.
When I backtest for "All Quotes", system does not crash, but has bas test report. Crash report and backtest reportbelow:
AmiBroker version 6.26.0.6260
( 64-bit, cooltool.dll 6.26.0, mfc42.dll 6.26.0, msvcrt.dll 7.0.7601 )

Microsoft Windows 7 version 6.1 (Build 7601)
Service Pack 1.0, Common Controls: 6.16

Unhandled exception
Type: CSysException
Code: c0000005
Description: ACCESS VIOLATION
Address: 000000013F5245A8

//
//_TRACE("CBI debug - Symbol " + Name() + " i " + WriteVal(i,1.0) );
// Handle programmed stops at this bar
bo.HandleStops( i )
------------------------------^
File: 'G:\DataFiles\Amibroker-EOD\Formulas\TradeMatrix\Trade Matrix - 20-4.afl', Ln: 2248, Col: 31
Error 47.
Exception occurred during AFL formula execution at address: 000000013F5245A8, code: C0000005
Call Stack:
000000013F5245A8 Broker, (function-name not available)() +0 byte(s)
000000013F51CE8F Broker, (function-name not available)() +0 byte(s)
000007FEE8E4CCD0 mfc140, (function-name not available)() +0 byte(s)
000007FEE8E4D81E mfc140, (function-name not available)() +0 byte(s)
000000013F3AC86E Broker, (function-name not available)() +0 byte(s)
000000013F3AB72C Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA407 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AAA0D Broker, (function-name not available)() +0 byte(s)
000000013F3AA407 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AABD9 Broker, (function-name not available)() +0 byte(s)
000000013F3AA407 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AA322 Broker, (function-name not available)() +0 byte(s)
000000013F3AABD9 Broker, (function-name not available)() +0 byte(s)
000000013F39D120 Broker, (function-name not available)() +0 byte(s)
000000013F3DC8DB Broker, (function-name not available)() +0 byte(s)
000000013F39F55A Broker, (function-name not available)() +0 byte(s)
000000013F416EB8 Broker, (function-name not available)() +0 byte(s)
000000013F3F8DDE Broker, (function-name not available)() +0 byte(s)
000000013F3FAED5 Broker, (function-name not available)() +0 byte(s)
000007FEE8E14159 mfc140, (function-name not available)() +0 byte(s)
000000013F3F11BF Broker, (function-name not available)() +0 byte(s)
000000013F3F25E6 Broker, (
Additional information:

Multi-threaded charts - ENABLED

Number of stock loaded: 27563
Currently selected stock: AAPL
Number of quotes (current stock): 8266

Workspace:
Data source = MSTK, Data local mode = 2, NumBars = 29000

Preferences:
Data source = (local), Data local mode = 1, NumBars = 2000

Command history:
2828 - Opens new Analysis window - a tool to test systems & explore market--New Analysis window
2971 - Opens currently selected window layout

Cache manager stats:
Number of list elements: 1037
Number of map elements: 1037
Hash table size: 5987

Memory status:
MemoryLoad: 37 %
TotalPhys: 12573816K AvailPhys: 7906332K
TotalPageFile: 25145772K AvailPageFile: 19826508K
TotalVirtual: 4294967168K AvailVirtual: 4293974412K

Log:
Logging started 2017-10-13 18:51:23
1.39 ms : Enabling low frag heap (0.06 ms)
1.45 ms : Launching splash screen (1.72 ms)
3.16 ms : Waiting for splash screen (7.37 ms)
10.53 ms : Alloc other stuff (2.83 ms)
13.36 ms : Loading amisci.dll (2.49 ms)
15.84 ms : Setting up SEH translator (82.51 ms)
98.36 ms : Initializing OLE (0.04 ms)
98.39 ms : Initializing RichEdit (0.59 ms)
98.98 ms : Checking current working directory (0.38 ms)
99.37 ms : Loading persistent variables (0.09 ms)
99.46 ms : Loading MRU lists (1.34 ms)
100.80 ms : Loading commisison table (0.05 ms)
100.85 ms : Loading preferences (1.60 ms)
102.45 ms : Initializing display settings (0.16 ms)
102.62 ms : Loading old groups and markets (0.20 ms)
102.82 ms : Loading GICS and ICB (2.09 ms)
104.90 ms : Loading plugins (0.14 ms)
105.04 ms : Loading 'C:\Program Files\AmiBroker\Plugins\CMAE.dll' (1.00 ms)
106.04 ms : Loading 'C:\Program Files\AmiBroker\Plugins\DDE.dll' (3.16 ms)
109.19 ms : Loading 'C:\Program Files\AmiBroker\Plugins\eSignal.dll' (20.47 ms)
129.66 ms : Loading 'C:\Program Files\AmiBroker\Plugins\IB.dll' (1.78 ms)
131.45 ms : Loading 'C:\Program Files\AmiBroker\Plugins\IQFeed.dll' (0.73 ms)
132.18 ms : Loading 'C:\Program Files\AmiBroker\Plugins\MS.dll' (0.80 ms)
132.98 ms : Loading 'C:\Program Files\AmiBroker\Plugins\ODBC.dll' (1.55 ms)
134.54 ms : Loading 'C:\Program Files\AmiBroker\Plugins\ODBCA.dll' (1.41 ms)
135.94 ms : Loading 'C:\Program Files\AmiBroker\Plugins\PSOSample.dll' (0.81 ms)
136.76 ms : Loading 'C:\Program Files\AmiBroker\Plugins\Tribes.dll' (0.78 ms)
137.54 ms : Checking for any new non-certified plugins (0.02 ms)
137.56 ms : Done. (0.02 ms)
137.58 ms : Loading AT interfaces (0.05 ms)
137.62 ms : Loading AFL function table (0.55 ms)
138.18 ms : Init chart infos (1.38 ms)
139.56 ms : Loading parameters (12.95 ms)
152.51 ms : Loading chart infos (0.73 ms)
153.24 ms : Loading custom tools (0.36 ms)
153.60 ms : Allocating lists (0.16 ms)
153.76 ms : Loading layers and alerts (2.32 ms)
156.08 ms : Loading miscellaneous data (286.16 ms)
442.24 ms : Adding MDI templates (1.04 ms)
443.28 ms : Register OLE server (2.76 ms)
446.03 ms : Creating main frame object (25.09 ms)
471.12 ms : Loading main frame (132.98 ms)
604.10 ms : Parsing command line (0.04 ms)
604.15 ms : Checking Broker.Document object registration (0.06 ms)
604.21 ms : Setting browser emulation to IE11 (0.03 ms)
604.24 ms : Dispatch commands via ProcessShellCommand (0.03 ms)
604.27 ms : Showing main frame window (56.75 ms)
661.01 ms : Setting up accelerators (4.61 ms)
665.62 ms : Loading database (LoadMarketData) (2361.84 ms)
3027.45 ms : Setting active symbol (114.49 ms)
3141.94 ms : Opening default chart (68.79 ms)
3210.73 ms : Loading default workspace/layout (532.56 ms)
3743.29 ms : Closing startup splash screen (async in 1 second) (0.32 ms)
3743.61 ms : Starting up schedule (0.29 ms)
3743.90 ms : *InitInstance finished

image

Every trade shows a hold period of 1 bar

It seems likely that you have an error in your CBT. The line of code that reports the Access Violation is probably not the real problem. That line is just trying to access memory that you have somehow corrupted.

My suggestion is to create the simplest CBI that still demonstrates the problem, and then post that code here for the group to evaluate and comment on.

Matt

Buy = Sell = Short = Cover = 0 ; 
Buy[0] = 1; 
ApplyStop( stopTypeNBar, stopModeBars, 5 ); 


SetCustomBacktestProc("");

if (Status("action") == actionPortfolio)
{
    bo = GetBacktesterObject();	//  Get backtester object
    
    bo.PreProcess();	//  Do pre-processing
    
    for (i = 0; i < BarCount; i++)	//  Loop through all bars
    {
        for (sig = bo.GetFirstSignal( i ); sig; sig = bo.GetNextSignal( i ) )
        {	
        
           if( sig.IsEntry() ) 
                bo.EnterTrade( i, sig.Symbol, sig.IsLong(), sig.Price, sig.PosSize );
                
           if( sig.IsExit() )
                bo.ExitTrade( i, sig.Symbol, sig.Price );
          
        }	
        
        bo.HandleStops( i );	//  Handle programmed stops at this bar
        bo.UpdateStats( i, 1 );	//  Update MAE/MFE stats for bar
        bo.UpdateStats( i, 2 );	//  Update stats at bar's end
    }	//  End of for loop over bars
    
    bo.PostProcess();	//  Do post-processing
}
1 Like

Matt, Aron,

Thanks for your responses. After more debugging, I clearly have code issues outside of CBT … so I will focus on those first. Don’t know enough of specific issues so can not post anything useful yet.

Thanks
Ara

@ara1: Good luck on your other issues.

@aron: That’s a good example, and I can’t see the error in it. Perhaps @Tomasz can provide some insight into why that very simple example causes an access violation.

The reason is elsewhere, not in CBT formula nor ApplyStop. The code works fine on all our testing machines. On a number of times in the past it has been demonstrated that @ara1 did things that are not supported like using invalid characters in the variable names. Doing things outside specifications may lead to problems.

The code posted by @aron is a complete example which I can copy and paste directly into the AB Formula Editor. It passes the code check, which would seem to indicate no invalid characters or other syntax errors. However, when I run a back test, it reports an Access Violation every time on my 64-bit Win10 machine. Minor changes to the code as well as to AB settings like Pad & Align do not seem to affect the behavior. Interesting that it does not fail for you.

Sorry, no matter how many times I run it, it does not crash in 6.26 64-bit nor in 32-bit.

If it's any help, I can reproduce a repeatable crash from the code on 6.26.0 64-Bit.

Interestingly it crashes when All Quotes are selected as the Range, but not when From-To Dates are.

Here's a link to the APX I saved it as.

I've also submitted the crash report to AB Support.

image

Thanks, with your APX file I managed to reproduce it. It occurred only with trade delays SET TO ZERO. Once you set delays to non-zero, you won’t see it. Still the formula in first place is incorrect.

The reason is plain fact that in backtestRegular mode stops are ALREADY HANDLED in FIRST phase, and you should NOT call HandleStops() in portfolio backtester code UNLESS you use other backtest modes such as backtestRegularRaw, backtestRotational, etc.

So DO NOT call HandleStops() or add

 // must be added if you want to call HandleStops in CBT
SetBacktestMode( backtestRegularRaw );

// but really you should NOT call HandleStops in regular mode because
// stops are ALREADY handled

to your formula so it does not trigger error.

Generally, as I wrote many times, I discourage using low level custom backtester. It is too complex for average user.

I will need to implement yet another preventive steps to not allow user to shoot yourself in the foot
and prevent invalid code from running (i.e. calling HandleStops in regular backtest mode)

2 Likes

I did some code review … I had all the delays in Settings menu set to zero as well as in the code where they were 1,0,1,0 … The results were still confusing until I saw Tomasz’ comment about bo.HandleStops. Removing this line from the code (I used Aron’s simplified code), system started working OK.

Tomasz’, your comment about implementing another preventive measure would be very useful.

Question: Will you also fix the delay setting of zero being a problem or is that required to stay that way for some reason? I am not sure if the the programmed delays to 1,0,1,0 is a problem or not but I do want to use delays of 1,0,1,0. I usually specify the delay in the code so don’t pay attention to the menu settings.

Ara

There are three solutions to that “problem”:

  • do not use low-level backtest, it is for experts only
  • if you need to call HandleStops you need to use SetBacktestMode( backtestRegularRaw ) in your code (or any other mode different than backtestRegular)
  • if you want to use backtestRegular, do NOT call HandleStops() - in regular backtest, stops are handled in first phase of backtest, but then stops won’t trigger for trades that you create using low-level call EnterTrade.

Once you remove HandleStops() call or when you add SetBacktestMode( backtestRegularRaw ) it works flawlessly regardless of what delays you use. As I wrote, in regular backtest, stops are handled in first phase of backtest. For this reason you should not cal HandleStops() in CBT when you are using backtestRegular mode. As I said low-level backtest is tricky. Average user should use mid-level instead. It also allows to call EnterTrade/ExitTrade but bo.ProcessTradeSignals “knows” how to handle stops properly internally depending on mode. In low level you are calling all functions yourself, but then you have to know when to call them and when not and in what order. If you call wrong functions in low-level or in incorrect order you may experience all kind of troubles and/or wrong results. All that leads to the fact that low level is tricky.

3 Likes