Using Custom Backtester. Script finds correct trades but Profit in Analysis window prints negative but is really positive

Hello,

Enclosed is a shorting script using the custom backtester. The script finds the trades based on Short = HHV(H,2) and makes a 5% limit order for tomorrow. Exit when cross below MA(C,5); Maximum of 3 open positions. All trade entry and exit points are found correctly. If there are too many trades the script sorts all incoming trades and takes the top HV100 scored trades to fill in remaining slots. This part all seems to work.

The problem: In the Analysis window output the Profit is opposite polarity of what it should be. Even when the short entry is bigger than cover exit the Profit is negative in the Analysis window. However, the percent change is shown correctly as negative. Could someone please identify the error in my ways? Thank you in advance. I suspect lines 42 and 53 but not sure what to change.

type or paste code here// 
// 
// 
// 

NumPos = 3;
RoundLotSize=1;
SetOption( "MaxOpenPositions", NumPos);
SetTradeDelays(0,0,0,0);

//PositionSize = -100/NumPos;

DollarValue= 1000;
PositionSize = DollarValue;

HV100 = 100* StDev(log(C/Ref(C,-1)),100)*sqrt(252);

SetBacktestMode( backtestRegularRaw);
PositionScore = HV100;

SetCustomBacktestProc( "" );

OutputFileName = "myoutput15.txt";

if ( Status ( "action" ) == actionPortfolio )
{
	bo = GetBacktesterObject();
	bo.PreProcess();
	dt = DateTime();
	rh=fopen(OutputFileName, "w");
	fputs( "Symbol, Price,  Score\n", rh);
	for ( bar = 0; bar < BarCount; bar++ )
	{
		strdt = DateTimeToStr( dt[bar]);
		Line = "\nDate : " + strdt + " NumOpenPos = " + bo.GetOpenPosQty() + "\n";
		_TRACE( Line);
		fputs( Line, rh);
		
		
		for (sig = bo.GetFirstSignal( bar ); sig; sig = bo.GetNextSignal( bar ))
		{  // loop through all signals at this bar
			if ( sig.IsExit() && !sig.IsLong() && bo.FindOpenPos(sig.Symbol) ) //Process long exits
			// ^^^^^^^^^^^^^^^^^^^ sig.IsLong() used in other codes
				{
					bo.ExitTrade( bar, sig.Symbol, sig.Price);
					Line2 = "ExitSignal : " + sig.Symbol + " " + sig.Price + " NumOpenPos=" + bo.GetOpenPosQty() + "\n";
					fputs( Line2, rh);
				}
		}
		QtyPos = bo.GetOpenPosQty();
		for (sig = bo.GetFirstSignal( bar ); (sig && (QtyPos<NumPos)); sig = bo.GetNextSignal( bar ))
		{  // loop through all signals at this bar	
			if (sig.IsEntry() && !sig.IsLong() && IsNull(bo.FindOpenPos(sig.Symbol)) ) 
			// ^^^^^^^^^^^^^^^^^^^ sig.IsLong() used in other codes
			{//Process long entries, no multiple Positions! 
				symbolHigh = StaticVarGet( sig.Symbol + "High");
				symbolShortLimitPrice = StaticVarGet( sig.Symbol + "ShortLimitPrice");
				if (symbolHigh[bar] > symbolShortLimitPrice[bar]) // Is High of day greater than ShortLimitPrice ?
				{
					bo.EnterTrade(bar, sig.Symbol, True, sig.Price, sig.PosSize);
					Line1 = "EntrySignal : " + sig.Symbol + " " + sig.Price + " " + "   " + sig.PosScore + " H=" + symbolHigh[bar] + " ShortLimitPrice=" + symbolShortLimitPrice[bar] + "\n";
					// ^^^^^^^^^^^^^^^^^^^ WHY IS sig.PosScore NEGATIVE is this code but positive in the long codes?? SORTS PROPERLY!
					fputs( Line1, rh);
				}
				QtyPos++;
			}
		}  // End of for loop over signals at this bar
		bo.HandleStops(bar); // Handle programmed stops at this bar
		
		//for (trade = bo.GetFirstOpenPos(); trade; trade = bo.GetNextOpenPos() ) //scalein
		//{ // loop throug all open positions
		//	if (trade.GetProfit() >= trade.GetEntryValue() ) // if time to scale-in
		//	{
		//		scaleSize = trade.GetEntryValue() / 2; //scale in the trade
		//		bo.ScaleTrade( bar, trade.Symbol, True, trade.GetPrice(bar, "C"), scaleSize);
		//	}
		//} // end of loop over trades at this bar
		bo.UpdateStats(bar, 1); // update MAE/MFE stats for bar
		bo.UpdateStats(bar, 2); // update stats at bar's end
	} //End of for loop over bars
	bo.PostProcess(); //Do Post-processing
	fclose(rh);
}	

LimitOrder = 4;
HHighs = 6;
 
HV100 = StDev(log(C/Ref(C,-1)),100)*(252^.5)*100; 

Setup = H == HHV(H, 2);

Lmt = LimitOrder; 
ShortLimitPrice = Ref(C,-1)*(1+Lmt/100);
ShortReal = Ref(Setup, -1) AND (H > ShortLimitPrice);
ShortPrice = Max(Open, ShortLimitPrice); 		

Short = ShortReal;

StaticVarSet(Name() + "ShortLimitPrice", ShortLimitPrice);
StaticVarSet(Name() + "High", H);

////////////////////////////////////////////////////////////////////////////////
// Cover Rules

FCross = C < MA(C,5);
Cover = Ref(FCross, -1) AND (BarsSince(Short) > 0); 
CoverPrice = Open;


Cover=ExRem(Cover, Short);
InPos = Flip(Short, Cover);




/////////////////////////////////////////////////////////////////////////////////

Thank you for your help


Rob

@robertcravens

take a look at this line of your code (I added the comment)

        // You are entering LONG....  3rd param should be FALSE
		bo.EnterTrade(bar, sig.Symbol, True, sig.Price, sig.PosSize); 

From the Porfolio Backtester Interface Reference Guide:

long EnterTrade ( long Bar, string Symbol, bool bLong, float Price, float PosSize, [optional] variant PosScore, [optional] variant RoundLotSize, [optional] variant MarginDeposit, [optional] variant TickSize, [optional] variant PointValue )

(By the way, this was also visible looking at the "Trade" column of the Backtest report).

3 Likes

Thank you! That fixed the issue.

Rob

1 Like