├── Instructions.md
├── README.md
├── charm
├── README.md
├── charm
├── charm_0div_0int
├── charm_chart
│ ├── README.md
│ ├── charm_exposure_horizontal_v2
│ └── charm_exposure_horiztonal_ES
├── charm_exposure
└── charm_exposure_spx
├── experimental
└── vwks
│ ├── README.md
│ └── vwks_daily
├── gex
├── futures
│ ├── cl_manual
│ └── es_manual
├── gex
├── gex_live_volume
├── readme.md
└── spx_ndx
│ ├── gex_spx_ndx_open_interest
│ ├── gex_spx_ndx_volume
│ ├── readme.md
│ └── temp_gex_spx
├── gex_chart
├── README.md
├── crossover_alert
│ ├── README.md
│ ├── gex_crossover_alert
│ ├── gex_crossover_alert_wlabels
│ ├── gex_crossover_spx
│ └── gex_crossover_stocks
├── gex_chart_lower
├── gex_chart_upper_bubbles_only_spx
├── gex_chart_upper_v3
├── gex_chart_upper_v5
├── gex_upper_only_bubbles
├── largest_strike
│ ├── README.md
│ ├── gex_number1
│ ├── spx_number1_on_ES_chart
│ └── spx_number1_on_spy_chart
├── live_volume
│ ├── README.md
│ ├── gex_live_volume_bubbles
│ └── gex_live_volume_bubbles_spx
├── lower
│ ├── README.md
│ ├── gex_horizontal_axis_spx
│ ├── gex_horizontal_axis_stocks
│ ├── gex_horizontal_axis_v3
│ └── gex_horizontal_es
└── multiple_expirations
│ ├── README.md
│ └── gex_horizontal_multi_spy
├── hurst_cycles
├── README.md
├── hurst_10_20_40_day_cycles_v2.ts
├── hurst_10_20_40_long_only_strat_tester.ts
├── hurst_10_20_40_short_only_strat_tester.ts
├── hurst_1_day_cycle_v2.ts
├── hurst_1_day_long_only_strat_tester.ts
└── hurst_1_day_short_only_strat_tester.ts
├── images
├── 2187logo.png
├── charm-option-chain.png
├── es-futures-options.png
├── es-vertical-volume-oi.png
├── gamma-exposure-horizontal.png
├── spy-open-interest.png
├── spy-spx-combo.png
├── spy_uoa.png
├── test
└── vanna-exposure-horizontal.png
├── modular
├── README.md
├── futures
│ └── options
│ │ └── es
│ │ ├── README.md
│ │ └── contract_code
└── greeks
│ ├── README.md
│ ├── delta
│ ├── gamma_vanna_charm
│ └── gamma_vanna_charm_0div_0int
├── near_the_money
├── README.md
├── near_the_money_daily_vix
├── near_the_money_daily_vix_upper
├── near_the_money_spy
├── near_the_money_spy_upper
├── near_the_money_stocks
├── near_the_money_stocks_upper
└── old
│ ├── README.md
│ ├── near_the_money_spy_daily.ts
│ └── near_the_money_spy_daily_upper.ts
├── near_the_money_spx
├── README.md
├── near_the_money_spx.ts
└── near_the_money_spx_upper.ts
├── optionVolume_vs_previousPeriod
├── README.md
└── optVol_vs_previousPeriod.ts
├── option_volume_and_openInterest_vertical_axis
├── es_nq
│ ├── README.md
│ ├── openInterest_vert_axis
│ └── volume_vert_axis
├── openInterest_vertical_axis.ts
├── readme.md
├── spx_and_ndx
│ ├── README.md
│ ├── openInterest_vertical_axis_index
│ └── volume_vertical_axis_index
└── volume_vertical_axis
├── peter_gap_rules
├── README.md
└── peter_gap_rules_not_working_right
├── requests
└── vwap
│ ├── vwap_bid_ask_signal_lower
│ └── vwap_bid_ask_signal_upper
├── shapes_and_art
├── README.md
├── circle.ts
├── cuphandle.ts
├── emojis
├── sierpinski.ts
├── star.ts
└── triangle.ts
├── tastylive_intern
├── README.md
└── ntm_strikes_multiple_expirations
├── unusual_options_new
├── README.md
├── option_prem_sum
├── spy_spx_combo
│ ├── README.md
│ ├── spy_spx_combo
│ └── spy_spx_combo2
├── strike_lines_spx_ndx
├── total_prem_spx_ndx
├── unusual_options_ES
├── unusual_options_NQ
├── unusual_options_manual
├── unusual_options_new
├── unusual_options_spx_ndx
└── unusual_volume_only
├── unusual_ticks
├── README.md
├── unusual_ticks_dollar
├── unusual_ticks_options_dollar
└── unusual_ticks_volume
└── vanna
├── README.md
├── vanna
├── vanna_0div_0Int
├── vanna_chart
├── README.md
├── vanna_exposure_horizontal_ES
└── vanna_exposure_horizontal_v2
├── vanna_exposure
└── vanna_exposure_spx
/Instructions.md:
--------------------------------------------------------------------------------
1 | # Thinkscript Indicators
2 |
3 |
4 | How to install:
5 |
6 | 1. Copy the indicator code.
7 |
8 | 2. In TOS click the edit studies and strategy icon.
9 |
10 | 3. Click "Create" to create a new study.
11 | 
12 |
13 |
14 | 4. Paste the indicator code and enter a name for the study. Then click ok.
15 | 
16 |
17 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ThinkScript
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
Indicators and Strategies
13 |
Clicking an image links to the code
14 |
15 |
Finding value in my work?
16 |

