I have already read How to imitate IBD Relative Strength Percentile Ranking of Stocks by @rocketPower a great many times.
I have also read @fxshrat post on how to bypass looping for SetForeign(Symbol); function.
I worked out several examples but finally landed in a conundrum .
Method 1. This first method is as simple as described by rocketpower. It scans the entire database of stocks. That's very simple. I somehow dont want to scan the entire database which includes highly illiquid and also junk penny stocks.
///1. SIMPLE METHOD SCANS ENTIRE WATCHLIST AND PENNY STOCKS WHICH ARE USELESS
SetBarsRequired( sbrAll ) ; /* for all baRS IN CUM FUNC*/
if ( Status( "stocknum" ) == 0 )
{
// CLEAR STATIC VARS
StaticVarRemove( "RS21*" );
StaticVarRemove( "RankRS21*" );
ListWL_SP500 = CategoryGetSymbols(categoryWatchlist, 0);
Sym_Count = 0;
// SINGLE LOOP: Calculate for all symbols, but mark invalid ones with Null
for ( i = 0; ( Symbol = StrExtract( ListWL_SP500, i ) ) != ""; i++ )
{
// Set context to this symbol and validate data
if(Status("actionex") != actionExEditVerifyFormula) {
SetForeign(Symbol);
}
RS21Value = ((C/Ref(C,-21))-1)*100;
RestorePriceArrays();
Raw21RS = StaticVarSet("RS21" + Symbol, RS21Value);
}
StaticVarGenerateRanks( "Rank", "RS21", 0, 1234 );
}
// TEST THIS
function GetRS21Rank() { return StaticVarGet("RankRS21" + Name()); }
GfxTextOut("GetRS21Rank " + GetRS21Rank() ,20,20);
- I want to eschew penny stocks and low liquid stocks from my ranking process. SO I tried this Method2 using IsTrue(VALIDATION) . I think this is not rational.
///2. VALIDATION TO ESCHEW PENNY STOCKS USING IsTrue(VALIDATION )
SetBarsRequired( sbrAll ) ; /* for all baRS IN CUM FUNC*/
if ( Status( "stocknum" ) == 0 )
{
// CLEAR STATIC VARS
StaticVarRemove( "RS21*" );
StaticVarRemove( "RS63*" );
StaticVarRemove( "RankRS21*" );
StaticVarRemove( "RankRS63*" );
ListWL_SP500 = CategoryGetSymbols(categoryWatchlist, 0);
Sym_Count = 0;
// SINGLE LOOP: Calculate for all symbols, but mark invalid ones with Null
for ( i = 0; ( Symbol = StrExtract( ListWL_SP500, i ) ) != ""; i++ )
{
// Set context to this symbol and validate data
if(Status("actionex") != actionExEditVerifyFormula) {
SetForeign(Symbol);
}
VALIDATION = C >10 AND MA(C,50)* MA(V,50) >= 20000 AND V > 1000; // VOLUME LIQUIDITY FILTER TO ESCHEW PENNY STOCKS
RS_MOM1M = ((C/MA(C,21))-1)*100 ;
RS21Value = IIf( IsTrue(VALIDATION ) , RS_MOM1M,0);
RestorePriceArrays();
Raw21RS = StaticVarSet("RS21" + Symbol, RS21Value);
}
StaticVarGenerateRanks( "Rank", "RS21", 0, 1234 );
}
// TEST THIS
function GetRS21Rank() { return StaticVarGet("RankRS21" + Name()); }
GfxTextOut("GetRS21Rank " + GetRS21Rank() ,20,20);
- Method 3 - I tried to filter out the penny and low liquid stocks by validating the last bar.
/////3. VALIDATION TO ESCHEW PENNY STOCKS LOGICALLY DISCARDS STOCKS CHECKING LAST BARS
SetBarsRequired( sbrAll ) ; /* for all baRS IN CUM FUNC*/
if ( Status( "stocknum" ) == 0 )
{
// CLEAR STATIC VARS
StaticVarRemove( "RS21*" );
ListWL_SP500 = CategoryGetSymbols(categoryWatchlist, 0);
Sym_Count = 0;
for ( i = 0; ( Symbol = StrExtract( ListWL_SP500, i ) ) != ""; i++ )
{
// Set context to this symbol and validate data
if(Status("actionex") != actionExEditVerifyFormula) {
SetForeign(Symbol);
}
//VALIDATION
IsValidArray = C > 6 AND V > 1000 AND (MA(C,50) * MA(V,50) >= 200000);
RS21Value = ((C/Ref(C,-21))-1)*100;
//APPLY VALIDATION - Set invalid bars to Null
RS21Value_Validated = IIf( IsValidArray, RS21Value, Null );
RS21Value_Last = LastValue( RS21Value_Validated );
RestorePriceArrays();
//If the last value was Null, this will be ignored.
if ( !IsNull(RS21Value_Last) )
{
StaticVarSet("RS21" + Symbol, RS21Value_Last);
Sym_Count++;
}
}
// GENERATE RANKS on the stored values
StaticVarGenerateRanks( "Rank", "RS21", 0, 1234 );
}
// TEST THIS
function GetRS21Rank() { return StaticVarGet("RankRS21" + Name()); }
GfxTextOut("GetRS21Rank " + GetRS21Rank() ,20,20);
- Method - I tried to filter the entire database before proceeding to the calculations.
/////4. VALIDATION TO ESCHEW PENNY STOCKS BY FILERING THE ENTIRE DATABASE BEFORE CALCULATIONS
SetBarsRequired( sbrAll ) ; /* for all baRS IN CUM FUNC*/
//Only keep symbols from watchlist that have valid data
ListWL_SP500 = CategoryGetSymbols(categoryWatchlist, 0);
filtered_tickerlist = "";
Sym_Count = 0;
// Process each symbol from the watchlist directly
for(i = 0; (Symbol = StrExtract(ListWL_SP500, i)) != ""; i++)
{
// Set context to this symbol and validate data
if(Status("actionex") != actionExEditVerifyFormula) {
SetForeign(Symbol);
}
// Comprehensive data validation
IsDataValid = NOT IsNull(SelectedValue(C)) AND NOT IsNull(SelectedValue(V)) AND SelectedValue(V) > 0 // Active trading
// above 3 CONDITIONS will filter out suspended non traded stocks
AND SelectedValue(C) > 6 // Minimum price
AND SelectedValue(MA(C,50)) * SelectedValue(MA(V,50)) >= 200000 // Liquidity filter
AND SelectedValue(V) > 1000; // Minimum volume
// Only include symbols with valid data
if(IsDataValid)
{
filtered_tickerlist = filtered_tickerlist + Symbol + ",";
Sym_Count ++;
}
else
{
printf("Excluding %s - Invalid data", Symbol);
}
RestorePriceArrays();
}
if ( Status( "stocknum" ) == 0 )
{
StaticVarRemove( "RS21*" );
StaticVarRemove( "RankRS21*" );
for ( n = 0; ( Symbol = StrExtract( filtered_tickerlist, n ) ) != ""; n++ )
{
// Set context to this symbol and validate data
if(Status("actionex") != actionExEditVerifyFormula) {
SetForeign(Symbol);
}
RS21Value = ((C/Ref(C,-21))-1)*100; // 21-day return
RestorePriceArrays();
Raw21RS = StaticVarSet("RS21" + Symbol, RS21Value);
}
StaticVarGenerateRanks( "Rank", "RS21", 0, 1234 ); /// 1224 suppoeted with equal ranks
}
// TEST THIS
function GetRS21Rank() { return StaticVarGet("RankRS21" + Name()); }
GfxTextOut("GetRS21Rank " + GetRS21Rank() ,20,20);
I have ranking for 63 day period, RVol ranking , VPC Ranking etc etc that I excluded here to shorten the post.
I would then call all these functions elsewhere and add other parameters like distance from 52wk high , highest volumes etc etc and explore the results which would display something like this
Now my dilemma is which Method is appropriate to filter out junk stocks.
And Method 4 takes too long time for exploration.
The profoundly enlightened members reply would be truly appreciated.
Thank you all so much.
