Hello Mike,
thanks from a newbie. I wasn´t aware of that.
I still have another problem:
Since I use low-level code (to be able to employ proprietary stops later on), I
need to use the signal list to exit/enter trades.
Since I want to have a per-trade output of my metrics, I need to use
trade.addcustommetric rather than bo.addcustommetric.
But when I use trade.addcustommetric in a signal list, I get an error (see code
below).
I understand the problem but don´t find a way out.
The same is true for trader.shares (see code). I need it to calculate correct
position value which is then subtracted from actual cash position to get the
new cash position after a trade.
Maybe, you can jump in once again, if you don´t mind? This whole CBI thing is
stilla little beyond me, to be homest>G<.
Thansk again
Markus
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 );
}
----- Original Message -----
From: Mike
To: [email protected]
Sent: Tuesday, July 14, 2009 8:14 PM
Subject: [amibroker] Re: Using CBI the first time
Hi,
I believe that your code says it all ;)
> } // End of for loop over trades at this bar
>
> ...
> trade.AddCustomMetric("My total equity", My_total_equity);
"trade" is null after the loop.
Mike
--- In [email protected], "Markus Witzler" <funny...@...> wrote:
>
> Hello all,
>
> I intend to create a proprietary formula for "My_total_equity" to able to
modify it later on to suit to my individual needs.
>
> Here, I_ use "Value of cash position (bo.cash) + value (all open positions
by their close)" as a start.
>
> When I run backtest, I get the following message:
>
> "Com Variable not initialized or has invalid type" though I initialized
"Value_open_positions=0" and also "My_total_equity=0;"
>
> The loop to determine the aggregate value of all open positions goes like
this:
>
> 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);
>
> } // End of for loop over trades at this bar
>
>
> My_total_equity=bo.cash+Value_open_positions;
>
> trade.AddCustomMetric("My total equity", My_total_equity);
>
> Where is the mistake? If the whole code is required, please let me know.
>
> Thanks
>
> Markus
>