0 DTE option flow for SPX (WIP)

ChocolateVol

New member
see code fix in next post
Hi, I'm stuck with this script. Syntax appears to be right but for some reason I cant figure out why its not working. Issue is popping up at the ATM_option line.

My goal is to track the intraday 0 DTE option volume for ATM calls and puts for SPX and SPY that are within the daily market maker's expected move (using the prior day's VIX close).

Once I can make it work for SPX calls I want to replicate for SPY and also use it on PUTS in a lower study or as an inverted negative histogram in the same plot.
I'm trying to track institutional buying/selling pressure (hence the threshold for size).

When the script is valid, ideally I want to explore beyond volume to track premium (price*volume) and gamma.

This on itself would ultimately always be a bias confirmation not an isolated trading signal.
 
Last edited by a moderator:
Solution
This study is great, thanks to all in this thread sharing.

One question, I am unable to get SPX premiums to display (even if my upper chart is SPY or /ES), I have also tried using SPXW as ticker as done with other scripts in this thread. Any idea why this isn't working?

Try this:
set show extended hours to off

Code:
# Run on 1 min chart only.  Calculates Premium. ( 1 min volume x 1 min OHLC4)
# Starts at 945. First 15 min lots of chaos and false signals.

declare lower;
declare once_per_bar;

input chain_width = 5;
input symbol = "SPXW"; #"SPXW"
input premium_extreme = 1000000;

def after945 = SecondsFromTime(945) >= 0;

def vix = close("VIX", AggregationPeriod.DAY)[1];
#def price = round(close(symbol...
Code:
declare lower;
declare once_per_bar;

input days = 1;
input chain_width = 5;
input threshold = 50;

def vix = close("VIX", AggregationPeriod.DAY)[1];
def SPX_1 = close("SPX", AggregationPeriod.DAY)[1];
def move = vix / Sqrt(252 / days) / 100;
def strike_up = Round (SPX_1 * (1 + move) / chain_width, 0.01) * chain_width;
def strike_down =  Round (SPX_1 * (1 - move) / chain_width, 0.01) * chain_width;

#get total call option volumes around the ATM strikes that are within the expected daily move

# get ATM strike
def ATM_Strike = Round (SPX_1 / chain_width, 0.01) * chain_width;

# get 0DTE expiration
def currentYear = (Round(GetYYYYMMDD() / 10000, 0)) - 2000;
def currentMonth = if GetMonth() <= 9 then Concat(0, GetMonth()) else GetMonth();
def currentDay = if GetDayOfMonth(GetYYYYMMDD()) <= 9 then Concat(0, GetDayOfMonth(GetYYYYMMDD())) else GetDayOfMonth(GetYYYYMMDD());

def expiration = currentYear + currentMonth + currentDay;

#define option series code

def ATM_option = ".SPXW" + expiration + "C";

def Call_Volume = fold strike = ATM_Strike to strike_up with v do v + if IsNaN(volume(Concat(ATM_option, AsPrice(strike)))) then 0 else if threshold > volume(Concat(ATM_option, AsPrice(strike))) then 0 else volume(Concat(ATM_option, AsPrice(strike)));

plot test = Call_Volume;
test.SetPaintingStrategy(PaintingStrategy.SQUARED_HISTOGRAM);
test.AssignValueColor(if Call_Volume > 1000 then Color.GREEN else Color.DARK_GRAY);
Hi, I'm stuck with this script. Syntax appears to be right but for some reason I cant figure out why its not working. Issue is popping up at the ATM_option line.

My goal is to track the intraday 0 DTE option volume for ATM calls and puts for SPX and SPY that are within the daily market maker's expected move (using the prior day's VIX close).

Once I can make it work for SPX calls I want to replicate for SPY and also use it on PUTS in a lower study or as an inverted negative histogram in the same plot.
I'm trying to track institutional buying/selling pressure (hence the threshold for size).

When the script is valid, ideally I want to explore beyond volume to track premium (price*volume) and gamma.

This on itself would ultimately always be a bias confirmation not an isolated trading signal.
Id like to see what shakes out of this
 
Code:
declare lower;
declare once_per_bar;

input Strike_Spacing = 5;
input symbol = "SPXW";
input manual_base_strike = 4125;

