87 lines
3.7 KiB
Plaintext
87 lines
3.7 KiB
Plaintext
ShortSqueeze SqueezeScan # TOS Short Squeeze Scanner
|
|
# Run in: TOS -> Tools -> Run Scan (or save to Scan Library)
|
|
# Data period: Pre-Market (select in scan data settings)
|
|
# Columns: Symbol, Ticker, SI%(manual), Squeeze, Gap%, PremkVol, PremkVolPct, PremkRange%, PremkAboveVWAP, PremkBid, PremkAsk, PremkMid
|
|
#
|
|
# HOW TO USE:
|
|
# 1. TOS -> Tools -> Run Scan. Paste this entire file into the "ThinkScript" box.
|
|
# 2. Set data period: Pre-Market. Exclusions: None.
|
|
# 3. Universe: US stocks, price > $1, volume > 0.
|
|
# (For a tighter list, add a static pre-filter for float < 30M shares.)
|
|
# 4. Run. Sort by SqueezeScore.
|
|
# 5. Manually enter each candidate's short float % (SI%) using TOS stock
|
|
# details page, S3 Partners, or your usual source. This column feeds
|
|
# the SqueezeScore but the technical flags work without it.
|
|
# 6. Best candidates: Squeeze=1 AND PremkAboveVWAP=0 AND PremkVolPct > 1.5
|
|
# AND SI% > 25.
|
|
|
|
input gapUpMin = 1.0; # min % gap up from prev close
|
|
input gapUpMax = 12.0; # max % gap up (above this = news/pop already done)
|
|
input volPctMin = 1.5; # min premarket volume as % of 1-day avg
|
|
input vwAPBand = 0.75; # % band around VWAP where "hug" is valid
|
|
input squeezeScoreMin = 1; # min score to show (1-5 scale)
|
|
|
|
# ---- Price levels (premarket context) ----
|
|
def prevClose = Close[-1];
|
|
def open = Open;
|
|
def high = High;
|
|
def low = Low;
|
|
def close = Close;
|
|
def vol = Volume;
|
|
|
|
def gapPct = if prevClose > 0 then (open - prevClose) / prevClose * 100.0 else Double.NaN;
|
|
|
|
# ---- Pre-market VWAP approximation ----
|
|
# Built from the day's bars so far, so it includes premarket prints.
|
|
def vwapCalc = if Sum(vol, 1) > 0 then Sum(close*vol, 1) / Sum(vol, 1) else Double.NaN;
|
|
|
|
def vwapPctFromClose = if vwapCalc > 0 then (close - vwapCalc) / vwapCalc * 100.0 else Double.NaN;
|
|
|
|
# ---- Pre-market volume as % of 1-day average ----
|
|
def avgVol1D = Average(vol, 22); # ~1 trading day of 1-min bars
|
|
def volPct = if avgVol1D > 0 then vol / avgVol1D * 100.0 else Double.NaN;
|
|
|
|
# ---- Pre-market range as % of prev close (narrow range = coiling) ----
|
|
def rangePct = if prevClose > 0 then (high - low) / prevClose * 100.0 else Double.NaN;
|
|
|
|
# ---- Is price hugging/just under VWAP? ----
|
|
def huggingVWAP = vwapCalc > 0 and vwapPctFromClose >= -vwAPBand and vwapPctFromClose <= vwAPBand;
|
|
|
|
# ---- Squeeze flags ----
|
|
def flagGap = gapPct >= gapUpMin and gapPct <= gapUpMax;
|
|
def flagVol = volPct >= volPctMin;
|
|
def flagHug = huggingVWAP;
|
|
def flagNarrow = rangePct <= 2.5; # narrow range = coiling, ready to spring
|
|
|
|
# ---- Squeeze score: 0-5 (add SI% manually in the column) ----
|
|
def score = (if flagGap then 1 else 0)
|
|
+ (if flagVol then 1 else 0)
|
|
+ (if flagHug then 1 else 0)
|
|
+ (if flagNarrow then 1 else 0)
|
|
+ 0; # SI% is manual - add +1 in your head if SI > 25
|
|
|
|
# ---- Composite squeeze signal ----
|
|
def squeezeSignal = flagGap and flagVol and flagHug and squeezeScore >= squeezeScoreMin;
|
|
|
|
# ---- Output columns ----
|
|
plot Ticker = GetSymbol();
|
|
plot Symbol = GetSymbol();
|
|
plot SI_Pct = Double.NaN; # MANUAL: paste short float % per ticker
|
|
plot Squeeze = squeezeSignal ? 1 : 0;
|
|
plot GapPctOut = gapPct;
|
|
plot PremkVol = vol;
|
|
plot PremkVolPct = volPct;
|
|
plot PremkRangePct = rangePct;
|
|
plot PremkAboveVWAP = if vwapPctFromClose > 0 then 1 else 0;
|
|
plot PremkVWAPPct = vwapPctFromClose;
|
|
plot PremkBid = BidPrice;
|
|
plot PremkAsk = AskPrice;
|
|
plot PremkMid = (BidPrice + AskPrice) / 2;
|
|
plot SqueezeScore = score;
|
|
|
|
# ---- Scanner conditions (filter rows) ----
|
|
# Adjust to taste. Starting: at least a gap-up + elevated volume + VWAP hug.
|
|
condition SqueezeSetup = squeezeSignal;
|
|
condition GapUpOnly = flagGap and flagVol;
|
|
condition VolSpikeOnly = flagVol;
|