[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[amibroker] Re: Support Issues



PureBytes Links

Trading Reference Links

Mark,

Yes, I agree. Which is exactly why I was attempting to remove all ambiguity before moving further.

I will need to find the time to go through it all once more in light of the comments to this thread.

But, I believe that I now sufficiently understand the behavior of UpdateStats with each of the values 0,1,2.

Of particular interest to me was the UpdateStats interaction with UsePrevBarEquityForPosSizing. Given that I use limit orders on End Of Day data, all my position sizing is calculated on the previous bar's equity (i.e. based on today's close for tomorrow's market).

With respect to HandleStops, my initial experiments all failed to reconcile with the default backtester, which is what caused me to go down the road of doing it all myself in the exit handling. I suspect that if I now backtrack and add the same conditional logic around HandleStops (i.e. checking for ActivateStopsImmediately) as I did with my exit loops, then that will put that question to rest.

Those two adjustments will go a long way to allowing me to truly focus on the setting of a position size, as opposed to having to spend so much time trying to get the correct template with which to properly handle interactions with the AA window settings.

As for _TRACE. Absolutely, I am a heavy user of that facility. In the end, it was the trace statements included in my sample that allowed me to compare my incremental equity/cash positions to the detailed log results of the default backtest scenario.

Mike

--- In amibroker@xxxxxxxxxxxxxxx, Mark Hike <markhike@xxx> wrote:
>
> Mike:
> 
> Based on my experience, the low level CBT is quite tricky. Because of its
> complexity, the document can only give you something to start with.
> For example, where you put HandleStops() would affect how it behaves.
> 
> I used a lot of _TRACE() in the code and figured out the things after many
> experiments.
> 
> But it is more than worthy of the time spent! CBT is the most powerful
> backtest engine you can have in the market. I have constructed some
> quantitative systems which can not otherwise be tested anywhere else.
> 
> 
> - Mark
> 
> 
> On Mon, Sep 21, 2009 at 8:24 AM, sfclimbers <sfclimbers@xxx> wrote:
> 
> >
> >
> > I received the message from support. Thank you.
> >
> > As to your comment
> >
> > "Low-level custom backtester interface is solely for advanced programmers
> > who want to implement/experiment with *their own* backtest methodologies
> > completely *different* than built-in one,
> > and comes without hand-holding."
> >
> > If 20 years of professional software development doesn't qualify me as an
> > advanced programmer, then I don't know what will.
> >
> > If we can't measure our assumptions against a known benchmark (i.e.
> > reproduce the built in behavior), then it becomes much more difficult to
> > determine whether we are using the API correctly.
> >
> > Anyway, your position is clear. I'll work out the rest on my own.
> >
> > Mike
> >
> > --- In amibroker@xxxxxxxxxxxxxxx <amibroker%40yahoogroups.com>, "Tomasz
> > Janeczko" <groups@> wrote:
> > >
> > > Hello,
> > >
> > > You received the answer via support channel.
> > >
> > > With regards to UpdateStats it is documented quite clearly
> > > http://www.amibroker.com/guide/a_custombacktest.html
> > >
> > > Quote from docs:
> > > "UpdateStats( long Bar, long TimeInsideBar )
> > >
> > > Low-level method that updates equity, exposure, trade excursions (for
> > MAE/MFE calculations) and other internal variables required for correct
> > calculation of statistics. You must NOT use this function in high-level and
> > mid-level approaches. TimeInsideBar parameter specifies intraday time
> > position.
> > >
> > > TimeInsideBar = 0 means opening of the bar,
> > > TimeInsideBar = 1 means middle of the bar,
> > > TimeInsideBar = 2 means end of bar.
> > >
> > > As certain internal calculations depend on end-of-bar calculations, this
> > method must be called once and only once with TimeInsideBar parameter set to
> > 2 at the end of processing of every bar inside in your custom backtesting
> > loop. May be called zero or more times for every bar inside backtesting loop
> > with TimeInsideBar parameter set to 0 (zero) or 1."
> > >
> > > Whenever you need to read/use any stats (including portfolio equity) on
> > open/in the middle/end of bar you should call UpdateStats with corresponding
> > value. That's all.
> > >
> > > The same goes with HandleStops.
> > > Quote from docs:
> > > "HandleStops( long Bar )
> > >
> > > This low-level method handles automatic stops (applystops). This method
> > MUST NOT be used in high-level and mid-level approaches. In low-level mode
> > you should call this method once for each bar inside trading loop."
> > >
> > > Low-level custom backtester interface is solely for advanced programmers
> > who want to implement/experiment with *their own* backtest methodologies
> > completely *different* than built-in one,
> > > and comes without hand-holding.
> > >
> > > Best regards,
> > > Tomasz Janeczko
> > > amibroker.com
> > > ----- Original Message -----
> > > From: Mike
> > > To: amibroker@xxxxxxxxxxxxxxx <amibroker%40yahoogroups.com>
> > > Sent: Monday, September 21, 2009 1:40 PM
> > > Subject: [amibroker] Re: Support Issues
> > >
> > >
> > >
> > >
> > >
> > > Unfortunately, no. None of my questions are answered by this otherwise
> > excellent document (which I have already read many times).
> > >
> > > Perhaps my questions were not clearly expressed in the help request. But
> > basically I want to know:
> > >
> > > 1.. When should we use bo.UpdateStats(bar, 0)
> > > 2.. When should we use bo.UpdateStats(bar, 1)
> > > 3.. When should we use bo.UpdateStats(bar, 2)
> > > 4.. When should we use bo.HandleStops(bar)
> > > The author of the document that you pointed to seemed equally confused.
> > When describing usage of UpdateStats he says:
> > >
> > > "The AmiBroker help is a little vague on how the TimeInsideBar parameter
> > works"
> > >
> > > He then goes on to say:
> > >
> > > "why it would be called with the value set to zero or more than once, I'm
> > not sure."
> > >
> > > In other words, he had the exact same questions that I have now. Further,
> > after much experimentation, I must question his conclusions on when and
> > where to use HandleStops(), at least as it applies to more recent versions
> > of AmiBroker.
> > >
> > > I have put togeather a sample Optimization, below, for a "percent of
> > equity" position sizing that runs once for each of:
> > >
> > > 1.. default high level AmiBroker backtester
> > > 2.. low level backtester template described in the UKB document that you
> > pointed to
> > > 3.. low level backtester using my own best guess at how these calls
> > should be made.
> > > If you (or anyone else) run it, you will see that my own best guess
> > appears to match the default AmiBroker behavior. The UKB template (as I've
> > understood it) does not match at all. I would like to get confirmation (or
> > correction) that my conclusions are accurate. My conclusions are spelled out
> > as comments in the code.
> > >
> > > For the purposes of this example, I am running a Long only strategy,
> > using AmiBroker version 5.26.5 beta, Norgate Premium Data for the period Jan
> > 1/08 - Dec 31/08 on a watchlist containing:
> > >
> > > a.. AAPL
> > > b.. IBM
> > > c.. ORCL
> > > d.. MSFT
> >
> > > I am exagerating the position size to force scenarios where we run out of
> > cash. The script can also be Backtested with default optimization argument
> > set to 3 in order to see _TRACE statements in an AA Window "Detail Log"
> > style report of the sfclimbers trades.
> > >
> > > Here is the code:
> > >
> > > // Simplify the example by disabling most of the variables that effect
> > > // position size when expressed as a percentage of equity.
> > >
> > > SetOption("AccountMargin", 100);
> > > SetOption("AllowPositionShrinking", false);
> > > SetOption("CommissionMode", 2);
> > > SetOption("CommissionAmount", 0);
> > > SetOption("InterestRate", 0);
> > > SetOption("MinShares", 1);
> > > SetOption("MinPosValue", 0);
> > >
> > > // These two options have a direct impact on low level backtest,
> > > // far beyond what was covered in the otherwise excellent UKB document.
> > > // Run this optimization once for each of the 4 combinations of these two
> >
> > > // options using a watchlist of AAPL, IBM, ORCL, MSFT from 1/1/08 -
> > 12/31/08.
> > >
> > > SetOption("UsePrevBarEquityForPosSizing", true);
> > > SetOption("ActivateStopsImmediately", true);
> > >
> > > // Simple random entry followed by N-bar stop.
> > >
> > > SetOption("InitialEquity", 500000.00);
> > > SetTradeDelays(0, 0, 0, 0);
> > > SetPositionSize(33, spsPercentOfEquity);
> > >
> > > Buy = Random(13000) > 0.5;
> > > BuyPrice = Open;
> > > Sell = 0;
> > > ApplyStop(stopTypeNBar, stopModeBars, 3, 0);
> > >
> > > // Use optimizer to generate output for each of default AB, UKB and
> > > // sfclimbers speculation. At a minimum it will illustrate that the
> > > // UKB article is incomplete and/or out of date. Whether or not the
> > > // sfclimbers conclusions are correct is the subject of this help
> > request!
> > >
> > > custom = Optimize("Custom", 3, 1, 3, 1);
> > > SetCustomBacktestProc("");
> > >
> > > if (Status("action") == actionPortfolio) {
> > > maxPosition = 0.33; // Must match call to SetPositionSize above
> > > marginMultiplier = 100 / GetOption("AccountMargin");
> > > usePreviousBar = GetOption("UsePrevBarEquityForPosSizing");
> > > activateStopsImmediately = GetOption("ActivateStopsImmediately");
> > > dates = DateTime();
> > >
> > > bo = getBacktesterObject();
> > >
> > > switch (custom) {
> > > case 1: {
> > > // Default AmiBroker behavior
> > > bo.Backtest();
> > > break;
> > > }
> > >
> > > case 2: {
> > > // User knowledge base template behavior
> > > bo.PreProcess();
> > >
> > > for (bar = 0; bar < BarCount; bar++) {
> > > size = bo.Equity * maxPosition;
> > > quit = 0;
> > >
> > > for (sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) {
> > > if (sig.IsEntry()) {
> > > lotSize = int((size / sig.Price) / RoundLotSize) * RoundLotSize;
> > >
> > > if (bo.Cash >= ((lotSize * sig.Price) / marginMultiplier) && quit == 0) {
> >
> > > sig.PosSize = -2000 - lotSize;
> > > } else if (bo.Cash > 0 && quit == 0) {
> > > sig.PosSize = 0; // Insufficient funds. Cancel signal.
> > > quit = 1;
> > > } else {
> > > sig.PosSize = 0; // Already hit insufficient funds. Cancel remaining
> > signals.
> > > quit++;
> > > }
> > >
> > > if (sig.PosSize < 0) {
> > > bo.EnterTrade(bar, sig.Symbol, sig.IsLong(), sig.Price, sig.PosSize);
> > > }
> > > } else if (sig.IsExit()) {
> > > bo.ExitTrade(bar, sig.Symbol, sig.Price);
> > > }
> > > }
> > >
> > > bo.HandleStops(bar);
> > > bo.UpdateStats(bar, 1);
> > > bo.UpdateStats(bar, 2);
> > > }
> > >
> > > bo.PostProcess();
> > > }
> > >
> > > case 3: {
> > > // sfclimbers behavior
> > > bo.PreProcess();
> > >
> > > for (bar = 0; bar < BarCount; bar++) {
> > > _TRACE(DateTimeToStr(dates[bar]) + "\t" + bar);
> > >
> > > /*
> > > * Conclusion 1:
> > > * Must consult UsePrevBarEquityForPosSizingand call updateStats(bar, 0)
> > > * to get initial equity.
> > > */
> > > if (!usePreviousBar) {
> > > bo.updateStats(bar, 0); // Update to bar open.
> > > baseEquity = bo.Equity; // Then calculate equity
> > > } else {
> > > baseEquity = bo.Equity; // Calculate equity
> > > bo.updateStats(bar, 0); // Then update to bar open.
> > > }
> > >
> > > size = baseEquity * maxPosition;
> > > _TRACE("\tBase Equity: " + baseEquity + ", Opening Equity: " + bo.Equity
> > + ", Pct. of Base: " + size + ", Starting Cash: " + bo.Cash);
> > >
> > > /*
> > > * Conclusion 2:
> > > * Must process regular exit signals at start of each bar, before new
> > entries.
> > > *
> > > * Conclusion 3:
> > > * Must consult ActivateStopsImmediately to determine whether to
> > additionally
> > > * process stops at start of each bar, before new entries.
> > > */
> > > for (sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) {
> > > if (sig.IsExit() && (sig.Reason == 1 || !activateStopsImmediately)) {
> > > if (pos = bo.FindOpenPos(sig.Symbol)) {
> > > msg = "\tExit (" + sig.Reason + ") " + WriteIf(sig.IsLong(), "Long: ",
> > "Short: ") + sig.Symbol + ", Shares: " + pos.Shares;
> > >
> > > /*
> > > * Conclusion 4:
> > > * Must call updateStats(bar, 1) after each trade entry or exit in order
> > > * to have up to date Equity and Cash data.
> > > */
> > > bo.ExitTrade(bar, sig.Symbol, sig.Price);
> > > bo.UpdateStats(bar, 1);
> > > _TRACE(msg + ", Cash Balance: " + bo.Cash);
> > > }
> > > }
> > > }
> > >
> > > quit = 0;
> > >
> > > for (sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) {
> > > if (sig.IsEntry()) {
> > > lotSize = int((size / sig.Price) / RoundLotSize) * RoundLotSize;
> > >
> > > if (bo.Cash >= ((lotSize * sig.Price) / marginMultiplier) && quit == 0) {
> >
> > > sig.PosSize = -2000 - lotSize;
> > > } else if (bo.Cash > 0 && quit == 0) {
> > > sig.PosSize = 0; // Insufficient funds. Cancel signal.
> > > quit = 1;
> > > } else {
> > > sig.PosSize = 0; // Already hit insufficient funds. Cancel remaining
> > signals.
> > > quit++;
> > > }
> > >
> > > if (sig.PosSize < 0) {
> > > msg = "\tEnter " + WriteIf(sig.IsLong(), "Long: ", "Short: ") +
> > sig.Symbol + ", Price: " + sig.Price + ", Shares: " + abs(sig.PosSize +
> > 2000) + " Margin Loan: " + (abs(sig.PosSize + 2000) * sig.Price) * (1 - (1 /
> > marginMultiplier));
> > > result = bo.EnterTrade(bar, sig.Symbol, sig.IsLong(), sig.Price,
> > sig.PosSize);
> > > bo.UpdateStats(bar, 1);
> > > _TRACE(msg + ", Cash Balance: " + bo.Cash + " Result: " + result);
> > > } else if (quit == 1) {
> > > _TRACE("\t" + sig.Symbol + " not entered because of insufficient funds");
> >
> > > }
> > > }
> > > }
> > >
> > > /*
> > > * Conclusion 5:
> > > * Must consult ActivateStopsImmediately to determine whether to process
> > stops
> > > * at end of each bar, after new entries.
> > > */
> > > if (activateStopsImmediately) {
> > > for (sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar)) {
> > > if (sig.IsExit() && sig.Reason != 1) {
> > > if (pos = bo.FindOpenPos(sig.Symbol)) {
> > > msg = "\tExit (" + sig.Reason + ") " + WriteIf(sig.IsLong(), "Long: ",
> > "Short: ") + sig.Symbol + ", Shares: " + pos.Shares;
> > >
> > > bo.ExitTrade(bar, sig.Symbol, sig.Price);
> > > bo.UpdateStats(bar, 1); // Update running stats after each trade.
> > > _TRACE(msg + ", Cash Balance: " + bo.Cash);
> > > }
> > > }
> > > }
> > > }
> > >
> > > /*
> > > * Conclusion 6:
> > > * HandleStops is obsolete and should no longer be called.
> > > */
> > > msg = ", Ending Cash: " + bo.Cash;
> > > bo.UpdateStats(bar, 2);
> > > _TRACE("\tEnding Equity: " + bo.Equity + msg);
> > > }
> > >
> > > bo.PostProcess();
> > > break;
> > > }
> > > }
> > > }
> > >
> > > Try with each of the following combinations (make changes in the code).
> > The UKB template will always be wrong:
> > >
> > > UsePrevBarEquityForPosSizing: true, ActivateStopsImmediately: true
> > > UsePrevBarEquityForPosSizing: true, ActivateStopsImmediately: false
> > > UsePrevBarEquityForPosSizing: false, ActivateStopsImmediately: true
> > > UsePrevBarEquityForPosSizing: false, ActivateStopsImmediately: false
> > >
> > >
> > > Any attempt at low level custom code cannot be trusted until somebody can
> > actually write low level custom backtester code that can be verified against
> > AmiBroker built in code. I want to experiment with non trivial position
> > sizing. But, I can't do it without a better description of how the low level
> > backtester is supposed to be used.
> > >
> > > I will send this note to support also, if you or Marcin prefer to reply
> > privately. But, I suspect that any reply would be helpful to the whole
> > group.
> > >
> > > Mike
> > >
> > >
> > > --- In amibroker@xxxxxxxxxxxxxxx <amibroker%40yahoogroups.com>, "Tomasz
> > Janeczko" <groups@> wrote:
> > > >
> > > > Hello,
> > > >
> > > > In short, all information you asked for in this particular request can
> > be found on-line:
> > > >
> > http://www.amibroker.org/userkb/2008/03/16/amibroker-custom-backtester-interface-2/
> > > >
> > > > Best regards,
> > > > Tomasz Janeczko
> > > > amibroker.com
> > > > ----- Original Message -----
> > > > From: "Mike" sfclimbers@
> > > > To: amibroker@xxxxxxxxxxxxxxx <amibroker%40yahoogroups.com>
> > > > Sent: Friday, September 18, 2009 7:17 PM
> > > > Subject: [amibroker] Re: Support Issues
> > > >
> > > >
> > > > > Well,
> > > > >
> > > > > Since there have been a few others, I guess I'll add my ticket to the
> > pile, just in case there really is a technical problem. The
> > > > > address I am registered with is a Yahoo dot com address.
> > > > >
> > > > > I received an auto reply for my support request #62580 on Thursday,
> > August 27, 2009. I have not received anything since then. I
> > > > > sent a follow up status request a week after that. Again, no reply.
> > > > >
> > > > > I have been checking my spam folder, but have not noticed anything
> > from AmiBroker in there. Though, admittedly, I get a lot of
> > > > > spam. So, I may have missed something.
> > > > >
> > > > > Mike
> > > > >
> > > > > --- In amibroker@xxxxxxxxxxxxxxx <amibroker%40yahoogroups.com>,
> > "Tomasz Janeczko" groups@ wrote:
> > > > >>
> > > > >> Jeremy,
> > > > >>
> > > > >> I have instructed Marcin to double check if there is any message
> > from you awaiting reply.
> > > > >>
> > > > >> Sometimes if there is long exchange between user and support, it may
> > happen that support
> > > > >> considers case as resolved, while customer expects some extra info.
> > If this happens, please just
> > > > >> reply again to any unanswered ticket and tell the support that you
> > are waiting for specific info.
> > > > >>
> > > > >> Best regards,
> > > > >> Tomasz Janeczko
> > > > >> amibroker.com
> > > > >> ----- Original Message -----
> > > > >> From: "nyctastudent" jberkovits1@
> > > > >> To: amibroker@xxxxxxxxxxxxxxx <amibroker%40yahoogroups.com>
> > > > >> Sent: Friday, September 18, 2009 3:08 PM
> > > > >> Subject: [amibroker] Re: Support Issues
> > > > >>
> > > > >>
> > > > >> > TJ,
> > > > >> >
> > > > >> > There might be an issue on the AmiBroker side. I am having a
> > problem geting a response to an item I submit on September 2nd.
> > > > >> > Its
> > > > >> > not due to spam filters. I sent a folow up email on the 17th and
> > still no reply. AmiBroker usually has the best support in the
> > > > >> > business. Something is causing a break in support communications.
> > If you need any aditional info from me please let meknow.
> > > > >> >
> > > > >> > Thanks for a great product.
> > > > >> >
> > > > >> >
> > > > >> > Best regards,
> > > > >> >
> > > > >> > Jeremy Berkovits, CMT
> > > > >> >
> > > > >> > Merc Partners
> > > > >> > 11 Great Neck Road
> > > > >> > Great Neck, NY-11021
> > > > >> >
> > > > >> > Direct: (516) 304-3200 EXT. 307
> > > > >> > Cell: (917) 698-3444
> > > > >> > jberkovits1@
> > > > >> > AOL IM: jberkovitscmt
> > > > >> > Yahoo IM: jeremy7827110028
> > > > >> >
> > > > >> >
> > > > >> >
> > > > >> >
> > > > >> >
> > > > >> > On Wed, Sep 2, 2009 at 8:42 AM, support@ wrote:
> > > > >> >
> > > > >> > Hello,
> > > > >> >
> > > > >> > Your message: "GICS Import File" has been received.
> > > > >> > Ticket number is #62757 (please DO NOT remove it from the subject
> > line when replying).
> > > > >> >
> > > > >> >
> > > > >> >
> > > > >> > ------------------------------------
> > > > >> >
> > > > >> > **** IMPORTANT PLEASE READ ****
> > > > >> > This group is for the discussion between users only.
> > > > >> > This is *NOT* technical support channel.
> > > > >> >
> > > > >> > TO GET TECHNICAL SUPPORT send an e-mail directly to
> > > > >> > SUPPORT {at} amibroker.com
> > > > >> >
> > > > >> > TO SUBMIT SUGGESTIONS please use FEEDBACK CENTER at
> > > > >> > http://www.amibroker.com/feedback/
> > > > >> > (submissions sent via other channels won't be considered)
> > > > >> >
> > > > >> > For NEW RELEASE ANNOUNCEMENTS and other news always check DEVLOG:
> > > > >> > http://www.amibroker.com/devlog/
> > > > >> >
> > > > >> > Yahoo! Groups Links
> > > > >> >
> > > > >> >
> > > > >> >
> > > > >>
> > > > >
> > > > >
> > > > >
> > > > >
> > > > > ------------------------------------
> > > > >
> > > > > **** IMPORTANT PLEASE READ ****
> > > > > This group is for the discussion between users only.
> > > > > This is *NOT* technical support channel.
> > > > >
> > > > > TO GET TECHNICAL SUPPORT send an e-mail directly to
> > > > > SUPPORT {at} amibroker.com
> > > > >
> > > > > TO SUBMIT SUGGESTIONS please use FEEDBACK CENTER at
> > > > > http://www.amibroker.com/feedback/
> > > > > (submissions sent via other channels won't be considered)
> > > > >
> > > > > For NEW RELEASE ANNOUNCEMENTS and other news always check DEVLOG:
> > > > > http://www.amibroker.com/devlog/
> > > > >
> > > > > Yahoo! Groups Links
> > > > >
> > > > >
> > > > >
> > > >
> > >
> >
> >  
> >
>




------------------------------------

**** IMPORTANT PLEASE READ ****
This group is for the discussion between users only.
This is *NOT* technical support channel.

TO GET TECHNICAL SUPPORT send an e-mail directly to 
SUPPORT {at} amibroker.com

TO SUBMIT SUGGESTIONS please use FEEDBACK CENTER at
http://www.amibroker.com/feedback/
(submissions sent via other channels won't be considered)

For NEW RELEASE ANNOUNCEMENTS and other news always check DEVLOG:
http://www.amibroker.com/devlog/

Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/amibroker/

<*> Your email settings:
    Individual Email | Traditional

<*> To change settings online go to:
    http://groups.yahoo.com/group/amibroker/join
    (Yahoo! ID required)

<*> To change settings via email:
    mailto:amibroker-digest@xxxxxxxxxxxxxxx 
    mailto:amibroker-fullfeatured@xxxxxxxxxxxxxxx

<*> To unsubscribe from this group, send an email to:
    amibroker-unsubscribe@xxxxxxxxxxxxxxx

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/