Markus,

To simplify your life, start first by not using any commissions in your 
backtest (see Settings of Auto Analysis window). Then do as you have outlined; 
set the position size to the Signal.Price multiplied by the number of shares 
desired. You definitely do not want to work with either trade list, that's too 
late - the trade has already taken place.

If you have any rounding issues, post your formula here, or send it  to support 
and they can help clarify for you.

Mike

--- In [email protected], "Markus Witzler" <funny...@...> wrote:
>
> Hi Mike,
> 
> thanks loads for your thorough explanations!
> 
> I´ll need to digest what you wrote but I´m still a little confused. I had 
> read the pdf you mentioned a couple of weeks ago but as it turns out 
> completely misunderstood!
> 
> I don´t understand how I make sure that exactly the number of shares is being 
> bought that I want (whatever amount of money that means)? If I specify 
> sig.possize in signal loop (which implies a given number shares?!), this 
> could maybe (in some cases) result - due to rounding issues- in a slightly 
> differing number of shares, right (I don´t know how AB rounds up or down)? 
> Buying/selling the exact number of shares is crucial for my purposes!
> 
> So, where do I do that? The closed trade list probably is not the right spot 
> to determine # of shares since the trades already have been closed. The open 
> trade list probably not as well since there the trades already have been 
> initiated, right? And in signal list, I can only specify the position size in 
> terms of money rather than the  number of shares, even if I did it like this:
> sharesize=round(((Heat*bo.cash)/(y*ATRmultiplier))/250)*250; // i.e. # of 
> shares/contracts
> 
> sig.possize=sharesize*sig.price;     // i.e. position value in terms of USD
> 
> The other issue you mentioned (determening a trade´s bar number) needs to 
> wait until I have understood this issue - but it sounds somehat complicated...
> 
> Sorry for my ignorance!
> 
> Markus
> 
> 
>   ----- Original Message ----- 
>   From: Mike 
>   To: [email protected] 
>   Sent: Wednesday, July 15, 2009 4:40 AM
>   Subject: [amibroker] Re: Using CBI the first time
> 
> 
> 
> 
> 
>   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 [email protected], "Markus Witzler" <funnybiz@> 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: [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" <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
>   > >
>   >
>


Reply via email to