Ken, I see your point about the sums. I wasn't thinking in terms of summing, so the code I posted last doesn't do that. Instead it gives the user a choice of metrics, and sets the OI field according to the ranking per the (single) chosen metric.
Sorry for any confusion caused by this. --- In [email protected], Ken Close <[EMAIL PROTECTED]> wrote: > > Progster: > > > I like the way you comment the code to explain, in more detail, what each > line or at least selected lines are doing. This is very helpful to newbies > in the custom backtester, like me, and will obviate the message I had > planned asking for just such a thing from the experienced users. Your > comments have helped me a lot, so thanks. > > As a partial test of my understanding of the code, I will attempt to explain > one of your comments/questions: > this from your copied code (whew on word wrap) > > // The index (k) into the sorted 'Signal' collection is the ordinal ranking. > > if ( qt ) > > { > > if ( run == 1 ) > > { // ROC case > > qt.OpenInt = k; > > NoteSet( sig.Symbol, sig.Symbol + " - OI displays: " + "ROC ranking\n" + > Announcement ) ; > > NoteSet( sig.Symbol, NoteGet(sig.Symbol) + "\n" + "Highest ROC(14) is > lowest number.\n"); > > } > > else if ( run == 2 ) > > { // RSI case > > // qt.OpenInt += k; // why? > > > > qt.OpenInt = k; > > NoteSet( sig.Symbol, sig.Symbol + " - OI displays: " + "RSI ranking\n" + > Announcement ) ; > > NoteSet( sig.Symbol, NoteGet(sig.Symbol) + "\n" + "Highest RSI(14) is > lowest number.\n"); > > } > > else{ > > qt.OpenInt += k; // other cases (why?) > > } > > } > > > > // target.isDirty = True; // not necessary > > Now, my original specification to Paul Ho was that I wanted the sum of the > ordinals of the individual indicators to be the super ordinal or combo > indicator. > Thus, the > qt.OpenInt += k; // other cases (why?) > takes the ordinal from the first indicator (created in the first qt.OpenInt > = k; statement above, and adds the ordinal value of the second pass to it, > thus make the sum. > From a previous message, Mike confirmed that qt.OpenInt += k; is the same as > qt.OpenInt = qt.OpenInt + k; > > I hope/think this is right. > > Of course, to add in challenge and complexity, what do the statement loops > look like when you want to sum three or four or more indicators. > > Perhaps one just cascades the if statements, the run numbers and still uses > the += k construct. > > So to add a third case to the initial switch statements in the ranking > function, we might add > > case 3: > res = stochD( 14 ); > break; > > Later, we have to add a section > else if ( run == 3 ) > { > qt.OpenInt += k; > } > > If my understanding of this is correct, for every additional indicator added > to the analysis, you add the same qt.OpenInt += k; statement (within the > properly bracketed if else statements); the preprocessor has sorted > everything for each indicator, so starting at the beginning, one adds the > ordinal values, then for each next step, one adds the ordinal values of that > step to the OpenInt from the previous step, resulting in the sum of all the > ordinals of the indicators in the analysis when all the loops or if/else > steps are done. > > Can someone confirm for me that this thinking is correct? Please. If it is > not, please take the time to explain how the += operator and previous > preprocessor sorts are working to get the sum of all of the ordinals. > > If this is right (or is correctly explained another way), then this has > increased my understanding of the custom backtester immensely. > > Thanks for the added information in your modified code. > > Ken > > > > > -----Original Message----- > From: [email protected] [mailto:[EMAIL PROTECTED] On Behalf > Of progster01 > Sent: Wednesday, July 09, 2008 10:28 AM > To: [email protected] > Subject: [amibroker] Re: More on Database Structure and Local Storage > > --- In [email protected], "Paul Ho" <paul.tsho@> wrote: > > Progster, you're correct in your interpretation. The only correction > > needed is that Tomasz first posted the original code, I added the > > storage part. > > Paul - Thanks for the confirmation! > > Below I add-on to this code a bit by making it write to the NotePad a note > which tells the observer what the OI field actually is showing. > > I've also made the metric a parameter. > > Something strange though - when I change the metric and re-run, all the > symbols update OI to reflect the new metric _except_ for the one which is > currently displayed. This is as observed in the NotePad. > > Can anyone tell why that might be? > (Tested in AB 5.14.0) > > ___ > > > /* > OrdinalRankFast_01.afl > > Uses custom backtester to do very fast ordinal ranking, writing the > result > to the OI field. > > Demo ranking by ROC OR RSI is provided. > > Run this code as a Backtest. > > *** WARNING: This code will change your database! *** > > Original code by: Tomasz Janeczko and Paul Ho > Originally from: > http://finance.groups.yahoo.com/group/amibroker/message/126512 > > 7/9/2008 Progster Added comments, and code to log > actions by this AFL > in the NotePad. > Made the ranking a parameter. > Changed RSI case to behave like the ROC case. This makes the range > of the OI field span the > # of stocks in the list to which this AFL is applied. > Observed that the symbol in the current chart does not update (!?) > > */ > > Announcement = "OI field has been set by OrdinalRankFast_01.afl" ; > > run = Param( "run", 1, 1, 2, 1 ); > > function ranking( Ordinal ) > { > switch ( Ordinal ) > { > case 1: > res = ROC( C, 14 ) + 1000; > break; > > case 2: > res = RSI( 14 ); > break; > > default: > res = EMA( C, 50 ); > break; > > } > return res; > } > > // WHAT YOU WANT TO RANK > // Internally, AB will sort/order the backtester's 'Signal' objects > according to > // absolute value of PositionScore. Later in the code, we will > retreive from these > // objects by stepping thru them sequentially. Since the 'Signal' > objects have already > // been sorted by AB into PositionScore order, the order in which they > will be > // encountered when we step-thru them _is_ the ordinal order of the ranking > metric. > PositionScore = ranking( run ); > > SetOption( "MaxOpenPositions", 50 ); //AB only keeps 2* maxpos > top > rank signals > > SetBacktestMode( backtestRegularRaw ); > > Buy = 1; // > make a buy signal for every stock on every bar > > Sell = Short = Cover = 0; > > ab = CreateObject( "broker.Application" ); > > // IsDirty flag tells AB that data has changed so when the user press > save, that area of the database is saved. > // Since this AFL will update the OI field, we mark the 'Stock' as > changed. > target = ab.Stocks( Name() ); // select a single 'Stock' > object from > the 'Stocks' collection > target.isDirty = True; > > SetCustomBacktestProc( "" ); // empty argument means use > current AFL > formula > > if ( Status( "action" ) == actionPortfolio ) { > bo = GetBacktesterObject(); > bo.PreProcess(); > dt = DateTime(); > > // fh = fopen("output.csv", "w"); uncomment these if you want to save it to > a csv file as well // fputs("Symbol,Date,Rank\n", fh); > > // On every bar > for ( i = 0; i < BarCount; i++ ) > { > // For every signal ... (one for each stock in this case, > based on Buy = 1, above) > k = 1; > for ( sig = bo.GetFirstSignal( i ); sig; sig = bo.GetNextSignal( i ) > ) > { > // Line = sig.Symbol + "," + DateTimeToStr(dt[i]) + "," + k + > "\n"; > // fputs(Line, fh); > > target = ab.Stocks( sig.Symbol ); // select a > 'Stock' > object from the 'Stocks' collection > > qt = target.Quotations( DateTimeToStr( dt[i] ) ); // > select a 'Quotation' object from the 'Quotations' collection > > // The index (k) into the sorted 'Signal' collection > is the ordinal ranking. > if ( qt ) > { > if ( run == 1 ){ // ROC > case > qt.OpenInt = k; > NoteSet( sig.Symbol, > sig.Symbol + " - OI displays: " + "ROC > ranking\n" + Announcement ) ; > NoteSet( sig.Symbol, > NoteGet(sig.Symbol) + "\n" + > > "Highest ROC(14) is lowest number.\n" ); > } > else if ( run == 2 ){ // RSI > case > // qt.OpenInt += k; // why? > > qt.OpenInt = k; > > NoteSet( sig.Symbol, > sig.Symbol + " - OI displays: " + "RSI ranking\n" + Announcement ) ; > NoteSet( sig.Symbol, > NoteGet(sig.Symbol) + "\n" + > > "Highest RSI(14) is lowest number.\n" ); > } > else{ > qt.OpenInt += k; // other cases > (why?) > } > } > > // target.isDirty = True; // not necessary > k++; > } > } > > bo.PostProcess(); > > // if(fh)fclose(fh); > > } // end of: if ( Status( "action" ) == actionPortfolio ) > > > // Try this at the end, to make OI for the currently displayed symbol > update. > // Not a fix. > // target = ab.Stocks( Name() ); // select a single > 'Stock' object > from the 'Stocks' collection > // target.isDirty = True; > > > > > > > > > > > ------------------------------------ > > Please note that this group is for discussion between users only. > > To get support from AmiBroker please send an e-mail directly to SUPPORT {at} > amibroker.com > > For NEW RELEASE ANNOUNCEMENTS and other news always check DEVLOG: > http://www.amibroker.com/devlog/ > > For other support material please check also: > http://www.amibroker.com/support.html > Yahoo! Groups Links >
