Detecting if the position is still Open, during Backtesting

Hi

During backtest I am not sure how my code can detect that a position is Closed, due to an ApplyStop command. Suppose I code something like this:

stopAmount = 0.0005;
ApplyStop( stopTypeLoss, stopModePoint, stopAmount, True ); 

bo = GetBacktesterObject();    //  Get backtester object
bo.PreProcess();    //  Do pre-processing (always required)

if (MYcondition)
   Buy[index] = true;

bo.ProcessTradeSignals( index );  //  Process trades at bar (always required)
openpos = bo.GetFirstOpenPos();   

if (openpos.IsOpen)
   printf("The position is still Open!\n");

Given that I want to have just one position open at a time. Is it enough to check for (openpos.IsOpen == True), to see if the position I opened from Buy[index] = true; is still ON?

Is this the simplest way to do it? I mean, do I have to use the bo = GetBacktesterObject(); ?

PS: I have not tested this code. I have just assembled pieces and ideas from many articles I read.

Your CBT code is wrong.

As for detection which exit signal has been triggered you may use Reason property of signal object.

BTW, 0.0005? 5 pips?

m = MA( Close, 20 );
Buy = Cross( Close, m ); 
Sell = Cross( m, Close ); 
Short = Cover = 0;

stopAmount = 0.001;// e.g. 10 pips EURUSD
ApplyStop( stopTypeLoss, stopModePoint, stopAmount, True ); 

StaticVarSet( "Date_" + Name(), DateTime() );

SetCustomBacktestProc("");
if( Status("action") == actionPortfolio )  {	
	bo = GetBacktesterObject(); 
	bo.PreProcess();

	/// @link https://forum.amibroker.com/t/detecting-if-the-position-is-still-open-during-backtesting/10783/2
	/// @link https://forum.amibroker.com/t/access-datetime-of-signal-bar-within-a-custom-backtest/9346
	/// @link https://forum.amibroker.com/t/output-signals-of-backtester/10297/1
	exit_list = "Regular,StopLoss,Profit Target,Trail stop,N-bar stop,Ruin stop";
	for (i = 0; i < BarCount; i++) {
		for (sig = bo.GetFirstSignal(i); sig; sig = bo.GetNextSignal(i)) {	
			if (sig.IsExit()) { // if exit signal
				sig_dt = StaticVarGet( "Date_" + sig.Symbol );
				currentExitDateTime = sig_dt[i];
				exit_reason = sig.Reason;
				// for checking either _TRACEF function or RawTextOutput method
				//_TRACEF( "Sig Exit Date (%s): %s, exit reason: %s", sig.Symbol, DateTimeToStr( currentExitDateTime ), StrExtract(exit_list, exit_reason -1) );				
				bo.RawTextOutput( StrFormat("Sig Exit Date (%s): %s, exit reason: %s", sig.Symbol, DateTimeToStr( currentExitDateTime ), StrExtract(exit_list, exit_reason -1)) );
			}
		}
        
		bo.ProcessTradeSignals( i );
	}
    
	bo.PostProcess();
}

405

BTW if you just want to know reason in result list then backtester tells you that one already without any CBT code. Just look at Trade column.

230


Put at the top of code.

SetOption( "MaxOpenPositions", 1 );

As for checking and counting open positions in CBT e.g. see below
(Keep in mind that _TRACEF line is slow! So comment it if not used for debugging.)

/// ....

StaticVarSet( "Date_" + Name(), DateTime() );

SetCustomBacktestProc("");
if ( Status( "action" ) == actionPortfolio ) {
    bo = GetBacktesterObject();
    bo.PreProcess();

    for ( i = 0; i < BarCount; i++ ) {
        cntOpenLong = 0;
        // iterate through open positions
        for ( openpos = bo.GetFirstOpenPos(); openpos; openpos = bo.GetNextOpenPos() ) {
            // check for open long positions
            if ( openpos.IsOpen && openpos.IsLong )  {
                openpos_dt = StaticVarGet( "Date_" + openpos.Symbol );// for _trace
                OpenLongDateTime = openpos_dt[i];// for _trace
                _TRACEF( "Position is open at Date (%s): %s", openpos.Symbol, DateTimeToStr( OpenLongDateTime ) );
                cntOpenLong++;  // count open long
            }
        }

///....

        bo.ProcessTradeSignals( i );
    }

    bo.PostProcess();
}
4 Likes

