Calling equity() function in chart

I'm trying to run a simple backtest with the Equity() function inside a chart. The array returned by Equity() is constant as if no trades are ever taken. What am I doing wrong?

// Run backtest over the visible date range.
// Return the cumulative annual return.
function Backtest(buyArray, sellArray)
{
  firstVisibleBarIndex = Status("FirstVisibleBarIndex");
  lastVisibleBarIndex = Status("LastVisibleBarIndex");
  fromIndex = firstVisibleBarIndex;
  toIndex = Min(BarCount - 1, lastVisibleBarIndex);

  dateNumArray = DateNum();
  fromDate = dateNumArray[fromIndex];
  toDate = dateNumArray[toIndex];

  Short = Cover = 0;
  Buy = buyArray;
  Sell = sellArray;
  SetPositionSize(100, spsPercentOfEquity);
  eq = Equity(1, 3, fromDate, toDate);

  plot(eq, "eq", colorRed, StyleOwnScale);

  numBars = toIndex - fromIndex + 1;
  car = 100.0 * ((eq[toIndex] / eq[fromIndex]) ^ (252.0 / numBars) - 1);

  dt = DateTime();
  str = "";
  str += DateTimeFormat("%Y%m%d", dt[fromIndex]) + "-" + DateTimeFormat("%Y%m%d", dt[toIndex]);
  str += " fromIndex=" + fromIndex + " toIndex=" + toIndex;
  str += " eq[" + fromIndex + "]=" + eq[fromIndex] + " eq[" + toIndex + "]=" + eq[toIndex];
  str += " CAR=" + car;
  _Trace(str);

  return car;
}


ticker = ParamStr("Ticker", "$SPX");
SetForeign(ticker, True, True);
ma150 = MA(C, 150);
car = Backtest(C >= ma150, C < ma150);
RestorePriceArrays();

The trace output looks like this:

20040202-20180212 fromIndex=4187 toIndex=7719 eq[4187]=200000 eq[7719]=200000 CAR=0

Buy/Sell/Short/Cover must be global as Equity() reads global variables. If they are not used outside Backtest function before, they must be explicitly declared global

function Backtest(...)
{
  global Buy, Sell, Short, Cover; // required by Equity()
...
} 

@Tomasz Yes, that works now. Thank you very much for catching my mistake.

1 Like

Hi @Steve,
Thank you for your code. I'm trying to produce the Equity plot by using the code as below, but not in a function as you do:

firstVisibleBarIndex = Status("FirstVisibleBarIndex");
lastVisibleBarIndex = Status("LastVisibleBarIndex");
fromIndex = firstVisibleBarIndex;
toIndex = Min(BarCount - 1, lastVisibleBarIndex);

dateNumArray = DateNum();
fromDate = dateNumArray[fromIndex];
toDate = dateNumArray[toIndex];

Short = Cover = 0;
Buy = buyArray;
Sell = sellArray;
SetPositionSize(100, spsPercentOfEquity);
eq = Equity(1, 3, fromDate, toDate);

plot(eq, "eq", colorRed, StyleOwnScale);

However, I've got error on this line:

toDate = dateNumArray[toIndex];

Error 10: Array subscript out of range. You must not acces array elements outside 0,,,(BacCount-1). You attempted to access non-existing -1st element of array.

Broker_2018-02-21_15-38-06

It's something to do with lastVisibleBarIndex. The error disappear when I changed the previous line as below:

toIndex = Min(BarCount - 1, lastVisibleBarIndex); //error

//change to 

toIndex = BarCount - 1; //no error

Do you happen to experience it?

@bursaware I did not observe negative lastVisibleBarIndex, but I did notice values greater than (BarCount-1). I'm not sure how either of those conditions could happen. Maybe @Tomasz can clarify what's happening.

firstvisiblebarindex lastvisiblebarindex may include right blank margin area of chart! They do not stop at barcount-1. So for example if you enter that area via zoom in at the end of chart or multiple times pressing END key (so only blank area is visible) then your subscript (i.e. [toIndex] ) goes outside of barcount-1 because toindex becomes larger (barcount-1+number of blank bars). That is why you get error.

Instead just use

FirstVisibleValue(bi);
LastVisibleValue(bi);

They do not exceed Barcount-1

So,

function Backtest(buyArray, sellArray)
{
	global Buy, Sell, Short, Cover; // required by Equity()
	
	bi = BarIndex();
	fromIndex = Nz(FirstVisibleValue(bi));
	toIndex = Nz(LastVisibleValue(bi));

	dateNumArray = DateNum();
	fromDate = dateNumArray[fromIndex];
	toDate = dateNumArray[toIndex];

	Short = Cover = 0;
	Buy = buyArray;
	Sell = sellArray;
	SetPositionSize(100, spsPercentOfEquity);
	eq = Equity(1, 3, fromDate, toDate);

	plot(eq, "eq", colorRed, StyleOwnScale);

	numBars = toIndex - fromIndex + 1;
	car = 100.0 * ((eq[toIndex] / eq[fromIndex]) ^ (252.0 / numBars) - 1);

	dt = DateTime();
	str = "";
	str += DateTimeFormat("%Y%m%d", dt[fromIndex]) + "-" + DateTimeFormat("%Y%m%d", dt[toIndex]);
	str += " fromIndex=" + fromIndex + " toIndex=" + toIndex;
	str += " eq[" + fromIndex + "]=" + eq[fromIndex] + " eq[" + toIndex + "]=" + eq[toIndex];
	str += " CAR=" + car;
	_Trace(str);

	return car;
}
5 Likes

Thanks @fxshrat and @Steve for code and explanation.

As advised by @fxshrat, using this mitigates the errors:

FirstVisibleValue(bi);
LastVisibleValue(bi);