def CurrentYear = GetYear()-2000;
def CurrentMonth = GetMonth();
def CurrentDOM = GetDayOfMonth(GetYYYYMMDD());
def DateString = CurrentYear * 10000 + CurrentMonth * 100 + CurrentDOM;

def base = manual_base_strike;

def strike_atm = base;
def strike_minus1 = base - Strike_Spacing;
def strike_minus2 = base - Strike_Spacing * 2;
def strike_plus1 =  base + Strike_Spacing;
def strike_plus2 =  base + Strike_Spacing * 2;

def call_volume = volume("." + symbol +  AsPrice(DateString) + "C" + AsPrice(strike_atm));
def call_volume1 = volume("." + symbol +  AsPrice(DateString) + "C" + AsPrice(strike_plus1));
def call_volume2 = volume("." + symbol + AsPrice(DateString) + "C" + AsPrice(strike_plus2));
def call_volume3 = volume("." + symbol + AsPrice(DateString) + "C" + AsPrice(strike_minus1));
def call_volume4 = volume("." + symbol +  AsPrice(DateString) + "C" + AsPrice(strike_minus2));

def put_volume = volume("." + symbol + AsPrice(DateString) + "P" + AsPrice(strike_atm));
def put_volume1 = volume("." + symbol +AsPrice(DateString) + "P"  + AsPrice(strike_minus1));
def put_volume2 = volume("." + symbol + AsPrice(DateString) + "P" + AsPrice(strike_minus2));
def put_volume3 = volume("." + symbol + AsPrice(DateString) + "P" + AsPrice(strike_plus1));
def put_volume4 = volume("." + symbol +AsPrice(DateString) + "P" + AsPrice(strike_plus2));


def callvolumetotal = call_volume+ call_volume1 + call_volume2 + call_volume3 + call_volume4;
def putvolumetotal = put_volume+ put_volume1 + put_volume2 + put_volume3 + put_volume4;

plot calls = callvolumetotal;
calls.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
calls.SetLineWeight(5);
calls.SetDefaultColor(Color.GREEN);

plot puts = -1*putvolumetotal;
puts.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
puts.SetLineWeight(5);
puts.SetDefaultColor(Color.RED);

Here is something basic to get you started. You can't use this on an SPX chart. You can use it on SPY or /ES.

SPX does not like indicators with volume. I believe because SPX is an index.
 
Last edited by a moderator:
@2187Nick is right. I also use the same concept and run the script on SPY etc. Please see below where I took both scripts above and merged relevant concepts. This should show both put/call volumes.

Rich (BB code):
declare lower;
declare once_per_bar;

input days = 1;
input chain_width = 5;
input threshold = 50;
input symbol = "SPXW";

def vix = close("VIX", AggregationPeriod.DAY)[1];
def SPX_1 = close("SPX", AggregationPeriod.DAY)[1];


def move = vix / Sqrt(252 / days) / 100;
def strike_up = Round (SPX_1 * (1 + move) / chain_width, 0.01) * chain_width;
def strike_down =  Round (SPX_1 * (1 - move) / chain_width, 0.01) * chain_width;

#get total call option volumes around the ATM strikes that are within the expected daily move

# get ATM strike
def ATM_Strike = Round (SPX_1 / chain_width, 0.01) * chain_width;

# get 0DTE expiration
def CurrentYear = GetYear()-2000;
def CurrentMonth = GetMonth();
def CurrentDay = GetDayOfMonth(GetYYYYMMDD());
def DateString = CurrentYear * 10000 + CurrentMonth * 100 + CurrentDay;

#AddLabel(yes, AsPrice(DateString));
#AddLabel(yes, "Spx_close" + strike_up + " " + strike_down  );

#define option series code


def Call_Volume = fold strike_c = ATM_Strike to strike_up with v do v +
                if IsNaN(volume("." + symbol +  AsPrice(DateString) + "C" + AsPrice(strike_c))) then 0
                else if threshold > volume("." + symbol +  AsPrice(DateString) + "C" + AsPrice(strike_c)) then 0
                else volume("." + symbol +  AsPrice(DateString) + "C" + AsPrice(strike_c));