17 |
18 |
19 |
20 |
21 | Table of Contents
22 |
23 | -
24 | Unusual Options
25 |
31 |
32 | -
33 | Greeks
34 |
39 |
40 | -
41 | Open Interest and Option Volume
42 |
46 |
47 | - Contributors
48 | - Contact
49 | - Acknowledgments
50 |
51 |
52 |
53 |
54 |
55 |
56 | ## Unusual Options
57 |
58 | ### Equities
59 |
60 |
61 |
62 |
63 | ### Futures
64 |
65 |
66 |
67 |
68 | ### SPY-SPX Combo
69 |
70 |
71 |
72 |
73 | ### Volume Only
74 | https://github.com/2187Nick/thinkscript/blob/main/unusual_options_new/unusual_volume_only
75 |
76 |
77 |
78 |
79 | ## Greeks
80 |
81 | ### Gamma
82 |
83 |
84 |
85 |
86 | ### Vanna
87 |
88 |
89 |
90 |
91 | ### Charm
92 |
93 |
94 |
95 |
96 |
97 | (back to top)
98 |
99 |
100 |
101 |
102 | ## Open Interest and Option Volume
103 |
104 | ### Open Interest
105 |
106 |
107 |
108 |
109 | ### Option Volume
110 |
111 |
112 |
113 |
114 | (back to top)
115 |
116 | ## Installation
117 |
118 | ### How to add indicators to TOS:
119 |
120 | https://github.com/2187Nick/thinkscript/blob/main/Instructions.md
121 |
122 | ### Clone the repo
123 | ```sh
124 | git clone https://github.com/2187Nick/thinkscript.git
125 | ```
126 |
127 |
128 |
129 | (back to top)
130 |
131 |
132 | ## Contributors
133 |
134 | Any contributions you make are **greatly appreciated**.
135 |
136 | If you have a suggestion that would make this better, please fork the repo and create a pull request.
137 |
138 | You can also join discord to give ideas and feedback.
139 |
140 | Don't forget to give the project a star! Thanks again!
141 |
142 | 1. Fork the Project
143 | 2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
144 | 3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
145 | 4. Push to the Branch (`git push origin feature/AmazingFeature`)
146 | 5. Open a Pull Request
147 |
148 | (back to top)
149 |
150 |
151 |
152 | ## Contact
153 |
154 | [@2187Nick](https://twitter.com/2187Nick) - nick@2187.io
155 |
156 | [Discord](https://discord.com/invite/vxKepZ6XNC)
157 |
158 | [Github](https://github.com/2187Nick)
159 |
160 | (back to top)
161 |
162 |
163 |
164 |
165 | ## Acknowledgments
166 |
167 | Notable Resources:
168 |
169 |
170 |
171 | (back to top)
172 |
173 |
--------------------------------------------------------------------------------
/charm/README.md:
--------------------------------------------------------------------------------
1 | # Working on the Charm Exposure Calculations. Charm itself is spot on.
2 |
3 |
4 | # Charm Exposure (Naive)
5 |
6 | This calculates Charm Exposure per passage of 1 day. (Might add a version that calculates based on passage of 1 hour.) Based on open interest.
7 |
8 | (Currently it only works for option contracts in the current month.)
9 |
10 | The Charm Exposure is displayed in millions.
11 |
12 |
13 | ######
14 | ######
15 |
16 | Charm Exposure based on Open Interest:
17 |
18 | Option's Charm * Contract Size * Open Interest * Spot Price
19 | Total Charm Exposure = Call Charm Exposure + Put Charm Exposure
20 |
21 | Charm Exposure based on Live Volume:
22 |
23 | Option's Charm * Contract Size * Volume * Spot Price
24 | Total Charm Exposure = Call Charm Exposure + Put Charm Exposure
25 |
26 | 
27 |
28 | To install:
29 |
30 | # Click the Trade tab then All Products.
31 | # Enter SPY and press enter.
32 | # Click Layout then Customize.
33 | # Click the scroll icon next to one of the Custom indicators.
34 | 
35 |
36 | # Give it a Column name: CharmX or CEX
37 | # Click thinkScript Editor
38 | # Paste the code. Select Apply and Ok.
39 | # Select the Add Items button. Then Ok and done.
40 |
41 | **** Make sure D (Day) is selected. To the right of the column name.
42 | 
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/charm/charm:
--------------------------------------------------------------------------------
1 | # Charm Jan 22, 2024
2 | # @2187Nick
3 | # ITM Calls & OTM Puts = Positive Charm
4 | # OTM Calls & ITM Puts = Negative Charm
5 | # This uses dividend and interest rate.
6 | # Use this on the Options Chain Page
7 |
8 | # Manually set for testing
9 | #def Vol = .12;
10 | #def S = 476;
11 | #t = 20/365;
12 | #strike = 472;
13 | def Vol = imp_volatility(getUnderlyingSymbol());
14 | def S = close(getUnderlyingSymbol());
15 |
16 | def today = GetYYYYMMDD();
17 | def t = GetDaysToExpiration()/365;
18 | def strike = getStrike();
19 | def r = getInterestRate();
20 | def q = getYield();
21 |
22 | def Sqr_IV_2 = Sqr(Vol)*.5 * t;
23 | def Vol_Sqrt_t = Vol * Sqrt(t);
24 | def Sqrt_2pi = 2.5066;
25 | def r_q_Sqr_Vol_2 = (r-q + 0.5 * Sqr(Vol))* t;
26 | def Vol_Sqrt_t_S = S * Vol_Sqrt_t;
27 | def d1 = (Log(S / strike) + r_q_Sqr_Vol_2) / Vol_Sqrt_t;
28 | def N1d1 = Exp(-.5*Sqr((Log(S / strike) + r_q_Sqr_Vol_2) / Vol_Sqrt_t)) / 2.5066;
29 |
30 | def d2 = d1 - Vol_Sqrt_t;
31 |
32 | # Abramowiz Stegun Approximation for Cumulative Normal Distribution
33 | script cnd
34 | {
35 | input data = 1;
36 | def a = AbsValue(data);
37 | def b1 = .31938153;
38 | def b2 = -.356563782;
39 | def b3 = 1.781477937;
40 | def b4 = -1.821255978;
41 | def b5 = 1.330274429;
42 | def b6 = .2316419;
43 | def e = 1 / (1 + b6 * a);
44 | def i = 1 - 1 / Sqrt(2 * Double.Pi) * Exp(-Power(a, 2) / 2) *
45 | (b1 * e + b2 * e * e + b3 * Power(e, 3) + b4 * Power(e, 4) + b5 * Power(e, 5));
46 | plot CND = if data < 0
47 | then 1 - i
48 | else i;
49 | }
50 |
51 | # for charm call
52 | def normcdf_d1 = cnd(d1).CND;
53 | #addlabel(yes, strike + "_normcdf_d1: " + normcdf_d1, color.white);
54 |
55 | # for charm put
56 | #def normcdf_d1_put = cnd(-d1).CND;
57 | #addlabel(yes, strike + "_normcdf_d1_put: " + normcdf_d1_put, color.yellow);
58 |
59 | def term1 = N1d1 * (( 2*(r-q) *t - d2 * Vol_Sqrt_t ) / ( 2 * t * Vol_Sqrt_t));
60 |
61 | # I believe these end up having the same output.
62 | # But leaving it here for anyone who wants to test.
63 | #def call_charm = (q*exp(-q *t)*normcdf_d1 - exp(-q *t) * term1)/365;
64 | #def put_charm = (-q*exp(-q *t)*normcdf_d1_put - exp(-q *t) * term1)/365;
65 |
66 |
67 | # Divide by 365 to get single day value of Charm.
68 | def charm = (q*exp(-q *t)*normcdf_d1 - exp(-q *t) * term1)/365;
69 | addlabel(yes, round(charm,4), color.cyan);
70 |
71 | assignBackgroundColor(color.black);
72 |
--------------------------------------------------------------------------------
/charm/charm_0div_0int:
--------------------------------------------------------------------------------
1 | # Charm Jan 14, 2024 1 Day Charm
2 | # @2187Nick
3 | # ITM Calls & OTM Puts = Positive Charm
4 | # OTM Calls & ITM Puts = Negative Charm
5 |
6 | # Manually set for testing
7 | #def Vol = .12;
8 | #def S = 476;
9 | #def exp = 240229;
10 | #t = 20/365;
11 | #strike = 472;
12 | def Vol = imp_volatility(getUnderLyingSymbol());
13 | def S = close(getUnderlyingSymbol());
14 |
15 | def today = GetYYYYMMDD();
16 | def exp = today + getDaysToExpiration();
17 | def t = GetDaysToExpiration()/365;
18 | def strike = getStrike();
19 |
20 | def Sqr_IV_2 = Sqr(Vol)*.5 * t;
21 | def Vol_Sqrt_t = Vol * Sqrt(t);
22 | def Sqrt_2pi = 2.5066;
23 | def Vol_Sqrt_t_S = S * Vol_Sqrt_t;
24 | def d1 = (Log(S / strike) + Sqr_IV_2) / Vol_Sqrt_t;
25 | def N1d1 = Exp(-.5*Sqr((Log(S / strike) + Sqr_IV_2) / Vol_Sqrt_t)) / Sqrt_2pi;
26 | def d2 = d1 - Vol_Sqrt_t;
27 |
28 | # Divide by 365 to get single day value of Charm.
29 | def charm = -(N1d1 * (( -d2 * Vol_Sqrt_t ) / ( 2 * t * Vol_Sqrt_t)))/365;
30 | addlabel(yes, charm, color.cyan);
31 |
32 | assignBackgroundColor(color.black);
33 |
--------------------------------------------------------------------------------
/charm/charm_chart/README.md:
--------------------------------------------------------------------------------
1 | # Working on the Charm Exposure Calculations. Charm itself is spot on.
2 |
3 |
4 | # Charm Exposure (Naive)
5 | 
6 |
7 | This calculates Charm Exposure per passage of 1 day. (Might add a version that calculates based on passage of 1 hour.) Based on open interest.
8 |
9 | (Currently it only works for option contracts in the current month.)
10 |
11 |
12 | ######
13 | ######
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/charm/charm_exposure:
--------------------------------------------------------------------------------
1 | # Charm Exposure Feb 6, 2024
2 | # @2187Nick
3 | # For Options Chain Page
4 | # Displayed in Millions
5 | ### Updating the formula
6 | # From: OI * charm * S * 365 /1000000,1
7 | # To: OI * charm * S /1000000,0
8 |
9 | # change in delta per day until expiration
10 |
11 | #CharmExposure = callOptionOpenInterest + putCallOptionOpenInterest*Charm*spotPrice*365
12 | # ITM Calls & OTM Puts = Positive Charm
13 | # OTM Calls & ITM Puts = Negative Charm
14 | def DateString = GetYYYYMMDD()-20000000+getdaystoexpiration()-1;
15 |
16 | input threshold = 0; # millions
17 | def Vol = imp_volatility(getUnderlyingSymbol());
18 | def S = close(getUnderlyingSymbol());
19 | def t = GetDaysToExpiration()/365;
20 | def strike = getStrike();
21 | def r = getInterestRate();
22 | def q = getYield();
23 |
24 | def Sqr_IV_2 = Sqr(Vol)*.5 * t;
25 | def Vol_Sqrt_t = Vol * Sqrt(t);
26 | def Sqrt_2pi = 2.5066;
27 | def r_q_Sqr_Vol_2 = (r-q + 0.5 * Sqr(Vol))* t;
28 | def Vol_Sqrt_t_S = S * Vol_Sqrt_t;
29 | def d1 = (Log(S / strike) + r_q_Sqr_Vol_2) / Vol_Sqrt_t;
30 | def N1d1 = Exp(-.5*Sqr((Log(S / strike) + r_q_Sqr_Vol_2) / Vol_Sqrt_t)) / 2.5066;
31 |
32 | def d2 = d1 - Vol_Sqrt_t;
33 |
34 | # Abramowiz Stegun Approximation for Cumulative Normal Distribution
35 | script cnd
36 | {
37 | input data = 1;
38 | def a = AbsValue(data);
39 | def b1 = .31938153;
40 | def b2 = -.356563782;
41 | def b3 = 1.781477937;
42 | def b4 = -1.821255978;
43 | def b5 = 1.330274429;
44 | def b6 = .2316419;
45 | def e = 1 / (1 + b6 * a);
46 | def i = 1 - 1 / Sqrt(2 * Double.Pi) * Exp(-Power(a, 2) / 2) *
47 | (b1 * e + b2 * e * e + b3 * Power(e, 3) + b4 * Power(e, 4) + b5 * Power(e, 5));
48 | plot CND = if data < 0
49 | then 1 - i
50 | else i;
51 | }
52 |
53 | # for charm call
54 | def normcdf_d1 = cnd(d1).CND;
55 |
56 | # for charm put
57 | #def normcdf_d1_put = cnd(-d1).CND;
58 | #addlabel(yes, strike + "_normcdf_d1_put: " + normcdf_d1_put, color.yellow);
59 |
60 | def term1 = N1d1 * (( 2*(r-q) *t - d2 * Vol_Sqrt_t ) / ( 2 * t * Vol_Sqrt_t));
61 |
62 | # Divide by 365 to get single day value of Charm.
63 | def charm = (q*exp(-q *t)*normcdf_d1 - exp(-q *t) * term1)/365;
64 |
65 |
66 | def cex = round((open_interest("."+getunderlyingSymbol()+ AsPrice(DateString) + "C" + AsPrice(getStrike())) + open_interest("."+getunderlyingSymbol()+AsPrice(DateString) + "P" + asPrice(getStrike()))) * 100 * charm * S/1000000,0);
67 |
68 | addlabel(IsPut() and cex <= -.1, cex, if cex <= (-1*threshold) then color.red else color.light_red);
69 | addlabel(IsPut() and cex >= 0, "", color.black);
70 |
71 | addlabel(!IsPut() and cex >= .1, cex, if cex >= threshold then color.green else color.light_green);
72 | addlabel(!IsPut() and cex < 0, "", color.black);
73 | assignBackgroundColor(color.black);
74 |
--------------------------------------------------------------------------------
/charm/charm_exposure_spx:
--------------------------------------------------------------------------------
1 | # Charm Exposure SPX Jan 22, 2024
2 | # @2187Nick
3 | # For Options Chain Page
4 | # Displayed in Millions
5 |
6 | # change in delta per day until expiration
7 |
8 | #CharmExposure = (callOptionOpenInterest + putCallOptionOpenInterest)*Charm*spotPrice*365
9 | # ITM Calls & OTM Puts = Positive Charm
10 | # OTM Calls & ITM Puts = Negative Charm
11 | def DateString = GetYYYYMMDD()-20000000+getdaystoexpiration()-1;
12 | input symbol = "SPXW";
13 | input threshold = 0; # millions
14 | def Vol = imp_volatility(getUnderlyingSymbol());
15 | def S = close(getUnderlyingSymbol());
16 | def t = GetDaysToExpiration()/365;
17 | def strike = getStrike();
18 | def r = getInterestRate();
19 | def q = getYield();
20 |
21 | def Sqr_IV_2 = Sqr(Vol)*.5 * t;
22 | def Vol_Sqrt_t = Vol * Sqrt(t);
23 | def Sqrt_2pi = 2.5066;
24 | def r_q_Sqr_Vol_2 = (r-q + 0.5 * Sqr(Vol))* t;
25 | def Vol_Sqrt_t_S = S * Vol_Sqrt_t;
26 | def d1 = (Log(S / strike) + r_q_Sqr_Vol_2) / Vol_Sqrt_t;
27 | def N1d1 = Exp(-.5*Sqr((Log(S / strike) + r_q_Sqr_Vol_2) / Vol_Sqrt_t)) / 2.5066;
28 |
29 | def d2 = d1 - Vol_Sqrt_t;
30 |
31 | # Abramowiz Stegun Approximation for Cumulative Normal Distribution
32 | script cnd
33 | {
34 | input data = 1;
35 | def a = AbsValue(data);
36 | def b1 = .31938153;
37 | def b2 = -.356563782;
38 | def b3 = 1.781477937;
39 | def b4 = -1.821255978;
40 | def b5 = 1.330274429;
41 | def b6 = .2316419;
42 | def e = 1 / (1 + b6 * a);
43 | def i = 1 - 1 / Sqrt(2 * Double.Pi) * Exp(-Power(a, 2) / 2) *
44 | (b1 * e + b2 * e * e + b3 * Power(e, 3) + b4 * Power(e, 4) + b5 * Power(e, 5));
45 | plot CND = if data < 0
46 | then 1 - i
47 | else i;
48 | }
49 |
50 | # for charm call
51 | def normcdf_d1 = cnd(d1).CND;
52 |
53 | # for charm put
54 | #def normcdf_d1_put = cnd(-d1).CND;
55 | #addlabel(yes, strike + "_normcdf_d1_put: " + normcdf_d1_put, color.yellow);
56 |
57 | def term1 = N1d1 * (( 2*(r-q) *t - d2 * Vol_Sqrt_t ) / ( 2 * t * Vol_Sqrt_t));
58 |
59 | # Divide by 365 to get single day value of Charm.
60 | def charm = (q*exp(-q *t)*normcdf_d1 - exp(-q *t) * term1)/365;
61 |
62 | def cex = Round((open_interest("." + symbol + AsPrice(DateString) + "C" + AsPrice(getStrike())) + open_interest("." + symbol + AsPrice(DateString) + "P" + AsPrice(getStrike()))) * 100 * charm * S /1000000,0);
63 |
64 | addlabel(IsPut() and cex <= -.1, cex, if cex <= (-1*threshold) then color.red else color.light_red);
65 | addlabel(IsPut() and cex >= 0, "", color.black);
66 |
67 | addlabel(!IsPut() and cex >= .1, cex, if cex >= threshold then color.green else color.light_green);
68 | addlabel(!IsPut() and cex < 0, "", color.black);
69 | assignBackgroundColor(color.black);
70 |
--------------------------------------------------------------------------------
/experimental/vwks/README.md:
--------------------------------------------------------------------------------
1 | # VWKS volume-weighted average strike-spot price ratio
2 |
3 |
4 | ### https://ink.library.smu.edu.sg/lkcsb_research/6568/
5 |
6 | Adjust the days to expiration as desired.
7 |
8 | Currently it is a basic implementation. Needs alot of work. Currently only works on Daily chart.
9 | If there is interest, it can be improved.
10 |
11 |
12 | 
13 |
14 | VWKS above 0 is considered bullish.
15 |
16 | VWKS below 0 is considered bullish.
17 |
18 |
19 | > Chart requirements for optimal use:
20 | ```bash
21 |
22 | Time frame: 30 days
23 |
24 | Aggregation Period: 1 Day
25 |
26 | ```
27 |
28 |
29 | > 🦖 How to use this(layman description):
30 | ```bash
31 |
32 | 1. If participants are buying more OTM Calls vs OTM Puts that is considered bullish based on the paper.
33 | 2. If participants are buying more OTM Puts vs OTM Callss that is considered bearish based on the paper.
34 |
35 | ```
36 |
--------------------------------------------------------------------------------
/gex/futures/cl_manual:
--------------------------------------------------------------------------------
1 | input threshold = 0; # millions
2 | input base_symbol = "LOZ"; #"WL5V";
3 | # ./WL5V24C67.5:XNYM
4 | #./LOZ24C68:XNYM
5 |
6 | input exchange = "XNYM"; #"XCME"; # XNYM, XCEC, XCBT
7 | def year = getYear() - 2000;
8 |
9 | ## Formula:
10 | ## ((Call_OI - Put_OI) * Gamma * Contract_Size * Underlying_Price)
11 |
12 | ## This can be modified to work with other futures options
13 | ## Adjust the for contract size and pricing
14 |
15 | def gex =
16 | if IsNan(
17 | (
18 | open_interest("./"+base_symbol+ year + "C" +AsPrice(getStrike())+":"+exchange) -
19 | open_interest("./"+base_symbol+ year + "P" +AsPrice(getStrike())+":"+exchange)
20 | ) * Gamma() * close(getunderlyingSymbol())
21 | ) then 0
22 | else round(
23 | (
24 | open_interest("./"+base_symbol+ year + "C" +AsPrice(getStrike())+":"+exchange) -
25 | open_interest("./"+base_symbol+ year + "P" +AsPrice(getStrike())+":"+exchange)
26 | ) * Gamma() * close(getunderlyingSymbol()) / 10000,
27 | 1
28 | );
29 |
30 | addlabel(IsPut() and gex <= -.1, gex, if gex <= (-1*threshold) then color.red else color.light_red);
31 | addlabel(IsPut() and gex >= 0, "", color.black);
32 |
33 | addlabel(!IsPut() and gex >= .1, gex, if gex >= threshold then color.green else color.light_green);
34 | addlabel(!IsPut() and gex < 0, "", color.black);
35 | assignBackgroundColor(color.black);
36 |
--------------------------------------------------------------------------------
/gex/futures/es_manual:
--------------------------------------------------------------------------------
1 | input threshold = 0; # millions
2 | input base_symbol = "E3DU";
3 |
4 | input exchange = "XCME"; # XNYM, XCEC, XCBT
5 | def year = getYear() - 2000;
6 |
7 | ## ES options are half the cost of contract price I believe
8 | ## Formula:
9 | ## ((Call_OI - Put_OI) * Gamma * Conctact_Size * Underlying_Price) / 2
10 |
11 | ## This can be modified to work with other futures options
12 | ## Adjust the for contract size and pricing
13 |
14 | #def DateString = GetYYYYMMDD()-20000000+getdaystoexpiration()-1;
15 | def q = if getYield() then getYield() else 0;
16 | def r = getInterestRate();
17 | def dte = getdaystoexpiration();
18 | def k = getStrike();
19 | def iv = imp_volatility(getUnderlyingSymbol());
20 | #def iv = seriesVolatility(series=1);
21 |
22 | def S = close(getUnderlyingSymbol());
23 | def t = dte/365;
24 |
25 | def d1 = (Log(S / k) + ((r - q + (Power(IV, 2)) / 2) * t)) / (IV * Sqrt(t));
26 | def d2 = d1 - IV * Sqrt(t);
27 | def phi_d1 = Exp(-(Power(d1, 2)) / 2) / Sqrt(2 * Double.Pi);
28 |
29 | def bsmGamma = Exp(-q * t) * phi_d1 / (S * IV * Sqrt(t));
30 | #AddLabel(yes, round(bsmGamma,2));
31 |
32 |
33 | #def gex = open_interest("./E3DU24P5690:XCME");
34 | #def gex = open_interest("./"+base_symbol+ year + "C" +AsPrice(getStrike())+":"+exchange);
35 |
36 | def gex =
37 | if IsNan(
38 | (
39 | open_interest("./"+base_symbol+ year + "C" +AsPrice(getStrike())+":"+exchange) -
40 | open_interest("./"+base_symbol+ year + "P" +AsPrice(getStrike())+":"+exchange)
41 | ) * bsmGamma * close(getunderlyingSymbol())
42 | ) then 0
43 | else round(
44 | (
45 | open_interest("./"+base_symbol+ year + "C" +AsPrice(getStrike())+":"+exchange) -
46 | open_interest("./"+base_symbol+ year + "P" +AsPrice(getStrike())+":"+exchange)
47 | ) * bsmGamma * close(getunderlyingSymbol()) / 20000,
48 | 1
49 | );
50 |
51 | addlabel(IsPut() and gex <= -.1, gex, if gex <= (-1*threshold) then color.red else color.light_red);
52 | addlabel(IsPut() and gex >= 0, "", color.black);
53 |
54 | addlabel(!IsPut() and gex >= .1, gex, if gex >= threshold then color.green else color.light_green);
55 | addlabel(!IsPut() and gex < 0, "", color.black);
56 | assignBackgroundColor(color.black);
57 |
--------------------------------------------------------------------------------
/gex/gex:
--------------------------------------------------------------------------------
1 | def DateString = GetYYYYMMDD()-20000000+getdaystoexpiration()-1;
2 |
3 | input threshold = 0; # millions
4 |
5 | def gex = if IsNan((open_interest("."+getunderlyingSymbol()+ AsPrice(DateString) + "C" +AsPrice(getStrike())) - open_interest("."+getunderlyingSymbol()+AsPrice(DateString) + "P" + AsPrice(getStrike())))* Gamma() * close(getunderlyingSymbol()) /10000) then 0 else round((open_interest("."+getunderlyingSymbol()+ AsPrice(DateString) + "C" + AsPrice(getStrike())) - open_interest("."+getunderlyingSymbol()+AsPrice(DateString) + "P" + AsPrice(getStrike())))* Gamma() * close(getunderlyingSymbol()) /10000,1);
6 | addlabel(IsPut() and gex <= -.1, gex, if gex <= (-1*threshold) then color.red else color.light_red);
7 | addlabel(IsPut() and gex >= 0, "", color.black);
8 |
9 | addlabel(!IsPut() and gex >= .1, gex, if gex >= threshold then color.green else color.light_green);
10 | addlabel(!IsPut() and gex < 0, "", color.black);
11 |
12 | assignBackgroundColor(color.black);
13 |
--------------------------------------------------------------------------------
/gex/gex_live_volume:
--------------------------------------------------------------------------------
1 | def DateString = GetYYYYMMDD()-20000000+getdaystoexpiration()-1;
2 |
3 | input threshold = 25; # millions
4 |
5 | def gex = if IsNan((volume("."+getunderlyingSymbol()+ AsPrice(DateString) + "C" + Asprice(getStrike())) - volume("."+getunderlyingSymbol()+AsPrice(DateString) + "P" + Asprice(getStrike())))* Gamma() * close(getunderlyingSymbol()) /10000) then 0 else round((volume("."+getunderlyingSymbol()+ AsPrice(DateString) + "C" + Asprice(getStrike())) - volume("."+getunderlyingSymbol()+AsPrice(DateString) + "P" + Asprice(getStrike())))* Gamma() * close(getunderlyingSymbol()) /10000,1);
6 |
7 | addlabel(IsPut() and gex <= -.1, gex, if gex <= (-1*threshold) then color.red else color.light_red);
8 | addlabel(IsPut() and gex >= 0, "", color.black);
9 |
10 | addlabel(!IsPut() and gex >= .1, gex, if gex >= threshold then color.green else color.light_green);
11 | addlabel(!IsPut() and gex < 0, "", color.black);
12 |
13 | assignBackgroundColor(color.black);
14 |
--------------------------------------------------------------------------------
/gex/readme.md:
--------------------------------------------------------------------------------
1 | # Gamma Exposure (Naive)
2 |
3 | This calculates gex per $1 move in the underlying asset. Based on open interest.
4 |
5 | (Currently it only works for option contracts in the current month.)
6 |
7 | The GEX is displayed in millions.
8 |
9 |
10 | ######
11 | ######
12 |
13 | GEX based on Open Interest:
14 |
15 | Option's Gamma * Contract Size * Open Interest * Spot Price
16 | Total GEX = Call GEX - Put GEX
17 |
18 | GEX based on Live Volume:
19 |
20 | Option's Gamma * Contract Size * Volume * Spot Price
21 | Total GEX = Call GEX - Put GEX
22 |
23 |
24 | 
25 |
26 | To install:
27 |
28 | # Click the Trade tab then All Products.
29 | # Enter SPY and press enter.
30 | # Click Layout then Customize.
31 | # Click the scroll icon next to one of the Custom indicators.
32 | 
33 |
34 | # Give it a name Column name: GEX
35 | # Click thinkScript Editor
36 | # Paste the code. Select Apply and Ok.
37 | # Select the Add Items button. Then Ok and done.
38 |
39 | **** Make sure D (Day) is selected. To the right of the column name.
40 | 
41 |
42 |
43 |
--------------------------------------------------------------------------------
/gex/spx_ndx/gex_spx_ndx_open_interest:
--------------------------------------------------------------------------------
1 | def DateString = GetYYYYMMDD()-20000000+getdaystoexpiration()-1;
2 |
3 | input threshold = 1000; # 1 billion
4 | def sym;
5 | if (getUnderlyingSymbol() == "NDX") {
6 | sym = 1;
7 | } else {
8 | sym = 0;
9 | };
10 |
11 | def gex = if IsNan((open_interest("."+getunderlyingSymbol()+(if sym then "P" else "W")+ AsPrice(DateString) + "C" +AsPrice(getStrike())) - open_interest("."+getunderlyingSymbol()+(if sym then "P" else "W")+AsPrice(DateString) + "P" + AsPrice(getStrike())))* Gamma() * close(getunderlyingSymbol()) /1000) then 0 else round((open_interest("."+getunderlyingSymbol()+(if sym then "P" else "W")+ AsPrice(DateString) + "C" +AsPrice(getStrike())) - open_interest("."+getunderlyingSymbol()+(if sym then "P" else "W")+AsPrice(DateString) + "P" + AsPrice(getStrike())))* Gamma() * close(getunderlyingSymbol())*close(getunderlyingSymbol()) *.01 /10000,1);
12 |
13 | addlabel(yes, gex );
14 |
15 | addlabel(IsPut() and gex <= -.1, gex, if gex <= (-1*threshold) then color.red else color.light_red);
16 | addlabel(IsPut() and gex >= 0, "", color.black);
17 |
18 | addlabel(!IsPut() and gex >= .1, gex, if gex >= threshold then color.green else color.light_green);
19 | addlabel(!IsPut() and gex < 0, "", color.black);
20 |
21 | assignBackgroundColor(color.black);
22 |
--------------------------------------------------------------------------------
/gex/spx_ndx/gex_spx_ndx_volume:
--------------------------------------------------------------------------------
1 | def DateString = GetYYYYMMDD()-20000000+getdaystoexpiration()-1;
2 |
3 | ### This works except for monthly expiration. Symbol is issue and daystoexpiration
4 |
5 | input sym = "W";
6 | input threshold = 25; # millions
7 |
8 | def gex = if IsNan((volume("."+getunderlyingSymbol()+sym+ AsPrice(DateString) + "C" +AsPrice(getStrike())) - volume("."+getunderlyingSymbol()+sym+AsPrice(DateString) + "P" + AsPrice(getStrike())))* Gamma() * close(getunderlyingSymbol()) /10000) then 0 else round((volume("."+getunderlyingSymbol()+sym+ AsPrice(DateString) + "C" +AsPrice(getStrike())) - volume("."+getunderlyingSymbol()+sym+AsPrice(DateString) + "P" + AsPrice(getStrike())))* Gamma() * close(getunderlyingSymbol()) /1000,1);
9 |
10 | addlabel(IsPut() and gex <= -.1, gex, if gex <= (-1*threshold) then color.red else color.light_red);
11 | addlabel(IsPut() and gex >= 0, "", color.black);
12 |
13 | addlabel(!IsPut() and gex >= .1, gex, if gex >= threshold then color.green else color.light_green);
14 | addlabel(!IsPut() and gex < 0, "", color.black);
15 |
16 | assignBackgroundColor(color.black);
17 |
--------------------------------------------------------------------------------
/gex/spx_ndx/readme.md:
--------------------------------------------------------------------------------
1 | # Gamma Exposure (Naive)
2 |
3 | This calculates gex per 1% move in the underlying asset.
4 |
5 | (Currently it only works for weekly option contracts in the current month.)
6 |
7 | The GEX is displayed in millions.
8 |
9 |
10 | ######
11 | ######
12 |
13 | GEX based on Open Interest:
14 |
15 | Option's Gamma * Contract Size * Open Interest * Spot Price ^2 * .01
16 | Total GEX = Call GEX - Put GEX
17 |
18 | GEX based on Live Volume:
19 |
20 | Option's Gamma * Contract Size * Volume * Spot Price ^2 * .01
21 | Total GEX = Call GEX - Put GEX
22 |
23 | 
24 |
25 |
--------------------------------------------------------------------------------
/gex/spx_ndx/temp_gex_spx:
--------------------------------------------------------------------------------
1 | # Gex on chain September 9, 2024
2 | # Twitter @2187Nick
3 | # This is a temporary gex indicator to use until TOS fixes 0dte Gamma()
4 |
5 | def CurrentYear = GetYear()-2000;
6 | def CurrentMonth = GetMonth();
7 | def CurrentDOM = GetDayOfMonth(GetYYYYMMDD());
8 | def DateString = CurrentYear*10000+CurrentMonth*100+CurrentDOM+getdaystoexpiration()-1;
9 |
10 | #def DateString = 231215;
11 | input symbol = "SPXW";
12 |
13 | input threshold = 0; # millions
14 | def q = if getYield() then getYield() else 0;
15 | def r = getInterestRate();
16 | def dte = getdaystoexpiration();
17 | def k = getStrike();
18 | def iv = imp_volatility(getUnderlyingSymbol());
19 | #def iv = seriesVolatility(series=1);
20 |
21 | def S = close(getUnderlyingSymbol());
22 | def t = dte/365;
23 |
24 | def d1 = (Log(S / k) + ((r - q + (Power(IV, 2)) / 2) * t)) / (IV * Sqrt(t));
25 | def d2 = d1 - IV * Sqrt(t);
26 | def phi_d1 = Exp(-(Power(d1, 2)) / 2) / Sqrt(2 * Double.Pi);
27 |
28 | def bsmGamma = Exp(-q * t) * phi_d1 / (S * IV * Sqrt(t));
29 | #addlabel(yes, bsmGamma);
30 |
31 | #Based on $10 move
32 | plot GEX = if IsNan((open_interest("."+symbol+ AsPrice(DateString) + "C" +AsPrice(getStrike())) - open_interest("."+symbol+AsPrice(DateString) + "P" + AsPrice(getStrike())))* bsmGamma * close(getunderlyingSymbol()) /10000) then 0 else round((open_interest("."+symbol+ AsPrice(DateString) + "C" +AsPrice(getStrike())) - open_interest("."+symbol+AsPrice(DateString) + "P" + AsPrice(getStrike())))* bsmGamma * close(getunderlyingSymbol()) /1000,0);
33 |
34 | addlabel(IsPut() and gex <= -.1, gex, if gex <= (-1*threshold) then color.red else color.light_red);
35 | addlabel(IsPut() and gex >= 0, "", color.black);
36 |
37 | addlabel(!IsPut() and gex >= .1, gex, if gex >= threshold then color.green else color.light_green);
38 | addlabel(!IsPut() and gex < 0, "", color.black);
39 |
40 | assignBackgroundColor(color.black);
41 |
--------------------------------------------------------------------------------
/gex_chart/README.md:
--------------------------------------------------------------------------------
1 | # Gamma Exposure (Naive)
2 |
3 | This calculates gex per $1 move in the underlying asset. Based on open interest.
4 |
5 | It automatically selects todays date for the option contract.
6 | To change the contract date set ManuallySetExpiration to "true" and type in the date you want.
7 |
8 | The GEX is displayed in millions.
9 |
10 | 
11 |
12 | # Only bubbles Version
13 | 
14 |
15 |
16 | # Chart Settings:
17 | * Make sure Time Axis/Expansion Area is not 0. Use 10+.
18 |
19 | > Chart requirements for optimal use:
20 | ```bash
21 |
22 | Time frame: 1 Day
23 |
24 | Aggregation Period: 1 Minute
25 |
26 | ```
27 |
28 | ######
29 | ######
30 |
31 | GEX based on Open Interest:
32 |
33 | Option's Gamma * Contract Size * Open Interest * Spot Price
34 | Total GEX = Call GEX - Put GEX
35 |
36 | ######
37 | ######
38 |
39 | > 🦖 How to use this(layman description):
40 | ```bash
41 |
42 | 1. Large Gamma Exposure strikes can act like a magnet for price.
43 | 2. Gamma increases when price is near the strike.
44 |
45 | ```
46 |
--------------------------------------------------------------------------------
/gex_chart/crossover_alert/README.md:
--------------------------------------------------------------------------------
1 | # Gamma Exposure with Crossover Alerts
2 |
3 | This gives an alert when the largest gex level changes.
4 |
5 | It automatically selects todays date for the option contract.
6 | To change the contract date set ManuallySetExpiration to "true" and type in the date you want.
7 |
8 |
9 | The GEX is displayed in millions.
10 |
11 | 
12 |
13 |
14 |
15 | > Chart requirements for optimal use:
16 | ```bash
17 |
18 | Time frame: 1 Day
19 |
20 | Aggregation Period: 1 Minute
21 |
22 | ```
23 |
24 | ######
25 | ######
26 |
27 | GEX based on Open Interest:
28 |
29 | Option's Gamma * Contract Size * Open Interest * Spot Price
30 | Total GEX = Call GEX - Put GEX
31 |
32 | ######
33 | ######
34 |
35 | > 🦖 How to use this(layman description):
36 | ```bash
37 |
38 | 1. Large Gamma Exposure strikes can act like a magnet for price.
39 | 2. Gamma increases when price is near the strike.
40 |
41 | ```
42 |
--------------------------------------------------------------------------------
/gex_chart/largest_strike/README.md:
--------------------------------------------------------------------------------
1 | # Plots Strike with Largest Gamma Exposure (For that Expiration)
2 |
3 | This calculates gex per $1 move in the underlying asset. Based on open interest.
4 |
5 | It automatically selects todays date for the option contract.
6 | To change the contract date set ManuallySetExpiration to "true" and type in the date you want.
7 |
8 | 
9 |
10 | ### SPX Number 1 GEX Strike on ES Chart
11 | 
12 |
13 |
14 |
15 | > Chart requirements for optimal use:
16 | ```bash
17 |
18 | Time frame: 1 Day
19 |
20 | Aggregation Period: 1 Minute
21 |
22 | ```
23 |
24 | ######
25 | ######
26 |
27 | GEX based on Open Interest:
28 |
29 | Option's Gamma * Contract Size * Open Interest * Spot Price
30 | Total GEX = Call GEX - Put GEX
31 |
32 | ######
33 | ######
34 |
35 | > 🦖 How to use this(layman description):
36 | ```bash
37 |
38 | 1. Large Gamma Exposure strikes can act like a magnet for price.
39 | 2. Gamma increases when price is near the strike.
40 |
41 | ```
42 |
--------------------------------------------------------------------------------
/gex_chart/live_volume/README.md:
--------------------------------------------------------------------------------
1 | # Gamma Exposure (Naive) Live Volume
2 |
3 | This calculates gex per $1 move in the underlying asset. Based on volume.
4 |
5 | Created upon request. Not sure if this indicator has any value yet.
6 |
7 | It automatically selects todays date for the option contract.
8 | To change the contract date set ManuallySetExpiration to "true" and type in the date you want.
9 |
10 | The GEX is displayed in Thousands.
11 |
12 | 
13 |
14 |
15 |
16 | > Chart requirements for optimal use:
17 | ```bash
18 |
19 | Time frame: 1 Day
20 |
21 | Aggregation Period: 1 Minute
22 |
23 | ```
24 |
25 | ######
26 | ######
27 |
28 | GEX based on Volume:
29 |
30 | Option's Gamma * Contract Size * Volume * Spot Price
31 | Total GEX = Call GEX - Put GEX
32 |
33 | ######
34 | ######
35 |
36 | > 🦖 How to use this(layman description):
37 | ```bash
38 |
39 | 1. To be determined
40 |
41 | ```
42 |
--------------------------------------------------------------------------------
/gex_chart/lower/README.md:
--------------------------------------------------------------------------------
1 | # Gamma Exposure (Naive)
2 |
3 | This calculates gex per $1 move in the underlying asset. Based on open interest.
4 |
5 | It automatically selects todays date for the option contract.
6 | To change the contract date set ManuallySetExpiration to "true" and type in the date you want.
7 |
8 | The GEX is displayed in millions.
9 |
10 | 
11 |
12 |
13 | > Chart requirements for optimal use:
14 | ```bash
15 |
16 | Time frame: 1 Day
17 |
18 | Aggregation Period: 1 Minute
19 |
20 | ```
21 |
22 | ######
23 | ######
24 |
25 | GEX based on Open Interest:
26 |
27 | Option's Gamma * Contract Size * Open Interest * Spot Price
28 | Total GEX = Call GEX - Put GEX
29 |
30 | ######
31 | ######
32 |
33 | > 🦖 How to use this(layman description):
34 | ```bash
35 |
36 | 1. Large Gamma Exposure strikes can act like a magnet for price.
37 | 2. Gamma increases when price is near the strike.
38 |
39 | ```
40 |
--------------------------------------------------------------------------------
/gex_chart/multiple_expirations/README.md:
--------------------------------------------------------------------------------
1 | # Gamma Exposure (Naive) Multiple Expirations Accumulated
2 |
3 | This calculates gex per $1 move in the underlying asset. Based on open interest.
4 |
5 | This version allows you to combine multiple expirations.
6 |
7 | Currently it will combine the gex per strike for expirations within the next 7 days(including weekends).
8 |
9 | Adjust the input: "Number of Days" to control expirations combined.
10 |
11 | Only works with SPY and QQQ for now.
12 |
13 | It automatically selects todays date for the option contract.
14 | To change the contract date set ManuallySetExpiration to "true" and type in the date you want.
15 |
16 | The GEX is displayed in millions.
17 | 
18 |
19 | > Chart requirements for optimal use:
20 | ```bash
21 |
22 | Time frame: 1 Day
23 |
24 | Aggregation Period: 1 Minute
25 |
26 | ```
27 |
28 | ######
29 | ######
30 |
31 | GEX based on Open Interest:
32 |
33 | Option's Gamma * Contract Size * Open Interest * Spot Price
34 | Total GEX = Call GEX - Put GEX
35 |
36 | ######
37 | ######
38 |
39 | > 🦖 How to use this(layman description):
40 | ```bash
41 |
42 | 1. Large Gamma Exposure strikes can act like a magnet for price.
43 | 2. Gamma increases when price is near the strike.
44 |
45 | ```
46 |
--------------------------------------------------------------------------------
/hurst_cycles/README.md:
--------------------------------------------------------------------------------
1 | # 🚀 This attempts to plot the Hurst cycle and display the next cycle peak or trough range. ** Use V2
2 |
3 | Category: Cycles (This is a work in progress)
4 |
5 | To learn more follow the current Hurst Cycles Experts:
6 |
7 | https://twitter.com/SentientTrader
8 |
9 | https://twitter.com/TradingHurst
10 |
11 |
12 |
13 | > Chart requirements for optimal use:
14 | ```bash
15 |
16 | Time Frame Aggregation Period: Day. Except for 1 day cycle. Use 15 min time frame.
17 |
18 | Extended Hours: On
19 |
20 | Note: V2 now works on historical look back.
21 | ```
22 |
23 |
24 |
25 |
26 | > Settings 👷:
27 |
28 | ```bash
29 |
30 | Upper:
31 | 1. Cycle: TenDay; (Ten Day is default. Select Twenty Day to monitor 20 day cycles)
32 |
33 |
34 | ```
35 |
36 |
37 |
38 |
39 | > 🧪 How this works(Most Basic Version):
40 |
41 | 
42 |
43 | # Shift the price graph forward in time by half the length of the average cycle.
44 |
45 | 
46 | # Measure the distance from the cycle low up to where the graphs intersect. This gives us the potential magnitude of the cycle peak.
47 |
48 | ```bash
49 |
50 | 1. Husrt indentified common cycles and their average wave length.
51 |
52 | A. David Hickson(Sentient Trader) extended Hurst model to include more common cycles at different time frames
53 |
54 | B. These indicators will use the common wave lengths they identified.
55 |
56 | 2. When price crosses the projection line the script measures the distance of the price movement. It then adds that amount to the
57 | current price(or subtracts if we are starting a down cycle).
58 |
59 | 3. 50% of the cycle magnitude is used as target 1 and target 2 is the full magnitude.
60 |
61 | 4. The chart will display this range highlighted in green or red.
62 |
63 | Note: Different instruments have different wave lengths. Feel free to dig into Hurst material for more details.
64 |
65 | ```
66 |
67 | > 🦖 Why this works:
68 | ```bash
69 | 1 Theory:
70 |
71 | ```
72 |
73 | > 🐰 Down the Rabbit Hole 🐇:
74 |
75 | Hurst analyzed price data using Fourier and spectral analysis.
76 |
77 | Intro to the Fourier Series and Joseph Fourier:
78 |
79 | https://www.youtube.com/playlist?list=PLWMUMyAolbNuWse5uM3HBwkrJEVsWOLd6
80 |
--------------------------------------------------------------------------------
/hurst_cycles/hurst_10_20_40_day_cycles_v2.ts:
--------------------------------------------------------------------------------
1 | # FLD Cross 10, 20, 40 Day Cycles Futures V2
2 | # This version doesn't repaint!
3 | # @2187Nick
4 | # Use aggregation period: "Day". Extended hours on.
5 | declare upper;
6 | declare once_per_bar;
7 | input cycle = {default "TenDay", "TwentyDay", "FortyDay"};
8 | def lookback = if cycle < 1 then 7 else if cycle > 0 and cycle < 2 then 12 else 25;
9 | def displace = if cycle < 1 then 4 else if cycle > 0 and cycle < 2 then 9 else 18; #8
10 | def line_color = if cycle < 1 then 5 else if cycle > 0 and cycle < 2 then 0 else 6;
11 |
12 | def currentBarNumber = if !IsNaN(close) then BarNumber() else Double.NaN;
13 | def lastBarNumber = HighestAll(currentBarNumber);
14 | def lookbackBar = lastBarNumber - lookback + 1;
15 |
16 | def mostRecentHigh = highest(high,lookback);
17 | def highBarNumber = CompoundValue(1, if high > mostRecentHigh[1] then currentBarNumber else highBarNumber[1], 0);
18 |
19 | def mostRecentLow = lowest(low,lookback);
20 | def lowBarNumber = CompoundValue(1, if low < mostRecentLow[1] then currentBarNumber else lowBarNumber[1], 0);
21 |
22 | #Plots a bubble showing where lookback bar is.
23 | AddChartBubble(currentBarNumber == lookbackBar, (high + low) / 2, lookback + "\nBar", Color.GRAY, yes);
24 |
25 | def DailySMA2 = Average(Fundamental(FundamentalType.HL2, period = AggregationPeriod.DAY)[displace], 1);
26 | plot sma2 = DailySMA2;
27 | sma2.SetDefaultColor(GetColor(line_color));
28 | sma2.SetLineWeight(3);
29 |
30 | def crossdownlevel = (DailySMA2 + DailySMA2[1]) / 2;
31 | # Distance from cycle high to the fld level
32 | def crossdownTGT1 = crossdownlevel - 0.5 * (mostRecentHigh - crossdownlevel);
33 | def crossdownTGT2 = crossdownlevel - (mostRecentHigh - crossdownlevel);
34 |
35 | # Check if price crossed the fld level this period
36 | def didwecrossdown = if close[1] > DailySMA2[1] and close < DailySMA2 then crossdownTGT1 else 0;
37 |
38 | def doPlot1 = 1;
39 | def crossdown_target1 = CompoundValue(1, if doPlot1 && close < DailySMA2 and didwecrossdown then crossdownTGT1 else crossdown_target1[1], Double.NaN);
40 | def crossdown_target2 = CompoundValue(1, if doPlot1 && close < DailySMA2 and didwecrossdown then crossdownTGT2 else crossdown_target2[1], Double.NaN);
41 | plot crossdownTarget1 = if close < DailySMA2 and crossdown_target1 < DailySMA2 then crossdown_target1 else Double.NaN;
42 | crossdownTarget1.SetDefaultColor(Color.VIOLET);
43 |
44 | AddLabel(close < DailySMA2 and close > crossdown_target2, "Target1: " + Round(crossdown_target1, 1), Color.RED);
45 | AddLabel(close < DailySMA2 and close > crossdown_target2, "Target2: " + Round(crossdown_target2, 1) , Color.RED);
46 | plot crossdownTarget2 = if close < DailySMA2 and crossdown_target1 < DailySMA2 then crossdown_target2 else Double.NaN;
47 | crossdownTarget2.SetDefaultColor(Color.VIOLET);
48 | AddCloud(crossdownTarget2, crossdownTarget1, Color.RED, Color.RED);
49 |
50 | def crossuplevel = (DailySMA2 + DailySMA2[1]) / 2;
51 | def crossupTGT1 = 0.5 * (crossuplevel - mostRecentLow) + crossuplevel;
52 | def crossupTGT2 = (crossuplevel - mostRecentLow) + crossuplevel;
53 |
54 | # Check if price crossed the fld level this period
55 | def didwecrossup = if close[1] < DailySMA2[1] and close > DailySMA2 then crossupTGT1 else 0;
56 |
57 | def crossup_target1 = CompoundValue(1, if doPlot1 && close > DailySMA2 and didwecrossup then crossupTGT1 else crossup_target1[1], Double.NaN);
58 | def crossup_target2 = CompoundValue(1, if doPlot1 && close > DailySMA2 and didwecrossup then crossupTGT2 else crossup_target2[1], Double.NaN);
59 |
60 | plot crossupTarget1 = if close > DailySMA2 and crossup_target1 > DailySMA2 then crossup_target1 else Double.NaN;
61 | crossupTarget1.SetDefaultColor(Color.BLUE);
62 |
63 | AddLabel(close > DailySMA2 and close < crossup_target2, "Target1: " + Round(crossup_target1, 1), Color.GREEN);
64 | AddLabel(close > DailySMA2 and close < crossup_target2, "Target2: " + Round(crossup_target2, 1), Color.GREEN);
65 | plot crossupTarget2 = if close > DailySMA2 and crossup_target1 > DailySMA2 then crossup_target2 else Double.NaN;
66 | crossupTarget2.SetDefaultColor(Color.BLUE);
67 |
68 | AddCloud(crossupTarget2, crossupTarget1, Color.GREEN, Color.GREEN);
69 |
--------------------------------------------------------------------------------
/hurst_cycles/hurst_10_20_40_long_only_strat_tester.ts:
--------------------------------------------------------------------------------
1 | # FLD Cross 10,20 and 40 Day Cycles Strategy Tester Long Only
2 | # @2187Nick
3 | # Use aggregation period: Day. Extended hours on.
4 | declare upper;
5 | declare once_per_bar;
6 | input cycle = {default "TenDay", "TwentyDay", "FortyDay"};
7 | def lookback = if cycle < 1 then 7 else if cycle > 0 and cycle < 2 then 12 else 25;
8 | def displace = if cycle < 1 then 4 else if cycle > 0 and cycle < 2 then 9 else 18; #8
9 | def line_color = if cycle < 1 then 5 else if cycle > 0 and cycle < 2 then 0 else 6;
10 |
11 | def currentBarNumber = if !IsNaN(close) then BarNumber() else Double.NaN;
12 | def lastBarNumber = HighestAll(currentBarNumber);
13 | def lookbackBar = lastBarNumber - lookback + 1;
14 |
15 | def highest = highest(high,lookback);
16 | def lowest = lowest(low,lookback);
17 |
18 | def mostRecentHigh = highest(high,lookback);
19 | def highBarNumber = CompoundValue(1, if high > mostRecentHigh[1] then currentBarNumber else highBarNumber[1], 0);
20 |
21 | def mostRecentLow = lowest(low,lookback);
22 | def lowBarNumber = CompoundValue(1, if low < mostRecentLow[1] then currentBarNumber else lowBarNumber[1], 0);
23 |
24 | #Plots a bubble showing where lookback bar is.
25 | AddChartBubble(currentBarNumber == lookbackBar, (high + low) / 2, lookback + "\nBar", Color.GRAY, yes);
26 |
27 | def DailySMA2 = Average(Fundamental(FundamentalType.HL2, period = AggregationPeriod.DAY)[displace], 1);
28 | plot sma2 = DailySMA2;
29 | sma2.SetDefaultColor(GetColor(line_color));
30 | sma2.SetLineWeight(3);
31 |
32 | # Find which ones is the lowest and we measure from there.
33 | #def crossdownlevel = if DailySMA2 <= DailySMA2[1] then DailySMA2 else DailySMA2[1];
34 | def crossdownlevel = (DailySMA2 + DailySMA2[1]) / 2;
35 | # Distance from cycle high to the fld level
36 | def crossdownTGT1 = crossdownlevel - 0.5 * (mostRecentHigh - crossdownlevel);
37 | def crossdownTGT2 = crossdownlevel - (mostRecentHigh - crossdownlevel);
38 |
39 | # Check if price crossed the fld level this period
40 | def didwecrossdown = if close[1] > DailySMA2[1] and close < DailySMA2 then crossdownTGT1 else 0;
41 |
42 | def doPlot1 = 1;
43 | def crossdown_target1 = CompoundValue(1, if doPlot1 && close < DailySMA2 and didwecrossdown then crossdownTGT1 else crossdown_target1[1], Double.NaN);
44 | def crossdown_target2 = CompoundValue(1, if doPlot1 && close < DailySMA2 and didwecrossdown then crossdownTGT2 else crossdown_target2[1], Double.NaN);
45 | plot crossdownTarget1 = if close < DailySMA2 and crossdown_target1 < DailySMA2 then crossdown_target1 else Double.NaN;
46 | crossdownTarget1.SetDefaultColor(Color.VIOLET);
47 |
48 | AddLabel(close < DailySMA2 and close > crossdown_target2, "Target1: " + Round(crossdown_target1, 1), Color.RED);
49 | AddLabel(close < DailySMA2 and close > crossdown_target2, "Target2: " + Round(crossdown_target2, 1) , Color.RED);
50 | plot crossdownTarget2 = if close < DailySMA2 and crossdown_target1 < DailySMA2 then crossdown_target2 else Double.NaN;
51 | crossdownTarget2.SetDefaultColor(Color.VIOLET);
52 | AddCloud(crossdownTarget2, crossdownTarget1, Color.RED, Color.RED);
53 |
54 | def crossuplevel = (DailySMA2 + DailySMA2[1]) / 2;
55 | def crossupTGT1 = 0.5 * (crossuplevel - mostRecentLow) + crossuplevel;
56 | def crossupTGT2 = (crossuplevel - mostRecentLow) + crossuplevel;
57 |
58 | # Check if price crossed the fld level this period
59 | def didwecrossup = if close[1] < DailySMA2[1] and close > DailySMA2 then crossupTGT1 else 0;
60 |
61 | def crossup_target1 = CompoundValue(1, if doPlot1 && close > DailySMA2 and didwecrossup then crossupTGT1 else crossup_target1[1], Double.NaN);
62 | def crossup_target2 = CompoundValue(1, if doPlot1 && close > DailySMA2 and didwecrossup then crossupTGT2 else crossup_target2[1], Double.NaN);
63 |
64 | plot crossupTarget1 = if close > DailySMA2 and crossup_target1 > DailySMA2 then crossup_target1 else Double.NaN;
65 | crossupTarget1.SetDefaultColor(Color.BLUE);
66 |
67 | AddLabel(close > DailySMA2 and close < crossup_target2, "Target1: " + Round(crossup_target1, 1), Color.GREEN);
68 | AddLabel(close > DailySMA2 and close < crossup_target2, "Target2: " + Round(crossup_target2, 1), Color.GREEN);
69 | plot crossupTarget2 = if close > DailySMA2 and crossup_target1 > DailySMA2 then crossup_target2 else Double.NaN;
70 | crossupTarget2.SetDefaultColor(Color.BLUE);
71 |
72 | AddCloud(crossupTarget2, crossupTarget1, Color.GREEN, Color.GREEN);
73 |
74 | addOrder(OrderType.BUY_TO_OPEN, didwecrossup, close, 100, Color.green, color.green, "Buy To Open");
75 | addOrder(OrderType.SELL_TO_CLOSE, close >= crossupTarget1, close, 1, Color.green, color.green, "Sell To Close");
76 | addOrder(OrderType.SELL_TO_CLOSE, high >= crossupTarget1, close, 1, Color.green, color.green, "Sell To Close");
77 | addOrder(OrderType.SELL_TO_CLOSE, close <= DailySMA2, close, 1, Color.green, color.green, "Sell To Close");
78 | #addOrder(OrderType.SELL_TO_CLOSE, open <= DailySMA2, close, 1, Color.green, color.green, "Sell To Close");
79 | #addOrder(OrderType.SELL_TO_CLOSE, low <= DailySMA2, close, 1, Color.green, color.green, "Sell To Close");
80 |
81 | #addOrder(OrderType.SELL_TO_OPEN, didwecrossdown, tickColor = GetColor(6), arrowColor = GetColor(6));
82 | #addOrder(OrderType.SELL_TO_OPEN, didwecrossdown, close, 100, Color.red, color.red, "Sell To Open");
83 | #addOrder(OrderType.BUY_TO_CLOSE, close <= crossdownTarget1 or close > DailySMA2, close, 1, Color.red, color.red, "Buy To Close");
84 |
--------------------------------------------------------------------------------
/hurst_cycles/hurst_10_20_40_short_only_strat_tester.ts:
--------------------------------------------------------------------------------
1 | # FLD Cross 10, 20, 40 Day Cycles Strategy Tester Short Only
2 | # @2187Nick
3 | # Use aggregation period: "Day". Extended hours on.
4 | declare upper;
5 | declare once_per_bar;
6 | input cycle = {default "TenDay", "TwentyDay", "FortyDay"};
7 | def lookback = if cycle < 1 then 7 else if cycle > 0 and cycle < 2 then 12 else 25;
8 | def displace = if cycle < 1 then 4 else if cycle > 0 and cycle < 2 then 9 else 18; #8
9 | def line_color = if cycle < 1 then 5 else if cycle > 0 and cycle < 2 then 0 else 6;
10 |
11 | def currentBarNumber = if !IsNaN(close) then BarNumber() else Double.NaN;
12 | def lastBarNumber = HighestAll(currentBarNumber);
13 | def lookbackBar = lastBarNumber - lookback + 1;
14 |
15 | def highest = highest(high,lookback);
16 | def lowest = lowest(low,lookback);
17 |
18 | def mostRecentHigh = highest(high,lookback);
19 | def highBarNumber = CompoundValue(1, if high > mostRecentHigh[1] then currentBarNumber else highBarNumber[1], 0);
20 |
21 | def mostRecentLow = lowest(low,lookback);
22 | def lowBarNumber = CompoundValue(1, if low < mostRecentLow[1] then currentBarNumber else lowBarNumber[1], 0);
23 |
24 | #Plots a bubble showing where lookback bar is.
25 | AddChartBubble(currentBarNumber == lookbackBar, (high + low) / 2, lookback + "\nBar", Color.GRAY, yes);
26 |
27 | def DailySMA2 = Average(Fundamental(FundamentalType.HL2, period = AggregationPeriod.DAY)[displace], 1);
28 | plot sma2 = DailySMA2;
29 | sma2.SetDefaultColor(GetColor(line_color));
30 | sma2.SetLineWeight(3);
31 |
32 | def crossdownlevel = (DailySMA2 + DailySMA2[1]) / 2;
33 | # Distance from cycle high to the fld level
34 | def crossdownTGT1 = crossdownlevel - 0.5 * (mostRecentHigh - crossdownlevel);
35 | def crossdownTGT2 = crossdownlevel - (mostRecentHigh - crossdownlevel);
36 |
37 | # Check if price crossed the fld level this period
38 | def didwecrossdown = if close[1] > DailySMA2[1] and close < DailySMA2 then crossdownTGT1 else 0;
39 |
40 | def doPlot1 = 1;
41 | def crossdown_target1 = CompoundValue(1, if doPlot1 && close < DailySMA2 and didwecrossdown then crossdownTGT1 else crossdown_target1[1], Double.NaN);
42 | def crossdown_target2 = CompoundValue(1, if doPlot1 && close < DailySMA2 and didwecrossdown then crossdownTGT2 else crossdown_target2[1], Double.NaN);
43 | plot crossdownTarget1 = if close < DailySMA2 and crossdown_target1 < DailySMA2 then crossdown_target1 else Double.NaN;
44 | crossdownTarget1.SetDefaultColor(Color.VIOLET);
45 |
46 | AddLabel(close < DailySMA2 and close > crossdown_target2, "Target1: " + Round(crossdown_target1, 1), Color.RED);
47 | AddLabel(close < DailySMA2 and close > crossdown_target2, "Target2: " + Round(crossdown_target2, 1) , Color.RED);
48 | plot crossdownTarget2 = if close < DailySMA2 and crossdown_target1 < DailySMA2 then crossdown_target2 else Double.NaN;
49 | crossdownTarget2.SetDefaultColor(Color.VIOLET);
50 | AddCloud(crossdownTarget2, crossdownTarget1, Color.RED, Color.RED);
51 |
52 | # Find which ones is the highest and we measure from there.
53 | #def crossuplevel = if DailySMA2 >= DailySMA2[1] then DailySMA2 else DailySMA2[1];
54 | def crossuplevel = (DailySMA2 + DailySMA2[1]) / 2;
55 | def crossupTGT1 = 0.5 * (crossuplevel - mostRecentLow) + crossuplevel;
56 | def crossupTGT2 = (crossuplevel - mostRecentLow) + crossuplevel;
57 |
58 | # Check if price crossed the fld level this period
59 | def didwecrossup = if close[1] < DailySMA2[1] and close > DailySMA2 then crossupTGT1 else 0;
60 |
61 | def crossup_target1 = CompoundValue(1, if doPlot1 && close > DailySMA2 and didwecrossup then crossupTGT1 else crossup_target1[1], Double.NaN);
62 | def crossup_target2 = CompoundValue(1, if doPlot1 && close > DailySMA2 and didwecrossup then crossupTGT2 else crossup_target2[1], Double.NaN);
63 |
64 | plot crossupTarget1 = if close > DailySMA2 and crossup_target1 > DailySMA2 then crossup_target1 else Double.NaN;
65 | crossupTarget1.SetDefaultColor(Color.BLUE);
66 |
67 | AddLabel(close > DailySMA2 and close < crossup_target2, "Target1: " + Round(crossup_target1, 1), Color.GREEN);
68 | AddLabel(close > DailySMA2 and close < crossup_target2, "Target2: " + Round(crossup_target2, 1), Color.GREEN);
69 | plot crossupTarget2 = if close > DailySMA2 and crossup_target1 > DailySMA2 then crossup_target2 else Double.NaN;
70 | crossupTarget2.SetDefaultColor(Color.BLUE);
71 |
72 | AddCloud(crossupTarget2, crossupTarget1, Color.GREEN, Color.GREEN);
73 |
74 | #addOrder(OrderType.BUY_TO_OPEN, didwecrossup, tickColor = GetColor(6), arrowColor = GetColor(6));
75 | #addOrder(OrderType.SELL_TO_CLOSE, close >= crossupTarget1 or close < DailySMA2, tickColor = GetColor(5), arrowColor = GetColor(5));
76 |
77 | #addOrder(OrderType.BUY_TO_OPEN, didwecrossup, close, 1, Color.green, color.green, "Buy To Open");
78 | #addOrder(OrderType.SELL_TO_CLOSE, close >= crossupTarget1 or close < DailySMA2, close, 1, Color.green, color.green, "Sell To Close");
79 |
80 | addOrder(OrderType.SELL_TO_OPEN, didwecrossdown, close, 100, Color.red, color.red, "Sell To Open");
81 | addOrder(OrderType.BUY_TO_CLOSE, close <= crossdownTarget1, close, 100, Color.red, color.red, "Buy To Close");
82 | addOrder(OrderType.BUY_TO_CLOSE, close >= DailySMA2, close, 100, Color.red, color.red, "Buy To Close");
83 |
--------------------------------------------------------------------------------
/hurst_cycles/hurst_1_day_cycle_v2.ts:
--------------------------------------------------------------------------------
1 | # FLD Cross 1 Day Cycle
2 | # @2187Nick
3 | # Use 15min chart. Extended hours on.
4 | declare upper;
5 | declare once_per_bar;
6 | #input cycle = {default "TenDay", "TwentyDay", "FortyDay", "EightDay"};
7 | def lookback = 50;
8 | def displace = 49;
9 | def line_color = 4;
10 | # if cycle < 1 then 5 else if cycle > 0 and cycle < 2 then 0 else if cycle > 1 and cycle < 3 then 6 else 1;
11 |
12 | def currentBarNumber = if !IsNaN(close) then BarNumber() else Double.NaN;
13 | def lastBarNumber = HighestAll(currentBarNumber);
14 | def lookbackBar = lastBarNumber - lookback + 1;
15 |
16 | def mostRecentHigh = highest(high,lookback);
17 | def highBarNumber = CompoundValue(1, if high > mostRecentHigh[1] then currentBarNumber else highBarNumber[1], 0);
18 |
19 | def mostRecentLow = lowest(low,lookback);
20 | def lowBarNumber = CompoundValue(1, if low < mostRecentLow[1] then currentBarNumber else lowBarNumber[1], 0);
21 |
22 | #Plots a bubble showing where lookback bar is.
23 | AddChartBubble(currentBarNumber == lookbackBar, (high + low) / 2, lookback + "\nBar", Color.GRAY, yes);
24 |
25 | def DailySMA2 = Average(Fundamental(FundamentalType.HL2, period = AggregationPeriod.fifteen_min)[displace], 1);
26 | plot sma2 = DailySMA2;
27 | sma2.SetDefaultColor(GetColor(line_color));
28 | sma2.SetLineWeight(3);
29 |
30 | def crossdownlevel = (DailySMA2 + DailySMA2[1]) / 2;
31 | # Distance from cycle high to the fld level
32 | def crossdownTGT1 = crossdownlevel - 0.5 * (mostRecentHigh - crossdownlevel);
33 | def crossdownTGT2 = crossdownlevel - (mostRecentHigh - crossdownlevel);
34 |
35 | # Check if price crossed the fld level this period
36 | def didwecrossdown = if close[1] > DailySMA2[1] and close < DailySMA2 then crossdownTGT1 else 0;
37 |
38 | def doPlot1 = 1;
39 | def crossdown_target1 = CompoundValue(1, if doPlot1 && close < DailySMA2 and didwecrossdown then crossdownTGT1 else crossdown_target1[1], Double.NaN);
40 | def crossdown_target2 = CompoundValue(1, if doPlot1 && close < DailySMA2 and didwecrossdown then crossdownTGT2 else crossdown_target2[1], Double.NaN);
41 | plot crossdownTarget1 = if close < DailySMA2 and crossdown_target1 < DailySMA2 then crossdown_target1 else Double.NaN;
42 | crossdownTarget1.SetDefaultColor(Color.VIOLET);
43 |
44 | AddLabel(close < DailySMA2 and close > crossdown_target2, "Target1: " + Round(crossdown_target1, 1), Color.RED);
45 | AddLabel(close < DailySMA2 and close > crossdown_target2, "Target2: " + Round(crossdown_target2, 1) , Color.RED);
46 | plot crossdownTarget2 = if close < DailySMA2 and crossdown_target1 < DailySMA2 then crossdown_target2 else Double.NaN;
47 | crossdownTarget2.SetDefaultColor(Color.VIOLET);
48 | AddCloud(crossdownTarget2, crossdownTarget1, Color.RED, Color.RED);
49 |
50 | def crossuplevel = (DailySMA2 + DailySMA2[1]) / 2;
51 | def crossupTGT1 = 0.5 * (crossuplevel - mostRecentLow) + crossuplevel;
52 | def crossupTGT2 = (crossuplevel - mostRecentLow) + crossuplevel;
53 |
54 | # Check if price crossed the fld level this period
55 | def didwecrossup = if close[1] < DailySMA2[1] and close > DailySMA2 then crossupTGT1 else 0;
56 |
57 | def crossup_target1 = CompoundValue(1, if doPlot1 && close > DailySMA2 and didwecrossup then crossupTGT1 else crossup_target1[1], Double.NaN);
58 | def crossup_target2 = CompoundValue(1, if doPlot1 && close > DailySMA2 and didwecrossup then crossupTGT2 else crossup_target2[1], Double.NaN);
59 |
60 | plot crossupTarget1 = if close > DailySMA2 and crossup_target1 > DailySMA2 then crossup_target1 else Double.NaN;
61 | crossupTarget1.SetDefaultColor(Color.BLUE);
62 |
63 | AddLabel(close > DailySMA2 and close < crossup_target2, "Target1: " + Round(crossup_target1, 1), Color.GREEN);
64 | AddLabel(close > DailySMA2 and close < crossup_target2, "Target2: " + Round(crossup_target2, 1), Color.GREEN);
65 | plot crossupTarget2 = if close > DailySMA2 and crossup_target1 > DailySMA2 then crossup_target2 else Double.NaN;
66 | crossupTarget2.SetDefaultColor(Color.BLUE);
67 |
68 | AddCloud(crossupTarget2, crossupTarget1, Color.GREEN, Color.GREEN);
69 |
--------------------------------------------------------------------------------
/hurst_cycles/hurst_1_day_long_only_strat_tester.ts:
--------------------------------------------------------------------------------
1 | # FLD Cross One Day Cycle Strategy Tester Long Only
2 | # @2187Nick
3 | # Use aggregation period: 15min. Extended hours on.
4 | declare upper;
5 | declare once_per_bar;
6 | def lookback = 50;
7 | def displace = 49;
8 | def line_color = 4;
9 |
10 | def currentBarNumber = if !IsNaN(close) then BarNumber() else Double.NaN;
11 | def lastBarNumber = HighestAll(currentBarNumber);
12 | def lookbackBar = lastBarNumber - lookback + 1;
13 |
14 | def highest = highest(high,lookback);
15 | def lowest = lowest(low,lookback);
16 |
17 | def mostRecentHigh = highest(high,lookback);
18 | def highBarNumber = CompoundValue(1, if high > mostRecentHigh[1] then currentBarNumber else highBarNumber[1], 0);
19 |
20 | def mostRecentLow = lowest(low,lookback);
21 | def lowBarNumber = CompoundValue(1, if low < mostRecentLow[1] then currentBarNumber else lowBarNumber[1], 0);
22 |
23 | #Plots a bubble showing where lookback bar is.
24 | AddChartBubble(currentBarNumber == lookbackBar, (high + low) / 2, lookback + "\nBar", Color.GRAY, yes);
25 |
26 | def DailySMA2 = Average(Fundamental(FundamentalType.HL2, period = AggregationPeriod.fifteen_min)[displace], 1);
27 | plot sma2 = DailySMA2;
28 | sma2.SetDefaultColor(GetColor(line_color));
29 | sma2.SetLineWeight(3);
30 |
31 | # Find which ones is the lowest and we measure from there.
32 | #def crossdownlevel = if DailySMA2 <= DailySMA2[1] then DailySMA2 else DailySMA2[1];
33 | def crossdownlevel = (DailySMA2 + DailySMA2[1]) / 2;
34 | # Distance from cycle high to the fld level
35 | def crossdownTGT1 = crossdownlevel - 0.5 * (mostRecentHigh - crossdownlevel);
36 | def crossdownTGT2 = crossdownlevel - (mostRecentHigh - crossdownlevel);
37 |
38 | # Check if price crossed the fld level this period
39 | def didwecrossdown = if close[1] > DailySMA2[1] and close < DailySMA2 then crossdownTGT1 else 0;
40 |
41 | def doPlot1 = 1;
42 | def crossdown_target1 = CompoundValue(1, if doPlot1 && close < DailySMA2 and didwecrossdown then crossdownTGT1 else crossdown_target1[1], Double.NaN);
43 | def crossdown_target2 = CompoundValue(1, if doPlot1 && close < DailySMA2 and didwecrossdown then crossdownTGT2 else crossdown_target2[1], Double.NaN);
44 | plot crossdownTarget1 = if close < DailySMA2 and crossdown_target1 < DailySMA2 then crossdown_target1 else Double.NaN;
45 | crossdownTarget1.SetDefaultColor(Color.VIOLET);
46 |
47 | AddLabel(close < DailySMA2 and close > crossdown_target2, "Target1: " + Round(crossdown_target1, 1), Color.RED);
48 | AddLabel(close < DailySMA2 and close > crossdown_target2, "Target2: " + Round(crossdown_target2, 1) , Color.RED);
49 | plot crossdownTarget2 = if close < DailySMA2 and crossdown_target1 < DailySMA2 then crossdown_target2 else Double.NaN;
50 | crossdownTarget2.SetDefaultColor(Color.VIOLET);
51 | AddCloud(crossdownTarget2, crossdownTarget1, Color.RED, Color.RED);
52 |
53 | def crossuplevel = (DailySMA2 + DailySMA2[1]) / 2;
54 | def crossupTGT1 = 0.5 * (crossuplevel - mostRecentLow) + crossuplevel;
55 | def crossupTGT2 = (crossuplevel - mostRecentLow) + crossuplevel;
56 |
57 | # Check if price crossed the fld level this period
58 | def didwecrossup = if close[1] < DailySMA2[1] and close > DailySMA2 then crossupTGT1 else 0;
59 |
60 | def crossup_target1 = CompoundValue(1, if doPlot1 && close > DailySMA2 and didwecrossup then crossupTGT1 else crossup_target1[1], Double.NaN);
61 | def crossup_target2 = CompoundValue(1, if doPlot1 && close > DailySMA2 and didwecrossup then crossupTGT2 else crossup_target2[1], Double.NaN);
62 |
63 | plot crossupTarget1 = if close > DailySMA2 and crossup_target1 > DailySMA2 then crossup_target1 else Double.NaN;
64 | crossupTarget1.SetDefaultColor(Color.BLUE);
65 |
66 | AddLabel(close > DailySMA2 and close < crossup_target2, "Target1: " + Round(crossup_target1, 1), Color.GREEN);
67 | AddLabel(close > DailySMA2 and close < crossup_target2, "Target2: " + Round(crossup_target2, 1), Color.GREEN);
68 | plot crossupTarget2 = if close > DailySMA2 and crossup_target1 > DailySMA2 then crossup_target2 else Double.NaN;
69 | crossupTarget2.SetDefaultColor(Color.BLUE);
70 |
71 | AddCloud(crossupTarget2, crossupTarget1, Color.GREEN, Color.GREEN);
72 |
73 | #addOrder(OrderType.BUY_TO_OPEN, didwecrossup, close, 100, Color.green, color.green, "Buy To Open");
74 | #addOrder(OrderType.SELL_TO_CLOSE, close >= crossupTarget1, close, 1, Color.green, color.green, "Sell To Close");
75 | #addOrder(OrderType.SELL_TO_CLOSE, high >= crossupTarget1, close, 1, Color.green, color.green, "Sell To Close");
76 | #addOrder(OrderType.SELL_TO_CLOSE, close <= DailySMA2, close, 1, Color.green, color.green, "Sell To Close");
77 | #addOrder(OrderType.SELL_TO_CLOSE, open <= DailySMA2, close, 1, Color.green, color.green, "Sell To Close");
78 | #addOrder(OrderType.SELL_TO_CLOSE, low <= DailySMA2, close, 1, Color.green, color.green, "Sell To Close");
79 |
80 | addOrder(OrderType.SELL_TO_OPEN, didwecrossdown, close, 100, Color.red, color.red, "Sell To Open");
81 | addOrder(OrderType.BUY_TO_CLOSE, close <= crossdownTarget1, close, 100, Color.red, color.red, "Buy To Close");
82 | addOrder(OrderType.BUY_TO_CLOSE, close >= DailySMA2, close, 100, Color.red, color.red, "Buy To Close");
83 |
--------------------------------------------------------------------------------
/hurst_cycles/hurst_1_day_short_only_strat_tester.ts:
--------------------------------------------------------------------------------
1 | # FLD Cross One Day Cycle Strategy Tester Long Only
2 | # @2187Nick
3 | # Use aggregation period: 15min. Extended hours on.
4 | declare upper;
5 | declare once_per_bar;
6 | def lookback = 50;
7 | def displace = 49;
8 | def line_color = 4;
9 |
10 | def currentBarNumber = if !IsNaN(close) then BarNumber() else Double.NaN;
11 | def lastBarNumber = HighestAll(currentBarNumber);
12 | def lookbackBar = lastBarNumber - lookback + 1;
13 |
14 | def highest = highest(high,lookback);
15 | def lowest = lowest(low,lookback);
16 |
17 | def mostRecentHigh = highest(high,lookback);
18 | def highBarNumber = CompoundValue(1, if high > mostRecentHigh[1] then currentBarNumber else highBarNumber[1], 0);
19 |
20 | def mostRecentLow = lowest(low,lookback);
21 | def lowBarNumber = CompoundValue(1, if low < mostRecentLow[1] then currentBarNumber else lowBarNumber[1], 0);
22 |
23 | #Plots a bubble showing where lookback bar is.
24 | AddChartBubble(currentBarNumber == lookbackBar, (high + low) / 2, lookback + "\nBar", Color.GRAY, yes);
25 |
26 | def DailySMA2 = Average(Fundamental(FundamentalType.HL2, period = AggregationPeriod.fifteen_min)[displace], 1);
27 | plot sma2 = DailySMA2;
28 | sma2.SetDefaultColor(GetColor(line_color));
29 | sma2.SetLineWeight(3);
30 |
31 | # Find which ones is the lowest and we measure from there.
32 | #def crossdownlevel = if DailySMA2 <= DailySMA2[1] then DailySMA2 else DailySMA2[1];
33 | def crossdownlevel = (DailySMA2 + DailySMA2[1]) / 2;
34 | # Distance from cycle high to the fld level
35 | def crossdownTGT1 = crossdownlevel - 0.5 * (mostRecentHigh - crossdownlevel);
36 | def crossdownTGT2 = crossdownlevel - (mostRecentHigh - crossdownlevel);
37 |
38 | # Check if price crossed the fld level this period
39 | def didwecrossdown = if close[1] > DailySMA2[1] and close < DailySMA2 then crossdownTGT1 else 0;
40 |
41 | def doPlot1 = 1;
42 | def crossdown_target1 = CompoundValue(1, if doPlot1 && close < DailySMA2 and didwecrossdown then crossdownTGT1 else crossdown_target1[1], Double.NaN);
43 | def crossdown_target2 = CompoundValue(1, if doPlot1 && close < DailySMA2 and didwecrossdown then crossdownTGT2 else crossdown_target2[1], Double.NaN);
44 | plot crossdownTarget1 = if close < DailySMA2 and crossdown_target1 < DailySMA2 then crossdown_target1 else Double.NaN;
45 | crossdownTarget1.SetDefaultColor(Color.VIOLET);
46 |
47 | AddLabel(close < DailySMA2 and close > crossdown_target2, "Target1: " + Round(crossdown_target1, 1), Color.RED);
48 | AddLabel(close < DailySMA2 and close > crossdown_target2, "Target2: " + Round(crossdown_target2, 1) , Color.RED);
49 | plot crossdownTarget2 = if close < DailySMA2 and crossdown_target1 < DailySMA2 then crossdown_target2 else Double.NaN;
50 | crossdownTarget2.SetDefaultColor(Color.VIOLET);
51 | AddCloud(crossdownTarget2, crossdownTarget1, Color.RED, Color.RED);
52 |
53 | def crossuplevel = (DailySMA2 + DailySMA2[1]) / 2;
54 | def crossupTGT1 = 0.5 * (crossuplevel - mostRecentLow) + crossuplevel;
55 | def crossupTGT2 = (crossuplevel - mostRecentLow) + crossuplevel;
56 |
57 | # Check if price crossed the fld level this period
58 | def didwecrossup = if close[1] < DailySMA2[1] and close > DailySMA2 then crossupTGT1 else 0;
59 |
60 | def crossup_target1 = CompoundValue(1, if doPlot1 && close > DailySMA2 and didwecrossup then crossupTGT1 else crossup_target1[1], Double.NaN);
61 | def crossup_target2 = CompoundValue(1, if doPlot1 && close > DailySMA2 and didwecrossup then crossupTGT2 else crossup_target2[1], Double.NaN);
62 |
63 | plot crossupTarget1 = if close > DailySMA2 and crossup_target1 > DailySMA2 then crossup_target1 else Double.NaN;
64 | crossupTarget1.SetDefaultColor(Color.BLUE);
65 |
66 | AddLabel(close > DailySMA2 and close < crossup_target2, "Target1: " + Round(crossup_target1, 1), Color.GREEN);
67 | AddLabel(close > DailySMA2 and close < crossup_target2, "Target2: " + Round(crossup_target2, 1), Color.GREEN);
68 | plot crossupTarget2 = if close > DailySMA2 and crossup_target1 > DailySMA2 then crossup_target2 else Double.NaN;
69 | crossupTarget2.SetDefaultColor(Color.BLUE);
70 |
71 | AddCloud(crossupTarget2, crossupTarget1, Color.GREEN, Color.GREEN);
72 |
73 | #addOrder(OrderType.BUY_TO_OPEN, didwecrossup, close, 100, Color.green, color.green, "Buy To Open");
74 | #addOrder(OrderType.SELL_TO_CLOSE, close >= crossupTarget1, close, 1, Color.green, color.green, "Sell To Close");
75 | #addOrder(OrderType.SELL_TO_CLOSE, high >= crossupTarget1, close, 1, Color.green, color.green, "Sell To Close");
76 | #addOrder(OrderType.SELL_TO_CLOSE, close <= DailySMA2, close, 1, Color.green, color.green, "Sell To Close");
77 | #addOrder(OrderType.SELL_TO_CLOSE, open <= DailySMA2, close, 1, Color.green, color.green, "Sell To Close");
78 | #addOrder(OrderType.SELL_TO_CLOSE, low <= DailySMA2, close, 1, Color.green, color.green, "Sell To Close");
79 |
80 | addOrder(OrderType.SELL_TO_OPEN, didwecrossdown, close, 100, Color.red, color.red, "Sell To Open");
81 | addOrder(OrderType.BUY_TO_CLOSE, close <= crossdownTarget1, close, 100, Color.red, color.red, "Buy To Close");
82 | addOrder(OrderType.BUY_TO_CLOSE, close >= DailySMA2, close, 100, Color.red, color.red, "Buy To Close");
83 |
--------------------------------------------------------------------------------
/images/2187logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2187Nick/thinkscript/a5d99b3d7e3c062da51d9ef865893b5aee8f311e/images/2187logo.png
--------------------------------------------------------------------------------
/images/charm-option-chain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2187Nick/thinkscript/a5d99b3d7e3c062da51d9ef865893b5aee8f311e/images/charm-option-chain.png
--------------------------------------------------------------------------------
/images/es-futures-options.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2187Nick/thinkscript/a5d99b3d7e3c062da51d9ef865893b5aee8f311e/images/es-futures-options.png
--------------------------------------------------------------------------------
/images/es-vertical-volume-oi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2187Nick/thinkscript/a5d99b3d7e3c062da51d9ef865893b5aee8f311e/images/es-vertical-volume-oi.png
--------------------------------------------------------------------------------
/images/gamma-exposure-horizontal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2187Nick/thinkscript/a5d99b3d7e3c062da51d9ef865893b5aee8f311e/images/gamma-exposure-horizontal.png
--------------------------------------------------------------------------------
/images/spy-open-interest.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2187Nick/thinkscript/a5d99b3d7e3c062da51d9ef865893b5aee8f311e/images/spy-open-interest.png
--------------------------------------------------------------------------------
/images/spy-spx-combo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2187Nick/thinkscript/a5d99b3d7e3c062da51d9ef865893b5aee8f311e/images/spy-spx-combo.png
--------------------------------------------------------------------------------
/images/spy_uoa.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2187Nick/thinkscript/a5d99b3d7e3c062da51d9ef865893b5aee8f311e/images/spy_uoa.png
--------------------------------------------------------------------------------
/images/test:
--------------------------------------------------------------------------------
1 | a
2 |
--------------------------------------------------------------------------------
/images/vanna-exposure-horizontal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2187Nick/thinkscript/a5d99b3d7e3c062da51d9ef865893b5aee8f311e/images/vanna-exposure-horizontal.png
--------------------------------------------------------------------------------
/modular/README.md:
--------------------------------------------------------------------------------
1 | ...
2 |
--------------------------------------------------------------------------------
/modular/futures/options/es/README.md:
--------------------------------------------------------------------------------
1 | ## Color coded the weeks and option prefix for easy verification script is working correctly.
2 | 
3 |
4 | #
5 | 
6 |
7 |
8 |
--------------------------------------------------------------------------------
/modular/greeks/README.md:
--------------------------------------------------------------------------------
1 | # Test function for Gamma, Vanna, and Charm
2 |  
3 |
4 | ## Set the date and strike. Then compare results to the online calculator @ https://perfiliev.co.uk/apps/black-scholes-pricer/
5 |
6 |
7 |
8 | ### Notes:
9 |
10 | 1. You must set the days to expiration if you are checking a date that is past the current month.
11 |
12 | 2. 1 Script calculates the greeks with 0 dividend and 0 interest rate.
13 |
14 | 3. The GEX, VEX, and CEX formulas are a work in progress.
15 |
--------------------------------------------------------------------------------
/modular/greeks/delta:
--------------------------------------------------------------------------------
1 | # Delta and Delta Exposure Functions. Sep 11, 2024
2 | # Twitter @2187Nick
3 | # Verify against this calculator:
4 | # https://perfiliev.co.uk/apps/black-scholes-pricer/
5 |
6 | # Note: Must set days to expiration if you are checking a date past the current month.
7 |
8 | declare lower;
9 | declare once_per_bar;
10 |
11 | input strike = 558.0;
12 |
13 | # If testing premarket then you can only use the previous days Open Interest
14 | # The Open Interest will update once the market opens.
15 | input PreMarket = {default "false", "true"};
16 | def day = if !PreMarket then 0 else 1;
17 |
18 | input ManuallySetExpiration = {default "false", "true"};
19 | input Expiration_YYMMDD = 240916;
20 | input ManuallySetdte = {default "false", "true"};
21 | input dte = 5.0;
22 |
23 | def DateString_auto = GetYYYYMMDD() - 20000000;
24 | def DateString = if ManuallySetExpiration then Expiration_YYMMDD else DateString_auto;
25 |
26 | def agg = AggregationPeriod.Day;
27 |
28 | def InterestRate = getInterestRate();
29 | def DividendYield = getYield();
30 | addlabel(yes, "InterestRate: " + AsPercent(InterestRate), color.white);
31 | addlabel(yes, "DividendYield: " + AsPercent(DividendYield), color.white);
32 |
33 | def seconds_left = SecondsTillTime(1615);
34 | def hours_left = seconds_left / 3600;
35 | def days_left = if hours_left <= 0 then 0 else hours_left / 24;
36 |
37 | def Vol = imp_volatility(getSymbol());
38 | addlabel(yes, "Volatility_Percentage: " + AsPercent(Vol), color.white);
39 | def S = close()[day];
40 | addlabel(yes, "S_close: " + S);
41 |
42 | # only works for current month expirations
43 | def t_auto = ((DateString - DateString_auto) + days_left) / 365;
44 | def t_manual = dte/365;
45 | #addlabel(yes, "t_manual: " + t_manual);
46 | def t = if ManuallySetdte then t_manual else t_auto;
47 | addlabel(yes, "days_left: " + Round(t*365,2));
48 | #def t = 1/365;
49 | def Sqr_Vol_2 = Sqr(Vol)*.5* t;
50 | def Vol_Sqrt_t = Vol * Sqrt(t);
51 | def Vol_Sqrt_t_S = S * Vol_Sqrt_t;
52 |
53 | def r = getInterestRate();
54 | def q = getYield();
55 |
56 | def r_q_Sqr_Vol_2 = (r-q + 0.5 * Sqr(Vol))* t;
57 |
58 | Script GREEKS {
59 | input strike = 0;
60 | input dateString = 0;
61 | input Vol = 0;
62 | input t = 0;
63 | input r = 0;
64 | input q = 0;
65 | input S = 0;
66 | input todayoryday = 0;
67 | input r_q_Sqr_Vol_2 = 0;
68 | input Vol_Sqrt_t = 0;
69 | input Vol_Sqrt_t_S = 0;
70 | input normcdf_d1 = 0;
71 | input normcdf_d1_put = 0;
72 | def d1 = (Log(S / strike) + r_q_Sqr_Vol_2) / Vol_Sqrt_t;
73 |
74 | def call_delta = Exp(-q * t) * normcdf_d1;
75 | def put_delta = -Exp(-q * t) * normcdf_d1_put;
76 |
77 | plot strikeDEX = Round(((open_interest("."+ getSymbol() + AsPrice(dateString) + "C" + AsPrice(strike),AggregationPeriod.DAY)[todayoryday]*call_delta) + (open_interest("."+ getSymbol() + AsPrice(dateString) + "P" + AsPrice(strike),AggregationPeriod.DAY)[todayoryday]*put_delta)) *S/1,0);
78 | }
79 |
80 | # Abramowiz Stegun Approximation for Cumulative Normal Distribution
81 | script cnd
82 | {
83 | input data = 1;
84 | def a = AbsValue(data);
85 | def b1 = .31938153;
86 | def b2 = -.356563782;
87 | def b3 = 1.781477937;
88 | def b4 = -1.821255978;
89 | def b5 = 1.330274429;
90 | def b6 = .2316419;
91 | def e = 1 / (1 + b6 * a);
92 | def i = 1 - 1 / Sqrt(2 * Double.Pi) * Exp(-Power(a, 2) / 2) *
93 | (b1 * e + b2 * e * e + b3 * Power(e, 3) + b4 * Power(e, 4) + b5 * Power(e, 5));
94 | plot CND = if data < 0
95 | then 1 - i
96 | else i;
97 | }
98 |
99 | def d1 = GREEKS(strike, dateString, Vol, t, r, q, S, day, r_q_Sqr_Vol_2, Vol_Sqrt_t, Vol_Sqrt_t_S).d1;
100 | #addlabel(yes, strike + "_d1: " + d1, color.yellow);
101 |
102 | # for charm call
103 | def normcdf_d1 = cnd(d1).CND;
104 | #addlabel(yes, strike + "_normcdf_d1: " + normcdf_d1, color.white);
105 |
106 | # for charm put
107 | def normcdf_d1_put = cnd(-d1).CND;
108 | #addlabel(yes, strike + "_normcdf_d1_put: " + normcdf_d1_put, color.yellow);
109 |
110 | # Add labels for delta
111 | def call_delta = GREEKS(strike, dateString, Vol, t, r, q, S, day, r_q_Sqr_Vol_2, Vol_Sqrt_t, Vol_Sqrt_t_S, normcdf_d1).call_delta;
112 | addlabel(yes, strike + "_call_delta: " + call_delta, color.pink);
113 |
114 | def put_delta = GREEKS(strike, dateString, Vol, t, r, q, S, day, r_q_Sqr_Vol_2, Vol_Sqrt_t, Vol_Sqrt_t_S, normcdf_d1, normcdf_d1_put).put_delta;
115 | addlabel(yes, strike + "_put_delta " + put_delta, color.light_green);
116 |
117 | plot dex_test = GREEKS(strike, dateString, Vol, t, r, q, S, day, r_q_Sqr_Vol_2, Vol_Sqrt_t, Vol_Sqrt_t_S, normcdf_d1, normcdf_d1_put).strikeDex;
118 | addlabel(yes, strike + "_dex: " + dex_test, color.cyan);
119 |
--------------------------------------------------------------------------------
/modular/greeks/gamma_vanna_charm:
--------------------------------------------------------------------------------
1 | # Gamma Vanna Charm Function Jan 22, 2024
2 | # Twitter @2187Nick
3 | # Verify against this calculator:
4 | # https://perfiliev.co.uk/apps/black-scholes-pricer/
5 |
6 | # Note: Must set days to expiration if you are checking a date past the current month.
7 |
8 | declare lower;
9 | declare once_per_bar;
10 |
11 | input strike = 480.0;
12 |
13 | # If testing premarket then you can only use the previous days Open Interest
14 | # The Open Interest will update once the market opens.
15 | input PreMarket = {default "false", "true"};
16 | def day = if !PreMarket then 0 else 1;
17 |
18 | input ManuallySetExpiration = {default "false", "true"};
19 | input Expiration_YYMMDD = 240216;
20 | input ManuallySetdte = {default "false", "true"};
21 | input dte = 25.0;
22 |
23 | def DateString_auto = GetYYYYMMDD() - 20000000;
24 | def DateString = if ManuallySetExpiration then Expiration_YYMMDD else DateString_auto;
25 |
26 | def agg = AggregationPeriod.Day;
27 |
28 | def InterestRate = getInterestRate();
29 | def DividendYield = getYield();
30 | addlabel(yes, "InterestRate: " + AsPercent(InterestRate), color.white);
31 | addlabel(yes, "DividendYield: " + AsPercent(DividendYield), color.white);
32 |
33 | def seconds_left = SecondsTillTime(1615);
34 | def hours_left = seconds_left / 3600;
35 | def days_left = if hours_left <= 0 then 0 else hours_left / 24;
36 |
37 | def Vol = imp_volatility(getSymbol());
38 | addlabel(yes, "Volatility_Percentage: " + AsPercent(Vol), color.white);
39 | def S = close()[day];
40 | addlabel(yes, "S_close: " + S);
41 |
42 | # only works for current month expirations
43 | def t_auto = ((DateString - DateString_auto) + days_left) / 365;
44 | def t_manual = dte/365;
45 | #addlabel(yes, "t_manual: " + t_manual);
46 | def t = if ManuallySetdte then t_manual else t_auto;
47 | addlabel(yes, "days_left: " + Round(t*365,2));
48 | #def t = 1/365;
49 | def Sqr_Vol_2 = Sqr(Vol)*.5* t;
50 | def Vol_Sqrt_t = Vol * Sqrt(t);
51 | def Vol_Sqrt_t_S = S * Vol_Sqrt_t;
52 |
53 | def r = getInterestRate();
54 | def q = getYield();
55 |
56 | def r_q_Sqr_Vol_2 = (r-q + 0.5 * Sqr(Vol))* t;
57 |
58 | Script GREEKS {
59 | input strike = 0;
60 | input dateString = 0;
61 | input Vol = 0;
62 | input t = 0;
63 | input r = 0;
64 | input q = 0;
65 | input S = 0;
66 | input todayoryday = 0;
67 | input r_q_Sqr_Vol_2 = 0;
68 | input Vol_Sqrt_t = 0;
69 | input Vol_Sqrt_t_S = 0;
70 | input normcdf_d1 = 0;
71 | input normcdf_d1_put = 0;
72 | def d1 = (Log(S / strike) + r_q_Sqr_Vol_2) / Vol_Sqrt_t;
73 |
74 | def N1d1 = Exp(-.5*Sqr((Log(S / strike) + r_q_Sqr_Vol_2) / Vol_Sqrt_t)) / 2.5066;
75 | def d2 = d1 - Vol_Sqrt_t;
76 | def term1 = N1d1 * (( 2*(r-q) *t - d2 * Vol_Sqrt_t ) / ( 2 * t * Vol_Sqrt_t));
77 |
78 | def call_charm = (q*exp(-q *t)*normcdf_d1 - exp(-q *t) * term1)/365;
79 | def put_charm = (-q*exp(-q *t)*normcdf_d1_put - exp(-q *t) * term1)/365;
80 |
81 | def vanna = -exp(-q * t) * N1d1 * (d2/Vol);
82 | def gamma = exp(-q * t) * N1d1 / Vol_Sqrt_t_S;
83 |
84 | plot strikeGEX = Round((open_interest("."+ getSymbol() + AsPrice(dateString) + "C" + AsPrice(strike),AggregationPeriod.DAY)[todayoryday] - open_interest("."+ getSymbol() + AsPrice(dateString) + "P" + AsPrice(strike),AggregationPeriod.DAY)[todayoryday]) * gamma*S/1,0);
85 |
86 | def strikeVEX = Round((open_interest("."+getSymbol()+ AsPrice(DateString) + "C" + AsPrice(strike),AggregationPeriod.DAY)[todayoryday] - open_interest("."+getSymbol()+AsPrice(DateString) + "P" + AsPrice(strike),AggregationPeriod.DAY)[todayoryday])* vanna * S * Vol/1,1);
87 |
88 | def strikeCEX = Round((open_interest("."+getSymbol()+ AsPrice(DateString) + "C" + AsPrice(strike),AggregationPeriod.DAY)[todayoryday] - open_interest("."+getSymbol()+AsPrice(DateString) + "P" + AsPrice(strike),AggregationPeriod.DAY)[todayoryday])* call_charm * S/1,1);
89 |
90 | }
91 |
92 | # Abramowiz Stegun Approximation for Cumulative Normal Distribution
93 | script cnd
94 | {
95 | input data = 1;
96 | def a = AbsValue(data);
97 | def b1 = .31938153;
98 | def b2 = -.356563782;
99 | def b3 = 1.781477937;
100 | def b4 = -1.821255978;
101 | def b5 = 1.330274429;
102 | def b6 = .2316419;
103 | def e = 1 / (1 + b6 * a);
104 | def i = 1 - 1 / Sqrt(2 * Double.Pi) * Exp(-Power(a, 2) / 2) *
105 | (b1 * e + b2 * e * e + b3 * Power(e, 3) + b4 * Power(e, 4) + b5 * Power(e, 5));
106 | plot CND = if data < 0
107 | then 1 - i
108 | else i;
109 | }
110 |
111 | def d1 = GREEKS(strike, dateString, Vol, t, r, q, S, day, r_q_Sqr_Vol_2, Vol_Sqrt_t, Vol_Sqrt_t_S).d1;
112 | #addlabel(yes, strike + "_d1: " + d1, color.yellow);
113 |
114 | # for charm call
115 | def normcdf_d1 = cnd(d1).CND;
116 | #addlabel(yes, strike + "_normcdf_d1: " + normcdf_d1, color.white);
117 |
118 | # for charm put
119 | def normcdf_d1_put = cnd(-d1).CND;
120 | #addlabel(yes, strike + "_normcdf_d1_put: " + normcdf_d1_put, color.yellow);
121 |
122 | def d2 = GREEKS(strike, dateString, Vol, t, r, q, S, day, r_q_Sqr_Vol_2, Vol_Sqrt_t, Vol_Sqrt_t_S).d2;
123 | #addlabel(yes, strike + "_d2: " + d2, color.violet);
124 |
125 | def N1d1 = GREEKS(strike, dateString, Vol, t, r, q, S, day, r_q_Sqr_Vol_2, Vol_Sqrt_t, Vol_Sqrt_t_S).N1d1;
126 | #addlabel(yes, strike + "_N1d1: " + N1d1, color.white);
127 |
128 | def term1 = GREEKS(strike, dateString, Vol, t, r, q, S, day, r_q_Sqr_Vol_2, Vol_Sqrt_t, Vol_Sqrt_t_S,normcdf_d1).term1;
129 | #addlabel(yes, strike + "_term1: " + term1, color.orange);
130 |
131 | def vanna_test2 = GREEKS(strike, dateString, Vol, t, r, q, S, day, r_q_Sqr_Vol_2, Vol_Sqrt_t, Vol_Sqrt_t_S).vanna;
132 | addlabel(yes, strike + "_vanna: " + vanna_test2, color.cyan);
133 |
134 | def vex_test2 = GREEKS(strike, dateString, Vol, t, r, q, S, day, r_q_Sqr_Vol_2, Vol_Sqrt_t, Vol_Sqrt_t_S).strikeVEX;
135 | addlabel(yes, strike + "_vex: " + vex_test2, color.violet);
136 |
137 | def cex_test = GREEKS(strike, dateString, Vol, t, r, q, S, day, r_q_Sqr_Vol_2, Vol_Sqrt_t, Vol_Sqrt_t_S, normcdf_d1).strikeCEX;
138 | addlabel(yes, strike + "_cex: " + cex_test, color.dark_orange);
139 |
140 | def charm_test_call = GREEKS(strike, dateString, Vol, t, r, q, S, day, r_q_Sqr_Vol_2, Vol_Sqrt_t, Vol_Sqrt_t_S, normcdf_d1).call_charm;
141 | addlabel(yes, strike + "_charm_call: " + charm_test_call, color.yellow);
142 |
143 | def charm_test_put = GREEKS(strike, dateString, Vol, t, r, q, S, day, r_q_Sqr_Vol_2, Vol_Sqrt_t, Vol_Sqrt_t_S, normcdf_d1, normcdf_d1_put).put_charm;
144 | addlabel(yes, strike + "_charm_put: " + charm_test_put, color.white);
145 |
146 | def gamma_test = GREEKS(strike, dateString, Vol, t, r, q, S, day, r_q_Sqr_Vol_2, Vol_Sqrt_t, Vol_Sqrt_t_S).gamma;
147 | addlabel(yes, strike + "_gamma: " + gamma_test, color.green);
148 |
149 | plot gex_test = GREEKS(strike, dateString, Vol, t, r, q, S, day, r_q_Sqr_Vol_2, Vol_Sqrt_t, Vol_Sqrt_t_S).strikeGex;
150 | addlabel(yes, strike + "_gex: " + gex_test, color.cyan);
151 |
--------------------------------------------------------------------------------
/modular/greeks/gamma_vanna_charm_0div_0int:
--------------------------------------------------------------------------------
1 | # Gamma Vanna Charm Function Jan 19, 2024
2 | # Twitter @2187Nick
3 | # Verify against this calculator:
4 | # https://perfiliev.co.uk/apps/black-scholes-pricer/
5 |
6 | # Still working on the formulas for GEX, CEX, and VEX
7 |
8 | declare lower;
9 | #declare once_per_bar;
10 |
11 | input strike = 480.0;
12 |
13 | # If testing premarket then you can only use the previous days Open Interest
14 | # The Open Interest will update once the market opens.
15 | input PreMarket = {default "false", "true"};
16 | def day = if !PreMarket then 0 else 1;
17 | input ManuallySetExpiration = {default "false", "true"};
18 | input Expiration_YYMMDD = 240126;
19 | def DateString_auto = GetYYYYMMDD() - 20000000;
20 | def DateString = if ManuallySetExpiration then Expiration_YYMMDD else DateString_auto;
21 | def agg = AggregationPeriod.Day;
22 |
23 | def InterestRate = getInterestRate();
24 | def DividendYield = getYield();
25 | addlabel(yes, "InterestRate: " + AsPercent(InterestRate), color.white);
26 | addlabel(yes, "DividendYield: " + AsPercent(DividendYield), color.white);
27 |
28 | def seconds_left = SecondsTillTime(1615);
29 | def hours_left = seconds_left / 3600;
30 | def days_left = if hours_left <= 0 then 0 else hours_left / 24;
31 |
32 | def Vol = imp_volatility(getSymbol());
33 | addlabel(yes, "Volatility_Percentage: " + AsPercent(Vol), color.white);
34 | def S = close()[day];
35 | #addlabel(yes, "S_close: " + S);
36 |
37 | def t = ((DateString - DateString_auto) + days_left) / 365;
38 | addlabel(yes, "days_left: " + Round(t*365,2));
39 | #def t = 1/365;
40 | def Sqr_Vol_2 = Sqr(Vol)*.5* t;
41 | def Vol_Sqrt_t = Vol * Sqrt(t);
42 | def Vol_Sqrt_t_S = S * Vol_Sqrt_t;
43 |
44 | Script GEX {
45 | input strike = 0;
46 | input dateString = 0;
47 | input Vol = 0;
48 | input t = 0;
49 | input S = 0;
50 | input todayoryday = 0;
51 | input Sqr_Vol_2 = 0;
52 | input Vol_Sqrt_t = 0;
53 | input Vol_Sqrt_t_S = 0;
54 | def d1 = (Log(S / strike) + Sqr_Vol_2) / Vol_Sqrt_t;
55 | def N1d1 = Exp(-.5*Sqr((Log(S / strike) + Sqr_Vol_2) / Vol_Sqrt_t)) / 2.5066;
56 | def d2 = d1 - Vol_Sqrt_t;
57 |
58 | # Divide by 365 to get single day value of Charm.
59 | def charm = -(N1d1 * (( -d2 * Vol_Sqrt_t ) / ( 2 * t * Vol_Sqrt_t)))/365;
60 |
61 | def vanna = -N1d1 * (d2/Vol);
62 |
63 | def gamma = N1d1 / Vol_Sqrt_t_S;
64 |
65 | plot strikeGEX = Round((open_interest("."+ getSymbol() + AsPrice(dateString) + "C" + AsPrice(strike),AggregationPeriod.DAY)[todayoryday] - open_interest("."+ getSymbol() + AsPrice(dateString) + "P" + AsPrice(strike),AggregationPeriod.DAY)[todayoryday]) * gamma*S/1,0);
66 |
67 | def strikeCEX = Round((open_interest("."+getSymbol()+ AsPrice(DateString) + "C" + AsPrice(strike),AggregationPeriod.DAY)[todayoryday] - open_interest("."+getSymbol()+AsPrice(DateString) + "P" + AsPrice(strike),AggregationPeriod.DAY)[todayoryday])* charm * S/1,1);
68 |
69 | def strikeVEX = Round((open_interest("."+getSymbol()+ AsPrice(DateString) + "C" + AsPrice(strike),AggregationPeriod.DAY)[todayoryday] - open_interest("."+getSymbol()+AsPrice(DateString) + "P" + AsPrice(strike),AggregationPeriod.DAY)[todayoryday])* vanna * S * Vol/1,1);
70 |
71 | }
72 |
73 | def vanna_test = GEX(strike, dateString, Vol, t, S, day, Sqr_Vol_2, Vol_Sqrt_t, Vol_Sqrt_t_S).vanna;
74 | addlabel(yes, strike + "_vanna: " + vanna_test, color.cyan);
75 | def vex_test = GEX(strike, dateString, Vol, t, S, day, Sqr_Vol_2, Vol_Sqrt_t, Vol_Sqrt_t_S).strikeVEX;
76 | addlabel(yes, strike + "_vex: " + vex_test, color.violet);
77 |
78 | def charm_test = GEX(strike, dateString, Vol, t, S, day, Sqr_Vol_2, Vol_Sqrt_t, Vol_Sqrt_t_S).charm;
79 | addlabel(yes, strike + "_charm: " + charm_test, color.yellow);
80 | def cex_test = GEX(strike, dateString, Vol, t, S, day, Sqr_Vol_2, Vol_Sqrt_t, Vol_Sqrt_t_S).strikeCEX;
81 | addlabel(yes, strike + "_cex: " + cex_test, color.dark_orange);
82 |
83 | def gamma_test = GEX(strike, dateString, Vol, t, S, day, Sqr_Vol_2, Vol_Sqrt_t, Vol_Sqrt_t_S).gamma;
84 | addlabel(yes, strike + "_gamma: " + gamma_test, color.green);
85 |
86 | plot gex_test = GEX(strike, dateString, Vol, t, S, day, Sqr_Vol_2, Vol_Sqrt_t, Vol_Sqrt_t_S).strikeGex;
87 | addlabel(yes, strike + "_gex: " + gex_test, color.cyan);
88 |
--------------------------------------------------------------------------------
/near_the_money/README.md:
--------------------------------------------------------------------------------
1 | 🚀 This monitors for a peak in option call premium at the highs and peak in option put premium at the lows.
2 | *** Oct 10 2023 VIX version not currently working. Use the SPY version for now.
3 |
4 | Category: Mean Reversion
5 |
6 |
7 |
8 | Designed for SPY and QQQ.
9 |
10 | New features/changes:
11 | 1. This version uses vix to set a range of strikes to monitor.
12 | 2. Starts at 945. First 15 min lots of chaos and false signals.
13 |
14 | > Chart requirements for optimal use:
15 | ```bash
16 |
17 | Time frame: 1 Day
18 |
19 | Aggregation Period: 1 Minute
20 |
21 | Note: This does work on a historical look back.
22 | ```
23 |
24 |
25 |
26 |
27 | > Settings 👷:
28 |
29 | ```bash
30 |
31 | Upper:
32 | 1. Strike Spacing: 1; (This sets the space between strikes. Ex: Current SPY price is 400. It will monitor calls
33 | and puts at strikes 398, 399, 400, 401 and 402)
34 | 2. Premium Extreme Level: 1000000; (This sets the $ amount to exceed for the Alert to activate)
35 |
36 | Lower:
37 | 1. Strike Spacing: 1;
38 | 2. Highline Millions: 1000000; (Allows you to plot a red line at the $ value in Millions for calls)
39 | 3. Lowline Millions: -1000000; (Allows you to plot a green line at the $ value in Millions for puts)
40 | ```
41 |
42 |
43 |
44 |
45 | > 🧪 How this works:
46 |
47 | ```bash
48 |
49 | Calculates the option premium(purchased or sold) for 5 strikes. ( itm +1, itm, atm, otm, otm +1)
50 |
51 | A. Option premium = Volume x Price. ( 1 minute volume x close price)
52 |
53 | Example: SPY 400 Call Option. Volume: 1000. Close Price: $1.50; Option Premium = $150K. (For that 1 min period)
54 |
55 | B. Sum the Call Option Premium for the 5 strikes.
56 |
57 | C. If the total amount is greater than Premium Extreme Level. Then alert bubble "Sell" will appear on that candle.
58 |
59 | Note: The upper indicator checks if price is moving up by comparing previous close price vs current price. It will only alert a "Sell"
60 | if we are moving up. It will fail to alert if that requirement is not met. ( I will improve on this in the future).
61 |
62 | Note: I avoid the signals during roughly the first 15 minutes of market open.
63 | ```
64 |
65 | > 🦖 Why this works:
66 | ```bash
67 | 1 Theory:
68 |
69 | As the stock price decreases eventually some market participants sell large amounts of puts. Betting that the stock will not continue to decrease.
70 |
71 | As the stock price increases eventually some market participants sell large amounts of calls. Betting that the stock will not continue to increase.
72 |
73 | Warning: If it is not a mean reverting day. Then you can easily get ran over.
74 |
75 | ```
76 |
--------------------------------------------------------------------------------
/near_the_money/near_the_money_daily_vix:
--------------------------------------------------------------------------------
1 | # near_the_money_spy_daily_vix
2 | # @2187Nick
3 |
4 | # May 16, 2023
5 | # This version usses vix to set a range of strikes to monitor.
6 | # Adds chart bubble when price is rising and call premium exceeds $1 million.
7 | # Adds chart bubble when price is falling and put premium exceeds $1 million.
8 |
9 | # Run on 1 min chart only. Calculates Premium. ( 1 min volume x 1 min OHLC4)
10 | # Starts at 945. First 15 min lots of chaos and false signals.
11 |
12 | declare lower;
13 | declare once_per_bar;
14 |
15 | input chain_width = 1;
16 | input symbol = "SPY"; #"SPXW"
17 | input premium_extreme = 1000000;
18 |
19 | def after945 = SecondsFromTime(945) >= 0;
20 |
21 | def vix = close("VIX", AggregationPeriod.DAY)[1];
22 | def price = round(close(symbol, AggregationPeriod.day)[1],0);
23 | #def price = round(close("SPX", AggregationPeriod.day)[1],0);
24 |
25 |
26 | def move = vix / Sqrt(252) / 100;
27 | def strike_down = Round (price * (1 - move) / chain_width, 0.01) * chain_width;
28 | def strike_up = Round (price * (1 + move) / chain_width, 0.01) * chain_width;
29 | addlabel(yes, "Strike: " + strike_down + " to " + strike_up, color.cyan);
30 |
31 |
32 | # get 0DTE expiration
33 | def CurrentYear = GetYear()-2000;
34 | def CurrentMonth = GetMonth();
35 | def CurrentDay = GetDayOfMonth(GetYYYYMMDD());
36 | def DateString = CurrentYear * 10000 + CurrentMonth * 100 + CurrentDay;
37 |
38 | def Call_VolumexOHLC = fold strike_c = strike_down to strike_up with v do v +
39 | if IsNaN(volume("." + symbol + AsPrice(DateString) + "C" + AsPrice(strike_c))) then 0
40 | else (volume("." + symbol + AsPrice(DateString) + "C" + AsPrice(strike_c))
41 | *ohlc4("." + symbol + AsPrice(DateString) + "C" + AsPrice(strike_c))
42 | );
43 |
44 | def Put_VolumexOHLC = fold strike_p = strike_down to strike_up with v_p do v_p +
45 | if IsNaN(volume("." + symbol + AsPrice(DateString) + "P" + AsPrice(strike_p)))then 0
46 | else (volume("." + symbol + AsPrice(DateString) + "P" + AsPrice(strike_p))
47 | *ohlc4("." + symbol + AsPrice(DateString) + "P" + AsPrice(strike_p))
48 | );
49 |
50 | plot calls_total = if after945 then Call_VolumexOHLC*100 else 0;
51 | calls_total.SetPaintingStrategy(PaintingStrategy.SQUARED_HISTOGRAM);
52 | calls_total.AssignValueColor(if calls_total > premium_extreme then Color.GREEN else Color.DARK_GRAY);
53 |
54 |
55 | plot puts_total = if after945 then -1.0 * put_VolumexOHLC*100 else 0;
56 | puts_total.SetPaintingStrategy(PaintingStrategy.SQUARED_HISTOGRAM);
57 | puts_total.AssignValueColor(if puts_total < -1.0 * premium_extreme then Color.RED else Color.DARK_GRAY);
58 |
59 | plot highline = premium_extreme;
60 | plot lowline = -1*premium_extreme;
61 | highline.SetDefaultColor(Color.red);
62 | lowline.SetDefaultColor(Color.green);
63 |
--------------------------------------------------------------------------------
/near_the_money/near_the_money_daily_vix_upper:
--------------------------------------------------------------------------------
1 | # near_the_money_spy_daiily_vix_upper
2 | # @2187Nick
3 |
4 | # May 16, 2023
5 | # This version usses vix to set a range of strikes to monitor.
6 | # Adds chart bubble when price is rising and call premium exceeds $1 million.
7 | # Adds chart bubble when price is falling and put premium exceeds $1 million.
8 |
9 | # Run on 1 min chart only. Calculates Premium. ( 1 min volume x 1 min OHLC4)
10 | # Starts at 945. First 15 min lots of chaos and false signals.
11 | declare once_per_bar;
12 |
13 | input chain_width = 1;
14 | input symbol = "SPY";
15 | input premium_extreme_level = 1000000;
16 |
17 | def after945 = SecondsFromTime(945) >= 0;
18 |
19 | def vix = close("VIX", AggregationPeriod.DAY)[1];
20 |
21 | def price = round(close(symbol, AggregationPeriod.day)[1],0);
22 | def move = vix / Sqrt(252) / 100;
23 |
24 | def strike_up = Round (price * (1 + move) / chain_width, 0.01) * chain_width;
25 | def strike_down = Round (price * (1 - move) / chain_width, 0.01) * chain_width;
26 |
27 | # get 0DTE expiration
28 | def CurrentYear = GetYear()-2000;
29 | def CurrentMonth = GetMonth();
30 | def CurrentDay = GetDayOfMonth(GetYYYYMMDD());
31 | def DateString = CurrentYear * 10000 + CurrentMonth * 100 + CurrentDay;
32 |
33 | def Call_VolumexOHLC = fold strike_c = strike_down to strike_up with v do v +
34 | if IsNaN(volume("." + symbol + AsPrice(DateString) + "C" + AsPrice(strike_c))) then 0
35 | else (volume("." + symbol + AsPrice(DateString) + "C" + AsPrice(strike_c))
36 | *ohlc4("." + symbol + AsPrice(DateString) + "C" + AsPrice(strike_c))
37 | );
38 |
39 | def Put_VolumexOHLC = fold strike_p = strike_down to strike_up with v_p do v_p +
40 | if IsNaN(volume("." + symbol + AsPrice(DateString) + "P" + AsPrice(strike_p))) then 0
41 | else (volume("." + symbol + AsPrice(DateString) + "P" + AsPrice(strike_p))
42 | *ohlc4("." + symbol + AsPrice(DateString) + "P" + AsPrice(strike_p))
43 | );
44 |
45 | def moving_up = if close[1] > close[2] then 1 else 0;
46 | def moving_down = close[1] < close[2];
47 |
48 | def calls_current_total = if after945 then Call_VolumexOHLC*100 else 0;
49 | def puts_current_total = if after945 then put_VolumexOHLC*100 else 0;
50 |
51 | AddChartBubble(puts_current_total > premium_extreme_level and moving_down, low, "Extreme" , color.Green, no);
52 | AddChartBubble(calls_current_total > premium_extreme_level and moving_up ==1, high+.1, "Extreme" , color.red);
53 |
--------------------------------------------------------------------------------
/near_the_money/near_the_money_spy:
--------------------------------------------------------------------------------
1 | # near_tm_spy_v4
2 | # 2187Nick
3 | declare lower;
4 | declare once_per_bar;
5 |
6 | input Strike_Spacing = 1;
7 | input highline_millions = 1000000;
8 | input lowline_millions = -1000000;
9 | plot highline = highline_millions;
10 | plot lowline = lowline_millions;
11 | highline.SetDefaultColor(Color.red);
12 | lowline.SetDefaultColor(Color.green);
13 |
14 | def DateString = GetYYYYMMDD()-20000000;
15 |
16 | def rounding_factor = if Strike_Spacing > 1 and Strike_Spacing < 25 then -1 else if Strike_Spacing > 24 then -2 else 0;
17 |
18 | def base = Round(close, rounding_factor);
19 | addlabel(yes, "ATM: " + base);
20 |
21 | def strike_atm = base;
22 | def strike_itm1_call = base - Strike_Spacing;
23 | def strike_itm2_call = base - Strike_Spacing*2;
24 | def strike_otm1_call = Strike_Spacing + base;
25 | def strike_otm2_call = Strike_Spacing + Strike_Spacing * 1 + base;
26 | #def strike_otm3_call = Strike_Spacing + Strike_Spacing * 2 + base;
27 |
28 | def strike_itm1_put = base + Strike_Spacing;
29 | def strike_itm2_put = base + Strike_Spacing*2;
30 | def strike_otm1_put = base - Strike_Spacing;
31 | def strike_otm2_put = base - Strike_Spacing - Strike_Spacing * 1;
32 | #def strike_otm3_put = base - Strike_Spacing - Strike_Spacing * 2;
33 |
34 |
35 | def call_close_itm1 = close("." + GetSymbol() + AsPrice(DateString) +"C" + strike_itm1_call);
36 | def call_volume_itm1 = volume("." + GetSymbol() + AsPrice(DateString) +"C" + strike_itm1_call);
37 |
38 | def call_close_itm2 = close("." + GetSymbol() + AsPrice(DateString) +"C" + strike_itm2_call);
39 | def call_volume_itm2 = volume("." + GetSymbol() + AsPrice(DateString) +"C" + strike_itm2_call);
40 |
41 | def call_close_price = close("." + GetSymbol() + AsPrice(DateString) +"C" + strike_atm);
42 | def call_volume = volume("." + GetSymbol() + AsPrice(DateString) +"C" + strike_atm);
43 |
44 | def call_close_otm1 = close("." + GetSymbol() + AsPrice(DateString) +"C" + strike_otm1_call);
45 | def call_volume1 = volume("." + GetSymbol() + AsPrice(DateString) +"C" + strike_otm1_call);
46 |
47 | def call_close_otm2 = close("." + GetSymbol() + AsPrice(DateString) +"C" + strike_otm2_call);
48 | def call_volume2 = volume("." + GetSymbol() + AsPrice(DateString) +"C" + strike_otm2_call);
49 |
50 | def put_close_price_itm1 = close("." + GetSymbol() + AsPrice(DateString) +"P" + strike_itm1_put);
51 | def put_volume_itm1 = volume("." + GetSymbol() + AsPrice(DateString) +"P" + strike_itm1_put);
52 |
53 | def put_close_price_itm2 = close("." + GetSymbol() + AsPrice(DateString) +"P" + strike_itm2_put);
54 | def put_volume_itm2 = volume("." + GetSymbol() + AsPrice(DateString) +"P" + strike_itm2_put);
55 |
56 | def put_close_price = close("." + GetSymbol() + AsPrice(DateString) +"P" + strike_atm);
57 | def put_volume = volume("." + GetSymbol() + AsPrice(DateString) +"P" + strike_atm);
58 |
59 | def put_close_otm1 = close("." + GetSymbol() + AsPrice(DateString) +"P" + strike_otm1_put);
60 | def put_volume1 = volume("." + GetSymbol() + AsPrice(DateString) +"P" + strike_otm1_put);
61 |
62 | def put_close_otm2= close("." + GetSymbol() + AsPrice(DateString) +"P" + strike_otm2_put);
63 | def put_volume2 = volume("." + GetSymbol() + AsPrice(DateString) +"P" + strike_otm2_put);
64 |
65 | def call_itm_volumexclose = if isNaN(call_volume_itm1 * call_close_itm1 * 100) then 0 else call_volume_itm1 * call_close_itm1 * 100;
66 | def call_itm_volumexclose1 = if isNaN(call_volume_itm2 * call_close_itm2 * 100) then 0 else call_volume_itm2 * call_close_itm2 * 100;
67 | def call_volumexclose = if IsNan(call_volume * call_close_price * 100) then 0 else call_volume * call_close_price * 100 ;
68 | def call_plusone_volumexclose = if IsNan(call_volume1 * call_close_otm1) then 0 else call_volume1 * call_close_otm1 * 100 ;
69 | def call_plustwo_volumexclose = if IsNan(call_volume2 * call_close_otm2 * 100) then 0 else call_volume2 * call_close_otm2 * 100;
70 |
71 | def calls_current_total = call_itm_volumexclose + call_itm_volumexclose1 + call_volumexclose + call_plusone_volumexclose + call_plustwo_volumexclose;
72 |
73 | plot oneperiodcalls = calls_current_total;
74 | oneperiodcalls.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
75 | oneperiodcalls.SetLineWeight(5);
76 | oneperiodcalls.setdefaultcolor(color.green);
77 |
78 | def put_itm_volumexclose = if isNaN(put_volume_itm1 * put_close_price_itm1 * 100) then 0 else put_volume_itm1 * put_close_price_itm1 * 100;
79 | def put_itm_volumexclose1 = if isNaN(put_volume_itm2 * put_close_price_itm2 * 100) then 0 else put_volume_itm2 * put_close_price_itm2 * 100;
80 | def put_volumexclose = if isNaN(put_volume * put_close_price * 100) then 0 else put_volume * put_close_price * 100;
81 | def put_minusone_volumexclose = if isNaN(put_volume1 * put_close_otm1 * 100) then 0 else put_volume1 * put_close_otm1 * 100;
82 | def put_minustwo_volumexclose = if isNaN(put_volume2 * put_close_otm2 * 100) then 0 else put_volume2 * put_close_otm2 * 100;
83 |
84 | def puts_current_total = put_itm_volumexclose + put_itm_volumexclose1 + put_volumexclose + put_minusone_volumexclose + put_minustwo_volumexclose;
85 |
86 | plot puts_1min = 1 - puts_current_total;
87 | puts_1min.SetPaintingStrategy(PaintingStrategy.histogram);
88 | puts_1min.SetLineWeight(5);
89 | puts_1min.setdefaultcolor(color.red);
90 |
--------------------------------------------------------------------------------
/near_the_money/near_the_money_spy_upper:
--------------------------------------------------------------------------------
1 | # near_tm_spy_upper_v4
2 | # 2187Nick
3 | declare upper;
4 | declare once_per_bar;
5 |
6 | input Strike_Spacing = 1;
7 | input Premium_Extreme_Level = 1000000;
8 |
9 | def DateString = GetYYYYMMDD()-20000000;
10 |
11 | def rounding_factor = if Strike_Spacing > 1 and Strike_Spacing < 25 then -1 else if Strike_Spacing > 24 then -2 else 0;
12 |
13 | def base = Round(close, rounding_factor);
14 |
15 | def strike_atm = base;
16 | def strike_itm1_call = base - Strike_Spacing;
17 | def strike_itm2_call = base - Strike_Spacing*2;
18 | def strike_otm1_call = Strike_Spacing + base;
19 | def strike_otm2_call = Strike_Spacing + Strike_Spacing * 1 + base;
20 | #def strike_otm3_call = Strike_Spacing + Strike_Spacing * 2 + base;
21 |
22 | def strike_itm1_put = base + Strike_Spacing;
23 | def strike_itm2_put = base + Strike_Spacing*2;
24 | def strike_otm1_put = base - Strike_Spacing;
25 | def strike_otm2_put = base - Strike_Spacing - Strike_Spacing * 1;
26 | #def strike_otm3_put = base - Strike_Spacing - Strike_Spacing * 2;
27 |
28 | def call_close_itm1 = close("." + GetSymbol() + AsPrice(DateString) +"C" + strike_itm1_call);
29 |
30 | def call_volume_itm1 = volume("." + GetSymbol() + AsPrice(DateString) +"C" + strike_itm1_call);
31 |
32 | def call_close_itm2 = close("." + GetSymbol() + AsPrice(DateString) +"C" + strike_itm2_call);
33 | def call_volume_itm2 = volume("." + GetSymbol() + AsPrice(DateString) +"C" + strike_itm2_call);
34 |
35 | def call_close_price = close("." + GetSymbol() + AsPrice(DateString) +"C" + strike_atm);
36 | def call_volume = volume("." + GetSymbol() + AsPrice(DateString) +"C" + strike_atm);
37 |
38 | def call_close_otm1 = close("." + GetSymbol() + AsPrice(DateString) +"C" + strike_otm1_call);
39 | def call_volume1 = volume("." + GetSymbol() + AsPrice(DateString) +"C" + strike_otm1_call);
40 |
41 | def call_close_otm2 = close("." + GetSymbol() + AsPrice(DateString) +"C" + strike_otm2_call);
42 | def call_volume2 = volume("." + GetSymbol() + AsPrice(DateString) +"C" + strike_otm2_call);
43 |
44 | def put_close_price_itm1 = close("." + GetSymbol() + AsPrice(DateString) +"P" + strike_itm1_put);
45 | def put_volume_itm1 = volume("." + GetSymbol() + AsPrice(DateString) +"P" + strike_itm1_put);
46 |
47 | def put_close_price_itm2 = close("." + GetSymbol() + AsPrice(DateString) +"P" + strike_itm2_put);
48 | def put_volume_itm2 = volume("." + GetSymbol() + AsPrice(DateString) +"P" + strike_itm2_put);
49 |
50 | def put_close_price = close("." + GetSymbol() + AsPrice(DateString) +"P" + strike_atm);
51 | def put_volume = volume("." + GetSymbol() + AsPrice(DateString) +"P" + strike_atm);
52 |
53 | def put_close_otm1 = close("." + GetSymbol() + AsPrice(DateString) +"P" + strike_otm1_put);
54 | def put_volume1 = volume("." + GetSymbol() + AsPrice(DateString) +"P" + strike_otm1_put);
55 |
56 | def put_close_otm2= close("." + GetSymbol() + AsPrice(DateString) +"P" + strike_otm2_put);
57 | def put_volume2 = volume("." + GetSymbol() + AsPrice(DateString) +"P" + strike_otm2_put);
58 |
59 |
60 | def call_itm_volumexclose = if isNaN(call_volume_itm1 * call_close_itm1 * 100) then 0 else call_volume_itm1 * call_close_itm1 * 100;
61 | def call_itm_volumexclose1 = if isNaN(call_volume_itm2 * call_close_itm2 * 100) then 0 else call_volume_itm2 * call_close_itm2 * 100;
62 | def call_volumexclose = if IsNan(call_volume * call_close_price * 100) then 0 else call_volume * call_close_price * 100 ;
63 | def call_plusone_volumexclose = if IsNan(call_volume1 * call_close_otm1) then 0 else call_volume1 * call_close_otm1 * 100 ;
64 | def call_plustwo_volumexclose = if IsNan(call_volume2 * call_close_otm2 * 100) then 0 else call_volume2 * call_close_otm2 * 100;
65 |
66 | def calls_current_total = call_itm_volumexclose + call_itm_volumexclose1 + call_volumexclose + call_plusone_volumexclose + call_plustwo_volumexclose;
67 |
68 |
69 | def put_itm_volumexclose = if isNaN(put_volume_itm1 * put_close_price_itm1 * 100) then 0 else put_volume_itm1 * put_close_price_itm1 * 100;
70 | def put_itm_volumexclose1 = if isNaN(put_volume_itm2 * put_close_price_itm2 * 100) then 0 else put_volume_itm2 * put_close_price_itm2 * 100;
71 | def put_volumexclose = if isNaN(put_volume * put_close_price * 100) then 0 else put_volume * put_close_price * 100;
72 | def put_minusone_volumexclose = if isNaN(put_volume1 * put_close_otm1 * 100) then 0 else put_volume1 * put_close_otm1 * 100;
73 | def put_minustwo_volumexclose = if isNaN(put_volume2 * put_close_otm2 * 100) then 0 else put_volume2 * put_close_otm2 * 100;
74 |
75 | def puts_current_total = put_itm_volumexclose + put_itm_volumexclose1 + put_volumexclose + put_minusone_volumexclose + put_minustwo_volumexclose;
76 |
77 | def moving_up = if close[1] > close[2] then 1 else 0;
78 | def moving_down = close[1] < close[2];
79 | AddChartBubble(puts_current_total > Premium_Extreme_Level and moving_down, low, "BULL" , color.Green, no);
80 | AddChartBubble(calls_current_total > Premium_Extreme_Level and moving_up ==1, high, "BEAR" , color.red);
81 |
--------------------------------------------------------------------------------
/near_the_money/near_the_money_stocks:
--------------------------------------------------------------------------------
1 | # near_the_money_stocks
2 | # 2187Nick
3 | # Mar 7, 2025
4 | declare upper;
5 | declare once_per_bar;
6 |
7 | input Strike_Spacing = 1.0;
8 | input Premium_Extreme_Level = 1000000;
9 |
10 | input ManuallySetExpiration = {default "false", "true"};
11 | input Expiration_YYMMDD = 250620;
12 |
13 | def DateString_auto = GetYYYYMMDD()-20000000;
14 | def DateString = if manuallysetexpiration then Expiration_YYMMDD else DateString_auto;
15 |
16 | def rounding_factor = if Strike_Spacing > 1 and Strike_Spacing < 25 then -1 else if Strike_Spacing > 24 then -2 else 0;
17 |
18 | plot highline = Premium_Extreme_Level;
19 | plot lowline = -Premium_Extreme_Level;
20 | highline.SetDefaultColor(Color.red);
21 | lowline.SetDefaultColor(Color.green);
22 |
23 | def base = Round(close, rounding_factor);
24 | #addlabel(yes, "ATM: " + base);
25 |
26 | def strike_atm = base;
27 | def strike_itm1_call = base - Strike_Spacing;
28 | def strike_itm2_call = base - Strike_Spacing*2;
29 | def strike_otm1_call = Strike_Spacing + base;
30 | def strike_otm2_call = Strike_Spacing + Strike_Spacing * 1 + base;
31 | #def strike_otm3_call = Strike_Spacing + Strike_Spacing * 2 + base;
32 |
33 | def strike_itm1_put = base + Strike_Spacing;
34 | def strike_itm2_put = base + Strike_Spacing*2;
35 | def strike_otm1_put = base - Strike_Spacing;
36 | def strike_otm2_put = base - Strike_Spacing - Strike_Spacing * 1;
37 | #def strike_otm3_put = base - Strike_Spacing - Strike_Spacing * 2;
38 |
39 |
40 | def call_close_itm1 = close("." + GetSymbol() + AsPrice(DateString) +"C" + strike_itm1_call);
41 | def call_volume_itm1 = volume("." + GetSymbol() + AsPrice(DateString) +"C" + strike_itm1_call);
42 |
43 | def call_close_itm2 = close("." + GetSymbol() + AsPrice(DateString) +"C" + strike_itm2_call);
44 | def call_volume_itm2 = volume("." + GetSymbol() + AsPrice(DateString) +"C" + strike_itm2_call);
45 |
46 | def call_close_price = close("." + GetSymbol() + AsPrice(DateString) +"C" + strike_atm);
47 | def call_volume = volume("." + GetSymbol() + AsPrice(DateString) +"C" + strike_atm);
48 |
49 | def call_close_otm1 = close("." + GetSymbol() + AsPrice(DateString) +"C" + strike_otm1_call);
50 | def call_volume1 = volume("." + GetSymbol() + AsPrice(DateString) +"C" + strike_otm1_call);
51 |
52 | def call_close_otm2 = close("." + GetSymbol() + AsPrice(DateString) +"C" + strike_otm2_call);
53 | def call_volume2 = volume("." + GetSymbol() + AsPrice(DateString) +"C" + strike_otm2_call);
54 |
55 | def put_close_price_itm1 = close("." + GetSymbol() + AsPrice(DateString) +"P" + strike_itm1_put);
56 | def put_volume_itm1 = volume("." + GetSymbol() + AsPrice(DateString) +"P" + strike_itm1_put);
57 |
58 | def put_close_price_itm2 = close("." + GetSymbol() + AsPrice(DateString) +"P" + strike_itm2_put);
59 | def put_volume_itm2 = volume("." + GetSymbol() + AsPrice(DateString) +"P" + strike_itm2_put);
60 |
61 | def put_close_price = close("." + GetSymbol() + AsPrice(DateString) +"P" + strike_atm);
62 | def put_volume = volume("." + GetSymbol() + AsPrice(DateString) +"P" + strike_atm);
63 |
64 | def put_close_otm1 = close("." + GetSymbol() + AsPrice(DateString) +"P" + strike_otm1_put);
65 | def put_volume1 = volume("." + GetSymbol() + AsPrice(DateString) +"P" + strike_otm1_put);
66 |
67 | def put_close_otm2= close("." + GetSymbol() + AsPrice(DateString) +"P" + strike_otm2_put);
68 | def put_volume2 = volume("." + GetSymbol() + AsPrice(DateString) +"P" + strike_otm2_put);
69 |
70 | def call_itm_volumexclose = if isNaN(call_volume_itm1 * call_close_itm1 * 100) then 0 else call_volume_itm1 * call_close_itm1 * 100;
71 | def call_itm_volumexclose1 = if isNaN(call_volume_itm2 * call_close_itm2 * 100) then 0 else call_volume_itm2 * call_close_itm2 * 100;
72 | def call_volumexclose = if IsNan(call_volume * call_close_price * 100) then 0 else call_volume * call_close_price * 100 ;
73 | def call_plusone_volumexclose = if IsNan(call_volume1 * call_close_otm1) then 0 else call_volume1 * call_close_otm1 * 100 ;
74 | def call_plustwo_volumexclose = if IsNan(call_volume2 * call_close_otm2 * 100) then 0 else call_volume2 * call_close_otm2 * 100;
75 |
76 | def calls_current_total = call_itm_volumexclose + call_itm_volumexclose1 + call_volumexclose + call_plusone_volumexclose + call_plustwo_volumexclose;
77 |
78 | plot oneperiodcalls = calls_current_total;
79 | oneperiodcalls.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
80 | oneperiodcalls.SetLineWeight(5);
81 | oneperiodcalls.setdefaultcolor(color.green);
82 |
83 | def put_itm_volumexclose = if isNaN(put_volume_itm1 * put_close_price_itm1 * 100) then 0 else put_volume_itm1 * put_close_price_itm1 * 100;
84 | def put_itm_volumexclose1 = if isNaN(put_volume_itm2 * put_close_price_itm2 * 100) then 0 else put_volume_itm2 * put_close_price_itm2 * 100;
85 | def put_volumexclose = if isNaN(put_volume * put_close_price * 100) then 0 else put_volume * put_close_price * 100;
86 | def put_minusone_volumexclose = if isNaN(put_volume1 * put_close_otm1 * 100) then 0 else put_volume1 * put_close_otm1 * 100;
87 | def put_minustwo_volumexclose = if isNaN(put_volume2 * put_close_otm2 * 100) then 0 else put_volume2 * put_close_otm2 * 100;
88 |
89 | def puts_current_total = put_itm_volumexclose + put_itm_volumexclose1 + put_volumexclose + put_minusone_volumexclose + put_minustwo_volumexclose;
90 |
91 | plot puts_1min = 1 - puts_current_total;
92 | puts_1min.SetPaintingStrategy(PaintingStrategy.histogram);
93 | puts_1min.SetLineWeight(5);
94 | puts_1min.setdefaultcolor(color.red);
95 |
--------------------------------------------------------------------------------
/near_the_money/near_the_money_stocks_upper:
--------------------------------------------------------------------------------
1 | # near_the_money_stocks_upper
2 | # 2187Nick
3 | # Mar 7, 2025
4 | declare upper;
5 | declare once_per_bar;
6 |
7 | input Strike_Spacing = 1.0;
8 | input Premium_Extreme_Level = 1000000;
9 |
10 | input ManuallySetExpiration = {default "false", "true"};
11 | input Expiration_YYMMDD = 250620;
12 |
13 | def DateString_auto = GetYYYYMMDD()-20000000;
14 |
15 |
16 | def DateString = if manuallysetexpiration then Expiration_YYMMDD else DateString_auto;
17 |
18 | def rounding_factor = if Strike_Spacing > 1 and Strike_Spacing < 25 then -1 else if Strike_Spacing > 24 then -2 else 0;
19 |
20 | def base = Round(close, rounding_factor);
21 |
22 | def strike_atm = base;
23 | def strike_itm1_call = base - Strike_Spacing;
24 | def strike_itm2_call = base - Strike_Spacing*2;
25 | def strike_otm1_call = Strike_Spacing + base;
26 | def strike_otm2_call = Strike_Spacing + Strike_Spacing * 1 + base;
27 | #def strike_otm3_call = Strike_Spacing + Strike_Spacing * 2 + base;
28 |
29 | def strike_itm1_put = base + Strike_Spacing;
30 | def strike_itm2_put = base + Strike_Spacing*2;
31 | def strike_otm1_put = base - Strike_Spacing;
32 | def strike_otm2_put = base - Strike_Spacing - Strike_Spacing * 1;
33 | #def strike_otm3_put = base - Strike_Spacing - Strike_Spacing * 2;
34 |
35 | def call_close_itm1 = close("." + GetSymbol() + AsPrice(DateString) +"C" + strike_itm1_call);
36 |
37 | def call_volume_itm1 = volume("." + GetSymbol() + AsPrice(DateString) +"C" + strike_itm1_call);
38 |
39 | def call_close_itm2 = close("." + GetSymbol() + AsPrice(DateString) +"C" + strike_itm2_call);
40 | def call_volume_itm2 = volume("." + GetSymbol() + AsPrice(DateString) +"C" + strike_itm2_call);
41 |
42 | def call_close_price = close("." + GetSymbol() + AsPrice(DateString) +"C" + strike_atm);
43 | def call_volume = volume("." + GetSymbol() + AsPrice(DateString) +"C" + strike_atm);
44 |
45 | def call_close_otm1 = close("." + GetSymbol() + AsPrice(DateString) +"C" + strike_otm1_call);
46 | def call_volume1 = volume("." + GetSymbol() + AsPrice(DateString) +"C" + strike_otm1_call);
47 |
48 | def call_close_otm2 = close("." + GetSymbol() + AsPrice(DateString) +"C" + strike_otm2_call);
49 | def call_volume2 = volume("." + GetSymbol() + AsPrice(DateString) +"C" + strike_otm2_call);
50 |
51 | def put_close_price_itm1 = close("." + GetSymbol() + AsPrice(DateString) +"P" + strike_itm1_put);
52 | def put_volume_itm1 = volume("." + GetSymbol() + AsPrice(DateString) +"P" + strike_itm1_put);
53 |
54 | def put_close_price_itm2 = close("." + GetSymbol() + AsPrice(DateString) +"P" + strike_itm2_put);
55 | def put_volume_itm2 = volume("." + GetSymbol() + AsPrice(DateString) +"P" + strike_itm2_put);
56 |
57 | def put_close_price = close("." + GetSymbol() + AsPrice(DateString) +"P" + strike_atm);
58 | def put_volume = volume("." + GetSymbol() + AsPrice(DateString) +"P" + strike_atm);
59 |
60 | def put_close_otm1 = close("." + GetSymbol() + AsPrice(DateString) +"P" + strike_otm1_put);
61 | def put_volume1 = volume("." + GetSymbol() + AsPrice(DateString) +"P" + strike_otm1_put);
62 |
63 | def put_close_otm2= close("." + GetSymbol() + AsPrice(DateString) +"P" + strike_otm2_put);
64 | def put_volume2 = volume("." + GetSymbol() + AsPrice(DateString) +"P" + strike_otm2_put);
65 |
66 |
67 | def call_itm_volumexclose = if isNaN(call_volume_itm1 * call_close_itm1 * 100) then 0 else call_volume_itm1 * call_close_itm1 * 100;
68 | def call_itm_volumexclose1 = if isNaN(call_volume_itm2 * call_close_itm2 * 100) then 0 else call_volume_itm2 * call_close_itm2 * 100;
69 | def call_volumexclose = if IsNan(call_volume * call_close_price * 100) then 0 else call_volume * call_close_price * 100 ;
70 | def call_plusone_volumexclose = if IsNan(call_volume1 * call_close_otm1) then 0 else call_volume1 * call_close_otm1 * 100 ;
71 | def call_plustwo_volumexclose = if IsNan(call_volume2 * call_close_otm2 * 100) then 0 else call_volume2 * call_close_otm2 * 100;
72 |
73 | def calls_current_total = call_itm_volumexclose + call_itm_volumexclose1 + call_volumexclose + call_plusone_volumexclose + call_plustwo_volumexclose;
74 |
75 |
76 | def put_itm_volumexclose = if isNaN(put_volume_itm1 * put_close_price_itm1 * 100) then 0 else put_volume_itm1 * put_close_price_itm1 * 100;
77 | def put_itm_volumexclose1 = if isNaN(put_volume_itm2 * put_close_price_itm2 * 100) then 0 else put_volume_itm2 * put_close_price_itm2 * 100;
78 | def put_volumexclose = if isNaN(put_volume * put_close_price * 100) then 0 else put_volume * put_close_price * 100;
79 | def put_minusone_volumexclose = if isNaN(put_volume1 * put_close_otm1 * 100) then 0 else put_volume1 * put_close_otm1 * 100;
80 | def put_minustwo_volumexclose = if isNaN(put_volume2 * put_close_otm2 * 100) then 0 else put_volume2 * put_close_otm2 * 100;
81 |
82 | def puts_current_total = put_itm_volumexclose + put_itm_volumexclose1 + put_volumexclose + put_minusone_volumexclose + put_minustwo_volumexclose;
83 |
84 | def moving_up = if close[1] > close[2] then 1 else 0;
85 | def moving_down = close[1] < close[2];
86 | AddChartBubble(puts_current_total > Premium_Extreme_Level and moving_down, low, "BUY" , color.Green, no);
87 | AddChartBubble(calls_current_total > Premium_Extreme_Level and moving_up ==1, high, "SELL" , color.red);
88 |
--------------------------------------------------------------------------------
/near_the_money/old/README.md:
--------------------------------------------------------------------------------
1 | 🚀 This monitors for a peak in option call premium at the highs and peak in option put premium at the lows.
2 |
3 | Category: Mean Reversion
4 |
5 |
6 |
7 | Designed for SPY and QQQ.
8 |
9 | > Chart requirements for optimal use:
10 | ```bash
11 |
12 | Time frame: 1 Day
13 |
14 | Aggregation Period: 1 Minute
15 |
16 | Note: This does work on a historical look back.
17 | ```
18 |
19 |
20 |
21 |
22 | > Settings 👷:
23 |
24 | ```bash
25 |
26 | Upper:
27 | 1. Strike Spacing: 1; (This sets the space between strikes. Ex: Current SPY price is 400. It will monitor calls
28 | and puts at strikes 398, 399, 400, 401 and 402)
29 | 2. Premium Extreme Level: 1000000; (This sets the $ amount to exceed for the Alert to activate)
30 |
31 | Lower:
32 | 1. Strike Spacing: 1;
33 | 2. Highline Millions: 1000000; (Allows you to plot a red line at the $ value in Millions for calls)
34 | 3. Lowline Millions: -1000000; (Allows you to plot a green line at the $ value in Millions for puts)
35 | ```
36 |
37 |
38 |
39 |
40 | > 🧪 How this works:
41 |
42 | ```bash
43 |
44 | Calculates the option premium(purchased or sold) for 5 strikes. ( itm +1, itm, atm, otm, otm +1)
45 |
46 | A. Option premium = Volume x Price. ( 1 minute volume x close price)
47 |
48 | Example: SPY 400 Call Option. Volume: 1000. Close Price: $1.50; Option Premium = $150K. (For that 1 min period)
49 |
50 | B. Sum the Call Option Premium for the 5 strikes.
51 |
52 | C. If the total amount is greater than Premium Extreme Level. Then alert bubble "Sell" will appear on that candle.
53 |
54 | Note: The upper indicator checks if price is moving up by comparing previous close price vs current price. It will only alert a "Sell"
55 | if we are moving up. It will fail to alert if that requirement is not met. ( I will improve on this in the future).
56 |
57 | Note: I avoid the signals during roughly the first 15 minutes of market open.
58 | ```
59 |
60 | > 🦖 Why this works:
61 | ```bash
62 | 1 Theory:
63 |
64 | As the stock price decreases eventually some market participants sell large amounts of puts. Betting that the stock will not continue to decrease.
65 |
66 | As the stock price increases eventually some market participants sell large amounts of calls. Betting that the stock will not continue to increase.
67 |
68 | Warning: If it is not a mean reverting day. Then you can easily get ran over.
69 |
70 | ```
71 |
--------------------------------------------------------------------------------
/near_the_money/old/near_the_money_spy_daily.ts:
--------------------------------------------------------------------------------
1 | # near_the_money_spy_daily_v2
2 | # 2187Nick
3 | declare lower;
4 | declare once_per_bar;
5 |
6 | input Strike_Spacing = 1;
7 | input highline_millions = 1000000;
8 | input lowline_millions = -1000000;
9 | plot highline = highline_millions;
10 | plot lowline = lowline_millions;
11 | highline.SetDefaultColor(Color.red);
12 | lowline.SetDefaultColor(Color.green);
13 |
14 | def CurrentYear = GetYear()-2000;
15 | def CurrentMonth = GetMonth();
16 | def CurrentDOM = GetDayOfMonth(GetYYYYMMDD());
17 |
18 | def rounding_factor = if Strike_Spacing > 1 and Strike_Spacing < 25 then -1 else if Strike_Spacing > 24 then -2 else 0;
19 |
20 | def base = Round(close, rounding_factor);
21 | addlabel(yes, "ATM: " + base);
22 |
23 | def strike_atm = base;
24 | def strike_itm1_call = base - Strike_Spacing;
25 | def strike_itm2_call = base - Strike_Spacing*2;
26 | def strike_otm1_call = Strike_Spacing + base;
27 | def strike_otm2_call = Strike_Spacing + Strike_Spacing * 1 + base;
28 | #def strike_otm3_call = Strike_Spacing + Strike_Spacing * 2 + base;
29 |
30 | def strike_itm1_put = base + Strike_Spacing;
31 | def strike_itm2_put = base + Strike_Spacing*2;
32 | def strike_otm1_put = base - Strike_Spacing;
33 | def strike_otm2_put = base - Strike_Spacing - Strike_Spacing * 1;
34 | #def strike_otm3_put = base - Strike_Spacing - Strike_Spacing * 2;
35 |
36 |
37 | def call_close_itm1 = close("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"C")) else Concat(CurrentDOM,"C")) + strike_itm1_call);
38 | def call_volume_itm1 = volume("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"C")) else Concat(CurrentDOM,"C")) + strike_itm1_call);
39 |
40 | def call_close_itm2 = close("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"C")) else Concat(CurrentDOM,"C")) + strike_itm2_call);
41 | def call_volume_itm2 = volume("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"C")) else Concat(CurrentDOM,"C")) + strike_itm2_call);
42 |
43 | def call_close_price = close("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"C")) else Concat(CurrentDOM,"C")) + strike_atm);
44 | def call_volume = volume("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"C")) else Concat(CurrentDOM,"C")) + strike_atm);
45 |
46 | def call_close_otm1 = close("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"C")) else Concat(CurrentDOM,"C")) + strike_otm1_call);
47 | def call_volume1 = volume("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"C")) else Concat(CurrentDOM,"C")) + strike_otm1_call);
48 |
49 | def call_close_otm2 = close("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"C")) else Concat(CurrentDOM,"C")) + strike_otm2_call);
50 | def call_volume2 = volume("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) +(if CurrentDOM < 10 then Concat(0,(CurrentDOM+"C")) else Concat(CurrentDOM,"C")) + strike_otm2_call);
51 |
52 | def put_close_price_itm1 = close("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"P")) else Concat(CurrentDOM,"P")) + strike_itm1_put);
53 | def put_volume_itm1 = volume("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"P")) else Concat(CurrentDOM,"P")) + strike_itm1_put);
54 |
55 | def put_close_price_itm2 = close("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"P")) else Concat(CurrentDOM,"P")) + strike_itm2_put);
56 | def put_volume_itm2 = volume("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"P")) else Concat(CurrentDOM,"P")) + strike_itm2_put);
57 |
58 | def put_close_price = close("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"P")) else Concat(CurrentDOM,"P")) + strike_atm);
59 | def put_volume = volume("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"P")) else Concat(CurrentDOM,"P")) + strike_atm);
60 |
61 | def put_close_otm1 = close("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"P")) else Concat(CurrentDOM,"P")) + strike_otm1_put);
62 | def put_volume1 = volume("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"P")) else Concat(CurrentDOM,"P")) + strike_otm1_put);
63 |
64 | def put_close_otm2= close("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"P")) else Concat(CurrentDOM,"P")) + strike_otm2_put);
65 | def put_volume2 = volume("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"P")) else Concat(CurrentDOM,"P")) + strike_otm2_put);
66 |
67 |
68 |
69 | def call_itm_volumexclose = if isNaN(call_volume_itm1 * call_close_itm1 * 100) then 0 else call_volume_itm1 * call_close_itm1 * 100;
70 | def call_itm_volumexclose1 = if isNaN(call_volume_itm2 * call_close_itm2 * 100) then 0 else call_volume_itm2 * call_close_itm2 * 100;
71 | def call_volumexclose = if IsNan(call_volume * call_close_price * 100) then 0 else call_volume * call_close_price * 100 ;
72 | def call_plusone_volumexclose = if IsNan(call_volume1 * call_close_otm1) then 0 else call_volume1 * call_close_otm1 * 100 ;
73 | def call_plustwo_volumexclose = if IsNan(call_volume2 * call_close_otm2 * 100) then 0 else call_volume2 * call_close_otm2 * 100;
74 |
75 | def calls_current_total = call_itm_volumexclose + call_itm_volumexclose1 + call_volumexclose + call_plusone_volumexclose + call_plustwo_volumexclose;
76 |
77 | plot oneperiodcalls = calls_current_total;
78 | oneperiodcalls.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
79 | oneperiodcalls.SetLineWeight(5);
80 | oneperiodcalls.setdefaultcolor(color.green);
81 |
82 | def put_itm_volumexclose = if isNaN(put_volume_itm1 * put_close_price_itm1 * 100) then 0 else put_volume_itm1 * put_close_price_itm1 * 100;
83 | def put_itm_volumexclose1 = if isNaN(put_volume_itm2 * put_close_price_itm2 * 100) then 0 else put_volume_itm2 * put_close_price_itm2 * 100;
84 | def put_volumexclose = if isNaN(put_volume * put_close_price * 100) then 0 else put_volume * put_close_price * 100;
85 | def put_minusone_volumexclose = if isNaN(put_volume1 * put_close_otm1 * 100) then 0 else put_volume1 * put_close_otm1 * 100;
86 | def put_minustwo_volumexclose = if isNaN(put_volume2 * put_close_otm2 * 100) then 0 else put_volume2 * put_close_otm2 * 100;
87 |
88 | def puts_current_total = put_itm_volumexclose + put_itm_volumexclose1 + put_volumexclose + put_minusone_volumexclose + put_minustwo_volumexclose;
89 |
90 | plot puts_1min = 1 - puts_current_total;
91 | puts_1min.SetPaintingStrategy(PaintingStrategy.histogram);
92 | puts_1min.SetLineWeight(5);
93 | puts_1min.setdefaultcolor(color.red);
94 |
--------------------------------------------------------------------------------
/near_the_money/old/near_the_money_spy_daily_upper.ts:
--------------------------------------------------------------------------------
1 | # near_the_money_spy_daily_upper_v2
2 | # 2187Nick
3 | declare upper;
4 | declare once_per_bar;
5 |
6 | input Strike_Spacing = 1;
7 | input Premium_Extreme_Level = 1000000;
8 |
9 | def CurrentYear = GetYear()-2000;
10 | def CurrentMonth = GetMonth();
11 | def CurrentDOM = GetDayOfMonth(GetYYYYMMDD());
12 |
13 | def rounding_factor = if Strike_Spacing > 1 and Strike_Spacing < 25 then -1 else if Strike_Spacing > 24 then -2 else 0;
14 |
15 | def base = Round(close, rounding_factor);
16 |
17 | def strike_atm = base;
18 | def strike_itm1_call = base - Strike_Spacing;
19 | def strike_itm2_call = base - Strike_Spacing*2;
20 | def strike_otm1_call = Strike_Spacing + base;
21 | def strike_otm2_call = Strike_Spacing + Strike_Spacing * 1 + base;
22 | #def strike_otm3_call = Strike_Spacing + Strike_Spacing * 2 + base;
23 |
24 | def strike_itm1_put = base + Strike_Spacing;
25 | def strike_itm2_put = base + Strike_Spacing*2;
26 | def strike_otm1_put = base - Strike_Spacing;
27 | def strike_otm2_put = base - Strike_Spacing - Strike_Spacing * 1;
28 | #def strike_otm3_put = base - Strike_Spacing - Strike_Spacing * 2;
29 |
30 | def call_close_itm1 = close("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"C")) else Concat(CurrentDOM,"C")) + strike_itm1_call);
31 | def call_volume_itm1 = volume("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"C")) else Concat(CurrentDOM,"C")) + strike_itm1_call);
32 |
33 | def call_close_itm2 = close("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"C")) else Concat(CurrentDOM,"C")) + strike_itm2_call);
34 | def call_volume_itm2 = volume("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"C")) else Concat(CurrentDOM,"C")) + strike_itm2_call);
35 |
36 | def call_close_price = close("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"C")) else Concat(CurrentDOM,"C")) + strike_atm);
37 | def call_volume = volume("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"C")) else Concat(CurrentDOM,"C")) + strike_atm);
38 |
39 | def call_close_otm1 = close("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"C")) else Concat(CurrentDOM,"C")) + strike_otm1_call);
40 | def call_volume1 = volume("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"C")) else Concat(CurrentDOM,"C")) + strike_otm1_call);
41 |
42 | def call_close_otm2 = close("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"C")) else Concat(CurrentDOM,"C")) + strike_otm2_call);
43 | def call_volume2 = volume("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) +(if CurrentDOM < 10 then Concat(0,(CurrentDOM+"C")) else Concat(CurrentDOM,"C")) + strike_otm2_call);
44 |
45 | def put_close_price_itm1 = close("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"P")) else Concat(CurrentDOM,"P")) + strike_itm1_put);
46 | def put_volume_itm1 = volume("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"P")) else Concat(CurrentDOM,"P")) + strike_itm1_put);
47 |
48 | def put_close_price_itm2 = close("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"P")) else Concat(CurrentDOM,"P")) + strike_itm2_put);
49 | def put_volume_itm2 = volume("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"P")) else Concat(CurrentDOM,"P")) + strike_itm2_put);
50 |
51 | def put_close_price = close("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"P")) else Concat(CurrentDOM,"P")) + strike_atm);
52 | def put_volume = volume("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"P")) else Concat(CurrentDOM,"P")) + strike_atm);
53 |
54 | def put_close_otm1 = close("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"P")) else Concat(CurrentDOM,"P")) + strike_otm1_put);
55 | def put_volume1 = volume("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"P")) else Concat(CurrentDOM,"P")) + strike_otm1_put);
56 |
57 | def put_close_otm2= close("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"P")) else Concat(CurrentDOM,"P")) + strike_otm2_put);
58 | def put_volume2 = volume("." + GetSymbol() + CurrentYear + (if CurrentMonth < 10 then Concat(0,(CurrentMonth)) else AsText(CurrentMonth)) + (if CurrentDOM < 10 then Concat(0,(CurrentDOM+"P")) else Concat(CurrentDOM,"P")) + strike_otm2_put);
59 |
60 |
61 | def call_itm_volumexclose = if isNaN(call_volume_itm1 * call_close_itm1 * 100) then 0 else call_volume_itm1 * call_close_itm1 * 100;
62 | def call_itm_volumexclose1 = if isNaN(call_volume_itm2 * call_close_itm2 * 100) then 0 else call_volume_itm2 * call_close_itm2 * 100;
63 | def call_volumexclose = if IsNan(call_volume * call_close_price * 100) then 0 else call_volume * call_close_price * 100 ;
64 | def call_plusone_volumexclose = if IsNan(call_volume1 * call_close_otm1) then 0 else call_volume1 * call_close_otm1 * 100 ;
65 | def call_plustwo_volumexclose = if IsNan(call_volume2 * call_close_otm2 * 100) then 0 else call_volume2 * call_close_otm2 * 100;
66 |
67 | def calls_current_total = call_itm_volumexclose + call_itm_volumexclose1 + call_volumexclose + call_plusone_volumexclose + call_plustwo_volumexclose;
68 |
69 |
70 | def put_itm_volumexclose = if isNaN(put_volume_itm1 * put_close_price_itm1 * 100) then 0 else put_volume_itm1 * put_close_price_itm1 * 100;
71 | def put_itm_volumexclose1 = if isNaN(put_volume_itm2 * put_close_price_itm2 * 100) then 0 else put_volume_itm2 * put_close_price_itm2 * 100;
72 | def put_volumexclose = if isNaN(put_volume * put_close_price * 100) then 0 else put_volume * put_close_price * 100;
73 | def put_minusone_volumexclose = if isNaN(put_volume1 * put_close_otm1 * 100) then 0 else put_volume1 * put_close_otm1 * 100;
74 | def put_minustwo_volumexclose = if isNaN(put_volume2 * put_close_otm2 * 100) then 0 else put_volume2 * put_close_otm2 * 100;
75 |
76 | def puts_current_total = put_itm_volumexclose + put_itm_volumexclose1 + put_volumexclose + put_minusone_volumexclose + put_minustwo_volumexclose;
77 |
78 | def moving_up = if close[1] > close[2] then 1 else 0;
79 | def moving_down = close[1] < close[2];
80 | AddChartBubble(puts_current_total > Premium_Extreme_Level and moving_down, low, "BUY" , color.Green);
81 | AddChartBubble(calls_current_total > Premium_Extreme_Level and moving_up ==1, high, "SELL" , color.red);
82 |
--------------------------------------------------------------------------------
/near_the_money_spx/README.md:
--------------------------------------------------------------------------------
1 | 🚀 This monitors for a peak in option call premium at the highs and peak in option put premium at the lows.
2 |
3 | Category: Mean Reversion
4 |
5 |
6 |
7 | Designed for SPX and NDX.
8 |
9 | > Chart requirements for optimal use:
10 | ```bash
11 |
12 | Time frame: 1 Day
13 |
14 | Aggregation Period: 1 Minute
15 |
16 | For SPX add these indicators to /ES chart. For NDX add these indicators to /NQ chart.
17 |
18 | Note: This does work on a historical look back.
19 | ```
20 |
21 |
22 |
23 |
24 | > Settings 👷:
25 |
26 | ```bash
27 |
28 | Upper:
29 | 1. Strike Spacing: 25;(This sets the space between strikes. Ex: Current SPX price is 4000. It will monitor calls
30 | and puts at strikes 3950, 3975, 4000, 4025 and 4050)
31 | 2. Premium Extreme Level: 1000000; (This sets the $ amount to exceed for the Alert to activate)
32 | 3. Symbol: SPXW; (Use NDXP for NDX options)
33 | 4. Set base strike manually: No; (Default is set to automatically set the base strike. Select Yes to manually set)
34 | 5. Manual base strike: 4025; (If #4 is set to Yes then you can enter the desired base strike)
35 |
36 |
37 | Lower:
38 | 1. Strike Spacing: 1;
39 | 2. Highline Millions: 1000000; (Allows you to plot a red line at the $ value in Millions for calls)
40 | 3. Lowline Millions: -1000000; (Allows you to plot a green line at the $ value in Millions for puts)
41 | 3. Symbol: SPXW; (Use NDXP for NDX options)
42 | 4. Set base strike manually: No; (Default is set to automatically set the base strike. Select Yes to manually set)
43 | 5. Manual base strike: 4025; (If #4 is set to Yes then you can enter the desired base strike)
44 |
45 | ```
46 |
47 |
48 |
49 |
50 | > 🧪 How this works:
51 |
52 | ```bash
53 |
54 | Calculates the option premium(purchased or sold) for 5 strikes. ( itm +1, itm, atm, otm, otm +1)
55 |
56 | A. Option premium = Volume x Price. ( 1 minute volume x close price)
57 |
58 | Example: SPY 400 Call Option. Volume: 1000. Close Price: $1.50; Option Premium = $150K. (For that 1 min period)
59 |
60 | B. Sum the Call Option Premium for the 5 strikes.
61 |
62 | C. If the total amount is greater than Premium Extreme Level. Then alert bubble "Sell" will appear on that candle.
63 |
64 | Note: The upper indicator checks if price is moving up by comparing previous close price vs current price. It will only alert a "Sell"
65 | if we are moving up. It will fail to alert if that requirement is not met. ( I will improve on this in the future).
66 |
67 | Note: I avoid the signals during roughly the first 15 minutes of market open.
68 | ```
69 |
70 | > 🦖 Why this works:
71 | ```bash
72 | 1 Theory:
73 |
74 | As the stock price decreases eventually some market participants sell large amounts of puts. Betting that the stock will not continue to decrease.
75 |
76 | As the stock price increases eventually some market participants sell large amounts of calls. Betting that the stock will not continue to increase.
77 |
78 | Warning: If it is not a mean reverting day. Then you can easily get ran over.
79 |
80 | ```
81 |
--------------------------------------------------------------------------------
/near_the_money_spx/near_the_money_spx.ts:
--------------------------------------------------------------------------------
1 | # near_the_money_spx_v4
2 | # 2187Nick
3 | declare lower;
4 | declare once_per_bar;
5 |
6 | input Strike_Spacing = 25;
7 | input highline_millions = 1000000;
8 | input lowline_millions = -1000000;
9 | plot highline = highline_millions;
10 | plot lowline = lowline_millions;
11 | highline.SetDefaultColor(Color.RED);
12 | lowline.SetDefaultColor(Color.GREEN);
13 |
14 | input symbol = "SPXW";
15 | input set_base_strike_maunually = no;
16 | input manual_base_strike = 4025;
17 |
18 | def CurrentYear = GetYear()-2000;
19 | def CurrentMonth = GetMonth();
20 | def CurrentDOM = GetDayOfMonth(GetYYYYMMDD());
21 | AddLabel(yes, "Today: " + AsPrice(GetYear()) + GetMonth() + GetDayOfMonth(GetYYYYMMDD()));
22 |
23 | def DateString = CurrentYear*10000+CurrentMonth*100+CurrentDOM;
24 |
25 | def rounding_factor = if Strike_Spacing > 1 and Strike_Spacing < 25 then -1 else if Strike_Spacing > 24 then -2 else 0;
26 |
27 | def auto_base = Round(close, rounding_factor);
28 | def base = if set_base_strike_maunually then manual_base_strike else auto_base;
29 | addlabel(yes, "base_strike: " + base);
30 |
31 |
32 | def strike_atm = base;
33 | def strike_itm1_call = base - Strike_Spacing;
34 | def strike_itm2_call = base - Strike_Spacing * 2;
35 | def strike_otm1_call = Strike_Spacing + base;
36 | def strike_otm2_call = Strike_Spacing + Strike_Spacing * 1 + base;
37 | #def strike_otm3_call = Strike_Spacing + Strike_Spacing * 2 + base;
38 |
39 | def strike_itm1_put = base + Strike_Spacing;
40 | def strike_itm2_put = base + Strike_Spacing * 2;
41 | def strike_otm1_put = base - Strike_Spacing;
42 | def strike_otm2_put = base - Strike_Spacing - Strike_Spacing * 1;
43 | #def strike_otm3_put = base - Strike_Spacing - Strike_Spacing * 2;
44 |
45 | def call_close_itm1 = close("." + symbol + AsPrice(DateString) +"C" + AsPrice(strike_itm1_call));
46 | def call_volume_itm1 = volume("." + symbol + AsPrice(DateString) +"C" + AsPrice(strike_itm1_call));
47 |
48 | def call_close_itm2 = close("." + symbol + AsPrice(DateString) +"C" + AsPrice(strike_itm2_call));
49 | def call_volume_itm2 = volume("." + symbol + AsPrice(DateString) +"C" + AsPrice(strike_itm2_call));
50 |
51 | def call_close_price = close("." + symbol + AsPrice(DateString) +"C" + AsPrice(strike_atm));
52 | def call_volume = volume("." + symbol + AsPrice(DateString) +"C" + AsPrice(strike_atm));
53 |
54 | def call_close_otm1 = close("." + symbol + AsPrice(DateString) +"C" + AsPrice(strike_otm1_call));
55 | def call_volume1 = volume("." + symbol + AsPrice(DateString) +"C" + AsPrice(strike_otm1_call));
56 |
57 | def call_close_otm2 = close("." + symbol + AsPrice(DateString) +"C" + AsPrice(strike_otm2_call));
58 | def call_volume2 = volume("." + symbol + AsPrice(DateString) +"C" + AsPrice(strike_otm2_call));
59 |
60 | def put_close_price_itm1 = close("." + symbol + AsPrice(DateString) +"P" + AsPrice(strike_itm1_put));
61 | def put_volume_itm1 = volume("." + symbol + AsPrice(DateString) +"P" + AsPrice(strike_itm1_put));
62 |
63 | def put_close_price_itm2 = close("." + symbol + AsPrice(DateString) +"P" + AsPrice(strike_itm2_put));
64 | def put_volume_itm2 = volume("." + symbol + AsPrice(DateString) +"P" + AsPrice(strike_itm2_put));
65 |
66 | def put_close_price = close("." + symbol + AsPrice(DateString) +"P" + AsPrice(strike_atm));
67 | def put_volume = volume("." + symbol + AsPrice(DateString) +"P" + AsPrice(strike_atm));
68 |
69 | def put_close_otm1 = close("." + symbol + AsPrice(DateString) +"P" + AsPrice(strike_otm1_put));
70 | def put_volume1 = volume("." + symbol + AsPrice(DateString) +"P" + AsPrice(strike_otm1_put));
71 |
72 | def put_close_otm2= close("." + symbol + AsPrice(DateString) +"P" + AsPrice(strike_otm2_put));
73 | def put_volume2 = volume("." + symbol + AsPrice(DateString) +"P" + AsPrice(strike_otm2_put));
74 |
75 | def call_itm_volumexclose = if IsNaN(call_volume_itm1 * call_close_itm1 * 100) then 0 else call_volume_itm1 * call_close_itm1 * 100;
76 | def call_itm_volumexclose1 = if IsNaN(call_volume_itm2 * call_close_itm2 * 100) then 0 else call_volume_itm2 * call_close_itm2 * 100;
77 | def call_volumexclose = if IsNaN(call_volume * call_close_price * 100) then 0 else call_volume * call_close_price * 100 ;
78 | def call_plusone_volumexclose = if IsNaN(call_volume1 * call_close_otm1) then 0 else call_volume1 * call_close_otm1 * 100 ;
79 | def call_plustwo_volumexclose = if IsNaN(call_volume2 * call_close_otm2 * 100) then 0 else call_volume2 * call_close_otm2 * 100;
80 |
81 | def calls_current_total = call_itm_volumexclose + call_itm_volumexclose1 + call_volumexclose + call_plusone_volumexclose + call_plustwo_volumexclose;
82 |
83 | plot oneperiodcalls = calls_current_total;
84 | oneperiodcalls.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
85 | oneperiodcalls.SetLineWeight(5);
86 | oneperiodcalls.SetDefaultColor(Color.GREEN);
87 |
88 | def put_itm_volumexclose = if IsNaN(put_volume_itm1 * put_close_price_itm1 * 100) then 0 else put_volume_itm1 * put_close_price_itm1 * 100;
89 | def put_itm_volumexclose1 = if IsNaN(put_volume_itm2 * put_close_price_itm2 * 100) then 0 else put_volume_itm2 * put_close_price_itm2 * 100;
90 | def put_volumexclose = if IsNaN(put_volume * put_close_price * 100) then 0 else put_volume * put_close_price * 100;
91 | def put_minusone_volumexclose = if IsNaN(put_volume1 * put_close_otm1 * 100) then 0 else put_volume1 * put_close_otm1 * 100;
92 | def put_minustwo_volumexclose = if IsNaN(put_volume1 * put_close_otm2 * 100) then 0 else put_volume2 * put_close_otm2 * 100;
93 |
94 | def puts_current_total = put_itm_volumexclose + put_itm_volumexclose1 + put_volumexclose + put_minusone_volumexclose + put_minustwo_volumexclose;
95 |
96 | plot puts_1min = 1 - puts_current_total;
97 | puts_1min.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
98 | puts_1min.SetLineWeight(5);
99 | puts_1min.SetDefaultColor(Color.RED);
100 |
--------------------------------------------------------------------------------
/near_the_money_spx/near_the_money_spx_upper.ts:
--------------------------------------------------------------------------------
1 | # near_the_money_spx_upper_v4
2 | # 2187Nick
3 | declare upper;
4 | declare once_per_bar;
5 |
6 | input Strike_Spacing = 25;
7 | input Premium_Extreme_Level = 1000000;
8 | input symbol = "SPXW";
9 | input set_base_strike_maunually = no;
10 | input manual_base_strike = 4025;
11 |
12 | def CurrentYear = GetYear()-2000;
13 | def CurrentMonth = GetMonth();
14 | def CurrentDOM = GetDayOfMonth(GetYYYYMMDD());
15 | def DateString = CurrentYear*10000+CurrentMonth*100+CurrentDOM;
16 |
17 | def rounding_factor = if Strike_Spacing > 1 and Strike_Spacing < 25 then -1 else if Strike_Spacing > 24 then -2 else 0;
18 |
19 | def auto_base = Round(close, rounding_factor);
20 |
21 | def base = if set_base_strike_maunually then manual_base_strike else auto_base;
22 | addlabel(yes, "base_strike: " + base);
23 |
24 | def strike_atm = base;
25 | def strike_itm1_call = base - Strike_Spacing;
26 | def strike_itm2_call = base - Strike_Spacing*2;
27 | def strike_otm1_call = Strike_Spacing + base;
28 | def strike_otm2_call = Strike_Spacing + Strike_Spacing * 1 + base;
29 | #def strike_otm3_call = Strike_Spacing + Strike_Spacing * 2 + base;
30 |
31 | def strike_itm1_put = base + Strike_Spacing;
32 | def strike_itm2_put = base + Strike_Spacing*2;
33 | def strike_otm1_put = base - Strike_Spacing;
34 | def strike_otm2_put = base - Strike_Spacing - Strike_Spacing * 1;
35 | #def strike_otm3_put = base - Strike_Spacing - Strike_Spacing * 2;
36 |
37 |
38 | def call_close_itm1 = close("." + symbol + AsPrice(DateString) +"C" + AsPrice(strike_itm1_call));
39 | def call_volume_itm1 = volume("." + symbol + AsPrice(DateString) +"C" + AsPrice(strike_itm1_call));
40 |
41 | def call_close_itm2 = close("." + symbol + AsPrice(DateString) +"C" + AsPrice(strike_itm2_call));
42 | def call_volume_itm2 = volume("." + symbol + AsPrice(DateString) +"C" + AsPrice(strike_itm2_call));
43 |
44 | def call_close_price = close("." + symbol + AsPrice(DateString) +"C" + AsPrice(strike_atm));
45 | def call_volume = volume("." + symbol + AsPrice(DateString) +"C" + AsPrice(strike_atm));
46 |
47 | def call_close_otm1 = close("." + symbol + AsPrice(DateString) +"C" + AsPrice(strike_otm1_call));
48 | def call_volume1 = volume("." + symbol + AsPrice(DateString) +"C" + AsPrice(strike_otm1_call));
49 |
50 | def call_close_otm2 = close("." + symbol + AsPrice(DateString) +"C" + AsPrice(strike_otm2_call));
51 | def call_volume2 = volume("." + symbol + AsPrice(DateString) +"C" + AsPrice(strike_otm2_call));
52 |
53 | def put_close_price_itm1 = close("." + symbol + AsPrice(DateString) +"P" + AsPrice(strike_itm1_put));
54 | def put_volume_itm1 = volume("." + symbol + AsPrice(DateString) +"P" + AsPrice(strike_itm1_put));
55 |
56 | def put_close_price_itm2 = close("." + symbol + AsPrice(DateString) +"P" + AsPrice(strike_itm2_put));
57 | def put_volume_itm2 = volume("." + symbol + AsPrice(DateString) +"P" + AsPrice(strike_itm2_put));
58 |
59 | def put_close_price = close("." + symbol + AsPrice(DateString) +"P" + AsPrice(strike_atm));
60 | def put_volume = volume("." + symbol + AsPrice(DateString) +"P" + AsPrice(strike_atm));
61 |
62 | def put_close_otm1 = close("." + symbol + AsPrice(DateString) +"P" + AsPrice(strike_otm1_put));
63 | def put_volume1 = volume("." + symbol + AsPrice(DateString) +"P" + AsPrice(strike_otm1_put));
64 |
65 | def put_close_otm2= close("." + symbol + AsPrice(DateString) +"P" + AsPrice(strike_otm2_put));
66 | def put_volume2 = volume("." + symbol + AsPrice(DateString) +"P" + AsPrice(strike_otm2_put));
67 |
68 | def call_itm_volumexclose = if isNaN(call_volume_itm1 * call_close_itm1 * 100) then 0 else call_volume_itm1 * call_close_itm1 * 100;
69 | def call_itm_volumexclose1 = if isNaN(call_volume_itm2 * call_close_itm2 * 100) then 0 else call_volume_itm2 * call_close_itm2 * 100;
70 | def call_volumexclose = if IsNan(call_volume * call_close_price * 100) then 0 else call_volume * call_close_price * 100 ;
71 | def call_plusone_volumexclose = if IsNan(call_volume1 * call_close_otm1) then 0 else call_volume1 * call_close_otm1 * 100 ;
72 | def call_plustwo_volumexclose = if IsNan(call_volume2 * call_close_otm2 * 100) then 0 else call_volume2 * call_close_otm2 * 100;
73 |
74 | def calls_current_total = call_itm_volumexclose + call_itm_volumexclose1 + call_volumexclose + call_plusone_volumexclose + call_plustwo_volumexclose;
75 |
76 | def put_itm_volumexclose = if isNaN(put_volume_itm1 * put_close_price_itm1 * 100) then 0 else put_volume_itm1 * put_close_price_itm1 * 100;
77 | def put_itm_volumexclose1 = if isNaN(put_volume_itm2 * put_close_price_itm2 * 100) then 0 else put_volume_itm2 * put_close_price_itm2 * 100;
78 | def put_volumexclose = if isNaN(put_volume * put_close_price * 100) then 0 else put_volume * put_close_price * 100;
79 | def put_minusone_volumexclose = if isNaN(put_volume1 * put_close_otm1 * 100) then 0 else put_volume1 * put_close_otm1 * 100;
80 | def put_minustwo_volumexclose = if isNaN(put_volume1 * put_close_otm2 * 100) then 0 else put_volume2 * put_close_otm2 * 100;
81 |
82 | def puts_current_total = put_itm_volumexclose + put_itm_volumexclose1 + put_volumexclose + put_minusone_volumexclose + put_minustwo_volumexclose;
83 |
84 | def moving_up = if close[1] > close[2] then 1 else 0;
85 | def moving_down = close[1] < close[2];
86 | AddChartBubble(puts_current_total > Premium_Extreme_Level and moving_down, low, "BULL" , color.Green);
87 | AddChartBubble(calls_current_total > Premium_Extreme_Level and moving_up ==1, high, "BEAR" , color.red);
88 |
--------------------------------------------------------------------------------
/optionVolume_vs_previousPeriod/README.md:
--------------------------------------------------------------------------------
1 | 🚀 This monitors for large changes in option volume.
2 |
3 | Category: Option Volume
4 | 
5 |
6 | Designed for SPY and QQQ.
7 |
8 | > Chart requirements for optimal use:
9 | ```bash
10 |
11 | Time frame: Any
12 |
13 | Note: This does work on a historical look back.
14 | ```
15 |
16 |
17 | > Settings 👷:
18 |
19 | ```bash
20 |
21 | Upper:
22 | 1. Strike Spacing: 1; (This sets the space between strikes. Ex: Current SPY price is 400. It will monitor calls
23 | and puts at strikes 398, 399, 400, 401 and 402)
24 | 2. Percent Minimum: 1000; (1000% increase in volume. Adjust this to your level of interest)
25 |
26 | ```
27 |
28 |
29 |
30 | > 🧪 How this works:
31 |
32 | ```bash
33 |
34 | Monitors the volume for each strike. Then compares the current period vs the previous period.
35 |
36 | A chart bubble will appear at the strike line and stay permanently. Useful for historical lookback.
37 |
38 | Labels will appear at the top of the chart only for the current period. Showing the % increase and strike if it meets your minimum.
39 |
40 |
41 | ```
42 |
43 | > 🦖 Why this works:
44 | ```bash
45 | 1 Theory:
46 |
47 | Large increase in option volume could give some insight into how market participants are positioning.
48 |
49 | Warning: It is not known if the options are bought or sold.
50 |
51 | ```
52 |
--------------------------------------------------------------------------------
/option_volume_and_openInterest_vertical_axis/es_nq/README.md:
--------------------------------------------------------------------------------
1 | 🚀 This plots the current day's live option volume and plots the open interest total(from yesterday's close).
2 |
3 | Category: Option Volume/Open Interest
4 |
5 | 
6 |
7 |
8 | Designed for ES and NQ. (Should work for any Futures Contract on the CME)
9 |
10 | > Chart requirements for optimal use:
11 | ```bash
12 |
13 | Time frame: 1 Day
14 |
15 | Aggregation Period: 1 Minute
16 |
17 | Time Axis: Expansion Area: 200 bars to the right
18 |
19 | ```
20 |
21 |
22 |
23 |
24 | > Settings 👷:
25 |
26 | ```bash
27 |
28 | 1. Symbol: /EW3X23; (You have to manually enter the contract symbol)
29 | 1. Strike Spacing: 5.0; (This sets the space between strikes. Ex: Current /ES price is 4000. It will monitor calls
30 | and puts at strikes 3990, 3995, 4000, 4005 and 4010)
31 | 2. Roundup: No; (Set this to "Yes" if you want to adjust the range monitored to higher strikes)
32 | 3. Shift line right: 10; (This controls where the vertical line will plot on your chart. Larger # pushes it to the right)
33 | 4. Division: 1000; (The volume or open interest is divided by this number. Gives user adjustability depending on chart size)
34 | 5. Space: 0.05; (This sets the space between the call and put bars)
35 |
36 |
37 |
38 | ```
39 |
40 |
41 | > 🧪 How this works:
42 |
43 | ```bash
44 |
45 | 1. Volume: Plots the live option volume for each strike.
46 |
47 | 2. Open Interest: Plots the open interest as of the previous day's close.
48 |
49 |
50 | ```
51 |
52 | > 🦖 How to use this(layman description):
53 | ```bash
54 |
55 | 1. Large one sided open interest levels. When there is a strike with large call open interest compared to put open interest.
56 | Its possible that dealers are at risk if the equity price starts moving towards that strike.
57 | a. The dealer previously sold the calls to a trader to collect the premium. The dealer has to protect his position.
58 | b. As the equity price moves towards this strike price(call option value increases) the dealer would have to buy the equity.
59 | c. This dynamic can cause these strike levels to act like a magnet. Possible pinning effect.
60 | d. If the equity price moves above this strike and the dealer doesnt have exposure at higher strikes.
61 | Then the dealer doesnt need to continue buying. Which could allow the price to fall back to the strike.
62 |
63 | ```
64 |
--------------------------------------------------------------------------------
/option_volume_and_openInterest_vertical_axis/readme.md:
--------------------------------------------------------------------------------
1 | 🚀 This plots the current day's live option volume and plots the open interest total(from yesterday's close).
2 |
3 | Category: Option Volume/Open Interest
4 |
5 | 
6 |
7 | Designed for SPY and QQQ. (Use manual version for any other instrument)
8 |
9 | > Chart requirements for optimal use:
10 | ```bash
11 |
12 | Time frame: 1 Day
13 |
14 | Aggregation Period: 1 Minute
15 |
16 | Time Axis: Expansion Area: 200 bars to the right
17 |
18 | ```
19 |
20 |
21 |
22 |
23 | > Settings 👷:
24 |
25 | ```bash
26 |
27 | 1. Strike Spacing: 1; (This sets the space between strikes. Ex: Current SPY price is 400. It will monitor calls
28 | and puts at strikes 398, 399, 400, 401 and 402)
29 | 2. Roundup: No; (Set this to "Yes" if you want to adjust the range monitored to higher strikes)
30 | 3. Shift line right: 10; (This controls where the vertical line will plot on your chart. Larger # pushes it to the right)
31 | 4. Division: 1000; (The volume or open interest is divided by this number. Gives user adjustability depending on chart size)
32 | 5. Space: 0.05; (This sets the space between the call and put bars)
33 |
34 | Manual Version:
35 | 1. Option series yymmdd: 221125; (Enter the specific expiration date you want to monitor)
36 |
37 |
38 | ```
39 |
40 |
41 | > 🧪 How this works:
42 |
43 | ```bash
44 |
45 | 1. Volume: Plots the live option volume for each strike.
46 |
47 | 2. Open Interest: Plots the open interest as of the previous day's close.
48 |
49 | 3. The option expiration date is automatically set to the current day.(Ideal for SPY and QQQ)
50 |
51 | 4. The manual version of these indicators allows you to set a specific expiration date.
52 |
53 | ```
54 |
55 | > 🦖 How to use this(layman description):
56 | ```bash
57 |
58 | 1. Large one sided open interest levels. When there is a strike with large call open interest compared to put open interest.
59 | Its possible that dealers are at risk if the equity price starts moving towards that strike.
60 | a. The dealer previously sold the calls to a trader to collect the premium. The dealer has to protect his position.
61 | b. As the equity price moves towards this strike price(call option value increases) the dealer would have to buy the equity.
62 | c. This dynamic can cause these strike levels to act like a magnet. Possible pinning effect.
63 | d. If the equity price moves above this strike and the dealer doesnt have exposure at higher strikes.
64 | Then the dealer doesnt need to continue buying. Which could allow the price to fall back to the strike.
65 |
66 | ```
67 |
--------------------------------------------------------------------------------
/option_volume_and_openInterest_vertical_axis/spx_and_ndx/README.md:
--------------------------------------------------------------------------------
1 | 🚀 This plots the current day's live option volume and plots the open interest total(from yesterday's close).
2 |
3 | Category: Option Volume/Open Interest
4 |
5 | 
6 |
7 | Designed for SPX and NDX
8 |
9 | > Chart requirements for optimal use:
10 | ```bash
11 |
12 | Time frame: 1 Day
13 |
14 | Aggregation Period: 1 Minute
15 |
16 | For SPX add these indicators to /ES chart. For NDX add these indicators to /NQ chart.
17 |
18 | Time Axis: Expansion Area: 200 bars to the right
19 |
20 | ```
21 |
22 |
23 |
24 |
25 | > Settings 👷:
26 |
27 | ```bash
28 |
29 | 1. Strike Spacing: 5; (This sets the space between strikes. Ex: Current SPX price is 4000. It will monitor calls
30 | and puts at strikes 3990, 3995, 4000, 4005 and 4010)
31 | 2. Symbol: SPXW; (Use NDXP for NDX options)
32 | 3. Roundup: No; (Set this to "Yes" if you want to adjust the range monitored to higher strikes)
33 | 4. Shift line right: 10; (This controls where the vertical line will plot on your chart. Larger # pushes it to the right)
34 | 5. Division: 100; (The volume or open interest is divided by this number. Gives user adjustability depending on chart size)
35 | 6. Space: 0.5; (This sets the space between the call and put bars)
36 |
37 | Manual Version:
38 | 1. Option series yymmdd: 221226; (Enter the specific expiration date you want to monitor)
39 |
40 |
41 | ```
42 |
43 |
44 | > 🧪 How this works:
45 |
46 | ```bash
47 |
48 | 1. Volume: Plots the live option volume for each strike.
49 |
50 | 2. Open Interest: Plots the open interest as of the previous day's close.
51 |
52 | 3. The option expiration date is automatically set to the current day.(Ideal for SPY and QQQ)
53 |
54 | 4. The manual version of these indicators allows you to set a specific expiration date.
55 |
56 | ```
57 |
58 | > 🦖 How to use this(layman description):
59 | ```bash
60 |
61 | 1. Large one sided open interest levels. When there is a strike with large call open interest compared to put open interest.
62 | Its possible that dealers are at risk if the equity price starts moving towards that strike.
63 | a. The dealer previously sold the calls to a trader to collect the premium. The dealer has to protect his position.
64 | b. As the equity price moves towards this strike price(call option value increases) the dealer would have to buy the equity.
65 | c. This dynamic can cause these strike levels to act like a magnet. Possible pinning effect.
66 | d. If the equity price moves above this strike and the dealer doesnt have exposure at higher strikes.
67 | Then the dealer doesnt need to continue buying. Which could allow the price to fall back to the strike.
68 |
69 | ```
70 |
--------------------------------------------------------------------------------
/peter_gap_rules/README.md:
--------------------------------------------------------------------------------
1 | # Peter Gap Rules Experimental
2 |
3 | This monitors for rare gap plays on SPY. Must use on 30min Chart with Extended hours turned off.
4 | The code is not finished. Dont trust the Bubbles on the chart, they repaint and are always wrong.
5 |
6 | ######
7 | ######
8 |
9 | 
10 |
11 |
12 | > Chart requirements for optimal use:
13 | ```bash
14 |
15 | Aggregation Period: 30 Minute
16 |
17 | Extended hours turned off
18 |
19 | ```
20 |
21 | ######
22 | ######
23 | Peter Gap Rule #1. If we are in an "UP" cycle on 30min and Daily.
24 |
25 | 1. Price gaps down. Atleast $1.
26 | 2. Opening Market breadth is roughly not less than -1500
27 | There is potential for the gap to fill.
28 |
29 | ######
30 | ######
31 | Peter Gap Rule #2. If we are in an "UP" cycle on 30min and Daily.
32 |
33 | 1. Price gaps up. Atleast $2.
34 | 2. MarketForecast breadth is roughly greater than 1200.
35 | Potential for Low of day in the 1st hour. High of day after 200pm EST.
36 |
37 | ######
38 | ######
39 | Peter Gap Rule #3. If we are in a "DOWN" cycle on 30min and Daily.
40 |
41 | 1. Price gaps up. Atleast $1.
42 | 2. Opening Market breadth is roughly less than 1500.
43 | There is potential for the gap to fill.
44 |
45 | ######
46 | ######
47 | Peter Gap Rule #4. If we are in an "DOWN" cycle on 30min and Daily.
48 |
49 | 1. Price gaps down. Atleast $2.
50 | 2. Market breadth is roughly -1200 or lower.
51 | Potential for High of day in the 1st hour. Low of day after 200pm EST.
52 |
53 |
54 | > 🦖 How to use this(layman description):
55 | ```bash
56 |
57 | 1. Peter Magic.
58 |
59 | ```
60 |
61 |
--------------------------------------------------------------------------------
/peter_gap_rules/peter_gap_rules_not_working_right:
--------------------------------------------------------------------------------
1 | # Peter Gap Rules Experimental Version. This does not work correctly. Dont trust it.
2 | # Using on 30 min SPY chart only.
3 | # Turn off extended hours trading.
4 | def agg = aggregationPeriod.DAY;
5 |
6 | def yday_close = close(period=agg) from 1 bar ago;
7 | def today_open = open(period=agg);
8 |
9 | def adjEndTime = 930;
10 | def adjStartTime = 930;
11 |
12 | def marketOpen = if SecondsTillTime(adjEndTime) == 0 then 1 else 0;
13 |
14 | def price = close("$ADD");
15 | def length = 19;
16 | def length2 = 39;
17 |
18 | def EMA19 = ExpAverage(price, length);
19 | def EMA39 = ExpAverage(price, length2);
20 | def slopewidth = EMA19 - EMA39;
21 | AddLabel(yes, “30MIN_Cycle: ” + slopewidth, if slopewidth > 0 then Color.GREEN else Color.RED);
22 | AddLabel(yes, “30MIN_Cycle: ” + if slopewidth > 124 then "UP" else if slopewidth < -124 then "DOWN" else "FLAT", if slopewidth > 25 then Color.GREEN else Color.RED );
23 |
24 | def breadth_open = open("$ADD", period=agg);
25 | def price_day = close("$ADD", period=agg);
26 | def EMA19_day = ExpAverage(price_day, length);
27 | def EMA39_day = ExpAverage(price_day, length2);
28 | def slopewidth_day = EMA19_day - EMA39_day;
29 | AddLabel(yes, "DAY_Cycle: ” + slopewidth_day, if slopewidth_day > 0 then Color.GREEN else Color.RED);
30 |
31 | AddLabel(yes, “DAY_Cycle: ” + if slopewidth_day > 74 then "UP" else if slopewidth_day < -74 then "DOWN" else "FLAT", if slopewidth_day > 25 then Color.GREEN else Color.RED );
32 |
33 | def peter_up = slopewidth_day > 74 and slopewidth > 124;
34 | def peter_down = slopewidth_day < -74 and slopewidth < -124;
35 |
36 | def gap_down = yday_close > today_open+1;
37 | def gap_up = today_open > yday_close+1;
38 | def gap_down_large = yday_close > today_open+2;
39 | def gap_up_large = today_open > yday_close+2;
40 |
41 | #Peter Gap Rule #1. If we are in an "UP" cycle on 30min and Daily.
42 | #1. Price gaps down. Atleast $1.
43 | #2. Opening Market breadth is roughly not less than -1500
44 | #There is potential for the gap to fill.
45 | addlabel(peter_up and gap_down and breadth_open > -1499, "Buy Calls. TGT: " + yday_close);
46 | def gap_rule1 = peter_up and gap_down and breadth_open > -1499;
47 | #plot gap1 = if gap_rule1 then 1 else double.nan;
48 | #gap1.AssignValueColor(color.green);
49 | addchartbubble(marketOpen and gap_rule1, low, "Up_Cycles\n" + "Gap Down\n"+ "Fill gap", color.green, no);
50 |
51 | #Peter Gap Rule #2. If we are in an "UP" cycle on 30min and Daily.
52 | #1. Price gaps up. Atleast $2.
53 | #2. MarketForecast breadth is roughly greater than 1200.
54 | #Potential for Low of day in the 1st hour. High of day after 200pm EST.
55 | addlabel(peter_up and gap_up_large and price > 1199, "Buy Calls. Low in 1st Hour. High after 200PM");
56 | def gap_rule2 = peter_up and gap_up_large and price > 1199;
57 | #plot gap2 = if gap_rule2 then 1 else double.nan;
58 | #gap2.AssignValueColor(color.cyan);
59 | addchartbubble(marketOpen and gap_rule2,low, "Up_Cycles\n"+ "Gap Up and Go", color.cyan, no);
60 |
61 | #Peter Gap Rule #3. If we are in a "DOWN" cycle on 30min and Daily.
62 | #1. Price gaps up. Atleast $1.
63 | #2. Opening Market breadth is roughly less than 1500.
64 | #There is potential for the gap to fill.
65 | addlabel(peter_down and gap_up and breadth_open < 1501, "Buy Puts. TGT: " + yday_close);
66 | def gap_rule3 = peter_down and gap_up and breadth_open < 1501;
67 | #plot gap3 = if gap_rule3 then 1 else double.nan;
68 | #gap3.AssignValueColor(color.magenta);
69 | addchartbubble(marketOpen and gap_rule3,high, "Down_Cycles\n"+ "Gap Up\n" + "Fill Gap", color.magenta, yes);
70 |
71 | #Peter Gap Rule #4. If we are in an "DOWN" cycle on 30min and Daily.
72 | #1. Price gaps down. Atleast $2.
73 | #2. MarketForecast breadth is roughly -1200 or lower.
74 | #Potential for High of day in the 1st hour. Low of day after 200pm EST.
75 | addlabel(peter_down and gap_down_large and price < -1199, "Buy Puts. High in 1st Hour. Low after 200PM");
76 | def gap_rule4 = peter_down and gap_down_large and price < -1199;
77 | #plot gap4 = if gap_rule4 then 1 else double.nan;
78 | #gap4.AssignValueColor(color.orange);
79 | addchartbubble(marketOpen and gap_rule4,high, "Down_Cycles\n"+ "Gap Down and Go", color.orange, yes);
80 |
--------------------------------------------------------------------------------
/requests/vwap/vwap_bid_ask_signal_lower:
--------------------------------------------------------------------------------
1 | declare once_per_bar;
2 | declare lower;
3 |
4 | def bidX = close(priceType = priceType.BID);
5 | def askX = close(priceType = priceType.ASK);
6 | def spread = askX - bidX;
7 |
8 | plot thespread = bidX * volume();
9 | thespread.setPaintingStrategy(PaintingStrategy.HISTOGRAM);
10 | thespread.SetDefaultColor(color.plum);
11 |
12 | plot threshold = 38000000;
13 | threshold.setDefaultColor(color.white);
14 |
--------------------------------------------------------------------------------
/requests/vwap/vwap_bid_ask_signal_upper:
--------------------------------------------------------------------------------
1 | # Request to demystify a harlind twitter post Feb 20, 2025
2 | # Price is 1 std dev below vwap
3 | # bid x volume > threshold
4 | # (ask - bid) <= 0.01
5 | # wide range down bar
6 | # @2187Nick
7 | # this is only monitoring for buy signals.
8 | # Can easily adapt to monitor for sell signals
9 |
10 | # 1min chart
11 |
12 | declare once_per_bar;
13 | declare upper;
14 |
15 | input threshold = 38000000;
16 |
17 | def current_vwap = reference VWAP();
18 | def lower_band = reference VWAP(numdevdn=-1.5,numdevup=1.0, timeFrame="DAY")."LowerBand";
19 | def upper_band = reference VWAP(numdevdn=-1.5,numdevup=1.0, timeFrame="DAY")."UpperBand";
20 | #addlabel(1, "lowerband_1std: " + lower_band);
21 | #addlabel(1, "upperband_1std: " + upper_band);
22 |
23 | plot vwap = current_vwap;
24 | vwap.setDefaultColor(color.plum);
25 | plot lower = lower_band;
26 | lower.setPaintingStrategy(PaintingStrategy.LINE);
27 | lower.setDefaultColor(color.yellow);
28 |
29 | def bidX = close(priceType = priceType.BID);
30 | def askX = close(priceType = priceType.ASK);
31 | def spread = askX - bidX;
32 | # he mentions .01 spread. We can add that in as a factor if needed.
33 |
34 | def bid_volume = bidX * volume();
35 | def both = if bid_volume > threshold and (low() <= lower_band) then 1 else 0;
36 |
37 | #plot signal = if both then low() else double.nan;
38 | #signal.setDefaultColor(color.green);
39 | #signal.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
40 | #signal.setLineWeight(5);
41 |
42 | def cent_spread = if spread <= .01 then 1 else 0;
43 |
44 | #plot signal2 = if cent_spread then low() else double.nan;
45 | #signal2.setDefaultColor(color.red);
46 | #signal2.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
47 | #signal2.setLineWeight(5);
48 |
49 | input lengthForAverage = 20; # Period to calculate average range
50 | input multiplier = 1.5; # How much wider than average to trigger alert
51 |
52 | def highLowRange = high - low;
53 | def averageRange = Average(highLowRange, lengthForAverage);
54 | def isDownBar = close < open;
55 | def isWideRange = highLowRange > (averageRange * multiplier);
56 |
57 | #plot Signal3 = isDownBar && isWideRange;
58 | #Signal3.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
59 | #Signal3.SetDefaultColor(Color.BLUE);
60 |
61 |
62 | plot finalSignal = isDownBar && isWideRange && cent_spread && both;
63 |
64 | finalSignal.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
65 | finalSignal.SetDefaultColor(Color.GREEN);
66 | finalSignal.setLineWeight(5);
67 |
--------------------------------------------------------------------------------
/shapes_and_art/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Shapes and Art
3 |
4 | Thinkscript doesnt have built in functions to draw shapes. Here is what I came up with using GPT4.
5 |
6 | 
7 |
8 | 
9 |
10 | 
11 |
12 | 
13 |
14 | ## Emojis
15 | 
16 |
17 |
--------------------------------------------------------------------------------
/shapes_and_art/circle.ts:
--------------------------------------------------------------------------------
1 | input centerPrice = 410;
2 | input radius = 0.2;
3 | input numberofbars_start = 40; # 40 bars from the right side of your chart.
4 | input numberofbars_end = 10; # 0 bars from the right side of your chart
5 | def circleStartBar = HighestAll(BarNumber()) - numberofbars_start;
6 | def circleEndBar = HighestAll(BarNumber()) - numberofbars_end;
7 |
8 | def bar = BarNumber();
9 | def angleStep = 360 / (circleEndBar - circleStartBar);
10 | def angle = (bar - circleStartBar) * angleStep;
11 |
12 | # plot points for full circle
13 | def y = if bar >= circleStartBar and bar <= circleEndBar then centerPrice + radius * Sin(angle * Double.Pi / 360) else Double.NaN;
14 | def y2 = if bar >= circleStartBar and bar <= circleEndBar then centerPrice - radius * Sin(angle * Double.Pi / 360) else Double.NaN;
15 |
16 | #plot Circle = y;
17 | #Circle.SetPaintingStrategy(PaintingStrategy.Line);
18 | #Circle.SetDefaultColor(color.cyan);
19 |
20 | #plot Circle2 = y2;
21 | #Circle2.SetPaintingStrategy(PaintingStrategy.Line);
22 | #Circle2.SetDefaultColor(color.cyan);
23 |
24 | #AddCloud(Circle, Circle2, color.violet, color.violet);
25 |
26 | AddChartBubble(bar >= circleStartBar and bar <= circleEndBar, y, "High", Color.green, yes);
27 | AddChartBubble(bar >= circleStartBar and bar <= circleEndBar, y2, "Low", Color.red, no);
28 |
29 | input radius2 = 0.1;
30 | def circleStartBar2 = HighestAll(BarNumber()) - 30;
31 | def circleEndBar2 = HighestAll(BarNumber()) - 10;
32 |
33 | def angleStep2 = 360 / (circleEndBar2 - circleStartBar2);
34 | def angle2 = (bar - circleStartBar2) * angleStep2;
35 |
36 | # plot points for full circle
37 | def y3 = if bar >= circleStartBar2 and bar <= circleEndBar2 then centerPrice + radius2 * Sin(angle2 * Double.Pi / 360) else Double.NaN;
38 | def y4 = if bar >= circleStartBar2 and bar <= circleEndBar2 then centerPrice - radius2 * Sin(angle2 * Double.Pi / 360) else Double.NaN;
39 |
40 | #plot Circle3 = y3;
41 | #Circle3.SetPaintingStrategy(PaintingStrategy.Points);
42 | #Circle3.SetDefaultColor(color.green);
43 |
44 | #plot Circle4 = y4;
45 | #Circle4.SetPaintingStrategy(PaintingStrategy.Points);
46 | #Circle4.SetDefaultColor(color.green);
47 |
48 | #(Circle3, Circle4, color.green, color.green);
49 |
--------------------------------------------------------------------------------
/shapes_and_art/cuphandle.ts:
--------------------------------------------------------------------------------
1 | input centerPrice = 410;
2 | input radius = 1;
3 | input numberofbars_start_cup = 40; # 40 bars from the right side of your chart.
4 | input numberofbars_end_cup = 10; # 0 bars from the right side of your chart
5 | def circleStartBar = HighestAll(BarNumber()) - numberofbars_start_cup;
6 | def circleEndBar = HighestAll(BarNumber()) - numberofbars_end_cup;
7 |
8 | def bar = BarNumber();
9 | def angleStep = 360 / (circleEndBar - circleStartBar);
10 | def angle = (bar - circleStartBar) * angleStep;
11 |
12 | # plot points for full circle
13 | def y = if bar >= circleStartBar and bar <= circleEndBar then centerPrice + radius * Sin(angle * Double.Pi / 360) else Double.NaN;
14 | def cup = if bar >= circleStartBar and bar <= circleEndBar then centerPrice - radius * Sin(angle * Double.Pi / 360) else Double.NaN;
15 |
16 | input numberofbars_start_handle = 10; # 40 bars from the right side of your chart.
17 | input numberofbars_end_handle = 3; # 0 bars from the right side of your chart
18 | def circleStartBar2 = HighestAll(BarNumber()) - numberofbars_start_handle;
19 | def circleEndBar2 = HighestAll(BarNumber()) - numberofbars_end_handle;
20 | def radius_handle = .2;
21 |
22 | def angleStep2 = 360 / (circleEndBar2 - circleStartBar2);
23 | def angle2 = (bar - circleStartBar2) * angleStep2;
24 |
25 | def handle = if bar >= circleStartBar2 and bar <= circleEndBar2 then centerPrice - radius_handle * Sin(angle2 * Double.Pi / 360) else Double.NaN;
26 |
27 | #plot Circle = y;
28 | #Circle.SetPaintingStrategy(PaintingStrategy.Line);
29 | #Circle.SetDefaultColor(color.cyan);
30 |
31 | #plot Circle2 = cup;
32 | #Circle2.SetPaintingStrategy(PaintingStrategy.Line);
33 | #Circle2.SetDefaultColor(color.magenta);
34 | #Circle2.SetLineWeight(5);
35 |
36 | #AddCloud(Circle, Circle2, color.violet, color.violet);
37 |
38 | #AddChartBubble(bar >= circleStartBar and bar <= circleEndBar, y, "Sun", Color.green, yes);
39 | AddChartBubble(bar >= circleStartBar and bar <= circleEndBar, cup, "Cup", Color.red, no);
40 | AddChartBubble(bar >= circleStartBar2+1 and bar <= circleEndBar2, handle, "Handle", Color.yellow, no);
41 |
42 | #plot Circle3 = handle;
43 | #Circle3.SetPaintingStrategy(PaintingStrategy.Line);
44 | #Circle3.SetDefaultColor(color.yellow);
45 |
--------------------------------------------------------------------------------
/shapes_and_art/emojis:
--------------------------------------------------------------------------------
1 | AddChartBubble(yes, 512, "💕 💕", color.red, yes);
2 | AddChartBubble(yes, 513, "🏂 🏂 \n 🏂 🏂 ", Color.blue, no);
3 | AddChartBubble(yes, 514, " 👽\n 👽👽\n👽👽👽", Color.violet, no);
4 |
5 | addlabel(yes, "💕 🌛 🌜 🌚 🌙 🎅 🎄 👮 🎓 🌾 🔧 🚒 👰 🏃 ♀ ️ 🚶 💃 🕺️ 🏇 🏌️ ️🛀 🛌️ 🛀 🏂 🏌 ️️ ️🏄 ️🤸️ ☝️ 👆 ✌️ 👈 👉 👂 👃 🎈 🎆 ✨ 🎉 🎎 🎍 🎑 🎏 🎞 ️🎐 🎟️ 🎑 🎀 🎠 🎁 🎪 🎯 💉 🔬 🏹 🗡 ️ ⚔ ️🍿 💖 ️🚸 🔰 🈯 ✅ ❎ 💠 ️💹 🆙 🆗 🔼 💫", Color.orange);
6 | addlabel(yes, "👉 👂 👃 🎈 🎆 ✨ 🎉 🎎 🎍 🎑 🎏 🎞 ️🎐 🎟️ 🎑 🎀 🎠 🎁 🎪 🎯 💉 🔬 🏹 🗡 ️ ⚔ ️🍿 💖 ️🚸 🔰 🈯 ✅ ❎ 💠 ️💹 🆙 🆗 🔼 💫", Color.light_GREEN);
7 | addlabel(yes, "👽 👾 🐻 🐻 ❄ ️🐼 ️🐍 🐍 ℉ ℃ ↪ ↩ ↮ ↯ ↱ ↰↪ ↬ ↲ ↳ ⇙ ⇖ ⇶ ▨ ▶ ◀ ◁ ▷ ▱ △ ▲ ◌ ● ◥ ◤ ◣ ◢ ◡◠ αΩ Ⅰ Ⅱ Ⅲ Ⅳ Ⅴ Ⅵ Ⅶ Ⅷ Ⅸ Ⅹ ﷼ ₨ 🤢 😤 💀 ☠ ️👻 🤖 💩 💩 😺 😸 😹 😼 😻 😽 🙈 🙉 🙊 🐵 🐶 🐺 🐱 🦁 🐯 🦊 🐮 🐷 🐻 ❄ ️🐰 🐳 🐋 🐟 🦆 🐓 🦃 🐦 🐞 👀", color.light_red);
8 | addlabel(yes, "🙈 🙉 🙊 🐵 🐶 🐺 🐱 🦁 🐯 🦊 🐮 🐷 🐻 ❄ ️🐰 🐳 🐋 🐟 🦆 🐓 🦃 🐦 🐞 👀", color.light_red);
9 |
--------------------------------------------------------------------------------
/shapes_and_art/sierpinski.ts:
--------------------------------------------------------------------------------
1 | def startBar = HighestAll(BarNumber()) - 20; # -30
2 | def endBar = HighestAll(BarNumber()) - 0; #- 10
3 | def middleBar = Round((startBar + endBar) / 2, 0);
4 | def bottomPrice = 405;
5 | def topPrice = 415;
6 |
7 | # Draw outer triangle
8 | plot TriangleA = if BarNumber() >= startBar and BarNumber() <= middleBar then bottomPrice + (topPrice - bottomPrice) * (BarNumber() - startBar) / (middleBar - startBar) else Double.NaN;
9 | TriangleA.SetPaintingStrategy(PaintingStrategy.line);
10 | TriangleA.SetDefaultColor(color.red);
11 | TriangleA.SetLineWeight(3);
12 |
13 | plot TriangleB = if BarNumber() >= middleBar and BarNumber() <= endBar then topPrice - (topPrice - bottomPrice) * (BarNumber() - middleBar) / (endBar - middleBar) else Double.NaN;
14 | TriangleB.SetPaintingStrategy(PaintingStrategy.line);
15 | TriangleB.SetDefaultColor(color.red);
16 | TriangleB.SetLineWeight(3);
17 |
18 | # Draw horizontal line (base of the triangle)
19 | plot BottomLine = if BarNumber() >= startBar and BarNumber() <= endBar then bottomPrice else Double.NaN;
20 | BottomLine.SetPaintingStrategy(PaintingStrategy.Line);
21 | BottomLine.SetDefaultColor(color.red);
22 | BottomLine.SetLineWeight(3);
23 |
24 | # Draw inner upside-down triangle
25 | def innerStartBar = startBar + (endBar - startBar) / 4;
26 | def innerEndBar = endBar - (endBar - startBar) / 4;
27 | def innerMiddleBar = Round((innerStartBar + innerEndBar) / 2, 0);
28 | def innerBottomPrice = bottomPrice + (topPrice - bottomPrice) / 2;
29 | def innerTopPrice = innerBottomPrice - (topPrice - bottomPrice) / 2;
30 |
31 | plot InnerTriangleA = if BarNumber() >= innerStartBar and BarNumber() <= innerMiddleBar then innerBottomPrice - (innerBottomPrice - innerTopPrice) * (BarNumber() - innerStartBar) / (innerMiddleBar - innerStartBar) else Double.NaN;
32 | InnerTriangleA.SetPaintingStrategy(PaintingStrategy.line);
33 | InnerTriangleA.SetDefaultColor(color.red);
34 | InnerTriangleA.SetLineWeight(3);
35 |
36 | plot InnerTriangleB = if BarNumber() >= innerMiddleBar and BarNumber() <= innerEndBar then innerTopPrice + (innerBottomPrice - innerTopPrice) * (BarNumber() - innerMiddleBar) / (innerEndBar - innerMiddleBar) else Double.NaN;
37 | InnerTriangleB.SetPaintingStrategy(PaintingStrategy.line);
38 | InnerTriangleB.SetDefaultColor(color.red);
39 | InnerTriangleB.SetLineWeight(3);
40 |
41 | # Draw horizontal line (base of the triangle)
42 | plot BottomLine2 = if BarNumber() >= innerStartBar and BarNumber() <= innerEndBar then innerBottomPrice else Double.NaN;
43 | BottomLine2.SetPaintingStrategy(PaintingStrategy.Line);
44 | BottomLine2.SetDefaultColor(color.red);
45 | BottomLine2.SetLineWeight(3);
46 |
47 | # ... previous code here ...
48 |
49 | # Define properties for the top triangle
50 | def bottomRightTriangleStartBar = middleBar;
51 | #(yes, "bottomRightTriangleStartBar: " + bottomRightTriangleStartBar, color.white);
52 | #addverticalline(barNumber()== bottomRightTriangleStartBar, "",color.white);
53 | def bottomRightTriangleEndBar = endBar;
54 | #addlabel(yes, "bottomRightTriangleEndBar: " + bottomRightTriangleEndBar, color.green);
55 | #addverticalline(barNumber()== bottomRightTriangleEndBar, "",color.green);
56 | def bottomRightTriangleMiddleBar = Round((bottomRightTriangleStartBar + bottomRightTriangleEndBar) / 2, 0);
57 | #addlabel(yes, "bottomRightTriangleMiddleBar: " + bottomRightTriangleMiddleBar, color.yellow);
58 | #addverticalline(barNumber()== bottomRightTriangleMiddleBar, "",color.yellow);
59 | def bottomRightTriangleBottomPrice = 408.75; #412; #topPrice;
60 | #addlabel(yes, "bottomRightTriangleBottomPrice: " + bottomRightTriangleBottomPrice);
61 | def bottomRightTriangleTopPrice = 405; #bottomPrice + (topPrice - bottomPrice) / 2;
62 | #addlabel(yes, "bottomRightTriangleTopPrice: " + bottomRightTriangleTopPrice);
63 |
64 | def bottomRightTriangleStartBar2 = Round((bottomRightTriangleStartBar + bottomRightTriangleEndBar) / 2, 0);
65 |
66 |
67 | # Draw additional upside-down triangle in the top triangle
68 | def bottomRightTriangleInnerStartBar = bottomRightTriangleStartBar + (bottomRightTriangleEndBar - bottomRightTriangleStartBar) / 4;
69 | def bottomRightTriangleInnerEndBar = bottomRightTriangleEndBar - (bottomRightTriangleEndBar - bottomRightTriangleStartBar) / 4;
70 | def bottomRightTriangleInnerMiddleBar = Round((bottomRightTriangleInnerStartBar + bottomRightTriangleInnerEndBar) / 2, 0);
71 |
72 | plot bottomRightTriangleInnerA = if BarNumber() >= bottomRightTriangleInnerStartBar and BarNumber() <= bottomRightTriangleInnerMiddleBar then bottomRightTriangleBottomPrice - (bottomRightTriangleBottomPrice - bottomRightTriangleTopPrice) * (BarNumber() - bottomRightTriangleInnerStartBar) / (bottomRightTriangleInnerMiddleBar - bottomRightTriangleInnerStartBar) else Double.NaN;
73 | bottomRightTriangleInnerA.SetPaintingStrategy(PaintingStrategy.line);
74 | bottomRightTriangleInnerA.SetDefaultColor(color.red);
75 | bottomRightTriangleInnerA.SetLineWeight(3);
76 |
77 | plot BottomRightTriangleInnerB = if BarNumber() >= bottomRightTriangleInnerMiddleBar and BarNumber() <= bottomRightTriangleInnerEndBar then bottomRightTriangleTopPrice + (bottomRightTriangleBottomPrice - bottomRightTriangleTopPrice) * (BarNumber() - bottomRightTriangleInnerMiddleBar) / (bottomRightTriangleInnerEndBar - bottomRightTriangleInnerMiddleBar) else Double.NaN;
78 | bottomRightTriangleInnerB.SetPaintingStrategy(PaintingStrategy.line);
79 | bottomRightTriangleInnerB.SetDefaultColor(color.red);
80 | bottomRightTriangleInnerB.SetLineWeight(3);
81 |
82 | #Draw horizontal line (base of the triangle)
83 | plot BottomLine3 = if BarNumber() >= Round((bottomRightTriangleStartBar + bottomRightTriangleMiddleBar) / 2, 0) and BarNumber() < Round((bottomRightTriangleEndBar + bottomRightTriangleMiddleBar) / 2, 0) then bottomRightTriangleBottomPrice-.75 else Double.NaN;
84 | BottomLine3.SetPaintingStrategy(PaintingStrategy.Line);
85 | BottomLine3.SetDefaultColor(color.red);
86 | BottomLine3.SetLineWeight(3);
87 | # Define properties for the bottom left triangle
88 | def bottomLeftTriangleStartBar = startBar;
89 | def bottomLeftTriangleEndBar = middleBar;
90 | def bottomLeftTriangleMiddleBar = Round((bottomLeftTriangleStartBar + bottomLeftTriangleEndBar) / 2, 0);
91 | def bottomLeftTriangleBottomPrice = 408.75;
92 | def bottomLeftTriangleTopPrice = 405;
93 |
94 | # Draw additional upside-down triangle in the top triangle
95 | def bottomLeftTriangleInnerStartBar = bottomLeftTriangleStartBar + (bottomLeftTriangleEndBar - bottomLeftTriangleStartBar) / 4;
96 | def bottomLeftTriangleInnerEndBar = bottomLeftTriangleEndBar - (bottomLeftTriangleEndBar - bottomLeftTriangleStartBar) / 4;
97 | def bottomLeftTriangleInnerMiddleBar = Round((bottomLeftTriangleInnerStartBar + bottomLeftTriangleInnerEndBar) / 2, 0);
98 |
99 | plot bottomLeftTriangleInnerA = if BarNumber() >= bottomLeftTriangleInnerStartBar and BarNumber() <= bottomLeftTriangleInnerMiddleBar then bottomLeftTriangleBottomPrice - (bottomLeftTriangleBottomPrice - bottomLeftTriangleTopPrice) * (BarNumber() - bottomLeftTriangleInnerStartBar) / (bottomLeftTriangleInnerMiddleBar - bottomLeftTriangleInnerStartBar) else Double.NaN;
100 | bottomLeftTriangleInnerA.SetPaintingStrategy(PaintingStrategy.line);
101 | bottomLeftTriangleInnerA.SetDefaultColor(color.red);
102 | bottomLeftTriangleInnerA.SetLineWeight(3);
103 |
104 | plot bottomLeftTriangleInnerB = if BarNumber() >= bottomLeftTriangleInnerMiddleBar and BarNumber() <= bottomLeftTriangleInnerEndBar then bottomLeftTriangleTopPrice + (bottomLeftTriangleBottomPrice - bottomLeftTriangleTopPrice) * (BarNumber() - bottomLeftTriangleInnerMiddleBar) / (bottomLeftTriangleInnerEndBar - bottomLeftTriangleInnerMiddleBar) else Double.NaN;
105 | bottomLeftTriangleInnerB.SetPaintingStrategy(PaintingStrategy.line);
106 | bottomLeftTriangleInnerB.SetDefaultColor(color.red);
107 | bottomLeftTriangleInnerB.SetLineWeight(3);
108 |
109 | # Draw horizontal line (base of the triangle)
110 | plot BottomLine4 = if BarNumber() >= Round((bottomLeftTriangleStartBar + bottomLeftTriangleMiddleBar) / 2, 0) and BarNumber() < Round((bottomLeftTriangleEndBar + bottomLeftTriangleMiddleBar) / 2, 0) then bottomLeftTriangleBottomPrice-.75 else Double.NaN;
111 | BottomLine4.SetPaintingStrategy(PaintingStrategy.Line);
112 | BottomLine4.SetDefaultColor(color.red);
113 | BottomLine4.SetLineWeight(3);
114 |
115 | # Define properties for the top triangle
116 | def topTriangleStartBar = middleBar - (endBar - startBar) / 4; # Adjusted start bar
117 | def topTriangleEndBar = middleBar + (endBar - startBar) / 4; # Adjusted end bar
118 | def topTriangleMiddleBar = Round((topTriangleStartBar + topTriangleEndBar) / 2, 0);
119 | def topTriangleBottomPrice = bottomPrice + (topPrice - bottomPrice) / 2; # Mid point of the outer triangle
120 | def topTriangleTopPrice = topPrice-1.25;
121 |
122 | # Draw additional upside-down triangle in the top triangle
123 | def topTriangleInnerStartBar = topTriangleStartBar + (topTriangleEndBar - topTriangleStartBar) / 4;
124 | def topTriangleInnerEndBar = topTriangleEndBar - (topTriangleEndBar - topTriangleStartBar) / 4;
125 | def topTriangleInnerMiddleBar = Round((topTriangleInnerStartBar + topTriangleInnerEndBar) / 2, 0);
126 |
127 | plot topTriangleInnerA = if BarNumber() >= topTriangleInnerStartBar and BarNumber() <= topTriangleInnerMiddleBar then topTriangleTopPrice - (topTriangleTopPrice - topTriangleBottomPrice) * (BarNumber() - topTriangleInnerStartBar) / (topTriangleInnerMiddleBar - topTriangleInnerStartBar) else Double.NaN;
128 | topTriangleInnerA.SetPaintingStrategy(PaintingStrategy.line);
129 | topTriangleInnerA.SetDefaultColor(color.red);
130 | topTriangleInnerA.SetLineWeight(3);
131 |
132 | plot topTriangleInnerB = if BarNumber() >= topTriangleInnerMiddleBar and BarNumber() <= topTriangleInnerEndBar then topTriangleBottomPrice + (topTriangleTopPrice - topTriangleBottomPrice) * (BarNumber() - topTriangleInnerMiddleBar) / (topTriangleInnerEndBar - topTriangleInnerMiddleBar) else Double.NaN;
133 | topTriangleInnerB.SetPaintingStrategy(PaintingStrategy.line);
134 | topTriangleInnerB.SetDefaultColor(color.red);
135 | topTriangleInnerB.SetLineWeight(3);
136 |
137 | # Draw horizontal line (base of the triangle)
138 | plot BottomLine5 = if BarNumber() >= topTriangleInnerStartBar and BarNumber() <= topTriangleInnerEndBar then topTriangleTopPrice-.75 else Double.NaN;
139 | BottomLine5.SetPaintingStrategy(PaintingStrategy.Line);
140 | BottomLine5.SetDefaultColor(color.red);
141 | BottomLine5.SetLineWeight(3);
142 |
--------------------------------------------------------------------------------
/shapes_and_art/star.ts:
--------------------------------------------------------------------------------
1 | def startBar = HighestAll(BarNumber()) - 30;
2 | def endBar = HighestAll(BarNumber()) - 10;
3 | def middleBar = (startBar + endBar) / 2;
4 | def bottomPrice = 407;
5 | def topPrice = 413;
6 | def middlePrice = (topPrice + bottomPrice) / 2;
7 |
8 | # Draw horizontal line (base of the triangle)
9 | plot BottomLine = if BarNumber() >= startBar and BarNumber() <= endBar then topPrice else Double.NaN;
10 | BottomLine.SetPaintingStrategy(PaintingStrategy.Line);
11 | BottomLine.SetDefaultColor(color.green);
12 | BottomLine.SetLineWeight(5);
13 |
14 | plot Triangle2A = if BarNumber() >= startBar and BarNumber() <= middleBar then topPrice - (topPrice - middlePrice) * (BarNumber() - startBar) / (middleBar - startBar) else Double.NaN;
15 | Triangle2A.SetPaintingStrategy(PaintingStrategy.Line);
16 | Triangle2A.SetDefaultColor(color.green);
17 | Triangle2A.SetLineWeight(5);
18 |
19 | plot Triangle2B = if BarNumber() >= middleBar and BarNumber() <= endBar then middlePrice + (topPrice - middlePrice) * (BarNumber() - middleBar) / (endBar - middleBar) else Double.NaN;
20 | Triangle2B.SetPaintingStrategy(PaintingStrategy.Line);
21 | Triangle2B.SetDefaultColor(color.green);
22 | Triangle2B.SetLineWeight(5);
23 |
24 | addcloud(Triangle2B, BottomLine, color.magenta, color.magenta);
25 | addcloud(Triangle2A, BottomLine, color.magenta, color.magenta);
26 |
27 | #def startBar = HighestAll(BarNumber()) - 30;
28 | #def endBar = HighestAll(BarNumber()) - 10;
29 | def bottomPrice2 = 411;
30 | def topPrice2 = 414;
31 |
32 | # Draw horizontal line (base of the triangle)
33 | plot BottomLine2 = if BarNumber() >= startBar and BarNumber() <= endBar then bottomPrice2 else Double.NaN;
34 | BottomLine2.SetPaintingStrategy(PaintingStrategy.Line);
35 | BottomLine2.SetDefaultColor(color.green);
36 | BottomLine2.SetLineWeight(5);
37 |
38 | # Draw inclined lines (sides of the triangle)
39 | #def middleBar = (startBar + endBar) / 2;
40 | plot LeftSide = if BarNumber() >= startBar and BarNumber() <= middleBar then bottomPrice2 + (topPrice2 - bottomPrice2) * (BarNumber() - startBar) / (middleBar - startBar) else Double.NaN;
41 | LeftSide.SetPaintingStrategy(PaintingStrategy.Line);
42 | LeftSide.SetDefaultColor(color.green);
43 | LeftSide.SetLineWeight(5);
44 |
45 | plot RightSide = if BarNumber() >= middleBar and BarNumber() <= endBar then topPrice2 - (topPrice2 - bottomPrice2) * (BarNumber() - middleBar) / (endBar - middleBar) else Double.NaN;
46 | RightSide.SetPaintingStrategy(PaintingStrategy.Line);
47 | RightSide.SetDefaultColor(color.green);
48 | RightSide.SetLineWeight(5);
49 |
50 | #def RightSide = if BarNumber() >= middleBar and BarNumber() <= endBar then topPrice2 - (topPrice2 - bottomPrice2) * (BarNumber() - middleBar) / (endBar - middleBar) else Double.NaN;
51 |
52 | addcloud(RightSide, BottomLine2, color.magenta, color.magenta);
53 | addcloud(LeftSide, BottomLine2, color.magenta, color.magenta);
54 |
--------------------------------------------------------------------------------
/shapes_and_art/triangle.ts:
--------------------------------------------------------------------------------
1 | def startBar = HighestAll(BarNumber()) - 30;
2 | def endBar = HighestAll(BarNumber()) - 10;
3 | def bottomPrice = 410;
4 | def topPrice = 413;
5 |
6 | # Draw horizontal line (base of the triangle)
7 | plot BottomLine = if BarNumber() >= startBar and BarNumber() <= endBar then bottomPrice else Double.NaN;
8 | BottomLine.SetPaintingStrategy(PaintingStrategy.Line);
9 | BottomLine.SetDefaultColor(color.green);
10 | BottomLine.SetLineWeight(5);
11 |
12 | # Draw inclined lines (sides of the triangle)
13 | def middleBar = (startBar + endBar) / 2;
14 | plot LeftSide = if BarNumber() >= startBar and BarNumber() <= middleBar then bottomPrice + (topPrice - bottomPrice) * (BarNumber() - startBar) / (middleBar - startBar) else Double.NaN;
15 | LeftSide.SetPaintingStrategy(PaintingStrategy.Line);
16 | LeftSide.SetDefaultColor(color.green);
17 | LeftSide.SetLineWeight(5);
18 |
19 | plot RightSide = if BarNumber() >= middleBar and BarNumber() <= endBar then topPrice - (topPrice - bottomPrice) * (BarNumber() - middleBar) / (endBar - middleBar) else Double.NaN;
20 | RightSide.SetPaintingStrategy(PaintingStrategy.Line);
21 | RightSide.SetDefaultColor(color.green);
22 | RightSide.SetLineWeight(5);
23 |
--------------------------------------------------------------------------------
/tastylive_intern/README.md:
--------------------------------------------------------------------------------
1 | # Collaborations with JiaJun
2 |
3 | ## Automatically monitor near the money strikes for multiple expirations
4 |
5 | 
6 |
7 | ### To hide the underlying stock chart and only view option plots:
8 | ```
9 | Uncheck "Show Price Subgraph"
10 | ```
11 | 
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/tastylive_intern/ntm_strikes_multiple_expirations:
--------------------------------------------------------------------------------
1 | declare lower;
2 | declare once_per_bar;
3 |
4 | def today = GetYYYYMMDD() + 1;
5 |
6 | plot ATMPutPrice = close(GetATMOption(GetSymbol(), today, OptionClass.PUT));
7 | ATMPutPrice.SetDefaultColor(Color.Red);
8 | ATMPutPrice.SetLineWeight(2);
9 | addlabel(1, "atm_put_option: " + (getATMOption(GetSymbol(), today, OptionClass.PUT)),color.red);
10 |
11 | plot ITMPutPrice = close(GetNextITMOption(GetATMOption(GetSymbol(), today, OptionClass.PUT)));
12 | ITMPutPrice.SetDefaultColor(Color.dark_red);
13 | ITMPutPrice.SetLineWeight(2);
14 | addlabel(1, "itm_put_option: " + (GetNextITMOption(getATMOption(GetSymbol(), today, OptionClass.PUT))),color.dark_red);
15 |
16 | plot OTMPutPrice = close(GetNextOTMOption(GetATMOption(GetSymbol(), today, OptionClass.PUT)));
17 | OTMPutPrice.SetDefaultColor(Color.light_red);
18 | OTMPutPrice.SetLineWeight(2);
19 | addlabel(1, "otm_put_option: " + (GetNextOTMOption(getATMOption(GetSymbol(), today, OptionClass.PUT))),color.light_red);
20 |
21 | plot ATMNextExpPutPrice = close(GetNextExpirationOption(GetATMOption(GetSymbol(), today, OptionClass.PUT)));
22 | ATMNextExpPutPrice.SetDefaultcolor(color.orange);
23 | ATMNextExpPutPrice.SetLineWeight(2);
24 | addlabel(1, "atm_next_exp_put_option: " + (GetNextExpirationOption(getATMOption(GetSymbol(), today, OptionClass.PUT))), color.orange);
25 |
26 | plot ITMNextExpPutPrice = close(GetNextExpirationOption(GetNextITMOption(GetATMOption(GetSymbol(), today, OptionClass.PUT))));
27 | ITMNextExpPutPrice.SetDefaultcolor(color.light_orange);
28 | ITMNextExpPutPrice.SetLineWeight(2);
29 | addlabel(1, "itm_next_exp_put_option: " + (GetNextExpirationOption(GetNextITMOption(getATMOption(GetSymbol(), today, OptionClass.PUT)))), color.light_orange);
30 |
31 | plot OTMNextExpPutPrice = close(GetNextExpirationOption(GetNextOTMOption(GetATMOption(GetSymbol(), today, OptionClass.PUT))));
32 | OTMNextExpPutPrice.SetDefaultcolor(color.dark_orange);
33 | OTMNextExpPutPrice.SetLineWeight(2);
34 | addlabel(1, "otm_next_exp_put_option: " + (GetNextExpirationOption(GetNextOTMOption(getATMOption(GetSymbol(), today, OptionClass.PUT)))), color.dark_orange);
35 |
36 |
37 |
38 | plot ATMCallPrice = close(GetATMOption(GetSymbol(), today, OptionClass.CALL));
39 | ATMCallPrice.SetDefaultColor(Color.Green);
40 | ATMCallPrice.SetLineWeight(4);
41 | addlabel(1, "atm_call_option: " + (getATMOption(GetSymbol(), today, OptionClass.CALL)), color.green);
42 |
43 | plot ITMCallPrice = close(GetNextITMOption(GetATMOption(GetSymbol(), today, OptionClass.CALL)));
44 | ITMCallPrice.SetDefaultColor(Color.dark_green);
45 | ITMCallPrice.SetLineWeight(2);
46 | addlabel(1, "itm_call_option: " + (GetNextITMOption(getATMOption(GetSymbol(), today, OptionClass.CALL))),color.dark_green);
47 |
48 | plot OTMCallPrice = close(GetNextOTMOption(GetATMOption(GetSymbol(), today, OptionClass.CALL)));
49 | OTMCallPrice.SetDefaultColor(Color.light_green);
50 | OTMCallPrice.SetLineWeight(2);
51 | addlabel(1, "otm_call_option: " + (GetNextOTMOption(getATMOption(GetSymbol(), today, OptionClass.CALL))),color.light_green);
52 |
53 | plot ATMNextExpCallPrice = close(GetNextExpirationOption(GetATMOption(GetSymbol(), today, OptionClass.CALL)));
54 | ATMNextExpCallPrice.SetDefaultColor(Color.blue);
55 | ATMNextExpCallPrice.SetLineWeight(4);
56 | addlabel(1, "atm_next_exp_call_option: " + (GetNextExpirationOption(getATMOption(GetSymbol(), today, OptionClass.CALL))), color.blue);
57 |
58 | plot ITMNextExpCallPrice = close(GetNextExpirationOption(GetNextITMOption(GetATMOption(GetSymbol(), today, OptionClass.CALL))));
59 | ITMNextExpCallPrice.SetDefaultColor(Color.cyan);
60 | ITMNextExpCallPrice.SetLineWeight(2);
61 | addlabel(1, "itm_next_exp_call_option: " + (GetNextExpirationOption(GetNextITMOption(getATMOption(GetSymbol(), today, OptionClass.CALL)))), color.cyan);
62 |
63 | plot OTMNextExpCallPrice = close(GetNextExpirationOption(GetNextOTMOption(GetATMOption(GetSymbol(), today, OptionClass.CALL))));
64 | OTMNextExpCallPrice.SetDefaultColor(Color.plum);
65 | OTMNextExpCallPrice.SetLineWeight(2);
66 | addlabel(1, "otm_next_exp_call_option: " + (GetNextExpirationOption(GetNextOTMOption(getATMOption(GetSymbol(), today, OptionClass.CALL)))), color.plum);
67 |
--------------------------------------------------------------------------------
/unusual_options_new/README.md:
--------------------------------------------------------------------------------
1 | ## 🚀 This plots unusual options live. *** Updated Feb 9, 2024
2 |
3 | Category: Option Volume
4 |
5 | *** The default setting only shows 10 strikes. Adjust the "Strikes" setting to see more than 10 strikes.
6 |
7 | 
8 |
9 | ## /ES Version. Automatically selects 0dte contract
10 | 
11 |
12 |
13 | New Features:
14 | 1. Set number of strikes to view
15 | 2. Ability to manually set expiration date
16 | 3. Should run much faster
17 |
18 | > Chart requirements for optimal use:
19 | ```bash
20 |
21 | Time frame: 1 Day
22 |
23 | Aggregation Period: 1 Minute
24 |
25 | ```
26 |
27 |
28 |
29 |
30 | > Settings 👷:
31 |
32 | ```bash
33 |
34 | 1. Strike Spacing: 1; (This sets the space between strikes. Ex: Current SPY price is 400. It will monitor calls
35 | and puts at strikes 398, 399, 400, 401 and 402)
36 | 2. Trade Size Dollar: 200000; (This sets the minimum trade size. 1min option volume * price.)
37 | 3. Strikes: 0; (Default is 0. Select up to 20. This will give 40 strikes total)
38 | 4. Roundup: No; (Set this to "Yes" if you want to adjust the range monitored to higher strikes)
39 | 5. Manually Set Expiration = false; (Default this selects current day. Which is good for SPY and QQQ)
40 | A. Set this to true and then set the Expiration in #6.
41 | 6. Expiration_YYMMDD = 230616;
42 |
43 |
44 | ```
45 |
46 |
47 | > 🧪 How this works:
48 |
49 | ```bash
50 |
51 | 1. This takes the 1 min volume of each option strike and multiplies it by the option price.
52 |
53 | 2. If the $ value of the above is greater than $200k then a bubble will appear on the strike line. (Green = Calls. Red = Puts).
54 |
55 | 3. The option expiration date is automatically set to the current day.(Ideal for SPY and QQQ)
56 |
57 | 4. The manual version of these indicators allows you to set a specific expiration date.
58 |
59 | ```
60 |
61 | > 🦖 How to use this(layman description):
62 | ```bash
63 |
64 | 1. Allows you to monitor for unusual option trades.
65 | 2. Gives you the ability to view the flow of options trades.
66 |
67 | Warning: Thinkorswim doesnt let us know if the options are being bought or sold.
68 |
69 | ```
70 |
--------------------------------------------------------------------------------
/unusual_options_new/spy_spx_combo/README.md:
--------------------------------------------------------------------------------
1 | 🚀 This plots unusual options live. *** Decenber 29, 2023
2 |
3 | Category: Option Volume
4 |
5 | Add both inidicators to the same SPY chart. It will display SPX and SPY large option trades.
6 |
7 | 
8 |
9 |
10 | > Chart requirements for optimal use:
11 | ```bash
12 |
13 | Time frame: 1 Day
14 |
15 | Aggregation Period: 1 Minute
16 |
17 | ```
18 |
19 |
20 |
21 |
22 | > Settings 👷:
23 |
24 | ```bash
25 |
26 | 1. Strike Spacing: 1; (This sets the space between strikes. Ex: Current SPY price is 400. It will monitor calls
27 | and puts at strikes 398, 399, 400, 401 and 402)
28 | 2. Trade Size Dollar: 200000; (This sets the minimum trade size. 1min option volume * price.)
29 | 3. Strikes: 4; (Default is 0. Select up to 20. This will give 40 strikes total)
30 |
31 | Optional:
32 | 4. Manually Set Expiration = false; (Default this selects current day. Which is good for SPY and QQQ)
33 | A. Set this to true and then set the Expiration in #6.
34 | 5. Expiration_YYMMDD = 230616;
35 |
36 |
37 | ```
38 |
39 |
40 | > 🧪 How this works:
41 |
42 | ```bash
43 |
44 | 1. This takes the 1 min volume of each option strike and multiplies it by the option price.
45 |
46 | 2. If the SPY option trade $ value is greater than $200k then a bubble will appear on the strike line. (Green = Calls. Red = Puts).
47 |
48 | 3. If the SPX option trade $ value is greater than $500k then a bubble will appear on the strike line. (Cyan = Calls. Orange = Puts).
49 |
50 | 3. The option expiration date is automatically set to the current day.
51 |
52 | 4. The manual version of these indicators allows you to set a specific expiration date.
53 |
54 | ```
55 |
56 | > 🦖 How to use this(layman description):
57 | ```bash
58 |
59 | 1. Allows you to monitor for unusual option trades.
60 | 2. Gives you the ability to view the flow of options trades.
61 |
62 | Warning: Thinkorswim doesnt let us know if the options are being bought or sold.
63 |
64 | ```
65 |
--------------------------------------------------------------------------------
/unusual_options_new/strike_lines_spx_ndx:
--------------------------------------------------------------------------------
1 | # strike_lines_spx_ndx
2 | # Add this w/unusual options spx ndx indicator
3 | # This only adds the strike lines.
4 | # Mar 6, 2025
5 |
6 | input strikeSpacing = 5.0;
7 | input strikes = 10;
8 | input color_choice = {default magenta, cyan, pink, light_gray, yellow, orange, green, gray, beige, white };
9 |
10 | def agg = AggregationPeriod.DAY;
11 | def openlevel = open(period = agg);
12 | def rounding_factor = if strikeSpacing > 1 and strikeSpacing < 25 then -1 else if strikeSpacing > 24 then -2 else 0;
13 | def base_strike = Round(openlevel, rounding_factor);
14 |
15 | plot strike_base = base_strike;
16 | plot strike_plus1 = base_strike + strikeSpacing;
17 | plot strike_plus2 = base_strike + strikeSpacing * 2;
18 | plot strike_plus3 = base_strike + strikeSpacing * 3;
19 | plot strike_plus4 = base_strike + strikeSpacing * 4;
20 | plot strike_plus5 = base_strike + strikeSpacing * 5;
21 | plot strike_plus6 = base_strike + strikeSpacing * 6;
22 | plot strike_plus7 = base_strike + strikeSpacing * 7;
23 | plot strike_plus8 = base_strike + strikeSpacing * 8;
24 | plot strike_plus9 = base_strike + strikeSpacing * 9;
25 | plot strike_plus10 = base_strike + strikeSpacing * 10;
26 | plot strike_plus11 = base_strike + strikeSpacing * 11;
27 | plot strike_plus12 = base_strike + strikeSpacing * 12;
28 | plot strike_plus13 = base_strike + strikeSpacing * 13;
29 | plot strike_plus14 = base_strike + strikeSpacing * 14;
30 | plot strike_plus15 = base_strike + strikeSpacing * 15;
31 | plot strike_plus16 = base_strike + strikeSpacing * 16;
32 | plot strike_plus17 = base_strike + strikeSpacing * 17;
33 | plot strike_plus18 = base_strike + strikeSpacing * 18;
34 | plot strike_plus19 = base_strike + strikeSpacing * 19;
35 | plot strike_plus20 = base_strike + strikeSpacing * 20;
36 | plot strike_plus21 = base_strike + strikeSpacing * 21;
37 |
38 | plot strike_minus1 = base_strike - strikeSpacing;
39 | plot strike_minus2 = base_strike - strikeSpacing * 2;
40 | plot strike_minus3 = base_strike - strikeSpacing * 3;
41 | plot strike_minus4 = base_strike - strikeSpacing * 4;
42 | plot strike_minus5 = base_strike - strikeSpacing * 5;
43 | plot strike_minus6 = base_strike - strikeSpacing * 6;
44 | plot strike_minus7 = base_strike - strikeSpacing * 7;
45 | plot strike_minus8 = base_strike - strikeSpacing * 8;
46 | plot strike_minus9 = base_strike - strikeSpacing * 9;
47 | plot strike_minus10 = base_strike - strikeSpacing * 10;
48 | plot strike_minus11 = base_strike - strikeSpacing * 11;
49 | plot strike_minus12 = base_strike - strikeSpacing * 12;
50 | plot strike_minus13 = base_strike - strikeSpacing * 13;
51 | plot strike_minus14 = base_strike - strikeSpacing * 14;
52 | plot strike_minus15 = base_strike - strikeSpacing * 15;
53 | plot strike_minus16 = base_strike - strikeSpacing * 16;
54 | plot strike_minus17 = base_strike - strikeSpacing * 17;
55 | plot strike_minus18 = base_strike - strikeSpacing * 18;
56 | plot strike_minus19 = base_strike - strikeSpacing * 19;
57 | plot strike_minus20 = base_strike - strikeSpacing * 20;
58 | plot strike_minus21 = base_strike - strikeSpacing * 21;
59 |
60 | strike_base.setDefaultColor(getColor(color_choice));
61 | strike_plus1.SetDefaultColor(getColor(color_choice));
62 | strike_plus2.SetDefaultColor(getColor(color_choice));
63 | strike_plus3.SetDefaultColor(getColor(color_choice));
64 | strike_plus4.SetDefaultColor(getColor(color_choice));
65 | strike_plus5.SetDefaultColor(getColor(color_choice));
66 | strike_plus6.SetDefaultColor(getColor(color_choice));
67 | strike_plus7.SetDefaultColor(getColor(color_choice));
68 | strike_plus8.SetDefaultColor(getColor(color_choice));
69 | strike_plus9.SetDefaultColor(getColor(color_choice));
70 | strike_plus10.SetDefaultColor(getColor(color_choice));
71 | strike_plus11.SetDefaultColor(getColor(color_choice));
72 | strike_plus12.SetDefaultColor(getColor(color_choice));
73 | strike_plus13.SetDefaultColor(getColor(color_choice));
74 | strike_plus14.SetDefaultColor(getColor(color_choice));
75 | strike_plus15.SetDefaultColor(getColor(color_choice));
76 | strike_plus16.SetDefaultColor(getColor(color_choice));
77 | strike_plus17.SetDefaultColor(getColor(color_choice));
78 | strike_plus18.SetDefaultColor(getColor(color_choice));
79 | strike_plus19.SetDefaultColor(getColor(color_choice));
80 | strike_plus20.SetDefaultColor(getColor(color_choice));
81 | strike_plus21.SetDefaultColor(getColor(color_choice));
82 |
83 | strike_minus1.SetDefaultColor(getColor(color_choice));
84 | strike_minus2.SetDefaultColor(getColor(color_choice));
85 | strike_minus3.SetDefaultColor(getColor(color_choice));
86 | strike_minus4.SetDefaultColor(getColor(color_choice));
87 | strike_minus5.SetDefaultColor(getColor(color_choice));
88 | strike_minus6.SetDefaultColor(getColor(color_choice));
89 | strike_minus7.SetDefaultColor(getColor(color_choice));
90 | strike_minus8.SetDefaultColor(getColor(color_choice));
91 | strike_minus9.SetDefaultColor(getColor(color_choice));
92 | strike_minus10.SetDefaultColor(getColor(color_choice));
93 | strike_minus11.SetDefaultColor(getColor(color_choice));
94 | strike_minus12.SetDefaultColor(getColor(color_choice));
95 | strike_minus13.SetDefaultColor(getColor(color_choice));
96 | strike_minus14.SetDefaultColor(getColor(color_choice));
97 | strike_minus15.SetDefaultColor(getColor(color_choice));
98 | strike_minus16.SetDefaultColor(getColor(color_choice));
99 | strike_minus17.SetDefaultColor(getColor(color_choice));
100 | strike_minus18.SetDefaultColor(getColor(color_choice));
101 | strike_minus19.SetDefaultColor(getColor(color_choice));
102 | strike_minus20.SetDefaultColor(getColor(color_choice));
103 | strike_minus21.SetDefaultColor(getColor(color_choice));
104 |
105 | strike_minus1.SetHiding(strikes <= 0);
106 | strike_plus1.SetHiding(strikes <= 0);
107 | strike_minus2.SetHiding(strikes <= 1);
108 | strike_plus2.SetHiding(strikes <= 1);
109 | strike_minus3.SetHiding(strikes <= 2);
110 | strike_plus3.SetHiding(strikes <= 2);
111 | strike_minus4.SetHiding(strikes <= 3);
112 | strike_plus4.SetHiding(strikes <= 3);
113 | strike_minus5.SetHiding(strikes <= 4);
114 | strike_plus5.SetHiding(strikes <= 4);
115 | strike_minus6.SetHiding(strikes <= 5);
116 | strike_plus6.SetHiding(strikes <= 5);
117 | strike_minus7.SetHiding(strikes <= 6);
118 | strike_plus7.SetHiding(strikes <= 6);
119 | strike_minus8.SetHiding(strikes <= 7);
120 | strike_plus8.SetHiding(strikes <= 7);
121 | strike_minus9.SetHiding(strikes <= 8);
122 | strike_plus9.SetHiding(strikes <= 8);
123 | strike_minus10.SetHiding(strikes <= 9);
124 | strike_plus10.SetHiding(strikes <= 9);
125 | strike_minus11.SetHiding(strikes <= 10);
126 | strike_plus11.SetHiding(strikes <= 10);
127 | strike_minus12.SetHiding(strikes <= 11);
128 | strike_plus12.SetHiding(strikes <= 11);
129 | strike_minus13.SetHiding(strikes <= 12);
130 | strike_plus13.SetHiding(strikes <= 12);
131 | strike_minus14.SetHiding(strikes <= 13);
132 | strike_plus14.SetHiding(strikes <= 13);
133 | strike_minus15.SetHiding(strikes <= 14);
134 | strike_plus15.SetHiding(strikes <= 14);
135 | strike_minus16.SetHiding(strikes <= 15);
136 | strike_plus16.SetHiding(strikes <= 15);
137 | strike_minus17.SetHiding(strikes <= 16);
138 | strike_plus17.SetHiding(strikes <= 16);
139 | strike_minus18.SetHiding(strikes <= 17);
140 | strike_plus18.SetHiding(strikes <= 17);
141 | strike_minus19.SetHiding(strikes <= 18);
142 | strike_plus19.SetHiding(strikes <= 18);
143 | strike_minus20.SetHiding(strikes <= 19);
144 | strike_plus20.SetHiding(strikes <= 19);
145 | strike_minus21.SetHiding(strikes <= 20);
146 | strike_plus21.SetHiding(strikes <= 20);
147 |
--------------------------------------------------------------------------------
/unusual_ticks/README.md:
--------------------------------------------------------------------------------
1 | ## 🚀 This plots unusual trades
2 |
3 | Category: Option/Stock/Futures Volume
4 |
5 |
6 | ## Unusual Option Trade
7 | 
8 |
9 |
10 | ## Unusual Stock Trade
11 | 
12 |
13 |
14 |
15 | > Chart requirements for optimal use:
16 | ```bash
17 |
18 | Time Interval: 1 Day
19 | Aggregation Period: 1 Tick
20 |
21 | ```
22 |
23 |
24 |
25 |
26 | > Settings 👷:
27 |
28 | ```bash
29 |
30 | 1. Volume Theshold: 100; (This sets the minimum volume size. 1 tick volume)
31 | 2. Dollar Theshold: 10000; (This sets the minimum trade size. 1 tick volume and tick price)
32 |
33 |
34 |
35 | ```
36 |
37 |
38 | > 🧪 How this works:
39 |
40 | ```bash
41 |
42 | 1. This takes the each tick volume and multiplies it by the price.
43 |
44 | 2. If the $ value of the above is greater than dollar threshold then a bubble will appear. (Green = Potentially Bought. Red = Potentially Sold).
45 |
46 | 3. If the tick volume is greater than volume threshold then a bubble will appear. (Green = Potentially Bought. Red = Potentially Sold).
47 |
48 |
49 | ```
50 |
51 | > 🦖 How to use this(layman description):
52 | ```bash
53 |
54 | 1. Allows you to monitor for unusual trades and we guess if it was bought or sold
55 | 2. If current tick is higher than previous tick = Buy
56 | 3. If current tick is lower than previous tick = Sell
57 |
58 |
59 |
60 | ```
61 |
--------------------------------------------------------------------------------
/unusual_ticks/unusual_ticks_dollar:
--------------------------------------------------------------------------------
1 | # unusual_ticks_dollars
2 | # @2187Nick w/grok3 assisting
3 | # This version we try to not have a flat direction.
4 | # Not sure if this is ideal. It is not bad. Seems to get alot correct
5 | # Mar 6, 2025
6 |
7 | input dollar_threshold = 10000;
8 |
9 | def lastPrice = close;
10 | def prevPrice = close[1];
11 | def priceChange = lastPrice - prevPrice;
12 | def tradeVolume = volume();
13 |
14 | # Track direction with persistence
15 | def isUpNow = priceChange > 0;
16 | def isDownNow = priceChange < 0;
17 | def isFlatNow = priceChange == 0;
18 |
19 | # Carry forward previous direction using a recursive definition
20 | def lastDirection = if isUpNow then 1
21 | else if isDownNow then -1
22 | else if isFlatNow then lastDirection[1]
23 | else 0;
24 | # 1 = UP, -1 = DOWN, 0 = initial/no data
25 |
26 | # Resolve direction (no FLAT)
27 | def isUp = lastDirection > 0;
28 | def isDown = lastDirection < 0;
29 |
30 | # Dollar value bubble
31 | def dollarValue = lastPrice * tradeVolume;
32 | AddChartBubble(dollarValue > dollar_threshold, lastPrice, "$"+round(dollarValue/1000,0) +"K" + "\n" +tradeVolume, if isUp then Color.GREEN
33 | else Color.RED , if isDown then yes else no);
34 |
--------------------------------------------------------------------------------
/unusual_ticks/unusual_ticks_options_dollar:
--------------------------------------------------------------------------------
1 | # unusual_ticks_options_dollar
2 | # @2187Nick w/grok3 assisting
3 | # This version we try to not have a flat direction.
4 | # Not sure if this is ideal. It is not bad. Seems to get alot correct
5 | # Mar 6, 2025
6 |
7 | input dollar_threshold = 10000;
8 |
9 | def lastPrice = close;
10 | def prevPrice = close[1];
11 | def priceChange = lastPrice - prevPrice;
12 | def tradeVolume = volume();
13 |
14 | # Track direction with persistence
15 | def isUpNow = priceChange > 0;
16 | def isDownNow = priceChange < 0;
17 | def isFlatNow = priceChange == 0;
18 |
19 | # Carry forward previous direction using a recursive definition
20 | def lastDirection = if isUpNow then 1
21 | else if isDownNow then -1
22 | else if isFlatNow then lastDirection[1]
23 | else 0;
24 | # 1 = UP, -1 = DOWN, 0 = initial/no data
25 |
26 | # Resolve direction (no FLAT)
27 | def isUp = lastDirection > 0;
28 | def isDown = lastDirection < 0;
29 |
30 | # Dollar value bubble
31 | def dollarValue = lastPrice * tradeVolume * 100;
32 | AddChartBubble(dollarValue > dollar_threshold, lastPrice, "$"+round(dollarValue/1000,0) +"K" + "\n" +tradeVolume, if isUp then Color.GREEN
33 | else Color.RED , if isDown then yes else no);
34 |
--------------------------------------------------------------------------------
/unusual_ticks/unusual_ticks_volume:
--------------------------------------------------------------------------------
1 | # unusual_ticks_volume
2 | # @2187Nick w/grok3 assisting
3 | # This version we try to not have a flat direction.
4 | # Not sure if this is ideal. It is not bad. Seems to get alot correct
5 | # Mar 6, 2025
6 |
7 | input volume_threshold = 10000;
8 |
9 | def lastPrice = close;
10 | def prevPrice = close[1];
11 | def priceChange = lastPrice - prevPrice;
12 | def tradeVolume = volume();
13 |
14 | # Track direction with persistence
15 | def isUpNow = priceChange > 0;
16 | def isDownNow = priceChange < 0;
17 | def isFlatNow = priceChange == 0;
18 |
19 | # Carry forward previous direction using a recursive definition
20 | def lastDirection = if isUpNow then 1
21 | else if isDownNow then -1
22 | else if isFlatNow then lastDirection[1]
23 | else 0;
24 | # 1 = UP, -1 = DOWN, 0 = initial/no data
25 |
26 | # Resolve direction (no FLAT)
27 | def isUp = lastDirection > 0;
28 | def isDown = lastDirection < 0;
29 |
30 | AddChartBubble(tradeVolume > volume_threshold, lastPrice, tradeVolume, if isUp then Color.GREEN
31 | else Color.RED , if isDown then yes else no);
32 |
--------------------------------------------------------------------------------
/vanna/README.md:
--------------------------------------------------------------------------------
1 | # Vanna Exposure (Naive)
2 |
3 | This calculates Vex per 1% move in the underlying volatility. Based on open interest.
4 |
5 | (Currently it only works for option contracts in the current month.)
6 |
7 | The VEX is displayed in millions.
8 |
9 | Vanna Exposure = Open Interest * Contract Size * Vanna * Spot Price * Underlying Volatility
10 |
11 | Total VEX = Call VEX + Put VEX
12 |
13 | 
14 |
15 | To install:
16 | - Click the Trade tab then All Products.
17 | - Enter SPY and press enter.
18 | - Click Layout then Customize.
19 | - Click the scroll icon next to one of the Custom indicators.
20 |
21 | 
22 |
23 | - Give it a name Column name: VEX
24 | - Click thinkScript Editor
25 | - Paste the code. Select Apply and Ok.
26 | - Select the Add Items button. Then Ok and done.
27 |
28 | **** Make sure D (Day) is selected. To the right of the column name.
29 |
30 | 
31 |
32 | ### Vanna Chart Version
33 | 
34 |
--------------------------------------------------------------------------------
/vanna/vanna:
--------------------------------------------------------------------------------
1 | # Vanna V2 Jan 22, 2024
2 | # @2187Nick
3 | # This uses dividend and interest rate.
4 | # Use this on the Options Chain Page
5 |
6 | # Manually set for testing
7 | #def Vol = .12;
8 | #def S = 476;
9 | #t = 20/365;
10 | #strike = 472;
11 | def Vol = imp_volatility(getUnderlyingSymbol());
12 | def S = close(getUnderlyingSymbol());
13 |
14 | #def today = GetYYYYMMDD();
15 | def t = GetDaysToExpiration()/365;
16 | def strike = getStrike();
17 | def r = getInterestRate();
18 | def q = getYield();
19 |
20 | def r_q_Sqr_Vol_2 = (r-q + 0.5 * Sqr(Vol))* t;
21 | def Sqr_IV_2 = Sqr(Vol)*.5 * t;
22 | def Vol_Sqrt_t = Vol * Sqrt(t);
23 | def Sqrt_2pi = 2.5066;
24 | def Vol_Sqrt_t_S = S * Vol_Sqrt_t;
25 | def d1 = (Log(S / strike) + r_q_Sqr_Vol_2) / Vol_Sqrt_t;
26 | def N1d1 = Exp(-.5*Sqr((Log(S / strike) + r_q_Sqr_Vol_2) / Vol_Sqrt_t)) / 2.5066;
27 |
28 | def d2 = d1 - Vol_Sqrt_t;
29 |
30 | def vanna = -exp(-q * t) * N1d1 * (d2/Vol);
31 | addlabel(yes, Round(vanna,2), color.cyan);
32 |
33 | assignBackgroundColor(color.black);
34 |
--------------------------------------------------------------------------------
/vanna/vanna_0div_0Int:
--------------------------------------------------------------------------------
1 | # Vanna Jan 14, 2024
2 | # @2187Nick
3 | # Note: This version uses 0 dividend and 0 interest rate.
4 | # Use this on the Options Chain Page
5 |
6 | # Manually set for testing
7 | #def Vol = .12;
8 | #def S = 476;
9 | #def exp = 240229;
10 | #t = 20/365;
11 | #strike = 472;
12 | def Vol = imp_volatility(getUnderlyingSymbol());
13 | def S = close(getUnderlyingSymbol());
14 |
15 | def t = GetDaysToExpiration()/365;
16 | def strike = getStrike();
17 |
18 | def Sqr_IV_2 = Sqr(Vol)*.5 * t;
19 | def Vol_Sqrt_t = Vol * Sqrt(t);
20 | def Sqrt_2pi = 2.5066;
21 | def Vol_Sqrt_t_S = S * Vol_Sqrt_t;
22 | def d1 = (Log(S / strike) + Sqr_IV_2) / Vol_Sqrt_t;
23 | def N1d1 = Exp(-.5*Sqr((Log(S / strike) + Sqr_IV_2) / Vol_Sqrt_t)) / Sqrt_2pi;
24 | def d2 = d1 - Vol_Sqrt_t;
25 |
26 | def vanna = -N1d1 * (d2/Vol);
27 | addlabel(yes, Round(vanna,2), color.cyan);
28 |
29 | assignBackgroundColor(color.black);
30 |
--------------------------------------------------------------------------------
/vanna/vanna_chart/README.md:
--------------------------------------------------------------------------------
1 | # Working on the Vanna Exposure Calculations. Vanna itself is spot on.
2 |
3 |
4 | # Vanna Exposure (Naive)
5 | 
6 |
7 | This calculates Vanna Exposure per 1% move in volatility. Based on open interest.
8 |
9 | (Currently it only works for option contracts in the current month.)
10 |
11 |
12 | ######
13 | ######
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/vanna/vanna_exposure:
--------------------------------------------------------------------------------
1 | # Vanna Exposure Jan 22, 2024
2 | # @2187Nick
3 | # For Options Chain Page
4 |
5 | #VannaExposure = (callOptionOpenInterest + putOptionOpenInterest) *Vanna*spotPrice*underlyingVolatility
6 | # Plots in millions.
7 |
8 | # Manually set for testing
9 | #def Vol = .12;
10 | #def S = 476;
11 | #t = 20/365;
12 | #strike = 472;
13 | input threshold = 0;
14 | def DateString = GetYYYYMMDD()-20000000+getdaystoexpiration()-1;
15 | def Vol = imp_volatility(getUnderlyingSymbol());
16 | def S = close(getUnderlyingSymbol());
17 |
18 | def r = getInterestRate();
19 | def q = getYield();
20 |
21 | def t = GetDaysToExpiration()/365;
22 | def strike = getStrike();
23 | def r_q_Sqr_Vol_2 = (r-q + 0.5 * Sqr(Vol))* t;
24 | def Sqr_IV_2 = Sqr(Vol)*.5 * t;
25 | def Vol_Sqrt_t = Vol * Sqrt(t);
26 | def Sqrt_2pi = 2.5066;
27 | def Vol_Sqrt_t_S = S * Vol_Sqrt_t;
28 | def d1 = (Log(S / strike) + r_q_Sqr_Vol_2) / Vol_Sqrt_t;
29 | def N1d1 = Exp(-.5*Sqr((Log(S / strike) + r_q_Sqr_Vol_2) / Vol_Sqrt_t)) / 2.5066;
30 |
31 | def d2 = d1 - Vol_Sqrt_t;
32 |
33 | def vanna = -exp(-q * t) * N1d1 * (d2/Vol);
34 |
35 | def VEX = Round((open_interest("."+getUnderlyingSymbol()+ AsPrice(DateString) + "C" + AsPrice(strike),AggregationPeriod.DAY) + open_interest("."+getUnderlyingSymbol()+AsPrice(DateString) + "P" + AsPrice(strike),AggregationPeriod.DAY))* vanna * S * Vol*100/1000000,0);
36 |
37 | # Change in delta per one percent move in IV
38 | # or change in vega per one percent move in underlying
39 | # Vanna is same formula for calls and puts
40 | # Vanna Exposure: Vanna * OI * S * vol
41 |
42 |
43 | addlabel(IsPut() and vex <= -.1, vex, if vex <= (-1*threshold) then color.red else color.light_red);
44 | addlabel(IsPut() and vex >= 0, "", color.black);
45 | addlabel(!IsPut() and vex >= .1, vex, if vex >= threshold then color.green else color.light_green);
46 | addlabel(!IsPut() and vex < 0, "", color.black);
47 | assignBackgroundColor(color.black);
48 |
--------------------------------------------------------------------------------
/vanna/vanna_exposure_spx:
--------------------------------------------------------------------------------
1 | # Vanna Exposure SPX Jan 16, 2024
2 | # @2187Nick
3 | # For Options Chain Page
4 | # Plots in millions.
5 |
6 | #VannaExposure = (callOptionOpenInterest + putOptionOpenInterest) * Vanna*spotPrice*underlyingVolatility
7 |
8 | # Manually set for testing
9 | #def Vol = .12;
10 | #def S = 476;
11 | #def exp = 240229;
12 | #t = 20/365;
13 | #strike = 472;
14 | input symbol = "SPXW";
15 | def agg = AggregationPeriod.DAY;
16 |
17 | input threshold = 0;
18 | def DateString = GetYYYYMMDD()-20000000+getdaystoexpiration()-1;
19 | def Vol = imp_volatility(getUnderlyingSymbol());
20 | def S = close(getUnderlyingSymbol());
21 | def r = getInterestRate();
22 | def q = getYield();
23 | def t = GetDaysToExpiration()/365;
24 | def strike = getStrike();
25 | def r_q_Sqr_Vol_2 = (r-q + 0.5 * Sqr(Vol))* t;
26 | def Sqr_IV_2 = Sqr(Vol)*.5 * t;
27 | def Vol_Sqrt_t = Vol * Sqrt(t);
28 | def Sqrt_2pi = 2.5066;
29 | def Vol_Sqrt_t_S = S * Vol_Sqrt_t;
30 | def d1 = (Log(S / strike) + r_q_Sqr_Vol_2) / Vol_Sqrt_t;
31 | def N1d1 = Exp(-.5*Sqr((Log(S / strike) + r_q_Sqr_Vol_2) / Vol_Sqrt_t)) / 2.5066;
32 |
33 | def d2 = d1 - Vol_Sqrt_t;
34 |
35 | def vanna = -exp(-q * t) * N1d1 * (d2/Vol);
36 |
37 | # Based on 1% move in VIX
38 | def VEX = Round((open_interest("."+symbol+ AsPrice(DateString) + "C" + AsPrice(strike),AggregationPeriod.DAY) + open_interest("."+symbol+AsPrice(DateString) + "P" + AsPrice(strike),AggregationPeriod.DAY))* vanna * S * Vol*100/1000000,0);
39 |
40 | # Change in delta per one percent move in IV
41 | # or change in vega per one percent move in underlying
42 | # Vanna is same formula for calls and puts
43 | # Vanna Exposure: Vanna * OI * S * vol
44 |
45 | addlabel(IsPut() and vex <= -.1, vex, if vex <= (-1*threshold) then color.red else color.light_red);
46 | addlabel(IsPut() and vex >= 0, "", color.black);
47 | addlabel(!IsPut() and vex >= .1, vex, if vex >= threshold then color.green else color.light_green);
48 | addlabel(!IsPut() and vex < 0, "", color.black);
49 | assignBackgroundColor(color.black);
50 |
--------------------------------------------------------------------------------