Hello all,
Thought I'd share my latest exploit. I've been beta testing @NorgateData new platform for a while now, and recently subscribed to the platinum package. Upon reading about everything it offers, I realized a lot of the fundamental data can help me partially model Mark Minervini's Specific Entry Point Analysis (SEPA) explained in his first book, "Trade Like a Stock Market Wizard". Mark's strategy seems to veer towards swing trading, but also seems to have its lineage in CANSLIM as well. I won't get too into the book's details, as you probably all should read it (and his second book!), but SEPA has five main points:
- Trend -> The trend template he explains is modeled
- Fundamentals -> Modeled
- Catalyst -> More news based so cannot mdel
- Entry Points -> Modeling his volatility contraction pattern is next on my list
- Exit Points -> next on my list
This script makes heavy use of Norgate Fundamental data using their custom function "NorgateFundamentals()", native function GetFnData() and some of my own functions, one of which I explained in my other post on IBD relative strength score. Norgate has been really great, I really wish they offered EOD and fundamental data for more countries, especially Canada!
Function modeling the trend template:
function Trending(Carray, Harray, Larray)
{
// 52 week high/low check, within 25%
W52wkHigh = Carray > 0.75 * HHV(Harray, 52 * 5) AND Carray > LLV(Larray, 52*5)*1.30;
// Check trend using SMAs
SMA050 = MA(Carray, 050);
SMA150 = MA(Carray, 150);
SMA200 = MA(Carray, 200);
UnwrappedSMA = Carray > SMA050 AND SMA050 > SMA150 AND SMA150 > SMA200;
UpTrend = SMA200 > Ref(SMA200, -22);
//Filter
Stage2 = W52wkHigh AND UnwrappedSMA AND UpTrend;
return Stage2;
}
Only stocks that satisfy the above Trending criteria and has a relative strength of > 75 are considered in this exploration. To cover the fundamentals aspect of the SEPA strategy and also some other technical analysis aspects common to IBD style trading, I use a scoring system to rank stocks. Earnings and Sales get double value, while most get a single point. Some more esoteric points get only half score.
Below is the main exploration script:
// SEPA Screener Based on Minervini Books
#include "C:\Users\mamus\Dropbox\Michael\Documents\AmiBroker Files\In Test\Cassiopeia\FuncLib.afl"
#include_once "Formulas\Norgate Data\Norgate Data Functions.afl"
/// Points System
TotalFactors = 0;
Score = 0;
// 1. IPO Date Filter
RecentIPO = BarCount < 252*10;
if (RecentIPO)
Score++;
TotalFactors++;
// 2. Market Cap Filter
MarketCap = NorgateFundamentals("mktcap"); // in millions
GoodCaps = MarketCap < 1e4 AND MarketCap > 1e2;
if (GoodCaps) Score++;
TotalFactors++;
// 3. ROE Filter
ROE = GetFnData("ReturnOnEquity");
GoodROE = ROE > 17;
if (GoodROE) Score++;
TotalFactors++;
// 4. Sales QoQ
QRG = GetFnData("QtrlyRevenueGrowth");
GoodSales = QRG > 20;
if (GoodSales) Score += 2;
TotalFactors += 2;
// 5. Good Earnings
QEG = GetFnData("QtrlyEarningsGrowth");
GoodEarns = QEG > 25;
if (GoodEarns) Score += 2;
TotalFactors += 2;
// 6. RS Line New High
RSL = RSLine(C);
RSLNewHigh = LastValue(RSL) >= LastValue(HHV(RSL, 63));
if (RSLNewHigh) Score++;
TotalFactors++;
// 7. RS Above 85
RS = GetRS(Name());
GoodRS = LastValue(RS) >= 85;
if (GoodRS) Score++;
TotalFactors++;
// 8. Earnings Surprise
ES = NorgateFundamentals("epssurpriseqprc");
GoodES = ES > 20;
if (GoodES) Score++;
TotalFactors++;
// 9. Annual Earnings
AE = NorgateFundamentals("ttmepschg");
GoodAE = AE > 20;
if (GoodAE) Score++;
TotalFactors++;
// 10. Net Profit Margin
NPM = NorgateFundamentals("ttmnpmgn");
GoodNPM = NPM > 10;
if (GoodNPM) Score++;
TotalFactors++;
// 11. Consensus growth rate
CGR = NorgateFundamentals("projltgrowthrate");
GoodCGR = CGR > 20;
if (GoodCGR) Score += 0.5;
TotalFactors += 0.5;
// 12. TTM Inventory Turnover
TIT = NorgateFundamentals("ttminvturn");
GoodTIT = TIT > 5;
if (GoodTIT) Score += 0.5;
TotalFactors += 0.5;
//Filter
ScorePct = Score / TotalFactors * 100;
Filter = Trending(C, H, L) AND RS > 75 AND ScorePct > 50;
Ranking = ScorePct;
AddColumn(BarCount/252, "Years Public");
AddColumn(MarketCap, "Market Cap");
AddColumn(ROE, "ROE");
AddColumn(QRG, "Qrtly Rev Gwth");
AddColumn(QEG, "Qtly Earn Gwth");
AddColumn(RSLNewHigh, "RSL New High");
AddColumn(RS, "RS");
AddColumn(ES, "Earn Surpr %");
AddColumn(AE, "TTM/TTM Earn %");
AddColumn(NPM, "Net Prof Mgn");
AddColumn(CGR, "Cons Gwth Rate");
AddColumn(TIT, "TTM Inv TO");
You'll notice I filter out anything that scores less than 50%. Running this screen on NASDAQ, NYSE and ARCA give me about 400 stocks or so, more than enough to make a crème de la crème stock universe. For I run some screens on this universe looking for simple breakouts, RS line new highs, stocks near highs, but my next conquest is to really find bases with substantial volatility contractions.
As usual, any comments, improvements and criticisms are welcome!
Thanks!
Mike