When running a backtest of a simple "system" I get cash and equity which doesn't make sense to me. I would assume that cash is what is left in the account subtracting the value of open positions. Running the backtest for the following "system":
RoundLotSize = 1;
InitialEQ = 100000;
MaxPositions = 1;
PercentEquityPositionSize = 100;
SetBacktestMode(backtestRegular);
SetTradeDelays(1, 1, 1, 1);
SetOption("allowsamebarexit", False);
SetOption("AllowPositionShrinking", True);
SetOption("initialequity", InitialEQ);
SetOption("MaxOpenPositions", MaxPositions);
//SetOption("CommissionMode", 0); //SET IN BACKTESTER YOUR APLICABLE COMISSIONS
SetOption("MinShares", 1);
SetPositionSize(PercentEquityPositionSize, spsPercentOfEquity); //COMMENT OUT IF YOU WANT COMPOUNDING
SetOption("AccountMargin", 1); //CHANGE IF YOU WANT TO USE MARGIN
SetOption("HoldMinBars", 1);
SetFormulaName("TestEquityAndCash");
Buy = Sell = Short = Cover = 0;
BuyPrice = SellPrice = ShortPrice = CoverPrice = O;
//ThisIsLastBar = BarIndex() == LastValue( BarIndex() );
// Divergence
bull1 = C > MA(C, 200);
cum1 = Ref(RSI(2), -1) + RSI(2);
// Rules
Buy = cum1 < 10;// and bull1 AND Open > 5 AND MA(V, 100) > 250000;
Sell = cum1 > 50; // OR ThisIsLastbar;
BuyPrice = Open;
SellPrice = Open;
SetCustomBacktestProc( "" );
if ( Status( "action" ) == actionPortfolio ) {
resultsFolder = "C:\\tmp\\";
positionsCSVFileName = "Positions.csv";
fh = fopen(resultsFolder + positionsCSVFileName, "w");
if (fh) {
dt = DateTime();
bo = GetBacktesterObject(); // Get backtester object
bo.PreProcess(); // Do pre-processing (always required)
for ( i = 0; i < BarCount; i++ ) { // Loop through all bars
bo.ProcessTradeSignals( i ); // Process trades at bar (always required)
fputs(NumToStr(dt[i], formatDateTime) + "," + "CASHPOSITION" + "," + StrFormat("%1.5f", bo.Cash) + "\n", fh);
fputs(NumToStr(dt[i], formatDateTime) + "," + "EQUITY" + "," + StrFormat("%1.5f", bo.Equity) + "\n", fh);
for ( openpos = bo.GetFirstOpenPos(); openpos; openpos = bo.GetNextOpenPos() ) {
// openpos variable now holds Trade object - you can query it
if (IsTrue(openpos.IsOpen)) {
multiplier = 1;
if (IsTrue(openpos.IsLong)) {
multiplier = 1;
} else {
multiplier = -1;
}
fputs(
NumToStr(dt[i], formatDateTime) + "," +
openpos.Symbol + "," +
StrFormat("%1.5f", multiplier*openpos.GetPositionValue()) +
"\n"
, fh);
}
}
} // End of for loop over bars
bo.PostProcess(); // Do post-processing (always required)
fclose(fh);
}
}
eqname = "~~~EQUITY";
if( Name() == eqname ) {
eq = Foreign( eqname, "Close", FixUp=1 );
Cash = Foreign( eqname, "Low", FixUp=1 );
ret = Nz((eq - Ref(eq, -1))/Ref(eq, -1));
resultsFolder = "C:\\tmp\\";
returnEquityCashCSVFileName = "ReturnEquityCash.csv";
includeHeader = True;
fh = fopen(resultsFolder + returnEquityCashCSVFileName, "w");
if (fh) {
y = Year();
m = Month();
d = Day();
if (includeHeader) {
fputs("Date,Return,Equity,Cash\n", fh);
}
for( i = 0; i < BarCount; i++ )
{
if (eq[i] > -100000000) {
fputs(StrFormat("%02.0f-%02.0f-%02.0f,", y[ i ], m[ i ], d[ i ] ) + StrFormat("%02.8f,", ret[i]) + StrFormat("%02.2f,", eq[i]) + StrFormat("%02.2f\n", Cash[i]), fh);
}
}
fclose(fh);
}
}
I get the following "result" for "Positions.csv"
22/02/2023,CASHPOSITION,100000.00000
22/02/2023,EQUITY,100000.00000
23/02/2023,CASHPOSITION,99000.10156
23/02/2023,EQUITY,99773.40625
23/02/2023,SPY,99763.09375
24/02/2023,CASHPOSITION,99000.10156
24/02/2023,EQUITY,98707.68750
24/02/2023,SPY,98697.37500
27/02/2023,CASHPOSITION,99576.70312
27/02/2023,EQUITY,99576.70312
28/02/2023,CASHPOSITION,99576.70312
28/02/2023,EQUITY,99576.70312
and for "ReturnEquityCash.csv"
Date,Return,Equity,Cash
2023-02-22,0.00000000,100000.00,100000.00
2023-02-23,-0.00226594,99773.41,99000.10
2023-02-24,-0.01068139,98707.69,99000.10
2023-02-27,0.00880393,99576.70,99576.70
2023-02-28,0.00000000,99576.70,99576.70
To me this doesn't seem right. Cash should be very small.
What am I not understanding here?
Thanks.