# VCP Search
declare lower;
# 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 ########################
input 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
input 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
input 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
input 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
input PVLimit = 0.10;
# 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
#def HighPrice = Highest(close, Timeframe);
def HighPrice = Highest(high, Timeframe);
# Make sure the current price is till within the base and not too much below
def NearHigh = close < HighPrice and close > 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
def Vma = SimpleMovingAvg(volume, VolTf);
# A negative slope of the linear regression of the average volume should indicate supply trends
def VolSlope = LinearRegressionSlope(Vma, VolTf);
# Volume is indeed decreasing if slope is negative
def 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
def PivotHighPrice = Highest(high, PivotLength);
def PivotLowPrice = Lowest(low, PivotLength);
def PivotWidth = (PivotHighPrice - PivotLowPrice) / close;
#def PivotStartHP = Ref(H, -PivotLength +1);
def PivotStartHP = Highest(high, PivotLength)[PivotLength];
def IsPivot = PivotWidth < PVLimit and PivotHighPrice == PivotStartHP;
# Now make sure the volume is really drying up in the pivot area
# Set initial value to true
#def VolDryUp = yes;
# loop throught PivotLength days and ensure volume is below average
#plot factorial = fold index = 1 to n + 1 with p = 1 do p * index;
def VolumeDrying = fold i = 0 to PivotLength - 1 with VolDryUp = yes do if VolDryUp and volume[i] < Vma[i] then yes else no;
#for (i = 0;
#i < PivotLength;
#i++)
# VolDryup = VolDryup AND Ref(V, -i) < Ref(Vma, -i);
#}
# Filter results #####################/
plot scan = NearHigh and VolDecreasing and IsPivot and VolumeDrying;
#EOF