def Put_Volume = fold strike_p = ATM_Strike to strike_up with v_p do v_p +
                if IsNaN(volume("." + symbol +  AsPrice(DateString) + "P" + AsPrice(strike_p))) then 0
                else if threshold > volume("." + symbol +  AsPrice(DateString) + "P" + AsPrice(strike_p)) then 0
                else volume("." + symbol +  AsPrice(DateString) + "P" + AsPrice(strike_p));



plot test = Call_Volume;
test.SetPaintingStrategy(PaintingStrategy.SQUARED_HISTOGRAM);
test.AssignValueColor(if Call_Volume > 1000 then Color.GREEN else Color.DARK_GRAY);

plot test_2 = -1.0 * put_Volume; #show below zero for display purposes
test_2.SetPaintingStrategy(PaintingStrategy.SQUARED_HISTOGRAM);
test_2.AssignValueColor(if put_Volume > -1.0 * 1000 then Color.RED else Color.DARK_GRAY);


 
Last edited:
Hi @RajB,

Fantastic work. Can you please explain how to change this from SPX to SPY or /ES?

And what do you generally look for with this study? Just getting into options and futures myself.
  • the idea/OP was from @ChocolateVol , maybe he can comment? It sounded like it was the beginning of an experiment/framework that could expand further and details needed to be figured out
  • If you want to look at SPY or /ES options, change the input symbol from SPXW to SPY or /ES.
 
@RajB nice work! and thanks for the feedback @2187Nick!

