Exiting one bar before the signal

my logic is if shares in open position is equal to one after scaling out then exit the trade. But it seems the position is exited one bar BEFORE the signal. I saw a similar thread where the position was exited one bar after.

for( sig = bo.GetFirstSignal( i ); sig; sig = bo.GetNextSignal( i ) )
        {
      
            if( MaxLossPerDayLimitHit )
            {
                if( sig.IsEntry() || sig.IsScale() )
                {
                    sig.Price = -1;
                    //_TRACE( "MaxLossPerDayLimit Hit loss for the day exceeded "+MaxLossPerDayLimit+". No Nore Trading For The Day. Signal for instrument " + sig.Symbol + " IGNORED on " + formatedDateTime );
                }
            }
            else
            {
                if( sig.Type == 6 )//if scaleout
                {
                    
                    openPosition = bo.FindOpenPos( sig.Symbol ); // Check for open position in stock

                    if( openPosition )
                    {
                        scaleoutid = StaticVarGet( openPosition.Symbol + chartid + "scaleoutid" );
						soutQty=soutMoneyValue=0;
                        openQty=openPosition.Shares;                    
                                                                   
                        for (j=1;j<=9;j++)
                        {
                        //scaleOutQTYAsPercentageOfOpenPosition1AtThisBar, scaleOutPrice1AtThisBar
                        sprcnt=StaticVarGet(openPosition.Symbol + chartid + "scaleOutQTYAsPercentageOfOpenPosition"+j+"AtThisBar");
                        sprice=StaticVarGet(openPosition.Symbol + chartid + "scaleOutPrice"+j+"AtThisBar");
                        qtyForThisSOut=round(openQty * sprcnt[i]/100);
                        soutMoneyValue=soutMoneyValue + qtyForThisSOut * sprice[i];
                        soutQty=soutQty+qtyForThisSOut;
                        openQty=openQty-qtyForThisSOut;
                        }   _TRACE("openQty="+openQty+", dateTime() = "+formatedDateTime);                                             
                        if (openQty==1)
                        {                       
                        //if only 1 share is left then instead of scaleOut just exit
                        bo.ExitTrade(i, openPosition.Symbol, sig.Price, 1);                        
                        }
                        else
                        {
                        sig.PosSize = soutMoneyValue;//round(soutQty); 
                        sig.Price = soutMoneyValue/soutQty;
                        }
                    }
                }

            }
        }  bo.ProcessTradeSignals( i );  

First the code is not complete runable formula. To help others to help you provide a working code.

Secondly, make sure you are not using Ref() on Buy/Sell/Short/Cover arrays as this effectively will shift signals (again this is guessing as no complete code was provided)

Thirdly. go to the Settings and set trade delays to zero.

Lastly:
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?

In short: Put _TRACE in your code and use Detailed log report mode.

  1. TradeDelays is set to 0.
  2. not using Ref() on Buy/Sell/Short/Cover arrays
  3. The _Trace prints correct time. I have added _TRACE("openQty="+openQty+", sig.Type="+sig.Type+", dateTime() = "+formatedDateTime); after bo.exitTrade().

But somehow the trade is exiting one bar BEFORE the signal. Everything else works perfectly. But When I add bo.ExitTrade() it behaves this way.

I am not able to post working code because It is somewhat hard for me to create a sample code that has scaleout signals. But I am sure the problem is in the code section I posted.

