PureBytes Links
Trading Reference Links
|
Me again, Joe - I couldn't help myself, and went back to work on the problem. Here's what I've found: I was getting a lot variances because the SPP data had a lot of stocks that either: 1) Never reported earnings 2) Reported earnings several quarters, and often several years, ago 3) Are IPOs with few data points (though SPP still had EPS and Sales data for them!?) 4) Are various classes of stock of an underlying issue with 0's across the board. In all instances, AB would return a null value for these or call Q0 whatever value it came across first. In order to eliminate these in AB I added a line to get the data of the first change and then filter by that date for earning reported after Nov. of '05. I also included a filter on Barcounts over 500. I ran through a few iterations of this. Increasing the number of bars of
course adds opportunity to both have data that doesn't match up and include stocks that might match up and be good opportunities. I settled on 500 so that it would be right around 2 years. I won't go into the results of all the data unless you ask for it, but I'm comfortable with 500. Given that the data gets worse the farther back in history we go, I think the best we can hope for is: CQIE - Consecutive Quarters of Increasing Earnings. I wrote an escape valve into the for loop and it seems to have worked. Only get one null stock and two that don't match. You might want to take a look at the code to see that I've not made any stupid mistakes and just getting lucky. CQIR - Consecutive Quarters of Increasing Revenue. Only two nulls. All others match. PerEPSChg - the percentage change of last reported earnings over the same quarter last year. Two nulls and three that are off. All
others are within 1% of SPP. PerRevChg - the percentage change of last reported sales over the same quarter last year. Two nulls and one off. All others are within 1% of SPP. With the Per*Chg stuff, SPP uses the formula that any change from 0 to +/-x is simply 100%. Increasing Sales and EPS over the past 4 quarters could be calculated with good accuracy, I just haven't written it in yet. Any other data I think we would want to put into a Canslim scan/exploration can come straight out of the GetExtraData() call. Here's my final code: EPS = GetExtraData("EPS"); Sales= GetExtraData("Sales");
Float= GetExtraData("SharesFloat"); Yr1ProjEPSGr= GetExtraData("Yr1ProjEPSGrowth"); SharesShort= GetExtraData("SharesShort"); SharesFloat= GetExtraData("SharesFloat"); ROE= GetExtraData("ROE"); InstHolds= GetExtraData("InstHolds"); ShrtInt=(SharesShort/(SharesFloat* 10000)); Change= (Sales != Ref(Sales,-1)) OR (EPS != Ref(EPS,-1));//When do either the Sales or the EPS change LEDate = ( ValueWhen( Sales != Ref( Sales, -1 ) OR EPS != Ref( EPS, -1 ), DateNum()))/100;//Filter out old EPS reports //Quarterly EPS EPS0 = Ref(EPS,-1); EPS1 = ValueWhen(Change,EPS,2); EPS2 = ValueWhen(Change,EPS,3); EPS3 = ValueWhen(Change,EPS,4); EPS4 = ValueWhen(Change,EPS,5); EPS5 = ValueWhen(Change,EPS,6); EPS6 = ValueWhen(Change,EPS,7); EPS7 = ValueWhen(Change,EPS,8); EPS8 = ValueWhen(Change,EPS,9); EPS9 = ValueWhen(Change,EPS,10); PerEPSChg = IIf(EPS4==EPS0,0,IIf(EPS4==0,IIf(EPS0<0,-100,100),((EPS0-EPS4)/abs(EPS4))*100));//Change in EPS last quarter over same quarter 1 yr ago. // Initialize the accumulator for the CQIE
CQIE= 0; for (i=1; i<= 7; i++) { CQIE = CQIE + IIf(ValueWhen(Change,EPS,i)>ValueWhen(Change,EPS,i+1),1,0); i= IIf(SelectedValue(ValueWhen(Change,EPS,i))>SelectedValue(ValueWhen(Change,EPS,i+1)),i,11); } //Quarterly Revenue Rev0= Ref(Sales,-1); Rev1= ValueWhen(Change,Sales,2); Rev2= ValueWhen(Change,Sales,3); Rev3= ValueWhen(Change,Sales,4); Rev4= ValueWhen(Change,Sales,5); Rev5= ValueWhen(Change,Sales,6); Rev6= ValueWhen(Change,Sales,7); Rev7= ValueWhen(Change,Sales,8); Rev8= ValueWhen(Change,Sales,9); Rev9= ValueWhen(Change,Sales,10); PerRevChg = IIf(Rev4==Rev0,0,IIf(Rev4==0,IIf(Rev0<0,-100,100),((Rev0-Rev4)/abs(Rev4))*100));// CQIR= 0; for (i=1;i<=7;i++) { CQI R = CQIR + IIf(ValueWhen(Change,Sales,i)>ValueWhen(Change,Sales,i+1),1,0); i= IIf(SelectedValue(ValueWhen(Change,Sales,i))>SelectedValue(ValueWhen(Change,Sales,i+1)),i,11); } AddColumn (CQIE,"CQIE",1.0); AddColumn (PerEPSChg,"PerEPSChg",1.1); AddColumn (CQIR,"CQIR",1.0); AddColumn (PerRevChg,"PerRevChg",1.1); AddColumn (ROE,"ROE"); AddColumn (ShrtInt,"ShortInt",1.1); AddColumn (InstHolds,"PerInstHolds"); Filter= 1 AND BarCount>500 AND LEDate>10511; With
LEDate, "105" means 2005 and the last two digits are the month. TTYL Jeff
Joe Landry <jelandry@xxxxxxxxxxxxx> wrote: Hi Jeff - Thanks for the interaction. I'd like to get this working myself as you can tell. And I stand corrected >= should be >, although that's not a bad metric to have a EPS staying flat or increasing. CANSLIM just tests to see if it's >=1. I've got a version of the CYIE but I'll have to check the definition again because I have >= again and have to verify the numbers. Others that need work are %EPSChange (and you cannot use QP's number because it's static, at least not on my part since I want to back test some of this. AND 1YrEPSGrowth. So if we look at what would be arrays there would be CQIE, CYIE, %EPSChange, 1YrEPSGrowth, %Cl/52Hi, and RS Rank....Float and %Inst could be tossed in to see if they made a difference but all you'd be getting is the last value. How are you verifying the numbers with QP? Did you build a view for the CANSLIM picks? Best regards JOE ----- Original Message ----- Sent: Wednesday, March 22, 2006 3:32 PM Subject: Re: [amibroker] Re: Single Value from Array
Hi Joe, The problem with keying off the months is that it returns a lot of incorrect data (1,000 on average). The only way I can explain this is that companies just don't report very consistently. I chose to key off a change (not necessarily greater than) either the Sales or the EPS because I figured one of those would have to change in order to constitute a new report. Since EPS is
such a small number, a change there probably won't register (.02 is pretty much the same as .024). By using Sales in addition to EPS I was able to return the correct data (according to SPP) of all but 11 stocks. I like your idea for figuring CQIE in a loop (my previous solution was nested IIF statements). Unfortunately, I can't get it to work. I believe the count is increasing whenever one quarter EPS is less than the following quarter's EPS (your code actually has less than or equal to, but I changed that part). The problem is this is not consecutive quarters of increasing EPS; it's merely consecutive two quarters of increasing EPS. From SPP: "The most recent quarter is compared to the preceding quarter. If the most recent quarter is greater than the preceding quarter (not equal), the count is increased by one.
This type of backwards comparison where each quarterly EPS is compared to the previous quarterly EPS goes on until one of two events occur: -
All 8 quarterly time periods have been processed or -
The security fails with a quarter that doesn't increase, the process will stop and the count is recorded The counting process results in a number from 0 – 7. A security with consecutive upward progress will get a value of 7 (8 quarters of steady upward progress). A security with a zero means the current quarter is less than the previous quarter." In effect, the loop needs another way out - when the change in EPS from i to i+1 is either 0 or less
than 0. CQIE needs to stop counting as soon as EPSi<=EPSi+1. I've tried a couple different methods, and still am. Any suggestions? Thanks! Jeff
Joe Landry <jelandry@xxxxxxxxxxxxx> wrote: Hi Jerrry - I take it you're trying to calculate the Continuous Quarterly Increase in Earnings. CQIE I added a few things to the code and I think this is right altho and I didn't look up the definition this morning or compare it to the QP database for the specific stocks I ran. This is one place where I would use a loop. Either that or repeat the statement 7 times for the 7 quarterly comparisons.
Note that I use the "event" or conditon that it is the change of quarter based on the date (the month that is) and not whether EPS was greater than the month before to trigger the comparisons, AND if the comparison or the condition is TRUE then I count it as a quarterly increase. You could also put the EPS1 thru EPS9 in a loop also, as well as the column statements. It would save a little writing but this works. Glad you picked up on the use of ValueWhen...a powerful function. Best regards JOE // Run an Explore against
a watchlist with "n last days = 1" for one bar EPS = GetExtraData("EPS"); Sales= GetExtraData("Sales"); Cond1 = ( Month()-1)%3 ==0; Cond2 = Month()!= Ref(Month(),-1); Quarter = Cond1 AND Cond2; Change = quarter; // I left this in here since you had it imbedded in each of the EPS0 ...EPS9 //C hange=((Sales != Ref( Sales, -1 )) OR (EPS != Ref(EPS,-1)));//When does either the Sales or the EPS change //Set the EPS values for each occurence of a change in either Sales or EPS. CQIE = 0; // Initialize the accumulator for the CQIE for (i=1; i<= 7; i++) { CQIE = CQIE + IIf(ValueWhen(quarter,EPS,i)>=ValueWhen(quarter,Ref(EPS,-1),i),1,0); _TRACE ("CQIE = "+CQIE + " Index "+i); } _TRACE ("CQIE outside loop
"+CQIE); // CQTot = CQIE + CQ2; EPS0= Ref(EPS,-1); EPS0 = ValueWhen(Change,EPS,1); EPS1 = ValueWhen(Change,EPS,2); EPS2 = ValueWhen(Change,EPS,3); EPS3 = ValueWhen(Change,EPS,4); EPS4 = ValueWhen(! Change,E PS,5); EPS5 = ValueWhen(Change,EPS,6); EPS6 = ValueWhen(Change,EPS,7); EPS7 = ValueWhen(Change,EPS,8); EPS8 = ValueWhen(Change,EPS,9); EPS9 = ValueWhen(Change,EPS,10); AddColumn (EPS0,"EPS0"); AddColumn (EPS1,"EPS1"); AddColumn (EPS2,"! EPS2"); AddColumn (EPS3,"EPS3"); AddColumn (EPS4,"EPS4"); AddColumn (EPS5,"EPS5"); AddColumn (EPS6,"EPS6"); AddColumn (EPS7,"EPS7");
AddColumn (EPS8,"EPS8"); AddColumn (EPS9,"EPS9"); AddColumn (CQIE,"CQIE"); Filter= 1; ----- Original Message ----- Sent: Wednesday, March 22, 2006 2:15 AM Subject: Re: [amibroker] Re: Single Value from Array
Hi Joe, I may have it. I liked your code, but my objective is to run a Canslim type of exploration/scan. But your code did turn me on to the ValueWhen() function. Coupling that with a simple check of Sales today against Sales of yesterday, or EPS today against EPS yesterday, puts me in a place where no more than 11 of the stocks AB returns vary more than .01 in any one quarter from the data reported by
SPP. No more than 70 (or so) vary by a penny in any one quarter; which seems to be a rounding error. (SPP seems to round down when dealing with fractions of a penny.) For not knowing how SPP is arriving at its data, nor when the quarters end, I think that's pretty good. I don't know why these stocks show up, but I'll keep looking into it. In the mean time, I think we can use this to determine quarterly EPS and Sales growth. I really do appreciate all the effort you've put into educating me. Perhaps you wouldn't mind spending a few more minutes and looking over my code? EPS = GetExtraData("EPS"); Sales= GetExtraData("Sales");
Change=((Sales != Ref( Sales, -1 )) OR (EPS != Ref(EPS,-1)));//When does either the Sales or the EPS change //Set the EPS values for each occurence of a change in either Sales or EPS. EPS0= Ref(EPS,-1); EPS1 =
ValueWhen(Change,EPS,2); EPS2 = ValueWhen(Change,EPS,3); EPS3 = ValueWhen(Change,EPS,4); EPS4 = ValueWhen(Change,EPS,5); EPS5 = ValueWhen(Change,EPS,6); EPS6 = ValueWhen(Change,EPS,7); EPS7 = ValueWhen(Change,EPS,8); EPS8 = ValueWhen(Change,EPS,9); EPS9 = ValueWhen(Change,EPS,10); AddColumn (EPS0,"EPS0"); AddColumn (EPS1,"EPS1"); AddColumn (EPS2,"! EPS2"); AddColumn (EPS3,"EPS3"); AddColumn (EPS4,"EPS4"); AddColumn (EPS5,"EPS5"); AddColumn (EPS6,"EPS6"); AddColumn (EPS7,"EPS7"); AddColumn (EPS8,"EPS8"); AddColumn (EPS9,"EPS9"); Filter= 1;
Joe Landry <jelandry@xxxxxxxxxxxxx> wrote: Cato cc: Quotes Plus Users: < /FONT> I'm thinking you probably don't ! need to apply iterative loops to get what you want. I also wanted to say that there are only 4 arrays available from QP via the functions Tomasz wrote in Amibroker. They are QRS, EPSRank, EPS, and Sales. I'm checking but not sure other arrays are available to Amibroker's plug in. QRS is calculated daily, EPSRank is done
weekly, EPS and Sales are reported quarterly. So these arrays, if you run an explore, will change only on the dates(bar) that the quarter changes. The other values are point values. What you get when you call a GetExtraData for example for PEG, is the last calculated PEG for that stock. You can't go get it's historical value nor use PEG as a backtesting criteria. Here's a small routine that does not use loops and presents the EPS at change of quarter on an Exploration. BTW, I would encourage the use of Explorations in the AA mode, especially if you're not using "for" loops.
Hope this helps. JOE // Exploration for Quarterly EPS - For example, run on single issue over 1000 bars. EPS = GetExtraData("EPS" ); Sales = GetExtraData("Sales"); QRS = GetExtraData("QRS"); EPSRank = GetExtraData("EPSRank"); // Bruce Robinson wrote this originally as a one line program but I split it so it // be more readable by me and others who are starting out. Cond1 = (( Month() - 1 ) % 3 == 0 ); // Remainder when prev month number is div'ed by 3. // Do an explore on Cond1 and see what it does. Cond2 = Month() != Ref( Month(),-1); // Cond2 to set 1 when month changes. QTR = IIf(Cond1 AND Cond2,1,0); Filter = 1; //QTR; // // to print only quarterly results, uncomment the use of QTR. AddColumn (Close,"Close" ); AddColumn (EPS,"EPS"); AddColumn (Sales,"Sales"); QuarterlyEPS = ValueWhen(QTR,EPS); // this is not needed the way I have the filter set up.
AddColumn (QuarterlyEPS,"QE EPS"); AddColumn (QRS,"QRS"); AddColumn (EPSRank,"EPSRank"); AddColumn (GetExtraData("PEG"),"PEG Ratio"! ); ----- Original Message ----- Sent: Tuesday, March 21, 2006 1:28 AM Subject: RE: [amibroker] Re: Single Value from Array
Terry, I want to thank you for the time you put into educating me. I learned a lot. I rewrote my code using what you taught me and everything worked out as it should. It was much faster, and much cleaner. Unfortunately, I haven't thought this through enough. It's looking more and more like what I want to do will simply not be possible. The code returns different values from the array, but several vary from what QP3's own software is telling me the earnings should be; even on the last earnings reported (which should be barcount-0). It gets worse the farther back in time I go. I'll have to study the problem some more. At least I learned a lot about loops and arrays! Cato
Terry <MagicTH@xxxxxxxxxxx> wrote: Cato, Almost. EPS is an array. AB let's you access individual array elements, called bars (bar = day in a daily database), with [brackets]. So, EPS[i] is just one
of the days in the database for the symbol in use. You were correct in your original assumption on that count. What you're missing is the necessity of breaking those out into separate elements since EPS already contains the values you want. Maybe an example is in order: Buy = C > 10 AND ESP > 20; //A simple example that buys if Price is > $10 and EPS > 20 A backtest evaluates each bar (or the range of
bars you select as dates to test) and it knows on each day (bar) what the values are. The EPS will change quarterly as it should. You don't really need to do anything special to make this happen. -----Original Message----- From: amibroker@xxxxxxxxxxxxxxx [mailto:amibroker@xxxxxxxxxxxxxxx] On Behalf Of Jeff Springer Sent: Monday, March 20, 2006 18:49 To:
amibroker@xxxxxxxxxxxxxxx Subject: RE: [amibroker] Re: Single Value from Array Thank you for your excellent reply. I think you pegged me right on. I was under the impression that the [] subscript referenced only a single number from that array. But you're telling me that EPS[x] is an array as well, albeit an array with the same number repeated for however many bars. So, if I can rephrase what you wrote, I don't need EPSx, I just need EPS with the various values for i to pull the number I want to manipulate out? I can understand that, and see that what I really need is
to discover the values for "i" at each change. Do I understand you correctly? If so, do you have any recommendations for discovering the values for "i"? Would it be much like your first post? I imagine I would use different variables for each occurrence of a change, but I probably shouldn't start assuming again. Again, your reply was very clear and clarifies a lot of questions I had. Thank you, again. Cato
Terry <MagicTH@xxxxxxxxxxx> wrote: I don't have QP3 so I can't get too specific, but I think you ha! ve a bas ic misunderstanding on how Amibroker is supposed to work. It's very common for people with coding experience to want AB
to work with single values. If I'm way off on understanding your issue, my apologies! AB is an array processing system. For example, you shouldn't mix arrays and single values as you have done in your Do loop. You have assigned a single value to an array with EPS0 = EPS[b-1]. So, you have assigned the same value to the entire EPS0 array. This array is the same size array as the ticker you are working with. Now you have 4 arrays, all barcount long, with the same value in each one. I think you are thinking you have an array that is one-quarter long (about 66 days), but it is not. Besides, you already have all the data in the original EPS array and it's already arranged by quarter. In abbreviated form you have
this: EPS 11111111111111122222222222222233333333333333334444444444444444 EPS0 11111111111111111111111111111111111111111111111111111111111111 EPS1
22222222222222222222222222222222222222222222222222222222222222 EPS2 33333333333333333333333333333333333333333333333333333333333333 EPS3 44444444444444444444444444444444444444444444444444444444444444 You need to get comfortable with data being in arrays and each bar simply represents the status "as of that bar". It really works well this way. Your EPS has a value everyday. If it doesn't change for an entire quarter, you simply have the same
value everyday. Then, on the day it changes, you'll have the new value for the next 66 days. On any given day you can simply refer to your EPS or Sales array and you will have the correct value. AB "knows" which day you are "on". Same answer for your original question about Ref(). It does refer to a single value -x bars in the past, it's just an array of single references so on any given day, the array "knows" the answer -x bars previously. Again, sorry if I am explaining something you already know. Thank you very much for replying, Terry. That's pretty much what I discovered over the weekend. Would you mind looking at my response to Bill Barnard and providing your input?
Terry <MagicTH@xxxxxxxxxxx> wrote: Try this:
i = 0; //Start at beginning of array do i++; while (myArray[i-1] == myArray[i]) //After this line executes, the value of i = the first changed array element. -- -----Original Message----- From: amibroker@xxxxxxxxxxxxxxx [mailto:amibroker@xxxxxxxxxxxxxxx] On Behalf Of Jeff Springer Sent: Monday, March 20, 2006 10:35 To: amibroker@xxxxxxxxxxxxxxx Subject: Re: [amibroker] Re: Single Value from Array I've figured it out, but have run into a new problem. I'm trying to get the history of EPS and Sales from the QP3 data, which are arrays. I didn't want to be this specific because I realize others don't have QP3 and I wanted to phrase my question in general terms that I think would work with all arrays. I think if you run this code on any array you should come up with the same error I got. Would you mind looking at it and giving your input? while (EPS1==EPS0 AND i<b); while (((EPS2==EPS0) OR (EPS2==EPS1)) AND i<b); while (((EPS3==EPS2) OR (EPS3==EPS1) OR (EPS3==EPS0)) AND i<b); There's more, but you can see the general pattern from these three. The EPS array is set up so
that each bar for a quarter has the same EPS value. When a new EPS comes out, the EPS changes (ideally; since I'll only be looking at stocks where EPS increases, I don't care if the code mistakes a new EPS for an unchanged EPS). I step back through the array to search for a different EPS.
This code works fine, but I would prefer that "i" continues counting up rather than reseting (as I've done with the "i=1;" line before each do loop). The problem with this is that the do loop checks the condition /after/ running the "EPSx=EPS[b-i];" line. So, when it hits a stock with few bars, the code errors out with the "outside 0... (barcount-1) range" error. Is there a way to put a
conditional statement in before the "EPSx=EPS[b-1];" line so that if "i" is greater than the barcount, then EPSx is null, or 0? I've tried changing the "EPSx=EPS[b-i];" line to "EPSx=iif(i>b, 0, EPS[b-i];" but that still errors out. Maybe there's something more basic I'm missing. Thank you, for your help. Cato Bill Barnard <wbarnard@xxxxxxx> wrote: --- In amibroker@xxxxxxxxxxxxxxx, Jeff Springer <fatboycato@xxx> wrote: > > Thank you so much for replying, Bill, but I don't think that will work for me. I was hoping to use the code in an exploration, and I think this code will only give me the data in a debugger window, correct? I tried assigning the _Trace calls to variables, and then displaying that variable with AddColumn, but of course that doesn't work. I'm too programming ignorant to know why. > > It seems to me that if Ref() calls up a specific value in the array, then it shouldn't be returning an array, just that specific value. I'm sure there's a good reason why it doesn't work this way, I only wish I had some way of calling up a value from an array and assigning that value, and only that value, to a variable.
---------------------------------------------
You are welcome. sorry it isn't what you need.
Ref() does produce an array, the original one shifted by a certain amount.
If you can describe what you are trying to do, very exactly, in English, I am sure the code would not be too difficult.
Yahoo! Mail Use Photomail to share photos without annoying attachments.
Yahoo! Mail Bring photos to life! New PhotoMail makes sharing a breeze.
Yahoo! Mail Bring photos to life! New PhotoMail makes sharing a breeze.
Yahoo! Messenger with Voice. PC-to-Phone calls for ridiculously low rates.
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 other support material please check also:
http://www.amibroker.com/support.html
YAHOO! GROUPS LINKS
|