Mark Minervini Trend Template ThinkorSwim Scanner

Nick

Active member
2019 Donor
VIP
@wtf_dude hi, for my learning, may request you to explain what does this scan do? what type of stocks can we get from this scan? Can i change this to weekly timeframe, if so, what input length is recommended... thank you very much
 

Rbuzon

New member
@wtf_dude Thank You for finding the RSI portion, i am trying to put it in all together but im getting an error "Exactly one plot expected"

any advice would help

Code:
## Code Start

input range = 252; #Number of Trading days
#input price = close; #Current closing price
#input length = 200; #hint length: The length of the moving average
input LookBack = 60; #hint LookBack: The agg-bars back moving average being compared to

def lo = lowest(low,range);
def hi = highest(high,range);

#The current stock price is at least 30 percent above its 52-week low.
def x = 1.3 * lo; #30% above its 52-week low
#def x = 2.0 * lo; #100% above its 52-week low

#The current stock price is within at least 25 percent of its 52-week high
def y = 0.75 * hi; #25% of its 52-week high
#def y = 0.80 * hi; #20% of its 52-week high
#def y = 0.90 * hi; #10% of its 52-week high

# The below reads as SimpleMovingAvg("length" = 200) is greater than SimpleMovingAvg("length" = 200) from 60 agg-bars ago.
#(Average(close, length) > Average(close, length)[LookBack])
declare lower;

input Correlation_with_Security = "SPY";
input length = 200;
input Period = AggregationPeriod.DAY;
input averagetype = AverageType.Simple;

def price = close;
def RSD = close/(close(correlation_with_security));
def RSDavg = MovingAverage(averagetype, RSD, length);

plot RSM = (( RSD / RSDavg) - 1 ) * 100;
plot zeroline = 0;

zeroline.SetDefaultColor(GetColor(2));
#
plot scan = (Average(close, length) > Average(close, length)[LookBack])
and SimpleMovingAvg("length" = 150)."SMA" is greater than SimpleMovingAvg("length" = 200)."SMA"
and SimpleMovingAvg("length" = 50)."SMA" is greater than SimpleMovingAvg("length" = 150)."SMA"
and SimpleMovingAvg("length" = 50)."SMA" is greater than SimpleMovingAvg("length" = 200)."SMA"
and close is greater than SimpleMovingAvg("length" = 200)."SMA"
and close is greater than SimpleMovingAvg("length" = 150)."SMA"
and close is greater than SimpleMovingAvg("length" = 50)."SMA"
and price >= x
and price >= y
;
 

Thomas

Active member
VIP
@Rbuzon OK, all fixed,.....any more difficulties, let me know.

Code:
#Copy this code into scanner.....add "volume," 1Mil,........"Last, 5"..........


## 1. The current stock price is above both the 150-day (30-week) and the 200-day (40-week) moving average price lines.
## 2. The 150-day moving average is above the 200-day moving average.
## 3. The 200-day moving average line is trending up for at least 1 month (preferably 4?5 months minimum in most cases).
## 4. The 50-day (10-week) moving average is above both the 150-day and 200-day moving averages.
## 5. The current stock price is trading above the 50-day moving average.
## 6. The current stock price is at least 30 percent above its 52-week low. (Many of the best selections will be 100 percent, 300 percent,
## or greater above their 52-week low before they emerge from a solid consolidation period and mount a large scale advance.)
## 7. The current stock price is within at least 25 percent of its 52-week high (the closer to a new high the better).
## 8. The relative strength ranking (as reported in Investor?s Business Daily) is no less than 70, and preferably in the 80s or 90s,
## which will generally be the case with the better selections
## NOTE: Point 8, I have not implemented, because TOS doesn'thave IDB rating.
##
## Reference to conditions above
## 3) (Average(close, length) > Average(close, length)[LookBack])
## 2) and SimpleMovingAvg("length" = 150)."SMA" is greater than SimpleMovingAvg("length" = 200)."SMA"
## 4) and SimpleMovingAvg("length" = 50)."SMA" is greater than SimpleMovingAvg("length" = 150)."SMA"
## 4) and SimpleMovingAvg("length" = 50)."SMA" is greater than SimpleMovingAvg("length" = 200)."SMA"
## 1) and close is greater than SimpleMovingAvg("length" = 200)."SMA"
## 1) and close is greater than SimpleMovingAvg("length" = 150)."SMA"
## 5) and close is greater than SimpleMovingAvg("length" = 50)."SMA"
## 6) and price > x
## 7) and price > y
##########################################################################################################################

## Code Start

input range = 252; #Number of Trading days
#input price = close; #Current closing price
#input length = 200; #hint length: The length of the moving average
input LookBack = 60; #hint LookBack: The agg-bars back moving average being compared to

