Signal not appearing in CBT

SetBarsRequired(sbrAll, sbrAll);
SetCustomBacktestProc("");

function applyCustomBacktesterRules()
{

    bo = GetBacktesterObject(); // Get backtester object
    bo.PreProcess();
    dt = DateTime();

    for( i = 0; i < BarCount; i++ )
    {
        _TRACE( "bar=" + i + ", bo.GetSignalQty(i, 0)=" + bo.GetSignalQty( i, 0 ) );

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

        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
    }

    bo.PostProcess();
}

Short = BarIndex()==1295;
Cover = BarIndex()==1298;


if (Status("action") == actionPortfolio)
applyCustomBacktesterRules();

I have a situation like above (not exact but similar). The short signal is NOT present in bar 1295. bo.GetSignalQty( i, 0 ) returns 0.
How do I debug this?

@AlgoEnthusiast the posted code works here (tested one symbol - all quotes - Analysis settings: Positions: Short):

1 Like

best to wrap CBT code in if( Status("action") == actionPortfolio ) block to ensure code execution in the correct phase.

Yes this code is a representation my code is different and because it is too long I cannot post it here. I am not able to debug it. How do I debug it?. The signal is there in exploration. I have checked excessive signals. The signal is present till the last line of the indicator code but vanishes in cbt.

You code has not specified the backtest mode.

SetBacktestMode( backtestRegularRaw2Multi );
This is very slow but no redundant signals are removed. look at other backtest modes as well.

bo.PreProcess() will depend on the kind of BT.

maybe you are executing code as backtestRegular which is the default.

1 Like

Please read the manual

Special attention should be given to the picture that shows how entry and signals are matched and how redundant ones are removed. See also SetBacktestMode function that controls what signals are kept and which are not.

Generally you should not be using CBT unless you understand the core principles explained in very detail in the manual.

Another important thing is PADDING. Depending on pad and align option, the quote might be padded to reference symbol and the absolute bar number in CBT that represent ALL bars that are present in any of the symbols under test might NOT be the bar number that you are referring to DO NOT use absolute hard coded bar numbers!!!!

Use date time instead. ONLY date times are guaranteed to accurately represent bars. Bar numbers are NOT ! Bar numbers vary when you use padding, other unaligned symbols, quickafl, etc.

5 Likes

Also, hard coding entry on a fixed bar or datetime could potentially result in many signals being skipped due to a finite limit

AmiBroker stores only (2*MaxOpenPositons) top-ranked entry signals per bar

So you would never get BT signals that you are looking for and those that would otherwise appear in AA-exploration.

1 Like

I want to avoid cbt but some very basic stuff like same bar scalein-exit, scaleout-exit can only be achieved using cbt. Is my understanding wrong?

Also actual portfolio backtesting values (buy qty, sell qty during portfolio backtesting) can be visualised on chart only using cbt.

No you don’t necessarily need cbt for scaling. There are examples in the manual of scaling without cbt.

I mean when ScaleIn and exit signals occur simultaneously on the same bar. We need cbt for that.

Yes on SetBacktestMode( backtestRegularRaw ); the signal shows up along with many other duplicate scalein and scaleout signals. I don't know how to debug this because when i check the short, cover count (see below trace command) it seems perfect. Where are the raw redundant signals. How do i trace?

_TRACE("Cum(Short==1)="+Cum(Short==1)+", Cum(Short==SigScaleIn)="+Cum(Short==SigScaleIn)+", Cum(Short==SigScaleOut)="+Cum(Short==SigScaleOut)+", Cum(Cover==1)="+Cum(Cover==1));
	_TRACE("Cum(Short!=1&&Short!=0&&Short!=sigScaleIn&&Short!=sigScaleOut)="+Cum(Short!=1&&Short!=0&&Short!=sigScaleIn&&Short!=sigScaleOut));
	_TRACE("Cum(cover!=1&&cover!=0&&cover!=sigScaleIn&&cover!=sigScaleOut)="+Cum(cover!=1&&cover!=0&&cover!=sigScaleIn&&cover!=sigScaleOut));

I am just going crazy over this. I don't know where the redundant signals are. On chart everything seems fine. But running backtest in backtestRegularRaw mode brings back the missing signal (along with a few duplicates). I don't know how to debug this. Tomasz any hints?

Setting your signals via bar number is a very bad idea, as the bar numbers for a particular date will change depending on the start date of your analysis as well as the indicators that you’re using because AmiBroker always tries to ensure that all indicators are valid no later than the first bar of the analysis date range. For example, if your AFL uses a 200 period simple moving average, then Bar 0 will be at least 200 bars prior to the start of your analysis date range.

During Phase 2 of the backtest (CBT), the bar numbers change again to align with the ~~~Equity symbol. Generally that means that bar 0 aligns with the first date and time that is within the analysis date range.

If you want to see if AmiBroker is eliminating your signals, try changing the Backtest Report to Detailed Log. All signals are shown for every bar, along with a date/time stamp

3 Likes

But how do I hunt down the redundant signals? Buy, sell, cover, short count is OK. I checked. Where else are this so called redundant raw signals. Please tell me how to debug.

@AlgoEnthusiast, did you test the different modes of SetBacktestMode that do not remove redundant signals?
Then in your CBT code you can then select what signal to actually process and what to discard.

In general, debugging in the CBT is done using a lot of detailed _TRACEF() calls (for example see this post) - I use DebugView++ as an external logger.

In any case, I suggest to reread and study carefully the previous post by @Tomasz to properly understand how Amibroker normally process signals.

1 Like

Not really. ScaleIn/Out go into Buy/Short array, while exits go into Sell/Cover so they don't technically need CBT to occur on same bar.

To get better understanding of what is happening in your code and how functions work, use advice given here: How do I debug my formula?

I will do this report back. thanks

@Tomasz @beppe
Ok. So I ran the backtest under backtestRegularRaw mode which does NOT remove redundant signals. I ran only with 1 stock. I traced the signal in cbt and find that bar no. 134 has following signals
short, short, scalein, short, scalein, short, scalein

My code on the other hand has only one signal on this bar i.e. Short=99998 (ScaleIn)

How do i proceed further?

You did not provide any screenshot, code or anything. Please follow this advice: How to ask a good question

But anyway, one thing to note: ScaleIn used in "Short" variable in the ABSENCE of already open position is treated as entry signal (Short).

1 Like

The code is too long to post here. The signals traced are sig.type. below the trace code.

 for( i = 0; i < BarCount; i++ )   
    {     
		for(j=0;j<bo.GetSignalQty(i, 0);j++){
		if(j==0)
		_TRACE("bar="+i+", bo.GetSignalQty(i, 0)="+bo.GetSignalQty(i, 0));
		for( sig = bo.GetFirstSignal( i ); sig; sig = bo.GetNextSignal( i ) ) 
		_TRACE("sig.Symbol= '"+sig.Symbol+"' "+sig.Type);
		}
}

But i don't understand one thing how can 1 stock have so many signals on one bar? how short=1 and short=scalein for same bar same stock? bar 120 is the bar with short signal (short open) and this bar has right signal in CBT too.

If i trace before CBT it shows only one signal on this bar i.e short=99998