StockFetcher Forums · Filter Exchange · Pocket Pivot Scan<< 1 2 3 >>Post Follow-up
kmadnani
15 posts
msg #152243
Ignore kmadnani
5/19/2020 7:18:29 PM

Experts could you please help convert the following PocketPivot scan from ThinkorSwim into Stockfetcher. The logic is expressed below along with the TOS code.


# Copyright 2015 Scott J. Johnson (http://scottjjohnson.com)

#This study checks price and volume to see if they met the pocket pivot criteria. The other criteria (strong fundamentals, no wedging, constructive basing, etc.) need to be evaluated separately. I made these additions/modifications to Gil's and Chris's vague and sometimes conflicting definition of a pocket pivot:

#Per Gil and Chris, the volume on the day of the pocket pivot must be higher than any down day in the previous 10 days. But if the volume is "choppy", then increase the period to 11 to 15 days. But they don't define "choppy". For the purposes of this script, I define choppy when the standard deviation of the volume is > 125% of the average. Update: I removed the stddev logic since it didn't eliminate any obviously poor pivots. I'm always looking at the volume on the previous 10 days.
#I only count the pocket pivot if the stock closes in the upper 62% of the day's price range. Up days that close lower in the range are considered stalling.
#Gil and Chris say daily price closes prior to the pivot should be "tight" without any specifics. I defined tight as where the average percent price change at close over the last 10 days is <= 1.5%. Update: I removed this rule after backtesting against Gil's examples.
#Gil and Chris have examples of pocket pivots off of the 50-day instead of the 10-day. At that point the stock is extended from the 10-day. That seems to conflict with the idea that a pocket pivot occurs after a quiet period in the stock so I have not implemented rules for 50-day PPs here.
#The low on the day of the pivot must be within 1.4% of the 10-day SMA or the price must have moved up through the 10-day during that day. Several of Gil/Chris's examples conflict. (Example: 1.24 in one example is described as too extended, but there are others where 1.6 or even 2.5% above the 10-day SMA isn't too extended. In the Trading Cockpit with the O'Neil Disciples, Chapter 5.) I'm choosing to use a middle and slightly conservative setting here. The more extended, the more risky the buy.
#Pocket pivots should not be bought when then stock is below the 50- or 200-day simple moving averages. I check only the 50-day here because when I checked the 200-day, TOS was hiding the study for recent IPOs with less than 200 days of price history.
input Period = 11; # normal volume lookback period (today + 10 prior days)
input MaximumDistanceFrom10DaySMAPercent = 1.4; # Price on pivot day should be near the 10-day SMA. MAX = 1.6 Per FOSL1, 1.23 per PII, but RAX not extended at 1.61 and 1.64.

# Volume functions
def DownVolume = If(close < close[1], volume, 0);
def HighestDownVolume = Highest(DownVolume, Period);

def FiftyDayAverageVolume = MovingAverage(AverageType.SIMPLE, volume, 50);

def IsVolumeGreaterHighestDownVolume = if (volume > HighestDownVolume) then 1 else 0;

# Price functions
def TenDaySMA = MovingAverage(AverageType.SIMPLE, close, 10);
def FiftyDaySMA = MovingAverage(AverageType.SIMPLE, close, 50);

def IsLowPriceNear10DaySMA = if ((AbsValue(low - TenDaySMA) / TenDaySMA) <= MaximumDistanceFrom10DaySMAPercent / 100) then 1 else 0;
def DidPricePass10DaySMA = if (low <= TenDaySMA && close >= TenDaySMA) then 1 else 0;

def IsPriceNear10DaySMA = if (IsLowPriceNear10DaySMA or DidPricePass10DaySMA) then 1 else 0;

def IsPriceAtOrAbove50DaySMA = if (close >= FiftyDaySMA) then 1 else 0;

def AveragePriceChangePercent = MovingAverage(AverageType.SIMPLE, AbsValue(close[1] - close[2]) / close[2], Period);

def IsCloseInUpperHalfOfRange = close >= close[1] && close > ((high - low) * .38 + low);