I was working separately on a different version that was skipping the automation for the date string (that's were my error was) and managed to correctly pull volumes for SPX (when charting SPY, wont work on SPX). Anyway, not enough progress to post an update.

@PT_Scalper So now that the date issue has been fixed, the next steps would be to:
1. Add both SPX and SPY and check if calls and puts volume on a standalone basis are indicative/reliable to confirm a bullish/bearish bias.
2. See if we can replicate for premium
3. See if we can replicate for gamma

By focusing on ATM only or within the market makers' expected move you should be capturing the bulk of the gamma flow for ODTE, minimizing RAM utilization on your PC since you are only looking at 1 expiration and limited strikes (so should be able to run continuously on a 1 min bar without crashing your ToS).

Other angles I need to explore are VVIX (VIX vol) and if any of the above can be combined for some kind of reliable signal.
 
@RajB nice work! and thanks for the feedback @2187Nick!

I was working separately on a different version that was skipping the automation for the date string (that's were my error was) and managed to correctly pull volumes for SPX (when charting SPY, wont work on SPX). Anyway, not enough progress to post an update.

@PT_Scalper So now that the date issue has been fixed, the next steps would be to:
1. Add both SPX and SPY and check if calls and puts volume on a standalone basis are indicative/reliable to confirm a bullish/bearish bias.
2. See if we can replicate for premium
3. See if we can replicate for gamma

By focusing on ATM only or within the market makers' expected move you should be capturing the bulk of the gamma flow for ODTE, minimizing RAM utilization on your PC since you are only looking at 1 expiration and limited strikes (so should be able to run continuously on a 1 min bar without crashing your ToS).

Other angles I need to explore are VVIX (VIX vol) and if any of the above can be combined for some kind of reliable signal.
Thank you for the feedback. I think my problem here is that if I use the SPXW as is within the study, it works. If I change to SPY or anything else it's not working.

I guess I don't know what the "W" is after SPX and if SPY or /ES has a specific ticker code in ToS that I'm not aware of?

Any help would be appreciated..
 
This is a setup I have been using last couple years. It calculates the premium.

The results are counter intuitive. When we are reaching a peak high intraday there will be large levels of calls bought/sold. When near peak low we see large levels of puts bought/sold.

Around $1 million in premium in SPY is a level I monitor.

Code:
# Run on 1 min chart only.  Calculates Premium. ( 1 min volume x 1 min OHLC4)
# Starts at 945. First 15 min lots of chaos and false signals.

declare lower;
declare once_per_bar;

input chain_width = 1;
input symbol = "SPY"; #"SPXW"
input premium_extreme = 1000000;

def after945 = SecondsFromTime(945) >= 0;

def vix = close("VIX", AggregationPeriod.DAY)[1];
def price = round(close(symbol, AggregationPeriod.day)[1],0);
#def price = round(close("SPX", AggregationPeriod.day)[1],0);


def move = vix / Sqrt(252) / 100;
def strike_down =  Round (price * (1 - move) / chain_width, 0.01) * chain_width;
def strike_up = Round (price * (1 + move) / chain_width, 0.01) * chain_width;
addlabel(yes, "Strike: " + strike_down + " to " + strike_up, color.cyan);


# get 0DTE expiration
def CurrentYear = GetYear()-2000;
def CurrentMonth = GetMonth();
def CurrentDay = GetDayOfMonth(GetYYYYMMDD());
def DateString = CurrentYear * 10000 + CurrentMonth * 100 + CurrentDay;

def Call_VolumexOHLC = fold strike_c = strike_down to strike_up with v do v +
                if IsNaN(volume("." + symbol +  AsPrice(DateString) + "C" + AsPrice(strike_c))) then 0
                else (volume("." + symbol +  AsPrice(DateString) + "C" + AsPrice(strike_c))
                *ohlc4("." + symbol +  AsPrice(DateString) + "C" + AsPrice(strike_c))
                );

def Put_VolumexOHLC = fold strike_p = strike_down to strike_up with v_p do v_p +
                if IsNaN(volume("." + symbol +  AsPrice(DateString) + "P" + AsPrice(strike_p)))then 0
                else (volume("." + symbol +  AsPrice(DateString) + "P" + AsPrice(strike_p))
                *ohlc4("." + symbol +  AsPrice(DateString) + "P" + AsPrice(strike_p))
                );

plot calls_total = if after945 then Call_VolumexOHLC*100 else 0;
calls_total.SetPaintingStrategy(PaintingStrategy.SQUARED_HISTOGRAM);
calls_total.AssignValueColor(if calls_total > premium_extreme then Color.GREEN else Color.DARK_GRAY);


plot puts_total = if after945 then -1.0 * put_VolumexOHLC*100 else 0;
puts_total.SetPaintingStrategy(PaintingStrategy.SQUARED_HISTOGRAM);
puts_total.AssignValueColor(if puts_total < -1.0 * premium_extreme then Color.RED else Color.DARK_GRAY);

plot highline = premium_extreme;
plot lowline = -1*premium_extreme;
highline.SetDefaultColor(Color.red);
lowline.SetDefaultColor(Color.green);

extreme.png
 
This is a setup I have been using last couple years. It calculates the premium.

The results are counter intuitive. When we are reaching a peak high intraday there will be large levels of calls bought/sold. When near peak low we see large levels of puts bought/sold.

Around $1 million in premium in SPY is a level I monitor.

Code:
# Run on 1 min chart only.  Calculates Premium. ( 1 min volume x 1 min OHLC4)
# Starts at 945. First 15 min lots of chaos and false signals.

declare lower;
declare once_per_bar;

input chain_width = 1;
input symbol = "SPY"; #"SPXW"
input premium_extreme = 1000000;

def after945 = SecondsFromTime(945) >= 0;

def vix = close("VIX", AggregationPeriod.DAY)[1];
def price = round(close(symbol, AggregationPeriod.day)[1],0);
#def price = round(close("SPX", AggregationPeriod.day)[1],0);


def move = vix / Sqrt(252) / 100;
def strike_down =  Round (price * (1 - move) / chain_width, 0.01) * chain_width;
def strike_up = Round (price * (1 + move) / chain_width, 0.01) * chain_width;
addlabel(yes, "Strike: " + strike_down + " to " + strike_up, color.cyan);


# get 0DTE expiration
def CurrentYear = GetYear()-2000;
def CurrentMonth = GetMonth();
def CurrentDay = GetDayOfMonth(GetYYYYMMDD());
def DateString = CurrentYear * 10000 + CurrentMonth * 100 + CurrentDay;

def Call_VolumexOHLC = fold strike_c = strike_down to strike_up with v do v +
                if IsNaN(volume("." + symbol +  AsPrice(DateString) + "C" + AsPrice(strike_c))) then 0
                else (volume("." + symbol +  AsPrice(DateString) + "C" + AsPrice(strike_c))
                *ohlc4("." + symbol +  AsPrice(DateString) + "C" + AsPrice(strike_c))
                );

def Put_VolumexOHLC = fold strike_p = strike_down to strike_up with v_p do v_p +
                if IsNaN(volume("." + symbol +  AsPrice(DateString) + "P" + AsPrice(strike_p)))then 0
                else (volume("." + symbol +  AsPrice(DateString) + "P" + AsPrice(strike_p))
                *ohlc4("." + symbol +  AsPrice(DateString) + "P" + AsPrice(strike_p))
                );

plot calls_total = if after945 then Call_VolumexOHLC*100 else 0;
calls_total.SetPaintingStrategy(PaintingStrategy.SQUARED_HISTOGRAM);
calls_total.AssignValueColor(if calls_total > premium_extreme then Color.GREEN else Color.DARK_GRAY);


plot puts_total = if after945 then -1.0 * put_VolumexOHLC*100 else 0;
puts_total.SetPaintingStrategy(PaintingStrategy.SQUARED_HISTOGRAM);
puts_total.AssignValueColor(if puts_total < -1.0 * premium_extreme then Color.RED else Color.DARK_GRAY);

plot highline = premium_extreme;
plot lowline = -1*premium_extreme;
highline.SetDefaultColor(Color.red);
lowline.SetDefaultColor(Color.green);

View attachment 18705
This thing is vicious! Excellent work!
 
This is a setup I have been using last couple years. It calculates the premium.

The results are counter intuitive. When we are reaching a peak high intraday there will be large levels of calls bought/sold. When near peak low we see large levels of puts bought/sold.

Around $1 million in premium in SPY is a level I monitor.

Code:
# Run on 1 min chart only.  Calculates Premium. ( 1 min volume x 1 min OHLC4)
# Starts at 945. First 15 min lots of chaos and false signals.

declare lower;
declare once_per_bar;

input chain_width = 1;
input symbol = "SPY"; #"SPXW"
input premium_extreme = 1000000;

def after945 = SecondsFromTime(945) >= 0;

def vix = close("VIX", AggregationPeriod.DAY)[1];
def price = round(close(symbol, AggregationPeriod.day)[1],0);
#def price = round(close("SPX", AggregationPeriod.day)[1],0);


def move = vix / Sqrt(252) / 100;
def strike_down =  Round (price * (1 - move) / chain_width, 0.01) * chain_width;
def strike_up = Round (price * (1 + move) / chain_width, 0.01) * chain_width;
addlabel(yes, "Strike: " + strike_down + " to " + strike_up, color.cyan);


# get 0DTE expiration
def CurrentYear = GetYear()-2000;
def CurrentMonth = GetMonth();
def CurrentDay = GetDayOfMonth(GetYYYYMMDD());
def DateString = CurrentYear * 10000 + CurrentMonth * 100 + CurrentDay;

def Call_VolumexOHLC = fold strike_c = strike_down to strike_up with v do v +
                if IsNaN(volume("." + symbol +  AsPrice(DateString) + "C" + AsPrice(strike_c))) then 0
                else (volume("." + symbol +  AsPrice(DateString) + "C" + AsPrice(strike_c))
                *ohlc4("." + symbol +  AsPrice(DateString) + "C" + AsPrice(strike_c))
                );

def Put_VolumexOHLC = fold strike_p = strike_down to strike_up with v_p do v_p +
                if IsNaN(volume("." + symbol +  AsPrice(DateString) + "P" + AsPrice(strike_p)))then 0
                else (volume("." + symbol +  AsPrice(DateString) + "P" + AsPrice(strike_p))
                *ohlc4("." + symbol +  AsPrice(DateString) + "P" + AsPrice(strike_p))
                );

plot calls_total = if after945 then Call_VolumexOHLC*100 else 0;
calls_total.SetPaintingStrategy(PaintingStrategy.SQUARED_HISTOGRAM);
calls_total.AssignValueColor(if calls_total > premium_extreme then Color.GREEN else Color.DARK_GRAY);


plot puts_total = if after945 then -1.0 * put_VolumexOHLC*100 else 0;
puts_total.SetPaintingStrategy(PaintingStrategy.SQUARED_HISTOGRAM);
puts_total.AssignValueColor(if puts_total < -1.0 * premium_extreme then Color.RED else Color.DARK_GRAY);

plot highline = premium_extreme;
plot lowline = -1*premium_extreme;
highline.SetDefaultColor(Color.red);
lowline.SetDefaultColor(Color.green);

View attachment 18705
@2187Nick is it possible to set alert whenever prices reaches the extremes?
 
@2187Nick is it possible to set alert whenever prices reaches the extremes?
Hey. I have never had good luck with alerts working consistently. Maybe somone else can add that in.

Here is the indicator that adds the extreme bubbles.

Code:
# Adds chart bubble when price is rising and call premium exceeds $1 million.
# Adds chart bubble when price is falling and put premium exceeds $1 million.
# 945 to 4pm
declare once_per_bar;

input chain_width = 1;
input symbol = "SPY";
input premium_extreme_level = 1000000;

def after945 = SecondsFromTime(945) >= 0;

def vix = close("VIX", AggregationPeriod.DAY)[1];

def price = round(close(symbol, AggregationPeriod.day)[1],0);
def move = vix / Sqrt(252) / 100;

def strike_up = Round (price * (1 + move) / chain_width, 0.01) * chain_width;
def strike_down =  Round (price * (1 - move) / chain_width, 0.01) * chain_width;

# get 0DTE expiration
def CurrentYear = GetYear()-2000;
def CurrentMonth = GetMonth();
def CurrentDay = GetDayOfMonth(GetYYYYMMDD());
def DateString = CurrentYear * 10000 + CurrentMonth * 100 + CurrentDay;

def Call_VolumexOHLC = fold strike_c = strike_down to strike_up with v do v +
                if IsNaN(volume("." + symbol +  AsPrice(DateString) + "C" + AsPrice(strike_c)))  then 0
                else (volume("." + symbol +  AsPrice(DateString) + "C" + AsPrice(strike_c))
                *ohlc4("." + symbol +  AsPrice(DateString) + "C" + AsPrice(strike_c))
                );

def Put_VolumexOHLC = fold strike_p = strike_down to strike_up with v_p do v_p +
                if IsNaN(volume("." + symbol +  AsPrice(DateString) + "P" + AsPrice(strike_p))) then 0
                else (volume("." + symbol +  AsPrice(DateString) + "P" + AsPrice(strike_p))
                *ohlc4("." + symbol +  AsPrice(DateString) + "P" + AsPrice(strike_p))
                );

def moving_up = if close[1] > close[2] then 1 else 0;
def moving_down = close[1] < close[2];

def calls_current_total = if after945 then Call_VolumexOHLC*100 else 0;
def puts_current_total = if after945 then  put_VolumexOHLC*100 else 0;

AddChartBubble(puts_current_total > premium_extreme_level and moving_down, low, "Extreme" , color.Green);
AddChartBubble(calls_current_total > premium_extreme_level and moving_up ==1, high+.1, "Extreme" , color.red);
 
This is a setup I have been using last couple years. It calculates the premium.

The results are counter intuitive. When we are reaching a peak high intraday there will be large levels of calls bought/sold. When near peak low we see large levels of puts bought/sold.

Around $1 million in premium in SPY is a level I monitor.

Code:
# Run on 1 min chart only.  Calculates Premium. ( 1 min volume x 1 min OHLC4)
# Starts at 945. First 15 min lots of chaos and false signals.

declare lower;
declare once_per_bar;

input chain_width = 1;
input symbol = "SPY"; #"SPXW"
input premium_extreme = 1000000;

def after945 = SecondsFromTime(945) >= 0;

def vix = close("VIX", AggregationPeriod.DAY)[1];
def price = round(close(symbol, AggregationPeriod.day)[1],0);
#def price = round(close("SPX", AggregationPeriod.day)[1],0);


def move = vix / Sqrt(252) / 100;
def strike_down =  Round (price * (1 - move) / chain_width, 0.01) * chain_width;
def strike_up = Round (price * (1 + move) / chain_width, 0.01) * chain_width;
addlabel(yes, "Strike: " + strike_down + " to " + strike_up, color.cyan);


# get 0DTE expiration
def CurrentYear = GetYear()-2000;
def CurrentMonth = GetMonth();
def CurrentDay = GetDayOfMonth(GetYYYYMMDD());
def DateString = CurrentYear * 10000 + CurrentMonth * 100 + CurrentDay;

def Call_VolumexOHLC = fold strike_c = strike_down to strike_up with v do v +
                if IsNaN(volume("." + symbol +  AsPrice(DateString) + "C" + AsPrice(strike_c))) then 0
                else (volume("." + symbol +  AsPrice(DateString) + "C" + AsPrice(strike_c))
                *ohlc4("." + symbol +  AsPrice(DateString) + "C" + AsPrice(strike_c))
                );

def Put_VolumexOHLC = fold strike_p = strike_down to strike_up with v_p do v_p +
                if IsNaN(volume("." + symbol +  AsPrice(DateString) + "P" + AsPrice(strike_p)))then 0
                else (volume("." + symbol +  AsPrice(DateString) + "P" + AsPrice(strike_p))
                *ohlc4("." + symbol +  AsPrice(DateString) + "P" + AsPrice(strike_p))
                );

plot calls_total = if after945 then Call_VolumexOHLC*100 else 0;
calls_total.SetPaintingStrategy(PaintingStrategy.SQUARED_HISTOGRAM);
calls_total.AssignValueColor(if calls_total > premium_extreme then Color.GREEN else Color.DARK_GRAY);


plot puts_total = if after945 then -1.0 * put_VolumexOHLC*100 else 0;
puts_total.SetPaintingStrategy(PaintingStrategy.SQUARED_HISTOGRAM);
puts_total.AssignValueColor(if puts_total < -1.0 * premium_extreme then Color.RED else Color.DARK_GRAY);

plot highline = premium_extreme;
plot lowline = -1*premium_extreme;
highline.SetDefaultColor(Color.red);
lowline.SetDefaultColor(Color.green);

View attachment 18705
This study is great, thanks to all in this thread sharing.

One question, I am unable to get SPX premiums to display (even if my upper chart is SPY or /ES), I have also tried using SPXW as ticker as done with other scripts in this thread. Any idea why this isn't working?
 
This study is great, thanks to all in this thread sharing.

One question, I am unable to get SPX premiums to display (even if my upper chart is SPY or /ES), I have also tried using SPXW as ticker as done with other scripts in this thread. Any idea why this isn't working?
Could it be the chart timeframe you are using? In looking at the script shows to be on 1min chart.
 
This is a setup I have been using last couple years. It calculates the premium.

The results are counter intuitive. When we are reaching a peak high intraday there will be large levels of calls bought/sold. When near peak low we see large levels of puts bought/sold.

Around $1 million in premium in SPY is a level I monitor.

Code:
# Run on 1 min chart only.  Calculates Premium. ( 1 min volume x 1 min OHLC4)
# Starts at 945. First 15 min lots of chaos and false signals.

declare lower;
declare once_per_bar;

input chain_width = 1;
input symbol = "SPY"; #"SPXW"
input premium_extreme = 1000000;

def after945 = SecondsFromTime(945) >= 0;

def vix = close("VIX", AggregationPeriod.DAY)[1];
def price = round(close(symbol, AggregationPeriod.day)[1],0);
#def price = round(close("SPX", AggregationPeriod.day)[1],0);


def move = vix / Sqrt(252) / 100;
def strike_down =  Round (price * (1 - move) / chain_width, 0.01) * chain_width;
def strike_up = Round (price * (1 + move) / chain_width, 0.01) * chain_width;
addlabel(yes, "Strike: " + strike_down + " to " + strike_up, color.cyan);


# get 0DTE expiration
def CurrentYear = GetYear()-2000;
def CurrentMonth = GetMonth();
def CurrentDay = GetDayOfMonth(GetYYYYMMDD());
def DateString = CurrentYear * 10000 + CurrentMonth * 100 + CurrentDay;

def Call_VolumexOHLC = fold strike_c = strike_down to strike_up with v do v +
                if IsNaN(volume("." + symbol +  AsPrice(DateString) + "C" + AsPrice(strike_c))) then 0
                else (volume("." + symbol +  AsPrice(DateString) + "C" + AsPrice(strike_c))
                *ohlc4("." + symbol +  AsPrice(DateString) + "C" + AsPrice(strike_c))
                );

def Put_VolumexOHLC = fold strike_p = strike_down to strike_up with v_p do v_p +
                if IsNaN(volume("." + symbol +  AsPrice(DateString) + "P" + AsPrice(strike_p)))then 0
                else (volume("." + symbol +  AsPrice(DateString) + "P" + AsPrice(strike_p))
                *ohlc4("." + symbol +  AsPrice(DateString) + "P" + AsPrice(strike_p))
                );

plot calls_total = if after945 then Call_VolumexOHLC*100 else 0;
calls_total.SetPaintingStrategy(PaintingStrategy.SQUARED_HISTOGRAM);
calls_total.AssignValueColor(if calls_total > premium_extreme then Color.GREEN else Color.DARK_GRAY);


plot puts_total = if after945 then -1.0 * put_VolumexOHLC*100 else 0;
puts_total.SetPaintingStrategy(PaintingStrategy.SQUARED_HISTOGRAM);
puts_total.AssignValueColor(if puts_total < -1.0 * premium_extreme then Color.RED else Color.DARK_GRAY);

plot highline = premium_extreme;
plot lowline = -1*premium_extreme;
highline.SetDefaultColor(Color.red);
lowline.SetDefaultColor(Color.green);

View attachment 18705
Hey I had a quick question, Thanks for this script. You did a nice job. I copy/Pasted your code into my own script and I am using this on a 1min for the SPY. It worked perfectly for a few days, then all of the sudden went blank as you can see from the screenshot. I know its a long shot, but does anyone have any ideas why it stopped working for me?
 

Attachments

  • Screenshot 2023-06-12 at 7.43.25 PM.png
    Screenshot 2023-06-12 at 7.43.25 PM.png
    119.4 KB · Views: 465
I need to work on top of @2187Nick awesome script above that uses premium, but below is just a teaser of what 1) SPX option volume flow around the ATM strikes (excluding SPY and /ES and above an arbitrary threshold) using 2min bars, combined with 2) a VVIX signal I started playing with would have looked like today. More to come before Friday hopefully.