def lo = lowest(low,range);
def hi = highest(high,range);

#The current stock price is at least 30 percent above its 52-week low.
def x = 1.3 * lo; #30% above its 52-week low
#def x = 2.0 * lo; #100% above its 52-week low

#The current stock price is within at least 25 percent of its 52-week high
def y = 0.75 * hi; #25% of its 52-week high
#def y = 0.80 * hi; #20% of its 52-week high
#def y = 0.90 * hi; #10% of its 52-week high

# The below reads as SimpleMovingAvg("length" = 200) is greater than SimpleMovingAvg("length" = 200) from 60 agg-bars ago.
#(Average(close, length) > Average(close, length)[LookBack])
declare lower;

input Correlation_with_Security = "SPY";
input length = 200;
input Period = AggregationPeriod.DAY;
input averagetype = AverageType.Simple;

def price = close;
def RSD = close/(close(correlation_with_security));
def RSDavg = MovingAverage(averagetype, RSD, length);

Def RSM = (( RSD / RSDavg) - 1 ) * 100;
#plot zeroline = 0;

#zeroline.SetDefaultColor(GetColor(2));

plot data = (Average(close, length) > Average(close, length)[LookBack])
and SimpleMovingAvg("length" = 150)."SMA" is greater than SimpleMovingAvg("length" = 200)."SMA"
and SimpleMovingAvg("length" = 50)."SMA" is greater than SimpleMovingAvg("length" = 150)."SMA"
and SimpleMovingAvg("length" = 50)."SMA" is greater than SimpleMovingAvg("length" = 200)."SMA"
and close is greater than SimpleMovingAvg("length" = 200)."SMA"
and close is greater than SimpleMovingAvg("length" = 150)."SMA"
and close is greater than SimpleMovingAvg("length" = 50)."SMA"
and price >= x
and price >= y
;
 
Last edited:

Bamilus

New member
@Rbuzon Not trying to be pedantic but want to clarify because this is an extremely common mistake.

Relative Strength does not equal Relative Strength Index. The former is comparing the relative performance of one ticker vs another. The second is a momentum oscillator that compares an individual stocks rate of change and looks for oversold and overbought opportunities. They are used for entirely different reasons and cannot be used interchangeably.
 

Winston

New member
Hi,

I am new here, hoping I can get some help. Hopefully it wasn't address before. I am looking to do a scan pre-market for stocks that are trading sideways. Thanks in advance.
  • 1. FastSma and SlowSMA within a certain PERCENT of each other
    • Able to change both SMA input
    • Able to change the PERCENT
  • 2. Stock Price within a certain Percent of the SMA
    • Able to which SMA
    • Able to change Stock Price Percent within SMA
 
just an idea! is anyone able to code the 4 stages Mark uses? something to mark on charts or in a watchlist to make an easy glace to know what stage the stock is in and from the watch list knowing without even looking at the chart
 
Last edited:

Moose

Member
@wtf_dude I don't remember where I copied this script. Maybe it has some value:

#I just looked at the code for the "RelativeStrength" study (not to be confused with Wilder's Relative Strength Index (RSI)) and it is quite possibly the worst script in the TOS library. It is patently useless as it merely divides the current stock's price by the comparison stock's price. The RS should be calculated by taking the rate of change over a period for the current stock divided by the rate of change over the same period for the comparison stock or index. Apples to apples, instead of AAPLs to watermelons.

#So here's a version of the RS based on H.M. Gartley's "Relative Velocity" (the original RS) work. Note that any value greater than 100 means the current stock is leading the comparison stock, conversely values under 100 mean that the comparison stock is outperforming the current stock.

Code:
# script by rhouser

#

declare lower;



input Comparison_Security = "SPX";

input period              = 10;

input price               = FundamentalType.CLOSE;



def comparisonPrice       = fundamental( price, Comparison_Security );

def comparisonRtOfChg     = comparisonPrice / comparisonPrice[ period ];



def currentStkPrice       = fundamental( price );

def currentStkRtOfChg     = currentStkPrice / currentStkPrice[ period ];



plot RS                   = if IsNaN( comparisonRtOfChg ) then Double.NaN else ( currentStkRtOfChg / comparisonRtOfChg ) * 100;

RS.setDefaultColor(GetColor(6));

RS.HideBubble();



plot BaseLine             = 100;

BaseLine.SetDefaultColor( Color.red );

BaseLine.HideBubble();

BaseLine.HideTitle();



#2) The SCAN script -- assumes you named the chart study "RS"

#RS( "SPX", 10, FundamentalType.CLOSE ).RS > 100



