SetCustomBacktestProc
("");
if
(Status("action") ==
actionPortfolio)
{
bo =
GetBacktesterObject(); // Get backtester object
bo.PreProcess();
// Do pre-processing
Initial_equity=bo.cash=
1000000.00;
My_total_equity=
0;
Value_open_positions=
0;
Heat=
0.1;
y=
0;
ATRmultiplier=
5;
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
// Long trades
if
(sig.IsEntry() && sig.IsLong()) // Process
long entries
{
ATRexRounded =
Foreign("~ATRExpLagRounded_"+sig.Symbol, "V"); // Get symbol's AtrExpLagRounded
array, which is simply an exp. MA of the Average True range of a given number of
days. I used a proprietary code to set the first day´s value as seed value
rather than zero, as AB´s ATR() function apparrently does.
ATRex = ATRexRounded[i];
// Reference a value in
the array
if
(i=0)
y=ATRexRounded[i];
else
if
(i>0)
y=ATRexRounded[i-
1];
}
trade.shares=
round(((Heat*bo.cash)/(y*ATRmultiplier))/250)*250; // i.e.
# of shares/contracts rounded to the nearest 250 lot and depending on the actual
cash position
sig.possize=pos_size_shares*sig.price;
// i.e.
position value, expressed in USD
bo.EnterTrade(i, sig.Symbol, True, sig.Price,
sig.PosSize);
trade.AddCustomMetric(
"initial equity", initial_equity); // to get per-trade
statistics!
trade.AddCustomMetric(
"Cash position", bo.cash);
trade.AddcustomMetric(
"Position size
[shares]",
trade.shares);
trade.AddCustomMetric(
"Position
Value",
sig.possize);
}
else
{
if
(sig.IsExit() && sig.IsLong()) // Process
long exits (cover longs)
bo.ExitTrade(i, sig.Symbol, sig.Price);
}
// Short side
if
(sig.IsEntry() && sig.IsLong()==False) // Process short entries
{
ATRexRounded =
Foreign("~ATRExpLagRounded_"+sig.Symbol, "V"); // Get symbol's AtrExpLagRounded
array
ATRex = ATRexRounded[i];
// Reference a value in
the array
if
(i=0)
{
y=ATRexRounded[i];
}
else
{
y=ATRexRounded[i-1];
}
trade.shares=round(((Heat*bo.cash)/(y*ATRmultiplier))/250)*250;
sig.possize=pos_size_shares*sig.price;
bo.EnterTrade(i, sig.Symbol, False, sig.Price, sig.PosSize);
}
else
{
if (sig.IsExit()
&& sig.IsLong()==False) // Process
(cover) short exits
bo.ExitTrade(i, sig.Symbol, sig.Price);
}
bo.HandleStops(i); // Process programmed stops or
applystop at this bar
} // End of for loop over signals at this
bar
for (trade =
bo.GetFirstOpenPos(); trade; trade = bo.GetNextOpenPos())
{ // Loop through all open positions
Value_open_positions=Value_open_positions+ trade.getprice(i,"C")*trade.shares;
trade.addCustomMetric("Value of open
positions", Value_open_positions);
My_total_equity=bo.cash+Value_open_positions;
trade.AddCustomMetric("My total
equity", My_total_equity);
} // End of for loop over trades at this
bar
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
AddToComposite( My_total_equity, "~~~My_total_equity", "X", atcFlagEnableInPortfolio |
atcFlagDefaults ); // to plot an indicator
AddToComposite( trade.shares,"~~~Position size [shares]",
"X",
atcFlagEnableInPortfolio | atcFlagDefaults );
AddToComposite( sig.possize, "~~~Position Value", "X", atcFlagEnableInPortfolio |
atcFlagDefaults );
AddToComposite( bo.cash, "~~~Cash position", "X", atcFlagEnableInPortfolio |
atcFlagDefaults );
AddToComposite( Value_open_positions, "~~~Value of open positions",
"X",
atcFlagEnableInPortfolio | atcFlagDefaults );
}