def IsPriceInTheProperRange = if (IsCloseInUpperHalfOfRange && IsPriceNear10DaySMA && IsPriceAtOrAbove50DaySMA) then 1 else 0;

# add a chart bubble if then PP criteria are met
AddChartBubble(IsVolumeGreaterHighestDownVolume && IsPriceInTheProperRange, low, "PP", Color.CYAN, no);

#Scan
def PParrow = IsVolumeGreaterHighestDownVolume and IsPriceInTheProperRange;
plot PP = PParrow;
PP.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
PP.SetLineWeight(2);
PP.AssignValueColor(Color.WHITE);

xarlor
272 posts
msg #152276
Ignore xarlor
5/21/2020 9:01:56 PM

My first draft below:

Fetcher[
average volume(30) > 500000
close > 1
not etf

/* the volume on the day of the pocket pivot must be higher than any down day in the previous 10 days */
/* Note: Scorched earth - can't isoalte just down days so went with volume > any volume in past 10 days */

set{var1,max(volume 1 day ago, volume 2 days ago)}
set{var2,max(volume 3 days ago, volume 4 days ago)}
set{var3,max(volume 5 days ago, volume 6 days ago)}
set{var4,max(volume 7 days ago, volume 8 days ago)}
set{var5,max(volume 9 days ago, volume 10 days ago)}

set{volh1,max(var1,var2)}
set{volh2,max(var3,var4)}
set{volh3,max(volh1,volh2)}
set{volh,max(volh3,var5)}

volume > volh

/* Only count the pocket pivot if the stock closes in the upper 62% of the day's price range. */

close > day position(0.62,1)

/* daily price closes prior to the pivot should be "tight" */

set{hiclose,close 1 day ago 10-day high}
set{loclose,close 1 day ago 10-day low}
set{cldiff,loclose / hiclose}
cldiff > .95

/* The low on the day of the pivot must be within 1.4% of the 10-day SMA or the price must have moved up through the 10-day during that day. */

set{malo1,low / ma(10)}
set{malo2,malo1 - 1}
set{malo,count(malo2 between 0 and -0.014,1)}
set{ma10cross,count(price crossed above ma(10),1)}
malo + ma10cross > 0

/* Pocket pivots should not be bought when then stock is below the 50- or 200-day simple moving averages. */
close > ma(50)
close > ma(200)

draw ma(10)

do not draw volh
do not draw cldiff
do not draw ma10cross
]



kmadnani
15 posts
msg #152295
Ignore kmadnani
5/23/2020 6:31:19 PM

That's a great start!. It caught AMT which is on my scan result for 5/22/2020. Following is the rest of the list flagged with pocket pivots from that day.

AMT 242.43 +14.27 35 1.0 -15.0
PDD 68.70 +8.70 261 1.0 39.0
SBAC 289.96 +8.67 42 1.0 -14.0
BIO 472.45 +5.66 65 6.0 34.0
KRTX 86.74 +3.00 N/A 5.0 -7.0
FIVN 104.71 +1.37 123 1.0 39.0
HII 182.77 +1.27 -34 5.0 -19.0
AVY 106.45 +.54 35 3.0 -11.0
LSXMK 32.62 +.50 -36 5.0 -9.0
SNDR 22.33 +.48 34 5.0 -2.0
KDP 27.16 +.28 39 5.0 8.0
IUSG 67.90 +.23 37 5.0 35.0
FLO 22.89 +.07 29 -1.0 5.0
IGIB 58.65 +.07 16 8.0 5.0
IGSB 54.07 +.01 15 9.0 8.0 com.devexperts.tos.ui.seahorselaf.controls.icon.SeahorseCharacterIcon@72307c64


xarlor
272 posts
msg #152301
Ignore xarlor
5/23/2020 10:22:19 PM

I was curious why the other 14 were getting filtered out and came up with the following.


