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 > > > > > >
