CBT with Optimize() - not specified any variables

Hello,

I am trying optimize in CBT. Based on google search results (cbt optimize site:amibroker.com) I saw that it should work but I did not find any details. I tried an optimize inside and outside the CBT but I receive the error message:
You have not specified any variables for optimization

image

Do you have any hints (or links)?

Example:

SetBacktestMode( backtestRegularRaw );
//======SETTINGS====================
SetOption( "PortfolioReportMode", 0 ); // 0 - trade list 1 - detailed log 2 - summary
SetOption( "GenerateReport", 1 ); // 0 suppress generation of report  1 force generation of full report
SetOption( "InitialEquity", 100000 );
RoundLotSize = 1;
SetTradeDelays( 0, 1, 1, 1 );
maxopenpos = 10 ;
SetOption( "MaxOpenPositions", maxopenpos );
SetPositionSize( 100 / maxopenpos, spsPercentOfEquity );
SetOption( "CommissionMode" , 3 );
SetOption( "CommissionAmount" , 0.01 );
SetOption( "holdminbars", 10 );
SetOption( "MinShares", 1 ); //

PositionScore = 1000 + ROC( Close, 100 );
Buy =   Ref( C  > ma( C, 100 ), -1 )  ;
Sell = C  < ma( C, 100 ) ;

SetCustomBacktestProc( "" );

if( Status( "action" ) == actionPortfolio )
{
    bo = GetBacktesterObject();	//  Get backtester object
    bo.PreProcess();	//  Do pre-processing
    stopmin = Optimize( "Stop", 0.2, 0.1, 0.4, 0.1 ) ;

    for( i = 0; i < BarCount; i++ )	//  Loop through all bars
    {
        for( sig = bo.GetFirstSignal( i ); sig; sig = bo.GetNextSignal( i ) )
        {
            //  Loop through all signals at this bar
            Posopen = bo.FindOpenPos( sig.Symbol );

            if( sig.IsEntry() )
            {
                bo.EnterTrade( i, sig.Symbol, sig.IsLong(), sig.Price, sig.PosSize );
            }

            bo.UpdateStats( i, 1 );

            if( sig.IsExit() )
                bo.ExitTrade( i, sig.Symbol, sig.Price );
        }

        bo.HandleStops( i );	//  Handle programmed stops at this bar

        for( trade = bo.GetFirstOpenPos(); trade; trade = bo.GetNextOpenPos() )	//loop through open positions

//======STOP LOSS====================
            if( trade.BarsInTrade > 1 AND trade.GetPrice( i, "L" ) <= trade.EntryPrice * ( 1 - stopmin ) )
            {
                bo.ExitTrade( i, trade.Symbol, trade.GetPrice( i, "C" ), 2 );	   // (1 - regular exit, 2 - max. loss, 3 - profit, 4 - trail, 5 - N-bar, 6 - ruin)
            }

        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
    // Here we add custom metric to backtest report
}

Thanks,
Peter

Hi,
This code below runs only when you are running a portfolio Backtest.

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

so using Optimization code within that will obviously not run when you run the optimizer.
.
stopmin = Optimize( "Stop", 0.2, 0.1, 0.4, 0.1 ) ;

so you can optimize the variable "stop" outside of the loop separately then backtest it.
During a backtest, the default value will be used in the Optimize line.

1 Like

Thanks! I did some tests and this seems to work:

stopmin = 0.2; //Optimize("3",0.2,0.1,0.3,0.1) ;
StaticVarSet( "stopmin", stopmin );
if (Status("action") == actionPortfolio) // gives information in what context given formula is run: 1 - actionIndicator (INDICATOR), 2 - actionCommentary (COMMENTARY), 3 - actionScan (SCAN), 4 - actionExplore (EXPLORATION), 5 - actionBacktest (BACKTEST / OPTIMIZE), 6 - actionPortfolio (portfolio backtest). 
{
    bo = GetBacktesterObject();	//  Get backtester object
    
    bo.PreProcess();	//  Do pre-processing
    
        stopmin= StaticVarGet( "stopmin" );// 0.2 ;

Optimize() function MUST NOT be called conditionally!

You must NOT place it inside any if() statement.

Optimize MUST be placed on global level.

It was already said on this forum: Misunderstanding of Optimize Exclude

And for God's sake DO NOT USE static variables ! They are NOT NEEDED ! Just move Optimize OUTSIDE the if() statement

// Optimize call OUTSIDE if()
stopmin = Optimize( "Stop", 0.2, 0.1, 0.4, 0.1 ) ;

if (Status("action") == actionPortfolio)
{
    bo = GetBacktesterObject();	//  Get backtester object
    // you can use stopmin variable DIRECTLY HERE !!!!

The stopmin variable assigned at global level is available in entire formula after it is defined, you don't need to store it in static variables. Don't make things complicated, when they are easy.

And I strongly suggest to stay away from custom backtester, if you have trouble with absolute basics like variable scope.

2 Likes