Markus,
If you haven't already, it would be a good idea to read
"AmiBroker Custom Backtester Interface.pdf" found in the files section of this
group.
The way your code is now, you are trying to mix and match
signals with trades, which is not permitted.
A signal does not become a
trade until *after* the signal has been processed by the backtester. There are
a number of portfoliio restrictions that may prevent a signal from actually
being accepted and made into a trade. For example, you may not have sufficient
funds, you may have exceeded the number of allowable open positions,
etc.
You need to set the position size on the Signal object. If the
signal becomes a trade, that is what will later dictate the Trade object's
shares. Note that a Signal's PosSize property can be expressed as a percetage
of equity (negative) or as a dollar amount (positive). Do the math and use a
positive number to control the number of shares (e.g. number of shares desired
multiplied by share price, remember to take into account commisions if you use
them).
You will not have bar by bar access to the trade list as you do
with signals. Therefore, you must determine the bar index of the trade based
on its entry date then use Foreign to reference the bar by bar data using the
bar index for that date. An example of this approach can be seen in a similar
post that I made a short while ago:
http://finance.groups.yahoo.com/group/amibroker/message/139969
As
for your custom trade metrics. I don't see a need for showing the number of
shares since this is already provided by AmiBroker in the backtest report.
Also, since Signal.PosSize ultimately ends up being the same as Trade.Shares,
this information is also already there. As for the cash position prior to the
trade, that would be available as the Low in ~~~Equity for the bar prior to
the bar of the trade as outlined in this message:
http://finance.groups.yahoo.com/group/amibroker/message/139634
Hope
that helps.
Mike
--- In amibroker@xxxxxxxxxps.com,
"Markus Witzler" <funnybiz@xx.> wrote:
>
> 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: amibroker@xxxxxxxxxps.com
> 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 amibroker@xxxxxxxxxps.com,
"Markus Witzler" <funnybiz@> 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
>
>
>