├── 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 | ![image](https://user-images.githubusercontent.com/75052782/203637160-8b7c4371-7b4f-46ab-aef3-ed830e04e2ec.png) 12 | 13 | 14 | 4. Paste the indicator code and enter a name for the study. Then click ok. 15 | ![image](https://user-images.githubusercontent.com/75052782/203637595-788c6ec2-0cd4-4976-8471-fabef037ea43.png) 16 | 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ThinkScript 2 | 3 | 4 | 5 | 6 |
7 |
8 | 9 | Logo 10 | 11 | 12 |

Indicators and Strategies

13 |

Clicking an image links to the code

14 |

15 |

Finding value in my work?

16 | Buy Me A Coffee 17 |
18 | 19 | 20 |
21 | Table of Contents 22 |
    23 |
  1. 24 | Unusual Options 25 | 31 |
  2. 32 |
  3. 33 | Greeks 34 | 39 |
  4. 40 |
  5. 41 | Open Interest and Option Volume 42 | 46 |
  6. 47 |
  7. Contributors
  8. 48 |
  9. Contact
  10. 49 |
  11. Acknowledgments
  12. 50 |
51 |
52 | 53 | 54 | 55 | 56 | ## Unusual Options 57 | 58 | ### Equities 59 | 60 | Logo 61 | 62 | 63 | ### Futures 64 | 65 | Logo 66 | 67 | 68 | ### SPY-SPX Combo 69 | 70 | Logo 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 | Logo 84 | 85 | 86 | ### Vanna 87 | 88 | Logo 89 | 90 | 91 | ### Charm 92 | 93 | Logo 94 | 95 | 96 | 97 |

(back to top)

98 | 99 | 100 | 101 | 102 | ## Open Interest and Option Volume 103 | 104 | ### Open Interest 105 | 106 | Logo 107 | 108 | 109 | ### Option Volume 110 | 111 | Logo 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 | ![image](https://github.com/2187Nick/thinkscript/assets/75052782/0a8a52b9-c835-4582-a59c-84a66c891a04) 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 | ![image](https://github.com/2187Nick/thinkscript/assets/75052782/d5f08b70-562f-4aef-8669-40ea5524da58) 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 | ![image](https://github.com/2187Nick/thinkscript/assets/75052782/ed16a9c6-db13-4070-9a17-1a39bbcf2f8e) 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 | ![image](https://github.com/2187Nick/thinkscript/assets/75052782/de7605eb-f630-479b-b09e-5acba073ff94) 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 | ![image](https://github.com/user-attachments/assets/a0095032-82a8-4c70-87d1-da0a044c31dd) 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 | ![image](https://github.com/2187Nick/thinkscript/assets/75052782/f10f65f1-8cd4-4dbc-a9e5-1eda8039c3da) 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 | ![image](https://github.com/2187Nick/thinkscript/assets/75052782/d5f08b70-562f-4aef-8669-40ea5524da58) 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 | ![image](https://github.com/2187Nick/thinkscript/assets/75052782/ed16a9c6-db13-4070-9a17-1a39bbcf2f8e) 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 | ![image](https://github.com/2187Nick/thinkscript/assets/75052782/d5ae03c2-86fe-41b0-9a3a-10815b4b2fe5) 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 | ![image](https://github.com/2187Nick/thinkscript/assets/75052782/12cbb105-9158-4b49-beb0-d4ecb3774ba6) 11 | 12 | # Only bubbles Version 13 | ![image](https://github.com/2187Nick/thinkscript/assets/75052782/cb529cc3-8825-4efa-8ded-9fb833c6ebb0) 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 | ![image](https://github.com/2187Nick/thinkscript/assets/75052782/39a0976c-2c02-440c-8dce-be982c46abc8) 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 | ![image](https://github.com/2187Nick/thinkscript/assets/75052782/34d69d2e-e034-4398-9474-0c589d4480d1) 9 | 10 | ### SPX Number 1 GEX Strike on ES Chart 11 | ![image](https://github.com/2187Nick/thinkscript/assets/75052782/c6c25c7e-a78b-4470-96dc-666e639e138a) 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 | ![image](https://github.com/2187Nick/thinkscript/assets/75052782/d3c2d8ce-5d5a-45f8-be58-68824f705cd7) 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 | ![image](https://github.com/2187Nick/thinkscript/assets/75052782/9827478c-9eeb-4a5d-8a73-fb8c4f22bcd2) 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 | ![image](https://github.com/user-attachments/assets/c0b5a45a-6b61-4e8f-9e85-b3b546b4e122) 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 | ![spy_hurst1](https://user-images.githubusercontent.com/75052782/204617147-2ac20707-0721-41fa-a070-24118aca21c0.png) 42 | 43 | # Shift the price graph forward in time by half the length of the average cycle. 44 | 45 | ![spy_hurst3](https://user-images.githubusercontent.com/75052782/204618239-95b0cd04-0cab-4542-85f8-81f9ec80af49.png) 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 | ![image](https://github.com/2187Nick/thinkscript/assets/75052782/42893005-1b6e-46be-bccc-0f33a36d7c91) 3 | 4 | # 5 | ![image](https://github.com/2187Nick/thinkscript/assets/75052782/62cb2d35-4680-4996-9c6b-f1bf288be038) 6 | 7 | 8 | -------------------------------------------------------------------------------- /modular/greeks/README.md: -------------------------------------------------------------------------------- 1 | # Test function for Gamma, Vanna, and Charm 2 | ![image](https://github.com/2187Nick/thinkscript/assets/75052782/424e73f2-531a-4dbe-8830-e78485c501ac) ![image](https://github.com/2187Nick/thinkscript/assets/75052782/407726be-f034-44d3-b085-79acaf576f60) 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 | ![image](https://user-images.githubusercontent.com/75052782/215549096-40627ceb-3cf6-4635-b49c-2b422b92bfa2.png) 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 | ![image](https://github.com/2187Nick/thinkscript/assets/75052782/373c8362-8aaf-4fe9-b451-6eac606c04df) 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 | ![image](https://user-images.githubusercontent.com/75052782/223152669-178be115-0e04-4786-8606-458c47f00edf.png) 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 | ![image](https://user-images.githubusercontent.com/75052782/223157070-59930589-b2fd-4b79-930d-47b31f4318a2.png) 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 | ![image](https://github.com/2187Nick/thinkscript/assets/75052782/3e0d386c-0cae-48a5-b6da-590c24a289c2) 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 | ![image](https://github.com/2187Nick/thinkscript/assets/75052782/ae96a3f2-b4f7-41b4-8dfa-99f3c6e941ff) 7 | 8 | ![image](https://github.com/2187Nick/thinkscript/assets/75052782/2380b5bd-6ea3-4d83-a081-7db17a5bed6e) 9 | 10 | ![image](https://github.com/2187Nick/thinkscript/assets/75052782/335abd7e-1e62-4a48-8aa9-16ee703af40e) 11 | 12 | ![image](https://github.com/2187Nick/thinkscript/assets/75052782/393ec3c4-3391-44c4-b0a5-d39e584853f7) 13 | 14 | ## Emojis 15 | ![image](https://github.com/2187Nick/thinkscript/assets/75052782/08b41bd2-08fd-44ba-8bf0-214e724f21f7) 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 | ![tasty_intern1](https://github.com/user-attachments/assets/af68a7fd-45ab-499a-bfe6-40d8fe983911) 6 | 7 | ### To hide the underlying stock chart and only view option plots: 8 | ``` 9 | Uncheck "Show Price Subgraph" 10 | ``` 11 | ![image](https://github.com/user-attachments/assets/df77b669-6f1d-42f0-9358-a7134b04dde1) 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 | ![2023-03-23-TOS_CHARTS_2](https://user-images.githubusercontent.com/75052782/227285731-0b805b9a-704c-462f-8780-d08926980c08.png) 8 | 9 | ## /ES Version. Automatically selects 0dte contract 10 | ![image](https://github.com/2187Nick/thinkscript/assets/75052782/25fee2da-6c91-4517-befe-bf9862f69233) 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 | ![image](https://github.com/2187Nick/thinkscript/assets/75052782/eb67f131-880a-4533-aa26-91a2575ce3d7) 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 | ![image](https://github.com/user-attachments/assets/b55f8db3-3174-436b-bfec-4a980bb91c5c) 8 | 9 | 10 | ## Unusual Stock Trade 11 | ![image](https://github.com/user-attachments/assets/c07af788-d7ff-4ba5-a87d-d7147fe28a3d) 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 | ![image](https://github.com/revelldd/thinkscript/assets/158004168/7a2857be-f690-46ff-91de-d64e32a60cb3) 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 | ![image](https://github.com/revelldd/thinkscript/assets/158004168/e892bba4-ed2b-4c2b-80f4-57abd071079a) 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 | ![image](https://github.com/revelldd/thinkscript/assets/158004168/352debd1-8eb1-451e-be6d-fd95e6eece6b) 31 | 32 | ### Vanna Chart Version 33 | ![image](https://github.com/2187Nick/thinkscript/assets/75052782/38a6b673-2780-4e1c-a9dd-85299ee37754) 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 | ![image](https://github.com/2187Nick/thinkscript/assets/75052782/b575ac83-16de-4304-b524-b903a7a97093) 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 | --------------------------------------------------------------------------------