I made some changes such that before scaleout if the quantity remaining after scaleout is going to be less than equal to 1 than scaleout everything. so if a signal comes in to scaleout 9 out of 10 shares than scaleout all 10. but now commission is wrongly charged for redundant scaleout and cover signals. see the code below

 bo = GetBacktesterObject(); // Get backtester object
    //bo.Backtest( True ); // Run backtests with no trade listing
    bo.PreProcess();
    stat = bo.GetPerformanceStats( 0 ); // Get Stats object for all trades
    cumprofit = 0;
    cumPAT = 0;
    dt = DateTime();
    thisBarDate = DateTimeConvert( 0, dt );
    MaxLossPerDayLimitHit = 0;
    //formatedDateTime = 0;
    //mw_base_tf_multiplier=StaticVarGet( trade.Symbol + chartid + "mw_base_tf_multiplier");
    tfMultiplier = round( timeIntervalChartInSecondsSelectedByUser / Interval() );
    loopCounterStartValue = BarCount - round( BarCount / mw_base_tf_multiplier ); //BarCount - round(BarCount/tfMultiplier);
    CapitalAtStartOfDay = bo.Equity;

    for( i = 0; i < BarCount; i++ )
    {
        formatedDateTime = DateTimeFormat( "%d-%m-%Y %H:%M:%S", dt[i] );

        if( i == 0 )
            isNewDay = true;
        else
            isNewDay = thisBarDate[i] != thisBarDate[i - 1];

        if( isNewDay )
        {
            // Note that CapitalAtStartOfDay is a scalar, not an array
            CapitalAtStartOfDay = bo.Equity;

        }


        MaxLossPerDayLimit = CapitalAtStartOfDay * maxLossPerDayLimitAsPercentageOfDayStartCapital / 100;
        MaxLossPerOpenPositionLimit = CapitalAtStartOfDay * maxLossPerTradeLimitAsPercentageOfDayStartCapital / 100;
        equityAtThisBar = bo.Equity;
        PortfolioLossForTheDay = CapitalAtStartOfDay - equityAtThisBar;
        MaxLossPerDayLimitHit = PortfolioLossForTheDay > MaxLossPerDayLimit;

        if( isNewDay )
        {

            _TRACE( "New Day " + formatedDateTime + ", CapitalAtStartOfDay=" + CapitalAtStartOfDay + ", equityAtThisBar=" + equityAtThisBar + ", MaxLossPerOpenPositionLimit=" + MaxLossPerOpenPositionLimit + ", MaxLossPerDayLimit=" + MaxLossPerDayLimit );
        }

        //_TRACE( "MaxLossPerDayLimitHit=" + MaxLossPerDayLimitHit + ", CapitalAtStartOfDay=" + CapitalAtStartOfDay + ", equityAtThisBar=" + equityAtThisBar + ", MaxLossPerDayLimit=" + MaxLossPerDayLimit +", MaxLossPerOpenPositionLimit="+MaxLossPerOpenPositionLimit+", formatedDateTime="+formatedDateTime);

        //et=symb=pr=0;

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

            if( MaxLossPerDayLimitHit )
            {
                if( sig.IsEntry() || sig.IsScale() )
                {
                    sig.Price = -1;
                    //_TRACE( "MaxLossPerDayLimit Hit loss for the day exceeded "+MaxLossPerDayLimit+". No Nore Trading For The Day. Signal for instrument " + sig.Symbol + " IGNORED on " + formatedDateTime );
                }
            }
            else
            {
                if( sig.Type == 6 )//if scaleout
                {

                    openPosition = bo.FindOpenPos( sig.Symbol ); // Check for open position in stock

                    if( openPosition )
                    {
                        scaleoutid = StaticVarGet( openPosition.Symbol + chartid + "scaleoutid" );
                        soutQty = soutMoneyValue = 0;
                        openQty = openPosition.Shares;

                        /*
                        if (openQty==1)
                        {
                        //if only 1 share is left then instead of scaleOut just exit
                        bo.ExitTrade(i, openPosition.Symbol, sig.Price, 1);
                        }
                        else
                        {  */
                        for( j = 1; j <= 9; j++ )
                        {
                            //scaleOutQTYAsPercentageOfOpenPosition1AtThisBar, scaleOutPrice1AtThisBar
                            sprcnt = StaticVarGet( openPosition.Symbol + chartid + "scaleOutQTYAsPercentageOfOpenPosition" + j + "AtThisBar" );
                            sprice = StaticVarGet( openPosition.Symbol + chartid + "scaleOutPrice" + j + "AtThisBar" );
                            qtyForThisSOut = round( openQty * sprcnt[i] / 100 );
                            //_TRACE("sprcnt="+sprcnt+", soutQty="+soutQty+", openQty="+openQty);
                            openQty = openQty - qtyForThisSOut;

                            if( openQty <= 1 )
                            {
                                qtyForThisSOut = qtyForThisSOut + openQty;
                                openQty = 0;
                                _TRACE( "exit trade if openqty<=1 triggered for symbol " + openPosition.Symbol + ", openQty=" + openQty + ", sig.Type=" + sig.Type + ", dateTime() = " + formatedDateTime );
                            }

                            soutMoneyValue = soutMoneyValue + qtyForThisSOut * sprice[i];
                            soutQty = soutQty + qtyForThisSOut;
                        }

                        sig.PosSize = soutMoneyValue;//round(soutQty);
                        sig.Price = soutMoneyValue / soutQty;
                    }
                }

            }
        }

        bo.ProcessTradeSignals( i );
    bo.PostProcess();
    //bo.ListTrades(); // Generate list of trades

This topic was automatically closed 100 days after the last reply. New replies are no longer allowed.