Markus,

Run the script below on a watchlist of just a handful of symbols (e.g.
4) over a short duration (e.g. month of October), then study the TRACE
output.

The TRACE output will show the complete lifecycle of signal to position
to closed trade.  To see the TRACE output, make sure that your AmiBroker
Log window is opened to the Trace tab. You may additionally need to
right click in the body area of the Trace tab page and make sure that
"Trace Output -> Internal" is selected.

To answer your specific questions:

1. I'm not entirely sure what you are asking. But, I believe that the
answer is yes, as shown in the TRACE output. At each bar, signals are
either accepted or rejected for that bar. Accepted signals will cause a
new trade to be added to the position list (entry signal) or an existing
trade to be moved from the open position list to the closed list (exit
signal). This process is repeated for each bar in sequence.

2. Yes. This can be seen in the TRACE output. The open and closed lists
include a running tally up to the current bar index.

3. No. The call to ProcessTradeSignals is the call responsible for
shuttling signals to open positions and open positions to closed trades
(on a bar by bar basis), not PostProcess.. PostProcess is a one time
call at the very end to clear out memory and move the remaining open
trades to the closed list.

Actually, AmiBroker does not seem to expose the final transfer of open
trades to closed except as reflected in the report. I was surprised to
see that the closed trade list does not get affected after PostProcess
(using standard edition 5.26.5), contrary to the documentation which
says "When backtest is completed (after PostProcess call) AmiBroker
closes out all open positions, so trade list includes all trades." You
can send a follow up to support for that one.

4. No, do not use ListTrades. Depending on what you were trying to do,
you could use UpdateStats, but I would advise staying away from that
until you really knew what was going on. It's pretty rare that you would
need that.

5. The last lines of the sample script show how to use LastValue and
ValueWhen to get the bar of the trade based on the date.

Mike

SetTradeDelays(0, 0, 0, 0);
SetPositionSize(2, spsPercentOfEquity);

weekDay = DayOfWeek();

Buy = weekDay == 1;
BuyPrice = Open;

Sell = weekDay == 5;
SellPrice = Close;

SetCustombacktestProc("");

