Does anyone know of a document that explains adding per signal metric to backtest report?

0 votes
More specifically, I want to show position score at time of entry signal in trade list.
asked Jun 12, 2017 in AmiBroker by The Doc

1 Answer

0 votes

Yes it is described in the User's guide

(see Example 3).

For more help on AFL programming use the

answered Jun 13, 2017 by anonymous
Thanks for the input, anonymous. I've been looking at that document for a long time and trying to adapt the examples to my needs, but in a language as powerful and flexible as AFL there are many twists and turns to negotiate.

As I understand it, example 3 starts with a list of trades created by backtest stage 1, then loops through all those trade objects from top to bottom. For each one it gets the value of a trade properties - trade.GetProfit() and trade.GetEntryValue(). For each trade it does some maths with those properties and lists the result with the trade. Then it sums them and lists the result at the end of the report.

In my case I need to refer to the signal property rather than the trade properties - specifically sig.PosScore.

Intuitively I want to loop through each trade found in the backtest stage 1, finding for each trade the entry signal and gaining the position score on the entry. I'd put that in a variable and bring it back to the trade object so I can add it as a metric on that trade.

Best docs I have so far are AmiBroker Custom Backtester Interface, Porfolio Backtester Interface Reference Guide and How to add user-defined metrics to backtest/optimization report.  - all excellent documents that contribute hugely, but getting a bit long in the tooth now. It's not quite clear how to connect bars  signals and trades.  

I think i will come down to something like the code that follows, taken from  
AmiBroker Custom Backtester Interface :

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
            if (sig.IsEntry() && sig.IsLong())    //  Process long entries
                bo.EnterTrade(i, sig.Symbol, True, sig.Price, sig.PosSize);
                if (sig.IsExit() && sig.IsLong())    //  Process long exits
                    bo.ExitTrade(i, sig.Symbol, sig.Price);
        }    //  End of for loop over signals at this bar
        bo.HandleStops(i);    //  Handle programmed stops at this bar
        for (trade = bo.GetFirstOpenPos(); trade; trade = bo.GetNextOpenPos())
        {    //  Loop through all open positions
            if (trade.GetProfit() >= trade.GetEntryValue())  //  If time to scale-in
                scaleSize = trade.GetEntryValue() / 2;    //  Scale-in the trade
                bo.ScaleTrade(i, trade.Symbol, True, trade.GetPrice(i, "C"), scaleSize);
        }    //  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

Anything anyone can add to help clarify will be most appreciated.