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 );
}