#3) The CUSTOM COLUMN script -- assumes you named the chart study "RS"

#plot RS = RS( "SPX", 10, FundamentalType.CLOSE ).RS;

#AssignBackgroundColor( if RS >= 100 then Color.UPTICK else Color.DOWNTICK );



#end
 
I found this share link on a page that appears to be a ToS page. It's for a MM Trend Template scan built up from individual conditions: https://tos.mx/dMgGC1.

I like this approach for ease of readability, but it uses a 'lookback' of only 22 days to ensure that the 200SMA has been trending upward. MM prefers 2 months minimum, and on his (authorized) MarketSmith version he uses 5 months - this gets more established trends. I modified the scan in the link to not only check that today's 200SMA is above the one from 5 months ago, but it checks today against 1 month ago, 1 month ago against 2 months ago, etc. This tightens the criteria to ensure that the 200SMA has been consistently rising for at least five months. To make that change, replace the 4th condition with this code:

Code:
SimpleMovingAvg("length" = 200)."SMA" is greater than SimpleMovingAvg("length" = 200)."SMA" from 22 bars ago
and SimpleMovingAvg("length" = 200)."SMA" from 22 bars ago is greater than SimpleMovingAvg("length" = 200)."SMA" from 43 bars ago
and SimpleMovingAvg("length" = 200)."SMA" from 43 bars ago is greater than SimpleMovingAvg("length" = 200)."SMA" from 65 bars ago
and SimpleMovingAvg("length" = 200)."SMA" from 65 bars ago is greater than SimpleMovingAvg("length" = 200)."SMA" from 87 bars ago
and SimpleMovingAvg("length" = 200)."SMA" from 87 bars ago is greater than SimpleMovingAvg("length" = 200)."SMA" from 109 bars ago
 
RSI (Relative Strength Index) is a very different thing than the Relative Strength that Minervini uses. RSI uses only the data from the stock in question whereas Relative Strength compares a stock to a different stock, index or the general market. In particular, the Relative Strength Rating that Minervini uses is a proprietary value published by Investor's Business Daily, and is created by comparing an individual stock against all of the stocks in their database (7000 or so). The number represents the percentile of the stock within the entire group; a stock with a Relative Strength Rating of 92, for instance, is currently stronger than 92% of all the stocks in their database.
 

MerryDay

Well-known member
VIP
@yarrione there are several scans in this thread. If you can create the mathematical expressions that identify stage-4 criteria, you should be able to modify one of the existing scans. If you have an issue with the correct syntax for your filters. Come back with the logic for stage-4 criteria expressed mathematically and someone should be able to provide direction. Try not to use vague terms, for example trending higher is not a mathematical expression. Math examples would be: percentage is greater than or greater than Bollinger bands, etc..
To determine what your mathematical expressions should be, look at how the existing scans are written and look at your charts. At what point does the plot meet what you are looking for? Then define those plot points using logic (if, then, else) and math.
HTH
 
Last edited:

Prison Mike

Member
@wtf_dude I don't remember where I copied this script. Maybe it has some value:

#I just looked at the code for the "RelativeStrength" study (not to be confused with Wilder's Relative Strength Index (RSI)) and it is quite possibly the worst script in the TOS library. It is patently useless as it merely divides the current stock's price by the comparison stock's price. The RS should be calculated by taking the rate of change over a period for the current stock divided by the rate of change over the same period for the comparison stock or index. Apples to apples, instead of AAPLs to watermelons.

#So here's a version of the RS based on H.M. Gartley's "Relative Velocity" (the original RS) work. Note that any value greater than 100 means the current stock is leading the comparison stock, conversely values under 100 mean that the comparison stock is outperforming the current stock.

Code:
# script by rhouser

#

declare lower;



input Comparison_Security = "SPX";

input period              = 10;

input price               = FundamentalType.CLOSE;



def comparisonPrice       = fundamental( price, Comparison_Security );

def comparisonRtOfChg     = comparisonPrice / comparisonPrice[ period ];



def currentStkPrice       = fundamental( price );

def currentStkRtOfChg     = currentStkPrice / currentStkPrice[ period ];



plot RS                   = if IsNaN( comparisonRtOfChg ) then Double.NaN else ( currentStkRtOfChg / comparisonRtOfChg ) * 100;

RS.setDefaultColor(GetColor(6));

RS.HideBubble();



plot BaseLine             = 100;

BaseLine.SetDefaultColor( Color.red );

BaseLine.HideBubble();

BaseLine.HideTitle();



#2) The SCAN script -- assumes you named the chart study "RS"

#RS( "SPX", 10, FundamentalType.CLOSE ).RS > 100