if (Status("action") == actionPortfolio) {
    bo = GetBacktesterObject();
    bo.PreProcess();

    for (bar = 0; bar < BarCount; bar++) {
       _TRACE("Bar " + bar);

       count = 0;

       for (trade = bo.GetFirstOpenPos(); trade; trade =
bo.GetNextOpenPos()) {
          count++;
       }

       _TRACE("  There were " + count + " open positions at the start of
the bar");

       count = 0;

       for (trade = bo.GetFirstTrade(); trade; trade = bo.GetNextTrade())
{
          count++;
       }

       _TRACE("  There were " + count + " closed trades at the start of
the bar");

       count = 0;
       count2 = 0;

       for (sig = bo.GetFirstSignal(bar); sig; sig =
bo.GetNextSignal(bar)) {
          if (sig.IsEntry()) {
             count++;
          } else {
             count2++;
          }
       }

       _TRACE("  There were " + count + " entry signals found during the
bar");
       _TRACE("  There were " + count2 + " exit signals found during the
bar");

       bo.ProcessTradeSignals(bar);
       count = 0;

       for (trade = bo.GetFirstOpenPos(); trade; trade =
bo.GetNextOpenPos()) {
          count++;
       }

       _TRACE("  There were " + count + " open positions after the bar");

       count = 0;

       for (trade = bo.GetFirstTrade(); trade; trade = bo.GetNextTrade())
{
          count++;
       }

       _TRACE("  There were " + count + " closed trades after the bar");
    }

    count = 0;

    for (trade = bo.GetFirstTrade(); trade; trade = bo.GetNextTrade()) {
       count++;
    }

    _TRACE("There were " + count + " closed trades before final
processing");

    bo.PostProcess();
    count = 0;

    for (trade = bo.GetFirstTrade(); trade; trade = bo.GetNextTrade()) {
       count++;
    }

    _TRACE("There were " + count + " closed trades after final processing
(including closed open trades)");

    indices = BarIndex();
    dates = DateTime();
    trade = bo.GetFirstTrade();

    _TRACE("The entry bar of the first trade was " +
LastValue(ValueWhen(trade.EntryDateTime == dates, indices)));
    _TRACE("The exit bar of the first trade was " +
LastValue(ValueWhen(trade.ExitDateTime == dates, indices)));
}


--- In [email protected], "Markus Witzler" <funny...@...> wrote:
>
> Hi Mike,
>
> sorry for getting back so late.
>
> Your comments shed some light on my probs.
>
> If I may, a few more things need to be clarified:
>
> 1. In the CBL low.level loop below, will the signal loop be processed
for one instance of "i", then the following trade loop (open and closed
trades). Afterwords, i gets incremented by one and the whole starts
again?
>
> 2. If so, did I understand you correctly that closed and open trade
lists hold ALL closed (respectively open) trades that have been
generated by signals (from signal list) up to the value "i" holds for
any given moment? I.e. if "i" holds the value of "10" the trade lists
(open or close) hold ALL trades up to that bar even though the bar
number is now beign store but the date (entry and exit)?
>
> 3. The command "postprocess" in mid- and low-level turns signals into
trades and thus moves them from one list to the other?! But then the
postprocess comand should stand beetween signal and trade list, right.
Otherwhise the shift would occur the NEXt time the loop is being
processed?!
>
> 4. You wrote" If necessary, you can write code to monitor the lists on
a bar by bar basis to track the trade activity" - could you givew me a
short clue what to do? Would I have to used "list trades" and
"updatestats" in each run of the loop after each trade?
>
> 5. You wrote "The bar index of the trade entry/exit is not stored as
part of the trade object. But, the entry/exit dates are. Using that
information you could calculate the bar index if you really needed it."
I may be interested how to do this as well. A short hint would be fine.
>
> I don´t wnat to make it more complex than it is, but I sometimes
just don´t understand the inner workings of CBT and thus can´t
come up with the proper code.
>
> Sorry for my ignorance!
>
> Markus
>
>
>
>
> ----- Original Message -----
> From: Mike
> To: [email protected]
> Sent: Thursday, October 29, 2009 12:36 AM
> Subject: [amibroker] Re: Trade lists vs. signal list in custom
backtester
>
>
> Hi,
>
> Using the mid and low level backtester, trades get added/removed
to/from the lists on a bar by bar basis at the point where the
respective signals get processed (e.g. bo.ProcessTradeSignals(i) in mid
level backtester).
>
> Once taken, open trades remain in the open list, possibly spanning
multiple bar indices, until they are closed. When closed, the trades are
moved to the closed list and will remain there for the duration of the
backtest.
>
> A trade does not appear in any list until a signal is accepted by the
backtester (e.g. the lists at bar 100 will not contain a trade that only
gets opened at bar 110). Once taken, it will always be accessible in one
of the lists from that point forward. If necessary, you can write code
to monitor the lists on a bar by bar basis to track the trade activity.
>
> The bar index of the trade entry/exit is not stored as part of the
trade object. But, the entry/exit dates are. Using that information you
could calculate the bar index if you really needed it.
>
> Mike
>
> --- In [email protected], "Markus Witzler" funnybiz@ wrote:
> >
> > Hello,
> >
> > I have trouble understanding trade lists (open/closed) in custom
backtester.
> >
> > As opposed to signal lists which carry an index variable and thus
only process signals for a specific bar, trade lists haven´t.
> >
> > Consider the following code template in low-level CBT mode
> > SetCustomBacktestProc("");
> > if (Status("action") == actionPortfolio)
> > {
> > bo = GetBacktesterObject(); // Get backtester object
> > bo.PreProcess(); // Do pre-processing
> > 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
> > . . . .
> > } // End of for loop over signals at this bar
> > for (trade = bo.GetFirstTrade(); trade; trade = bo.GetNextTrade())
> > {
> > . . . .
> > }
> > for (trade = bo.GetFirstOpenPos(); trade; trade =
bo.GetNextOpenPos())
> > {
> > . . . .
> > }
> > bo.HandleStops(i); // Handle programmed stops 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
> > }
> > I understand, that each run, signal list is being processed for a
different value of "i". But how is trade list being used. Since there is
no index variable "i", I can´t figure out if trade objects are being
searched for a different value of "i" than in signal list, or if whole
list of trades (for all bars) is being processed at each occurrence of
"i" in the main loop.
> >
> > Can someone help me clear this up?
> >
> > Thanks
> >
> > Markus
> >
>


Reply via email to