View attachment 18712
If you would share your code I'll see if I can put a +/- Gex value in the ATM strike and will see if I can make a lable or bubble to alert when it changes from a certain amount of one to the other.
 
Hey I had a quick question, Thanks for this script. You did a nice job. I copy/Pasted your code into my own script and I am using this on a 1min for the SPY. It worked perfectly for a few days, then all of the sudden went blank as you can see from the screenshot. I know its a long shot, but does anyone have any ideas why it stopped working for me?
Hey. Try setting Time Interval = Today
 
Could it be the chart timeframe you are using? In looking at the script shows to be on 1min chart.

Yes I'm on a 1 min chart with extended trading hours turned off, the same settings work with SPY as an input.

Also it looks like valid strikes are being pulled, just no data is being plotted

OksP4CW.png


maybe its possible that in between the two edge strikes being displayed the script is checking invalid ones?
 

Join useThinkScript to post your question to a community of 21,000+ developers and traders.

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
256 Online
Create Post

Similar threads

Similar threads

The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
  • Exclusive indicators
  • Proven strategies & setups
  • Private Discord community
  • ‘Buy The Dip’ signal alerts
  • Exclusive members-only content
  • Add-ons and resources
  • 1 full year of unlimited support

Frequently Asked Questions

What is useThinkScript?

useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.

How do I get started?

We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.

If you are new, or just looking for guidance, here are some helpful links to get you started.

What are the benefits of VIP Membership?
VIP members get exclusive access to these proven and tested premium indicators: Buy the Dip, Advanced Market Moves 2.0, Take Profit, and Volatility Trading Range. In addition, VIP members get access to over 50 VIP-only custom indicators, add-ons, and strategies, private VIP-only forums, private Discord channel to discuss trades and strategies in real-time, customer support, trade alerts, and much more. Learn all about VIP membership here.
How can I access the premium indicators?
To access the premium indicators, which are plug and play ready, sign up for VIP membership here.
Back
Top