SavingFace

Bitcoin Power Law

Feb 9th, 2025
456
1
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 33.09 KB | Cryptocurrency | 1 0
  1.  
  2. // © x77x
  3.  
  4. //@version=5
  5. indicator("77-Power Law", overlay = true)
  6.  
  7. /////////////////////////////////////////////////////////////////MVRV
  8. // Inputs
  9. timeframe = timeframe.isintraday ? "D" : timeframe.period
  10. MC = request.security("GLASSNODE:BTC_MARKETCAP", timeframe, close)
  11. MC_Realised = request.security("COINMETRICS:BTC_MARKETCAPREAL", timeframe, close)
  12. version = 'Z-Score'
  13.  
  14.  
  15. // Standard Deviation
  16. var MCap = array.new<float>()
  17. array.push(MCap, MC)
  18. Stdev = array.stdev(MCap)
  19.  
  20. //MVRV and Range Values
  21. MVRV = version == 'Standard' ? MC/MC_Realised : (MC-MC_Realised)/Stdev
  22.  
  23. lval_s = (1)
  24. hval_s = (3)
  25.  
  26. lval_z = (0)
  27. hval_z = (5)
  28. lvl6 = input(5.5,title = 'MVRV TOP')
  29.  
  30. lval = version == 'Standard' ? lval_s : lval_z
  31. hval = version == 'Standard' ? hval_s : hval_z
  32.  
  33.  
  34. //MVRV Glow
  35. glow = MVRV < lval ? color.rgb(255, 89, 0, 60) : MVRV > lvl6 ? color.rgb(255, 255, 255, 60) : na
  36. plot(close, color=glow, linewidth=10,title = 'MVRV Extreme Glow')
  37.  
  38. ////// Power Law
  39. // Days X-Axis Value
  40. start = time == timestamp(2010, 7, 18, 0, 0) // First BLX Bitcoin Date
  41. days = request.security('BNC:BLX', 'D', ta.barssince(start))
  42. offset = 564 // days between 2009/1/1 and "start"
  43. d = days + offset
  44.  
  45. // Power Law
  46.  
  47. a = input(-16.493, 'Power Law Intercept',group = "Power Law Settings")
  48. b = input(5.688, 'Power Law Slope',group = "Power Law Settings")
  49. e = a + b * math.log10(d)
  50. y = math.pow(10, e)
  51.  
  52. price_power_law = y
  53. // Calculate +350% of the power law result
  54. y_plus_350_percent = y * 4.5
  55.  
  56. // Calculate +250% of the power law result
  57. y_plus_250_percent = y * 3.5
  58.  
  59. // Calculate +150% of the power law result
  60. y_plus_150_percent = y * 2.5
  61.  
  62. // Calculate +60% of the power law result
  63. y_plus_60_percent = y * 1.6
  64.  
  65. // Calculate -30% of the power law result
  66. y_minus_30_percent = y * 0.7
  67.  
  68. // Calculate -60% of the power law result
  69. y_minus_60_percent = y * 0.4
  70.  
  71.  
  72. // Extreme QE lol
  73.  
  74. a2 = -13.36632341
  75. b2 = 5.03
  76. e2 = a2 + b2 * math.log10(d)
  77. y2 = math.pow(10, e2)
  78.  
  79. EXQE_log = y * 8.5
  80. EXQE_price = EXQE_log
  81.  
  82. //////////////////////////////////////////////////////
  83. var int futureBars = 650
  84. decay = 12000
  85.  
  86. ext_BTC_trend = y * 1.709 + decay
  87.  
  88. //ext_t = plot(ext_BTC_trend, color=color.rgb(255, 0, 0), title="PL Extension", linewidth = 1, offset = futureBars,
  89. //show_last = futureBars+1)
  90.  
  91.  
  92. // Label Deltas
  93. delta_powerL = math.round((y / close - 1.0) * 100)
  94. m2 = close < y ? '+' : ''
  95.  
  96. // Plot
  97. //p3 = plot(EXQE_price, color=#ff5a00, title='Extreme QE')
  98. p7 = plot(y_plus_350_percent, color=#ff5a00, title='350%')
  99. p2 = plot(y_plus_250_percent, color=#ff5a00, title='250%')
  100. p5 = plot(y_plus_150_percent, color=#ff5a00, title = '150%')
  101. p6 = plot(y_plus_60_percent, color=#ff5a00, title = '60%')
  102. p1 = plot(y, color=#ff0000, title='Power Law',linewidth = 1)
  103. p9 = plot(y_minus_30_percent, color=color.rgb(54, 58, 69, 50), title='-30')
  104. p4 = plot(y_minus_60_percent, color=#ffebba, title='Support')
  105.  
  106. fill = input(true, 'Plot Power Law Fill?',group = "Power Law Settings")
  107. fill(p5, p7, color=fill ? #b13e001a : na,title = 'Power Law Fill')
  108. fill(p5, p1, color=fill ? #b13e001a : na,title = 'Power Law Fill')
  109. fill(p1, p4, color=fill ? #5d606b33 : na,title = 'Power Law Fill')
  110.  
  111.  
  112. //Power Law Extension
  113. len5 = 1
  114. src5 = close
  115. PL_P_line = ta.ema(src5, len5)
  116.  
  117. // Add a dropdown menu in the settings
  118. selectedOption = input.string(defval="Power Law % Line", title="Select Line/Bar", options=["Power Law % Line", "Clock Price Line", "Colored Bars"],group = "Power Law Settings")
  119.  
  120. // PL Price Line
  121. show_PLprice_line = (selectedOption == "Power Law % Line")
  122.  
  123. PLprice_line = PL_P_line < y_minus_30_percent ? #ff5a00 : PL_P_line < y ? #5d606b : PL_P_line < y_plus_60_percent? #b87333 : PL_P_line < y_plus_150_percent ? #90bff9 : PL_P_line < y_plus_250_percent ? #ffffff : PL_P_line < y_plus_350_percent ? #ffffff : PL_P_line < EXQE_price ? #da00ff : na
  124.  
  125. plot(show_PLprice_line ? PL_P_line : na, title="Power Law Price Line", color=PLprice_line)
  126.  
  127. // Input parameters
  128. startYear = 2010
  129.  
  130. // Define colors and associate them with each segment (1 through 12)
  131. barColors = array.from(#5d606b, // ⏱ 1
  132. #5d606bf0, // ⏱ 2
  133. #ff5a00, // ⏱ 3
  134. #ff5900fc, // ⏱ 4
  135. #5d606bf2, // ⏱ 5
  136. #5d606bfc, // ⏱ 6
  137. #5d606bfa, // ⏱ 7
  138. #5d606bf7, // ⏱ 8
  139. #5d606bf5, // ⏱ 9
  140. #d7c089, // ⏱ 10
  141. #ffebba, // ⏱ 11
  142. #ffffff) // ⏱ 12
  143.  
  144. // Calculate the current year and the number of months passed since the start year
  145. currentYear = year(time)
  146. yearsPassed = currentYear - startYear
  147. monthsPassed = (yearsPassed * 12) + (month(time) - 1)
  148.  
  149. // Determine the current cycle segment (1 to 12)
  150. cycleSegment = monthsPassed % 48 // 4 years = 48 months
  151. currentSegment = math.floor(cycleSegment / 4)
  152.  
  153. // Ensure the currentSegment is within bounds (0 to 11)
  154. currentSegment := math.max(0, math.min(currentSegment, 11))
  155.  
  156. // Get the current color for the cycle segment
  157. currentColor = array.get(barColors, currentSegment)
  158.  
  159. // Show Clock Price Line if selected
  160. show_ClockPrice_line = (selectedOption == "Clock Price Line")
  161. plot(show_ClockPrice_line ? close : na, title='Clock Price Line', color=currentColor, linewidth=1)
  162.  
  163. // Show Colored Bars if selected
  164. show_ColoredBars = (selectedOption == "Colored Bars")
  165. barcolor(show_ColoredBars ? currentColor : na)
  166.  
  167. // Track the previous segment to detect color changes (use int for typing, and assign to na initially)
  168. var int previousSegment = na
  169. colorChanged = (currentSegment != previousSegment)
  170.  
  171.  
  172. // Update previousSegment after processing the current bar
  173. previousSegment := currentSegment
  174.  
  175. // Labels
  176.  
  177. var label lbl1 = na
  178. var label lbl2 = na
  179. var label lbl3 = na
  180. var label lbl4 = na
  181. var label lbl5 = na
  182. var label lbl6 = na
  183. var label lbl7 = na
  184.  
  185. label.delete(lbl1)
  186. label.delete(lbl2)
  187. label.delete(lbl3)
  188. label.delete(lbl4)
  189. label.delete(lbl5)
  190. label.delete(lbl6)
  191. label.delete(lbl7)
  192.  
  193. //PL % Lables
  194. lbl1 := label.new(bar_index, y_plus_350_percent, style=label.style_label_left, text='350% = ' + str.tostring(y_plus_350_percent, '#.##'), textcolor=#ff5a00, color=#363a4503,size =size.small)
  195. lbl2 := label.new(bar_index, y_plus_250_percent, style=label.style_label_left, text='250% = ' + str.tostring(y_plus_250_percent, '#.##'), textcolor=#ff5a00, color=#363a4503,size =size.small)
  196. lbl3 := label.new(bar_index, y_plus_150_percent, style=label.style_label_left, text='150% = ' + str.tostring(y_plus_150_percent, '#.##'), textcolor=#ff5a00, color=#363a4503,size =size.small)
  197. lbl7 := label.new(bar_index, y_plus_60_percent, style=label.style_label_left, text='60% = ' + str.tostring(y_plus_60_percent, '#.##'), textcolor=#ff5a00, color=#363a4503,size =size.small)
  198. lbl4 := label.new(bar_index, y, style=label.style_label_left, text='Power Law = ' + str.tostring(y, '#.##'), textcolor=#ee2132, color=#363a4503,size =size.small)
  199. lbl5 := label.new(bar_index, y_minus_60_percent, style=label.style_label_left, text='Support -60% = ' + str.tostring(y_minus_60_percent, '#.##'), textcolor=#ffebba, color=#363a4503,size =size.small)
  200. //lbl6 := label.new(bar_index, EXQE_price, style=label.style_label_left, text='Extreme QE = ' + str.tostring(EXQE_price, '#.##'), textcolor=#ff5a00, color=#363a4503,size =size.small)
  201.  
  202. /////////////////////////////////////
  203.  
  204. ///////////////////////////////////////////////////////////////// Realized price
  205.  
  206. // Get the timeframe to daily since all indicators are daily
  207. f_resInMinutes() =>
  208. _resInMinutes = timeframe.multiplier * (
  209. timeframe.isseconds ? 1. / 60 :
  210. timeframe.isminutes ? 1. :
  211. timeframe.isdaily ? 60. * 24 :
  212. timeframe.isweekly ? 60. * 24 * 7 :
  213. timeframe.ismonthly ? 60. * 24 * 30.4375 : na)
  214.  
  215. f_resInDays() => f_resInMinutes() / 60 / 24
  216. timeframe_divisor = f_resInDays() // Use when doing moving averages
  217.  
  218. // Inputs
  219. CVDD_extention_slope_factor = 100
  220. CVDD_extention_intercept_factor = 100
  221. CVDD_shift = 120
  222.  
  223. // Query
  224. btc_high = request.security("BTCUSD", "D", high)
  225. btc_low = request.security("BTCUSD", "D", low)
  226. MCR = request.security("COINMETRICS:BTC_MARKETCAPREAL","D",close)
  227. TV = ta.sma(request.security("GLASSNODE:BTC_TOTALVOLUME","D",close), math.round(500 / timeframe_divisor)) //Total Volume of transfer
  228.  
  229. //Calculate CVDD
  230. CVDD = (MCR-TV) / 22000000
  231. CVDD_bottom = CVDD * CVDD_shift/100
  232.  
  233. top_factor_CVDD = -8.1775E-13 * CVDD_extention_slope_factor/100 * time + 1.965805965 * CVDD_extention_intercept_factor/100
  234. top_factor_CVDD := math.pow(10, top_factor_CVDD)
  235.  
  236. // Plot
  237. plot(not na(CVDD) and time > timestamp(2011, 08, 06) ? CVDD_bottom : na, color = #b13e00, title = "Shifted CVDD",display=display.none, linewidth = 1)
  238. plot(not na(CVDD) and time > timestamp(2011, 08, 06) ? CVDD * top_factor_CVDD : na,display=display.none, color = color.rgb(255, 255, 255), title = "CVDD Extension", linewidth = 1)
  239. plot(not na(CVDD) and time > timestamp(2011, 08, 06) ? CVDD : na, color = #b13e00, title = "CVDD",display=display.none, linewidth = 1)
  240.  
  241. bkg_color_above = color.rgb(255, 255, 255, 84)
  242. plotshape(btc_high >= CVDD * top_factor_CVDD, style=shape.diamond, color=color.rgb(255, 255, 255, 80), location=location.abovebar, size=size.tiny, title="CVDD High Highlight")
  243.  
  244.  
  245. ////150 day ema
  246. resolution = 'D'
  247. lowema_short = input.int(150, minval=1, title=' BMSB EMA',group = "BMSB EMA Settings")
  248. is_show_lowma2 = input(true, title='Show BMSB?',group = "BMSB EMA Settings")
  249. ema_short_low = request.security(syminfo.tickerid, resolution, ta.ema(close, lowema_short))
  250. BMSB=is_show_lowma2?ema_short_low:na
  251. PL_color = BMSB < y ? #5d606b : BMSB > y_plus_250_percent ? #da00ff : BMSB > y_plus_150_percent? #ffffff : BMSB > y_plus_60_percent ? #90bff9 : BMSB < y_plus_250_percent ? #b87333 : na
  252.  
  253. plot(BMSB, color=PL_color, linewidth=2, title="BMSB")
  254.  
  255. ///////////////////Halvings
  256.  
  257.  
  258. showLabels = input(defval=true, title="Show Halving labels",group = "Halving Settings")
  259.  
  260. // New color inputs for lines and labels
  261. lineColor = input(defval=#b13e00, title="Line Color",group = "Halving Settings")
  262. labelBackgroundColor = input(defval=#b13e00, title="Label Background Color",group = "Halving Settings")
  263. labelTextColor = input(defval=color.rgb(0, 0, 0), title="Label Text Color",group = "Halving Settings")
  264.  
  265. // Arrays for halving dates and descriptions
  266. var halvingDates = array.new_int(4)
  267. var halvingTexts = array.new_string(4)
  268.  
  269. // Populate arrays with halving information
  270. array.set(halvingDates, 0, timestamp('GMT', 2012, 11, 28))
  271. array.set(halvingDates, 1, timestamp('GMT', 2016, 7, 9))
  272. array.set(halvingDates, 2, timestamp('GMT', 2020, 5, 11))
  273. array.set(halvingDates, 3, timestamp('GMT', 2024, 4, 19))
  274.  
  275. array.set(halvingTexts, 0, "⛏ 1st Halving\n - Nov 28, 2012")
  276. array.set(halvingTexts, 1, "⛏ 2nd Halving\n - Jul 9, 2016")
  277. array.set(halvingTexts, 2, "⛏ 3rd Halving\n - May 11, 2020")
  278. array.set(halvingTexts, 3, "⛏ 4th Halving\n - Apr 19, 2024")
  279.  
  280. // Adjusted drawHalvingEvent function to use the input colors
  281. drawHalvingEvent(date, labelText) =>
  282. if (time[1] < date and time >= date)
  283. line.new(x1=bar_index, y1=low, x2=bar_index, y2=high, xloc=xloc.bar_index, extend=extend.both, color=lineColor)
  284. if showLabels
  285. label.new(bar_index[1], y_minus_60_percent, text=labelText, style=label.style_label_upper_left, color=labelBackgroundColor, textcolor=labelTextColor, textalign=text.align_left,size =size.small)
  286.  
  287. // Loop through each halving event and draw it
  288. for i = 0 to array.size(halvingDates) - 1
  289. drawHalvingEvent(array.get(halvingDates, i), array.get(halvingTexts, i))
  290.  
  291.  
  292. //////////////////////////////
  293.  
  294. // NOTES
  295.  
  296. // The "Spring" is the confirmed Miner capitulation period:
  297. // - The 1st "gray" circle is the start of Capitulation (1 month Hash Rate crosses UNDER 2 month Hash Rate)
  298. // - Last "green" circle is the end of Capitulation (1 month Hash Rate crosses OVER 2 month Hash Rate)
  299. // - The "greener" the spring gets (up until blue) represents Hash Rate recovery (it is increasing)
  300. // - The "blue" circle is the first instance of positive momentum following recovery of Hash Rate (1m HR > 2m HR). This is historically a rewarding place to buy with limited downside.
  301.  
  302. // INPUTS
  303.  
  304. type = 'Oscillator'
  305. len_s = 30
  306. len_l = 60
  307. signals = input(true, 'Plot Signals',group = "HASHRATE Signal")
  308. source = 'INTOTHEBLOCK:BTC_HASHRATE'
  309.  
  310. ////////////////// HASH RATE MA
  311.  
  312. // HR on TV only has "yesterday's" value --> use "lookahead_on" when running live (on current bar), to pull forward yesterdays data
  313. live_HR_raw = request.security(source, 'D', close, gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_on)
  314. live_HR_short = request.security(source, 'D', ta.sma(close, len_s), gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_on)
  315. live_HR_long = request.security(source, 'D', ta.sma(close, len_l), gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_on)
  316.  
  317. hist_HR_raw = request.security(source, 'D', close, gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_off)
  318. hist_HR_short = request.security(source, 'D', ta.sma(close, len_s), gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_off)
  319. hist_HR_long = request.security(source, 'D', ta.sma(close, len_l), gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_off)
  320.  
  321. daily_s10 = request.security(syminfo.tickerid, 'D', ta.sma(close, 10), gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_off)
  322. daily_s20 = request.security(syminfo.tickerid, 'D', ta.sma(close, 20), gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_off)
  323.  
  324.  
  325. // DAILY TIMEFRAME MGMT
  326.  
  327. is_newbar(res) =>
  328. t = time(res) // res calculated below \/
  329. ta.change(t) != 0 ? true : false
  330.  
  331. // Check how many bars are in our upper (otf) timeframe
  332. since_new_bar = ta.barssince(is_newbar('D')) //1-360 for minutes, D = Daily, W = Weekly, M = Monthly
  333. D_total_bars = int(na)
  334. D_total_bars := since_new_bar == 0 ? since_new_bar[1] : D_total_bars[1] // calculates the total number of current time frame bars in the OTF
  335.  
  336. // Hash INDICATOR
  337.  
  338. HR_short = float(na)
  339. HR_long = float(na)
  340. HR_raw = float(na)
  341. s10 = float(na)
  342. s20 = float(na)
  343.  
  344. HR_short := barstate.isrealtime ? live_HR_short : hist_HR_short
  345. HR_long := barstate.isrealtime ? live_HR_long : hist_HR_long
  346. HR_raw := barstate.isrealtime ? live_HR_raw : hist_HR_raw
  347.  
  348. s10 := barstate.isrealtime ? since_new_bar == D_total_bars ? daily_s10 : s10[1] : daily_s10
  349. s20 := barstate.isrealtime ? since_new_bar == D_total_bars ? daily_s20 : s20[1] : daily_s20
  350.  
  351. capitulation = ta.crossunder(HR_short, HR_long)
  352. miner_capitulation = HR_short < HR_long
  353. recovering = HR_short > HR_short[1] and HR_short > HR_short[2] and HR_short > HR_short[3] and miner_capitulation
  354. recovering2 = ta.crossover(HR_short, HR_long)
  355.  
  356. // HASH BOTTOM + PA SIGNAL
  357.  
  358. buy = false
  359. buy := ta.crossover(s10, s20) and ta.barssince(recovering2) < ta.barssince(ta.crossunder(s10, s20)) and ta.barssince(recovering2) < ta.barssince(capitulation) or s10 > s20 and ta.crossover(HR_short, HR_long)
  360.  
  361. buy_plot = buy
  362.  
  363. // PLOT - SIGNALS
  364.  
  365. // Clear previous labels to avoid overlap on the first bar
  366. if bar_index == 0
  367. var label[] all_labels = array.new_label()
  368.  
  369. // Persistent flag: true if a capitulation label is currently active (has been shown)
  370. // and not yet reset by a hash buy signal.
  371. var bool capitulationShown = false
  372.  
  373. if signals
  374. // Plot the hash buy signal label when its condition is met (label.new call is on one line)
  375. if buy_plot
  376. label.new(bar_index, EXQE_price, text="Hash Buy", style=label.style_circle, color=color.new(#ffebba7e, 90), textcolor=color.new(#ffebba7e, 90), size=size.tiny)
  377. capitulationShown := false
  378. // Plot the capitulation signal label only if it hasn't been shown since the last hash buy signal (label.new call is on one line)
  379. if capitulation and not capitulationShown
  380. label.new(bar_index, EXQE_price, text="Capitulation", style=label.style_circle, color=#ff59001b, textcolor=#ff59001b, size=size.tiny)
  381. capitulationShown := true
  382.  
  383. //////////// Yearly returns
  384.  
  385.  
  386. // Inputs
  387. //{
  388. show_separator = input.bool (defval=false, title="New Year Line", group='New Year Settings')
  389. color_separator = input.color (defval=#ffffff, title="Line Color", group='New Year Settings')
  390.  
  391.  
  392.  
  393. input_table_enable = input.bool (defval=true , title="Enable Table", group=" Yearly eturns Table Settings")
  394. input_table_size = input.string(defval="Small" , title="Size" , group="Yearly Returns Table Settings", options=["Auto", "Tiny", "Small", "Normal", "Large", "Huge"])
  395. input_table_position = input.string(defval="Bottom Right", title="Position" , group="Yearly Returns Table Settings", options=["Top Left", "Top Right", "Bottom Left", "Bottom Right"])
  396. input_table_direction = input.string(defval="Horizontal" , title="Direction" , group="Table Settings", options=["Vertical", "Horizontal"])
  397. input_sort_order = input.string(defval="Ascending", title="Sort By" , group="Yearly Returns Table Settings", options=["Ascending", "Descending"])
  398. //}
  399.  
  400.  
  401. table_size = switch input_table_size
  402. "Auto" => size.auto
  403. "Tiny" => size.tiny
  404. "Small" => size.small
  405. "Normal" => size.normal
  406. "Large" => size.large
  407. "Huge" => size.huge
  408.  
  409. table_position = switch input_table_position
  410. "Top Left" => position.top_left
  411. "Top Right" => position.top_right
  412. "Bottom Left" => position.bottom_left
  413. "Bottom Right" => position.bottom_right
  414.  
  415.  
  416. GetLineStyle (line_style) =>
  417. switch line_style
  418. "Dashed" => hline.style_dashed
  419. "Dotted" => hline.style_dotted
  420. "Solid" => hline.style_solid
  421.  
  422. GetOpen (timeframe) => request.security(syminfo.tickerid, timeframe, close[1], lookahead=barmerge.lookahead_on)
  423.  
  424.  
  425. var float[] yearly_returns = array.new_float(0)
  426. var int[] year_array = array.new_int(0)
  427. var float yearly_openPrice = 0.0
  428. var table returns_table = table(na)
  429.  
  430.  
  431. //////////////// Plot Yearly return
  432. //{
  433. // Check if it is a new year
  434. bool isNewYear = year(time) != year(time[1])
  435.  
  436. // Get the Yearly Opening price
  437. yearly_openPrice := GetOpen('12M')
  438.  
  439. // Calculate the yearly return
  440. float yearly_return = 100 * (close - yearly_openPrice) / yearly_openPrice
  441.  
  442. color plot_color = yearly_return > 0 ? #ffebba : #b13e00
  443.  
  444.  
  445. // Show Background color
  446. color separator_col = show_separator and isNewYear ? color_separator : na
  447. bgcolor(separator_col, title="Year separator", editable=false)
  448. //}
  449.  
  450.  
  451. // Plot current and previous yearly return labels
  452. label past_return_label = na
  453. label current_return_label = na
  454.  
  455. if (year(time) != year(time[1]))
  456. // Only push non-NaN values to array
  457. bool isNaN = na(yearly_return[1])
  458. if (not isNaN)
  459. // Concatenate yearly return with BTC clock segment
  460. string combinedLabelText = str.tostring(yearly_return[1], format.percent) + " ⏱: " + str.tostring(currentSegment) + ""
  461.  
  462. past_return_label := label.new(bar_index[1], y_minus_60_percent, combinedLabelText, textcolor=#101010, color=plot_color[1], style=label.style_label_up, textalign=text.align_left, size=size.small)
  463.  
  464. array.push(yearly_returns, yearly_return[1])
  465. array.push(year_array, year - 1)
  466.  
  467. label.delete(past_return_label[1])
  468.  
  469. // Plot current year returns
  470. if (barstate.islast)
  471. //current_return_label := label.new(bar_index, y4, str.tostring(yearly_return, format.percent), textcolor=#000000, color=plot_color, style=label.style_label_lower_left, textalign=text.align_left, size=size.small)
  472.  
  473. array.push(yearly_returns, yearly_return)
  474. array.push(year_array , year )
  475.  
  476. label.delete(current_return_label[1])
  477. //}
  478.  
  479. // Function to insert cells into the table with black text color
  480. InsertCell(id, int col_index, int row_index, string _text, color _colour=#aaaaaa) =>
  481. table.cell(table_id=id, column=col_index, row=row_index, text=_text, text_size=table_size, bgcolor=_colour, text_color=#000000)
  482.  
  483. // Set the minimum year for filtering
  484. minYear = 2011
  485.  
  486. // Check if it's the last bar and the table should be shown
  487. if (barstate.islast and input_table_enable and array.size(yearly_returns) > 0)
  488.  
  489. int _header_size = 2
  490. int _returns_size = array.size(yearly_returns) + 1 // +1 to add the BTC Time row
  491.  
  492. _table = switch input_table_direction
  493. "Vertical" => array.from(_header_size , _returns_size + 1) // Add 1 to rows size for BTC Time row
  494. "Horizontal" => array.from(_returns_size + 1, _header_size) // Add 1 to columns size for BTC Time column
  495.  
  496. int _column_size = array.get(_table, 0)
  497. int _rows_size = array.get(_table, 1)
  498.  
  499. returns_table := table.new(table_position, columns=_column_size, rows=_rows_size, border_width=1)
  500.  
  501. // Insert headers to table
  502. if input_table_direction == "Vertical"
  503. InsertCell(returns_table, 0, 0, "Year")
  504. InsertCell(returns_table, 1, 0, "% Returns")
  505. InsertCell(returns_table, 0, _rows_size - 1, "BTC Time") // Add BTC Time label
  506. else
  507. InsertCell(returns_table, 0, 0, "Year")
  508. InsertCell(returns_table, 0, 1, "% Returns")
  509. InsertCell(returns_table, _column_size - 1, 0, "BTC Time") // Add BTC Time label
  510.  
  511. // Insert data to table for years 2014 and later
  512. for i=0 to array.size(yearly_returns) - 1
  513. year_value = array.get(year_array, i)
  514.  
  515. // Only process if the year is 2014 or later
  516. if year_value >= minYear
  517. color col = array.get(yearly_returns, i) > 0 ? #ffebba : #b13e00
  518.  
  519. string _year = str.tostring(year_value)
  520. string _returns = str.tostring(array.get(yearly_returns, i), format.percent)
  521.  
  522. if input_table_direction == "Vertical"
  523. int _row_pos = input_sort_order == "Descending" ? _rows_size - i - 2 : i + 1 // Adjust to leave space for BTC Time row
  524. InsertCell(returns_table, 0 ,_row_pos, _year)
  525. InsertCell(returns_table, 1 ,_row_pos, _returns, _colour=col)
  526. else
  527. int _column_pos = input_sort_order == "Descending" ? _column_size - i - 2 : i + 1 // Adjust to leave space for BTC Time column
  528. InsertCell(returns_table, _column_pos, 0, _year)
  529. InsertCell(returns_table, _column_pos, 1, _returns, _colour=col)
  530.  
  531. // Insert BTC Time into the table
  532. string btcTimeText = str.tostring(currentSegment) // BTC time info (cycle segment)
  533.  
  534. if input_table_direction == "Vertical"
  535. InsertCell(returns_table, 1, _rows_size - 1, btcTimeText, _colour=#aaaaaa) // Insert in last row
  536. else
  537. InsertCell(returns_table, _column_size - 1, 1, btcTimeText, _colour=#aaaaaa) // Insert in last column
  538.  
  539. ////////////////////
  540.  
  541.  
  542. var yearLabels = array.new_string(100)
  543.  
  544. // Populate the year labels array
  545. array.set(yearLabels, 0, "Bull Year 1 In ")
  546. array.set(yearLabels, 1, "Bull Year 2 In ")
  547. array.set(yearLabels, 2, "Bull Year 3 IN ")
  548. array.set(yearLabels, 3, "Bear IN ")
  549.  
  550. // Function to calculate and format the countdown to the next year
  551. getYearCountdown() =>
  552. var nextYear = year(timenow) + 1
  553. var nextYearLabel = array.get(yearLabels, nextYear - 2023)
  554. var nextYearTimestamp = timestamp(nextYear, 1, 1, 0, 0, 0)
  555. var secondsLeft = math.abs(nextYearTimestamp - timenow) / 1000
  556. var days = math.floor(secondsLeft / 86400)
  557. str.format(" {0}⏱:{1}d", nextYearLabel, days)
  558.  
  559. // Display the label for the current year
  560. if barstate.islast
  561. var labelText = getYearCountdown()
  562. var label = label.new(bar_index, y_minus_60_percent, text=labelText, style=label.style_label_upper_left, color=color.rgb(0, 0, 0, 99), textcolor=#ffebba, textalign=text.align_left, size=size.small, xloc=xloc.bar_index)
  563. label.set_text(label, labelText)
  564. //////////////////////////////////////////////////////
  565.  
  566. //ALERTS
  567.  
  568. alertcondition(capitulation, title='Alert - Capitulation')
  569. alertcondition(buy and not buy[1], title='Alert - Hash Buy')
  570. //alertcondition(buy2, title='Alert - Call Spike')
  571. alertcondition(btc_high >= CVDD * top_factor_CVDD, title='Alert - CVDD Diamond')
  572. alertcondition(MVRV < lval?MVRV > lvl6:na, title='Alert - MVRV Extreme')
  573.  
  574.  
  575. ///////////////////////////////////////// Power Law Projection ////////////////////////////////////////////////////
  576.  
  577. // Project into the future Power Law
  578. var int future_days = 500
  579. future_y = array.new_float(future_days)
  580. future_y_minus_60 = array.new_float(future_days)
  581. future_y_plus_60 = array.new_float(future_days)
  582. future_y_plus_150 = array.new_float(future_days) // New array for +150% deviation
  583. future_y_plus_250 = array.new_float(future_days) // New array for +250% deviation
  584. future_y_plus_350 = array.new_float(future_days) // New array for +350% deviation
  585.  
  586. // Precompute future values for power law and deviations
  587. for i = 0 to future_days - 1
  588. future_d = d + i
  589. future_e = a + b * math.log10(future_d)
  590. power_law_value = math.pow(10, future_e)
  591.  
  592. // Store original power law projection
  593. array.set(future_y, i, power_law_value)
  594.  
  595. // Calculate -60% of the power law result
  596. power_law_value_minus_60 = power_law_value * 0.4
  597. array.set(future_y_minus_60, i, power_law_value_minus_60)
  598.  
  599. // Calculate +60% of the power law result
  600. power_law_value_plus_60 = power_law_value * 1.6
  601. array.set(future_y_plus_60, i, power_law_value_plus_60)
  602.  
  603. // Calculate +150% of the power law result
  604. power_law_value_plus_150 = power_law_value * 2.5
  605. array.set(future_y_plus_150, i, power_law_value_plus_150)
  606.  
  607. // Calculate +250% of the power law result
  608. power_law_value_plus_250 = power_law_value * 3.5
  609. array.set(future_y_plus_250, i, power_law_value_plus_250)
  610.  
  611. // Calculate +350% of the power law result
  612. power_law_value_plus_350 = power_law_value * 4.5
  613. array.set(future_y_plus_350, i, power_law_value_plus_350)
  614.  
  615. // Plot future projection for power law
  616. var line future_line = na
  617. if bar_index == last_bar_index
  618. future_line := line.new(x1=bar_index, y1=y, x2=bar_index + future_days, y2=array.get(future_y, future_days - 1), color=#ff000033, width=2)
  619.  
  620. // Plot future projection for -60% power law
  621. var line future_line_minus_60 = na
  622. if bar_index == last_bar_index
  623. future_line_minus_60 := line.new(x1=bar_index, y1=y * 0.4, x2=bar_index + future_days, y2=array.get(future_y_minus_60, future_days - 1), color=#ffebba78, width=2)
  624.  
  625. // Plot future projection for +60% power law
  626. var line future_line_plus_60 = na
  627. if bar_index == last_bar_index
  628. future_line_plus_60 := line.new(x1=bar_index, y1=y * 1.6, x2=bar_index + future_days, y2=array.get(future_y_plus_60, future_days - 1), color=#ff590033, width=2)
  629.  
  630. // Plot future projection for +150% power law
  631. var line future_line_plus_150 = na
  632. if bar_index == last_bar_index
  633. future_line_plus_150 := line.new(x1=bar_index, y1=y * 2.5, x2=bar_index + future_days, y2=array.get(future_y_plus_150, future_days - 1), color=#ff590033, width=2)
  634.  
  635. // Plot future projection for +250% power law
  636. var line future_line_plus_250 = na
  637. if bar_index == last_bar_index
  638. future_line_plus_250 := line.new(x1=bar_index, y1=y * 3.5, x2=bar_index + future_days, y2=array.get(future_y_plus_250, future_days - 1), color=#ff590033, width=2)
  639.  
  640. // Plot future projection for +350% power law
  641. var line future_line_plus_350 = na
  642. if bar_index == last_bar_index
  643. future_line_plus_350 := line.new(x1=bar_index, y1=y * 4.5, x2=bar_index + future_days, y2=array.get(future_y_plus_350, future_days - 1), color=#ff590033, width=2)
  644.  
  645. //////////////////////////////
  646. // Variables to store labels so they can be deleted later
  647. var label power_law_label = na
  648. var label minus_60_label = na
  649. var label plus_60_label = na
  650. var label plus_150_label = na
  651. var label plus_250_label = na
  652. var label plus_350_label = na
  653.  
  654. // Add labels at the end of the projections, deleting the previous label first
  655. if (bar_index == last_bar_index)
  656. // Delete previous labels if they exist
  657. if not na(power_law_label)
  658. label.delete(power_law_label)
  659. if not na(minus_60_label)
  660. label.delete(minus_60_label)
  661. if not na(plus_60_label)
  662. label.delete(plus_60_label)
  663. if not na(plus_150_label)
  664. label.delete(plus_150_label)
  665. if not na(plus_250_label)
  666. label.delete(plus_250_label)
  667. if not na(plus_350_label)
  668. label.delete(plus_350_label)
  669.  
  670. // Create new labels and store them in variables
  671. power_law_label := label.new(bar_index + future_days, array.get(future_y, future_days - 1), text="Power Law = " + str.tostring(array.get(future_y, future_days - 1), format.mintick), color=#00897b00, style=label.style_label_left, textcolor=color.rgb(255, 0, 0, 50), yloc=yloc.price,size =size.small)
  672. minus_60_label := label.new(bar_index + future_days, array.get(future_y_minus_60, future_days - 1), text="-60% = " + str.tostring(array.get(future_y_minus_60, future_days - 1), format.mintick), color=#00897b00, style=label.style_label_left, textcolor=color.rgb(255, 235, 186, 50), yloc=yloc.price,size =size.small)
  673. plus_60_label := label.new(bar_index + future_days, array.get(future_y_plus_60, future_days - 1), text="+60% = " + str.tostring(array.get(future_y_plus_60, future_days - 1), format.mintick), color=#ff590000, style=label.style_label_left, textcolor=#ff590080, yloc=yloc.price,size =size.small)
  674. plus_150_label := label.new(bar_index + future_days, array.get(future_y_plus_150, future_days - 1), text="+150% = " + str.tostring(array.get(future_y_plus_150, future_days - 1), format.mintick), color=#ff590000, style=label.style_label_left, textcolor=#ff590080, yloc=yloc.price,size =size.small)
  675. plus_250_label := label.new(bar_index + future_days, array.get(future_y_plus_250, future_days - 1), text="+250% = " + str.tostring(array.get(future_y_plus_250, future_days - 1), format.mintick), color=#ff590000, style=label.style_label_left, textcolor=#ff590080, yloc=yloc.price,size =size.small)
  676. plus_350_label := label.new(bar_index + future_days, array.get(future_y_plus_350, future_days - 1), text="+350% = " + str.tostring(array.get(future_y_plus_350, future_days - 1), format.mintick), color=#ff590000, style=label.style_label_left, textcolor=#ff590080, yloc=yloc.price,size =size.small)
  677.  
  678.  
  679.  
  680. //Target Price Line
  681.  
  682. // Input for target price
  683. target_price = input.float(222308.0, title="Target Price", tooltip="Enter the price level for the horizontal line.")
  684.  
  685. // Get current price (closing price of the latest bar)
  686. current_price = close
  687.  
  688. // Calculate percentage difference (how far price needs to rise to reach the target)
  689. percent_diff = ((target_price - current_price) / current_price) * 100
  690.  
  691. //Color
  692. LL_color = #ffebba
  693.  
  694. // Plot horizontal line at target price
  695. line_price = hline(target_price, title="Target Price Line", color=LL_color, linewidth=1, linestyle=hline.style_solid)
  696.  
  697. // Variable to store the label
  698. var label target_label = na
  699.  
  700. // Delete the previous label if it exists
  701. if target_label != na
  702. label.delete(target_label)
  703.  
  704. // Create a new label with customizable background color
  705. target_label := label.new(x=bar_index + 260, y=target_price, text="Target: " + str.tostring(target_price) + "\nTo Target: " + str.tostring(percent_diff, "#.##") + "%", style=label.style_label_down, size=size.small, color=LL_color, textcolor=#0b0b0b)
  706.  
  707. // Alert condition: Trigger alert when price reaches or exceeds the target price
  708. price_reached = current_price >= target_price
  709. alertcondition(price_reached, "Price has reached the target")
  710.  
  711. ///////////////////////TP Background
  712.  
  713.  
  714. // Define halving dates
  715. TPhalvingDates = array.new_int(0)
  716. array.push(TPhalvingDates, timestamp("2012-11-28 00:00"))
  717. array.push(TPhalvingDates, timestamp("2016-07-09 00:00"))
  718. array.push(TPhalvingDates, timestamp("2020-05-11 00:00"))
  719. array.push(TPhalvingDates, timestamp("2024-04-19 00:00"))
  720. array.push(TPhalvingDates, timestamp("2028-04-17 00:00"))
  721.  
  722. // 40-week duration in milliseconds
  723. fortyWeeksMs = 40 * 7 * 24 * 60 * 60 * 1000
  724.  
  725. // Determine the timeframe settings
  726. timeFrameMs = timeframe.isdaily ? 24 * 60 * 60 * 1000 :
  727. timeframe.isweekly ? 7 * 24 * 60 * 60 * 1000 :
  728. timeframe.ismonthly ? 30 * 24 * 60 * 60 * 1000 : na
  729.  
  730. highlightColor = timeframe.isdaily ? #b13e0041 :
  731. timeframe.isweekly ? #b13e0041 :
  732. timeframe.ismonthly ? #b13e0041 : na
  733.  
  734. offsetValue = timeframe.isdaily ? 280 :
  735. timeframe.isweekly ? 40 :
  736. timeframe.ismonthly ? 10 : na
  737.  
  738. // Check if the current bar is within the 40-week window of any halving
  739. var bool inHighlightWindow = false
  740. inHighlightWindow := false // Reset for each bar
  741.  
  742. if not na(timeFrameMs) // Only calculate if a valid timeframe is detected
  743. for i = 0 to array.size(halvingDates) - 1
  744. halvingStart = array.get(halvingDates, i)
  745. halvingEnd = halvingStart + fortyWeeksMs
  746. barStart = time
  747. barEnd = time + timeFrameMs
  748. if (barStart <= halvingEnd and barEnd >= halvingStart)
  749. inHighlightWindow := true
  750. break // Exit the loop once a matching window is found
  751.  
  752. // Highlight the background only during the 40-week window for the current timeframe
  753. bgcolor(inHighlightWindow ? highlightColor : na, offset=offsetValue)
  754.  
  755.  
  756.  
Advertisement
Add Comment
Please, Sign In to add comment