TL;DR - according to the rules in the OP, at a maximum, only AMT and SBAC should appear in your filter for 05/22/2020. That's based on absolute rules not requiring our personal interpretation.

  • 8 failed my Scorched Earth volume check. Don't know how to get around this one.

  • 2 failed "Only count the pocket pivot if the stock closes in the upper 62% of the day's price range." These 2 should not have appeared in your scan either.

  • The other 4 failed my definition of "daily price closes prior to the pivot should be tight". Relaxing this to .75 brought them back. I would argue PDD and KDP do not have "tight" daily price closes, however.

  • Still, those 4 failed "The low on the day of the pivot must be within 1.4% of the 10-day SMA or the price must have moved up through the 10-day during that day". These 4 should not appear in your scan either. In fact, ignoring all other filters, only FIVN, AMT, and SBAC satisfy this rule.

  • HII, KDP, LSXMK, and AVY are below either the ma(50) or ma(200) and should not appear in your results.

    Fetcher[
    symlist(AMT,PDD,SBAC,BIO,KRTX,FIVN,HII,AVY,LSXMK,SNDR,KDP,IUSG,FLO,IGIB,IGSB)

    /* Only count the pocket pivot if the stock closes in the upper 62% of the day's price range. */

    close > day position(0.62,1)

    /* The low on the day of the pivot must be within 1.4% of the 10-day SMA or the price must have moved up through the 10-day during that day. */

    set{malo1,low / ma(10)}
    set{malo2,malo1 - 1}
    set{malo,count(malo2 between 0 and -0.014,1)}
    set{ma10cross,count(price crossed above ma(10),1)}
    malo + ma10cross > 0

    /* Pocket pivots should not be bought when then stock is below the 50- or 200-day simple moving averages. */
    close > ma(50)
    close > ma(200)

    draw ma(10)

    do not draw ma10cross
    ]







  • kmadnani
    15 posts
    msg #152329
    Ignore kmadnani
    5/25/2020 5:23:50 PM

    Fore the scorched volume alternative. Following TOS study has the logic for buying and selling volume. Plus it filters buying or selling volume > 95% on the day. Maybe that can be used to filter stocks with the pocket pivot criteria volume

    # CustVolumeStudy by 7of9 for BRT

    declare lower;

    #Inputs

    input Show30DayAvg = yes;
    input ShowTodayVolume = yes;
    input ShowPercentOf30DayAvg = yes;
    input UnusualVolumePercent = 200;
    input Show30BarAvg = yes;
    input ShowCurrentBar = yes;
    input ShowPercentOf30BarAvg = yes;
    input ShowSellVolumePercent = yes;
    input ShowBuyVolumePercent=yes;

    def O = open;
    def H = high;
    def C = close;
    def L = low;
    def V = volume;
    def buying = V*(C-L)/(H-L);
    def selling = V*(H-C)/(H-L);

    # Selling Volume

    Plot SellVol = selling;
    SellVol.setPaintingStrategy(PaintingStrategy.Histogram);
    SellVol.SetDefaultColor(Color.Red);
    SellVol.HideTitle();
    SellVol.HideBubble();
    SellVol.SetLineWeight(5);

    # Total Volume

    Plot BuyVol = volume;
    BuyVol.setPaintingStrategy(PaintingStrategy.Histogram);
    BuyVol.SetDefaultColor(Color.Dark_Green);
    BuyVol.HideTitle();
    BuyVol.HideBubble();
    BuyVol.SetLineWeight(5);

    #Volume Data

    def volLast30DayAvg = (volume(period = "DAY")[1] + volume(period = "DAY")[2] + volume(period = "DAY")[3] + volume(period = "DAY")[4] + volume(period = "DAY")[5] + volume(period = "DAY")[6] + volume(period = "DAY")[7] + volume(period = "DAY")[8] + volume(period = "DAY")[9] + volume(period = "DAY")[10] + volume(period = "DAY")[11] + volume(period = "DAY")[12] + volume(period = "DAY")[13] + volume(period = "DAY")[14] + volume(period = "DAY")[15] + volume(period = "DAY")[16] + volume(period = "DAY")[17] + volume(period = "DAY")[18] + volume(period = "DAY")[19] + volume(period = "DAY")[20] + volume(period = "DAY")[21] + volume(period = "DAY")[22] + volume(period = "DAY")[23] + volume(period = "DAY")[24] + volume(period = "DAY")[25] + volume(period = "DAY")[26] + volume(period = "DAY")[27] + volume(period = "DAY")[28] + volume(period = "DAY")[29] + volume(period = "DAY")[30]) / 30;
    def today = volume(period = "DAY");
    def percentOf30Day = Round((today / volLast30DayAvg) * 100, 0);
    def avg30Bars = (volume[1] + volume[2] + volume[3] + volume[4] + volume[5] + volume[6] + volume[7] + volume[8] + volume[9] + volume[10] + volume[11] + volume[12] + volume[13] + volume[14] + volume[15] + volume[16] + volume[17] + volume[18] + volume[19] + volume[20] + volume[21] + volume[22] + volume[23] + volume[24] + volume[25] + volume[26] + volume[27] + volume[28] + volume[29] + volume[30]) / 30;
    def curVolume = volume;
    def percentOf30Bar = Round((curVolume / avg30Bars) * 100, 0);
    def SellVolPercent = Round((Selling / Volume) * 100, 0);
    def BuyVolPercent = 100 - SellVolPercent;

    # Labels

    AddLabel(Show30DayAvg, "Avg 30 Days: " + Round(volLast30DayAvg, 0), Color.LIGHT_GRAY);

    AddLabel(ShowTodayVolume, "Today: " + today, (if percentOf30Day >= UnusualVolumePercent then Color.GREEN else if percentOf30Day >= 100 then Color.ORANGE else Color.LIGHT_GRAY));

    AddLabel(ShowPercentOf30DayAvg, percentOf30Day + "%", (if percentOf30Day >= UnusualVolumePercent then Color.GREEN else if percentOf30Day >= 100 then Color.ORANGE else Color.WHITE) );

    AddLabel(Show30BarAvg, "Avg 30 Bars: " + Round(avg30Bars, 0), Color.LIGHT_GRAY);

    AddLabel(ShowCurrentBar, "Cur Bar: " + curVolume, (if percentOf30Bar >= UnusualVolumePercent then Color.GREEN else if PercentOf30Bar >= 100 then Color.ORANGE else Color.LIGHT_GRAY));

    AddLabel(ShowPercentOf30BarAvg, PercentOf30Bar + "%", (if PercentOf30Bar >= UnusualVolumePercent then Color.GREEN else if PercentOf30Bar >= 100 then Color.ORANGE else Color.WHITE) );

    AddLabel(ShowSellVolumePercent, "Cur Bar Sell %: " + SellVolPercent, (if SellVolPercent > 51 then Color.RED else if SellVolPercent < 49 then Color.GREEN else Color.ORANGE));

    AddLabel(ShowBuyVolumePercent, "Cur Bar Buy %: " + BuyVolPercent, (if BuyVolPercent < 49 then Color.RED else if BuyVolPercent > 51 then Color.GREEN else Color.ORANGE));

    input length = 50;

    plot Vol = volume;
    plot VolAvg = Average(volume, length);

    Vol.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
    Vol.SetLineWeight(3);
    Vol.DefineColor("Up", Color.UPTICK);
    Vol.DefineColor("Down", Color.DOWNTICK);
    Vol.AssignValueColor(if close > close[1] then Vol.color("Up") else if close < close[1] then Vol.color("Down") else GetColor(1));
    VolAvg.SetDefaultColor(GetColor(8));


    Mansor
    62 posts
    msg #152332
    Ignore Mansor
    modified
    5/25/2020 8:24:52 PM

    X - Could you produce a filter that can yield results on basic stock fetcher settings as well? Edit - Nvm, I used filter from post #4 and removed sym list.

    KD - Thanks for sharing custom vol study for tos.

    xarlor
    272 posts
    msg #152333
    Ignore xarlor
    modified
    5/26/2020 8:05:27 AM

    @kmadnani One of the limitations of SF is you can't store a variable for recall later. For example, if I identify that 3 days ago was a down day and assign it a variable 3dd, I can't then input 3dd into "volume 3dd ago".

    @Mansor, Honestly, I don't know what I was thinking when I wrote the volume bit. In trying to come up with a solution to only identifying down-days and counting their volume, I got lost in the weeds. That mess of volume code can be replaced with a single line: volume is at a 11 day high.

    Updated filter below, maybe this works with basic.

    Fetcher[
    average volume(30) > 500000
    close > 1
    not etf

    /* the volume on the day of the pocket pivot must be higher than any down day in the previous 10 days */
    /* Note: Scorched earth - can't isoalte just down days so went with volume > any volume in past 10 days */

    volume is at a 11 day high

    /* Only count the pocket pivot if the stock closes in the upper 62% of the day's price range. */

    close > day position(0.62,1)

    /* daily price closes prior to the pivot should be tight */

    set{hiclose,close 1 day ago 10-day high}
    set{loclose,close 1 day ago 10-day low}
    set{cldiff,loclose / hiclose}
    cldiff > .95

    /* The low on the day of the pivot must be within 1.4% of the 10-day SMA or the price must have moved up through the 10-day during that day. */

    set{malo1,low / ma(10)}
    set{malo2,malo1 - 1}
    set{malo,count(malo2 between 0 and -0.014,1)}
    set{ma10cross,count(price crossed above ma(10),1)}
    malo + ma10cross > 0

    /* Pocket pivots should not be bought when then stock is below the 50- or 200-day simple moving averages. */
    close > ma(50)
    close > ma(200)

    draw ma(10)

    do not draw volh
    do not draw cldiff
    do not draw ma10cross
    ]



    kmadnani
    15 posts
    msg #152339
    Ignore kmadnani
    5/26/2020 3:56:48 PM

    Pocket Pivot Scan for 5/26/2020 (Some of these are below the 200DMA but they are flagged in the TOS scan)

    CCEP 38.00 +1.35 -35 4.0 -20.0
    CMI 167.11 +12.07 63 1.0 1.0
    EQT 14.75 +1.01 197 4.0 -9.0
    FAST 39.72 +1.04 41 1.0 32.0
    IGIB 58.74 +.09 16 9.0 6.0
    IGSB 54.11 +.04 15 10.0 9.0
    IONS 56.04 +1.57 35 3.0 -8.0
    MSA 120.22 +3.83 38 5.0 16.0
    RY 63.78 +4.91 29 1.0 -4.0
    SLGN 32.94 +.56 30 -4.0 -10.0
    TAL 57.32 +4.02 85 1.0 14.0
    TCOM 26.04 +2.24 -36 -2.0 21.0
    USFD 19.33 +1.52 99 6.0 -9.0
    VRSK 160.46 +3.18 32 5.0 35.0
    WMGI 29.75 +.30 53 1.0 0.0
    WNS 48.22 +6.27 40 5.0 -8.0
    WYNN 84.89 +6.64 97 -1.0 -4.0
    YY 62.65 +6.82 49 -1.0 4.0

    nibor100
    495 posts
    msg #152378
    Ignore nibor100
    5/30/2020 2:24:27 PM

    @kmadnani,

    Could you post your TOS pocket pivot scan results from Friday?

    I've added some stuff to Xarlor's filter and I'd like to compare my results to yours.

    thanks,
    Ed S.

    nibor100
    495 posts
    msg #152381
    Ignore nibor100
    5/30/2020 9:04:05 PM

    @kmadnani,

    Please provide the other details that limit your TOS results to those that you have been posting as there is no way that scan you provided in your 1st post limits any large group of stocks to just those 15 on May22, and the 18 on May 26.

    There must be some other volume or price criteria etc.

    Thanks,
    Ed S.

    StockFetcher Forums · Filter Exchange · Pocket Pivot Scan<< 1 2 3 >>Post Follow-up

    *** Disclaimer *** StockFetcher.com does not endorse or suggest any of the securities which are returned in any of the searches or filters. They are provided purely for informational and research purposes. StockFetcher.com does not recommend particular securities. StockFetcher.com, Vestyl Software, L.L.C. and involved content providers shall not be liable for any errors or delays in the content, or for any actions taken based on the content.


    Copyright 2018 - Vestyl Software L.L.C.Terms of Service | License | Questions or comments? Contact Us
    EOD Data sources: DDFPlus & CSI Data Quotes delayed during active market hours. Delay times are at least 15 mins for NASDAQ, 20 mins for NYSE and Amex. Delayed intraday data provided by DDFPlus