#3) The CUSTOM COLUMN script -- assumes you named the chart study "RS"

#plot RS = RS( "SPX", 10, FundamentalType.CLOSE ).RS;

#AssignBackgroundColor( if RS >= 100 then Color.UPTICK else Color.DOWNTICK );



#end
Thanks @Moose for posting this

Paired up with the Trend Template scan I found a "RS" value between 90 - 110(maybe even 96- 103) produces the best looking set ups. Anything over about 105 looks like it has already taken off.
 

naposs

New member
Thanks @Moose for posting this

Paired up with the Trend Template scan I found a "RS" value between 90 - 110(maybe even 96- 103) produces the best looking set ups. Anything over about 105 looks like it has already taken off.
can you please share the scanner after you paired, I could not make it as you stated. thank you
 

Prison Mike

Member
Code:
# script by rhouser
input Comparison_Security = "SPX";
input period              = 10;
input price               = FundamentalType.CLOSE;
def comparisonPrice       = fundamental( price, Comparison_Security );
def comparisonRtOfChg     = comparisonPrice / comparisonPrice[ period ];
def currentStkPrice       = fundamental( price );
def currentStkRtOfChg     = currentStkPrice / currentStkPrice[ period ];
plot RS                   = if IsNaN( comparisonRtOfChg ) then Double.NaN else ( currentStkRtOfChg / comparisonRtOfChg ) * 100;

plot scan=  RS > 95 and RS < 105;

Or the code can be used in a watchlist column and filtered that way.
 

Docbrown83

New member
Hey guys, I found this from another site and was wondering if it could be translated to TOS. May help with VCP determination. If this has already been posted, please disregard.


Code:
// VCP Search

// Goal is to easily find possible VCP pivots that are tight enough to be attractive to buy

// Must be used with an Amibroker analysis that selects only a universe of stocks that meet the trend template and
// other minimum requirements for an uptrending growth stock (per Minervini parameters)

// Michael Mustillo 2020/05/04

// Tunables ////////////////////////////////////////////////
{
Timeframe          = 252;  // one year of trading. Looking at growth stock a base is usually starts at a new ATH
// the above concept also tends to elminate stocks with too much overhead supply

VolTf             = 50;  // 50 days for volume averaging (similar to most IBD-inspired charts)

// Most good bases only retrace up to 30%. Even if the base is deeper, it's probably not a good
// idea to buy cheats pivots (3C patterns) that are really deep into the base
BaseLowerLimit     = 0.6;

// Pivot length. How long does the last contraction need to be to qualify?
// Three days is probably the absolute minimum if combined with a dry-up in supply
PivotLength     = 5;

// How wide can the pivot be to be a pivot? 6% seems to be a sweet spot for a high quality final contraction
// 10% is the limit
PVLimit         = 0.10;
}

Ticker = Name();

// Filter parameters ///////////////////////////////////////
{
// Stock should not be making a new high, but be close to it
// initial correction in the base must be less than 30%, but could be more in a volatile or bear market


// Price within base
// find the highest price over the timeframe
HighPrice = HHV(C, Timeframe);


// Make sure the current price is till within the base and not too much below
NearHigh  = C < HighPrice AND C > BaseLowerLimit * HighPrice;

// Average volume is decreasing
// volume must be contracting and/or below average, preferably both to ensure supply is indeed drying up
// Use the typical 50-day average for volume
Vma = MA(V, VolTf);

// A negative slope of the linear regression of the average volume should indicate supply trends
VolSlope = LinRegSlope(Vma, VolTf);

// Volume is indeed decreasing if slope is negative
VolDecreasing = VolSlope < 0;


// Pivot Quality
// The last few days must be tight, < 10%, preferably less than 6% if possible to get a tight entry and good
// stop-loss
// The high of the pivot should be in the first day of the pivot formation to really be a contraction
// The low can occur anywhere in the pivot
PivotHighPrice  = HHV(H, PivotLength);
PivotLowPrice    = LLV(L, PivotLength);
PivotWidth         = (PivotHighPrice - PivotLowPrice)/C;
PivotStartHP    = Ref(H, -PivotLength +1);
IsPivot         = PivotWidth < PVLimit AND PivotHighPrice == PivotStartHP;


// Now make sure the volume is really drying up in the pivot area
// Set initial value to true
VolDryUp = True;

// loop throught PivotLength days and ensure volume is below average
for (i = 0; i < PivotLength; i++)
    VolDryup = VolDryup AND Ref(V, -i) < Ref(Vma, -i);
}

// Filter results ///////////////////////////////////////////

Filter = NearHigh AND VolDecreasing AND IsPivot AND VolDryUp;

//EOF
 

Similar threads

Top