Thank you very much @fxshrat for the very detailed answer.

I am going through every detail in order to expand my knowledge. I may come back for clarifications.

Thank you again.

Hi @fxshrat

As I am studying your example and the documentation, I now realise that my question should have been titled: Detecting if the position is still Open, during actionIndicator

Suppose this script runs in Indicator/Chart mode. It only generates Buy signals. But how about StopLoss signals? Does the ApplyStop generate such signals? Ie does it change the Sell array?

My test says it does not. I can see the StopLoss signals in the backtester, but I do not see any down arrows in the chart.

m = MA( Close, 20 );
Buy = Cross( Close, m ); 
Sell = 0;
//Sell = Cross( m, Close ); 
Short = Cover = 0;

stopAmount = 0.002;// e.g. 20 pips EURUSD
ApplyStop( stopTypeLoss, stopModePoint, stopAmount, True ); 

/* Plot Buy and Sell Signal Arrows */
shape = Buy * shapeUpArrow + Sell * shapeDownArrow;
PlotShapes( shape, colorGreen, 0, IIf( Buy, Low, High ) );

What I am trying to do is a script that runs in indicator mode, runs with live data and generates signals. The user (me) looks at the signals and enters them in a different live trading platform. Both Amibroker script and the live platform operate with same stoploss settings (ie 10 pips). When the trade is stopped by a stoploss the amibroker script whould be able to know this.

This is what I am missing: How will the ApplyStop inform my script in IndicatrMode that there was a StopLoss?

And ofcourse I need to be able to test all these in backtest mode. Can this be done with one script? Do I need to write different script for live mode and different for backtesting? In this case I am afraid that the algorithm may not be exactly the same.

You said backtesting in thread subject and were using CBT code.

Now you talk about live trading all of the sudden.
Yes, live trading is different from backtesting.

If in live trading using IB then you can retrieve open position list via API.
Take a look at IBcontroller manual.
Also take a look at PlaceOrder etc. (well, read all of IBcontroller manual)


As for ApplyStop itself.

Have you read function reference?

1 - regular exit
2 - max. loss
3 - profit target
4 - trailing
5 - n-bar stop
6 - ruin stop 

-> e.g.

m = MA( Close, 20 );
Buy = Cross( Close, m ); 
Sell = Cross( m, Close ); 

Short = Cover = 0;

stopAmount = 0.002;// e.g. 20 pips EURUSD
/// @link https://www.amibroker.com/guide/afl/applystop.html
ApplyStop( stopTypeLoss, stopModePoint, stopAmount, True ); 


if ( Status( "action" ) == actionIndicator ) {
	/// @link https://www.amibroker.com/guide/afl/equity.html
	eq = Equity(1, 0);// single security backtester, evaluate stops
	
	Plot( C, "Price", colorDefault, styleCandle );

	/* Plot Buy and Sell Signal Arrows */
	shape = Buy * shapeUpArrow + Sell * shapeDownArrow;
	PlotShapes( shape, IIf( Buy, colorGreen, colorRed ), 0, IIf( Buy, Low, High ) );

	exit_stoploss = SELL == 2;
	PlotShapes( exit_stoploss * shapeDownArrow, colorOrange, 0, H, -12 );
}

27

2 Likes

Thank you very much @fxshrat.

After reading your example I understood. This is exactly what I wanted: I needed to call the EQUITY function and check from (SELL == 2).

I am not using IB so no need to use their API. By Live system I mean AB on live feed giving signals that a human operator can manually enter in a trading platform. And somehow the same script to be able to go through backtesting.

Thank you again!