dusun1

Untitled

Dec 16th, 2022
244
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.19 KB | None | 0 0
  1. // This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
  2. // © Leviathan
  3.  
  4. // Some Volume Profile elements are inspired by @LonesomeTheBlue's volume profile script
  5.  
  6. //@version=5
  7. indicator("Market sessions and Volume profile - By Leviathan", overlay=true, max_boxes_count=500, max_bars_back=1000)
  8.  
  9. //==========================
  10. //Inputs
  11. //==========================
  12. sessionType = input.string('Daily', 'Session Type', options=['Tokyo','London','New York','Daily','Weekly', 'Monthly', 'Quarterly', 'Yearly'])
  13.  
  14. showProf = input.bool(true, 'Show Volume Profile', group='Display')
  15. showSbox = input.bool(true, 'Show Session Box', group='Display')
  16. showPoc = input.bool(true, 'Show POC', group='Display')
  17. showVA = input.bool(true, 'Show VAH and VAL', group='Display')
  18. showVAb = input.bool(false, 'Show Value Area Box', group='Display')
  19. showCur = input.bool(true, 'Show Live Zone', group='Display')
  20. showLabels = input.bool(true, 'Show Session Lables', group='Display')
  21. showFx = input.bool(false, 'Show Forex Sessions (no profile)', group='Display')
  22. resolution = input.int(30, 'Resolution', minval=5, tooltip='The higher the value, the more refined of a profile, but less profiles shown on chart', group='Volume Profile Settings')
  23. VAwid = input.int(70, 'Value Area Volume %', minval=1, maxval=100, group='Volume Profile Settings')
  24. dispMode = input.string('Mode 2', 'Bar Mode', ['Mode 1', 'Mode 2', 'Mode 3'], group='Volume Profile Settings')
  25. volType = input.string('Volume', 'Profile Data Type', options=['Volume', 'Open Interest'], group='Volume Profile Settings')
  26. smoothVol = input.bool(false, 'Smooth Volume Data', tooltip='Useful for assets that have very large spikes in volume over large bars - helps create better profiles', group='Volume Profile Settings')
  27. dataTf = ''
  28.  
  29. bullCol = input.color(color.rgb(76, 175, 79, 50), 'Up Volume', group='Appearance')
  30. bearCol = input.color(color.rgb(255, 82, 82, 50), 'Down Volume', group='Appearance')
  31. VAbCol = input.color(color.rgb(107, 159, 255, 90), 'Value Area Box', group='Appearance' )
  32. pocCol = input.color(color.red, 'POC', inline='p', group='Appearance')
  33. pocWid = input.int(1, 'Thickness', inline='p', group='Appearance')
  34. vahCol = input.color(color.aqua, 'VAH', inline='h', group='Appearance')
  35. vahWid = input.int(1, 'Thickness', inline='h', group='Appearance')
  36. valCol = input.color(color.aqua, 'VAL', inline='l', group='Appearance')
  37. valWid = input.int(1, 'Thickness', inline='l', group='Appearance')
  38. boxBg = input.color(color.rgb(255, 153, 0, 100), 'Box', inline='m', group='Appearance')
  39. boxWid = input.int(1, 'Thickness', inline='m', group='Appearance')
  40.  
  41. //==========================
  42. //Constants / Variable Declaration
  43. //==========================
  44. var int zoneStart = 0
  45. var int tokyoStart = 0
  46. var int londonStart = 0
  47. var int nyStart = 0
  48. int lookback = bar_index - zoneStart
  49. var activeZone = false
  50.  
  51. // Defining arrays that store the information
  52. var vpGreen = array.new_float(resolution, 0) // Sum of volume on long bars
  53. var vpRed = array.new_float(resolution, 0) // Same thing but with red bars
  54. var zoneBounds = array.new_float(resolution, 0) // array that stores the highest value that can be in a zone
  55.  
  56. //Values to store current intra bar data
  57. var float[] ltfOpen = array.new_float(0)
  58. var float[] ltfClose = array.new_float(0)
  59. var float[] ltfHigh = array.new_float(0)
  60. var float[] ltfLow = array.new_float(0)
  61. var float[] ltfVolume = array.new_float(0)
  62.  
  63. //Getting OI Data
  64. string userSymbol = syminfo.prefix + ":" + syminfo.ticker
  65. string openInterestTicker = str.format("{0}_OI", userSymbol)
  66. string timeframe = syminfo.type == "futures" and timeframe.isintraday ? "1D" : timeframe.period
  67. deltaOi = request.security(openInterestTicker, timeframe, close-close[1], ignore_invalid_symbol = true)
  68.  
  69. //Selecting what vol type to use
  70. vol() =>
  71. out = smoothVol ? ta.ema(volume, 5) : volume
  72. if volType == 'Open Interest'
  73. out := deltaOi
  74. out
  75.  
  76. //Getting intrabar intial data
  77. [dO, dC, dH, dL, dV] = request.security_lower_tf(syminfo.tickerid, dataTf, [open, close, high, low, vol()])
  78.  
  79. //==========================
  80. //Functions
  81. //==========================
  82. resetProfile(enable) =>
  83. if enable
  84. array.fill(vpGreen, 0)
  85. array.fill(vpRed, 0)
  86. array.clear(ltfOpen)
  87. array.clear(ltfHigh)
  88. array.clear(ltfLow)
  89. array.clear(ltfClose)
  90. array.clear(ltfVolume)
  91.  
  92. profHigh = ta.highest(high, lookback+1)[1]
  93. profLow = ta.lowest(low, lookback+1)[1]
  94.  
  95. tr = ta.atr(1)
  96. atr = ta.atr(14)
  97.  
  98. get_vol(y11, y12, y21, y22, height, vol) =>
  99. nz(math.max(math.min(math.max(y11, y12), math.max(y21, y22)) - math.max(math.min(y11, y12), math.min(y21, y22)), 0) * vol / height)
  100.  
  101. profileAdd(o, h, l, c, v, g, w) =>
  102. //Array to store how much to distribute in each zone, on scale of 1 for full gap size to 0
  103. zoneDist = array.new_float(resolution, 0)
  104. distSum = 0.0
  105. // Going over each zone
  106. for i = 0 to array.size(vpGreen) - 1
  107. // Checking to see if cur bar is in zone
  108. zoneTop = array.get(zoneBounds, i)
  109. zoneBot = zoneTop - g
  110.  
  111. body_top = math.max(c, o)
  112. body_bot = math.min(c, o)
  113. itsgreen = c >= o
  114.  
  115. topwick = h - body_top
  116. bottomwick = body_bot - l
  117. body = body_top - body_bot
  118.  
  119. bodyvol = body * v / (2 * topwick + 2 * bottomwick + body)
  120. topwickvol = 2 * topwick * v / (2 * topwick + 2 * bottomwick + body)
  121. bottomwickvol = 2 * bottomwick * v / (2 * topwick + 2 * bottomwick + body)
  122.  
  123. if volType == 'Volume'
  124. array.set(vpGreen, i, array.get(vpGreen, i) + (itsgreen ? get_vol(zoneBot, zoneTop, body_bot, body_top, body, bodyvol) : 0) + get_vol(zoneBot, zoneTop, body_top, h, topwick, topwickvol) / 2 + get_vol(zoneBot, zoneTop, body_bot, l, bottomwick, bottomwickvol) / 2)
  125. array.set(vpRed, i, array.get(vpRed, i) + (itsgreen ? 0 : get_vol(zoneBot, zoneTop, body_bot, body_top, body, bodyvol)) + get_vol(zoneBot, zoneTop, body_top, h, topwick, topwickvol) / 2 + get_vol(zoneBot, zoneTop, body_bot, l, bottomwick, bottomwickvol) / 2)
  126. else if volType == 'Open Interest'
  127. if v > 0
  128. array.set(vpGreen, i, array.get(vpGreen, i) + get_vol(zoneBot, zoneTop, body_bot, body_top, body, v))// + get_vol(zoneBot, zoneTop, body_top, h, topwick, topwickvol) / 2 + get_vol(zoneBot, zoneTop, body_bot, l, bottomwick, bottomwickvol) / 2)
  129. if v < 0
  130. array.set(vpRed, i, array.get(vpRed, i) + get_vol(zoneBot, zoneTop, body_bot, body_top, body, -v))// + get_vol(zoneBot, zoneTop, body_top, h, topwick, topwickvol) / 2 + get_vol(zoneBot, zoneTop, body_bot, l, bottomwick, bottomwickvol) / 2)
  131.  
  132. calcSession(update) =>
  133. array.fill(vpGreen, 0)
  134. array.fill(vpRed, 0)
  135. if bar_index > lookback and update
  136. gap = (profHigh - profLow) / resolution
  137.  
  138. // Defining profile bounds
  139. for i = 0 to resolution - 1
  140. array.set(zoneBounds, i, profHigh - gap * i)
  141.  
  142. // Putting each bar inside zone into the volume profile array
  143. if array.size(ltfOpen) > 0
  144. for j = 0 to array.size(ltfOpen) - 1
  145. profileAdd(array.get(ltfOpen, j), array.get(ltfHigh, j), array.get(ltfLow, j), array.get(ltfClose, j), array.get(ltfVolume, j), gap, 1)
  146.  
  147. pocLevel() =>
  148. float maxVol = 0
  149. int levelInd = 0
  150. for i = 0 to array.size(vpRed) - 1
  151. if array.get(vpRed, i) + array.get(vpGreen, i) > maxVol
  152. maxVol := array.get(vpRed, i) + array.get(vpGreen, i)
  153. levelInd := i
  154.  
  155. float outLevel = na
  156. if levelInd != array.size(vpRed) - 1
  157. outLevel := array.get(zoneBounds, levelInd) - (array.get(zoneBounds, levelInd) - array.get(zoneBounds, levelInd+1)) / 2
  158. outLevel
  159.  
  160. valueLevels(poc) =>
  161. float gap = (profHigh - profLow) / resolution
  162. float volSum = array.sum(vpRed) + array.sum(vpGreen)
  163. float volCnt = 0
  164.  
  165. float vah = profHigh
  166. float val = profLow
  167.  
  168. //Finding poc index
  169. int pocInd = 0
  170. for i = 0 to array.size(zoneBounds)-2
  171. if array.get(zoneBounds, i) >= poc and array.get(zoneBounds, i + 1) < poc
  172. pocInd := i
  173.  
  174. volCnt += (array.get(vpRed, pocInd) + array.get(vpGreen, pocInd))
  175. for i = 1 to array.size(vpRed)
  176. if pocInd + i >= 0 and pocInd + i < array.size(vpRed)
  177. volCnt += (array.get(vpRed, pocInd + i) + array.get(vpGreen, pocInd + i))
  178. if volCnt >= volSum * (VAwid/100)
  179. break
  180. else
  181. val := array.get(zoneBounds, pocInd + i) - gap
  182. if pocInd - i >= 0 and pocInd - i < array.size(vpRed)
  183. volCnt += (array.get(vpRed, pocInd - i) + array.get(vpGreen, pocInd - i))
  184. if volCnt >= volSum * (VAwid/100)
  185. break
  186. else
  187. vah := array.get(zoneBounds, pocInd - i)
  188.  
  189. [val, vah]
  190.  
  191. drawNewZone(update) =>
  192. if bar_index > lookback and update and array.sum(vpGreen) + array.sum(vpRed) > 0
  193. gap = (profHigh - profLow) / resolution
  194. float leftMax = bar_index[lookback]
  195. float rightMax = bar_index[int(lookback / 1.4)]
  196. float rightMaxVol = array.max(vpGreen)+array.max(vpRed)
  197. float buffer = gap / 10
  198. if showLabels
  199. label.new((bar_index - 1 + int(leftMax))/2, profHigh, sessionType, color=color.rgb(0,0,0,100), textcolor=chart.fg_color)
  200. if showProf
  201. for i = 0 to array.size(vpRed) - 1
  202. greenEnd = int(leftMax + (rightMax - leftMax) * (array.get(vpGreen, i) / rightMaxVol))
  203. redEnd = int(greenEnd + (rightMax - leftMax) * (array.get(vpRed, i) / rightMaxVol))
  204. if dispMode == 'Mode 2'
  205. box.new(int(leftMax), array.get(zoneBounds, i) - buffer, greenEnd, array.get(zoneBounds, i) - gap + buffer, bgcolor=bullCol, border_width=0)
  206. box.new(greenEnd, array.get(zoneBounds, i) - buffer, redEnd, array.get(zoneBounds, i) - gap + buffer, bgcolor=bearCol, border_width=0)
  207. else if dispMode == 'Mode 1'
  208. box.new(int(leftMax), array.get(zoneBounds, i) - buffer, greenEnd, array.get(zoneBounds, i) - gap + buffer, bgcolor=bullCol, border_width=0)
  209. else
  210. box.new(int(leftMax), array.get(zoneBounds, i) - buffer, greenEnd, array.get(zoneBounds, i) - gap + buffer, bgcolor=bullCol, border_width=0)
  211. box.new(int(leftMax)-redEnd+greenEnd, array.get(zoneBounds, i) - buffer, int(leftMax), array.get(zoneBounds, i) - gap + buffer, bgcolor=bearCol, border_width=0)
  212.  
  213. box.new(int(leftMax), profHigh, bar_index-1, profLow, chart.fg_color, boxWid, line.style_dashed, bgcolor=boxBg)
  214. poc = pocLevel()
  215. [val, vah] = valueLevels(poc)
  216. if showPoc
  217. line.new(int(leftMax), poc, bar_index-1, poc, color=pocCol, width=pocWid)
  218. if showVA
  219. line.new(int(leftMax), vah, bar_index-1, vah, color=vahCol, width=vahWid)
  220. line.new(int(leftMax), val, bar_index-1, val, color=valCol, width=valWid)
  221. if showVAb
  222. box.new(int(leftMax), vah, bar_index-1, val, border_color=color.rgb(54, 58, 69, 100), bgcolor=VAbCol)
  223.  
  224.  
  225. //if update
  226. // resetProfile(true)
  227.  
  228. drawCurZone(update, delete) =>
  229. var line pocLine = na
  230. var line vahLine = na
  231. var line valLine = na
  232. var box outBox = na
  233. var label sessionLab = na
  234.  
  235. var redBoxes = array.new_box(array.size(vpRed), na)
  236. var greenBoxes = array.new_box(array.size(vpRed), na)
  237.  
  238. if bar_index > lookback and update and array.sum(vpGreen) + array.sum(vpRed) > 0
  239. //Clearing the previous boxes and array
  240. if not na(pocLine)
  241. line.delete(pocLine)
  242. if not na(vahLine)
  243. line.delete(vahLine)
  244. if not na(valLine)
  245. line.delete(valLine)
  246. if not na(outBox)
  247. box.delete(outBox)
  248. if not na(sessionLab)
  249. label.delete(sessionLab)
  250.  
  251. for i = 0 to array.size(redBoxes) - 1
  252. if not na(array.get(redBoxes, i))
  253. box.delete(array.get(redBoxes, i))
  254. box.delete(array.get(greenBoxes, i))
  255.  
  256.  
  257. gap = (profHigh - profLow) / resolution
  258. float leftMax = bar_index[lookback]
  259. float rightMax = bar_index[int(lookback / 1.4)]
  260. float rightMaxVol = array.max(vpGreen)+array.max(vpRed)
  261. float buffer = gap / 10
  262. if showLabels
  263. sessionLab := label.new((bar_index - 1 + int(leftMax))/2, profHigh, sessionType, color=color.rgb(0,0,0,100), textcolor=chart.fg_color)
  264. if showProf
  265. for i = 0 to array.size(vpRed) - 1
  266. greenEnd = int(leftMax + (rightMax - leftMax) * (array.get(vpGreen, i) / rightMaxVol))
  267. redEnd = int(greenEnd + (rightMax - leftMax) * (array.get(vpRed, i) / rightMaxVol))
  268. if dispMode == 'Mode 2'
  269. array.set(greenBoxes, i, box.new(int(leftMax), array.get(zoneBounds, i) - buffer, greenEnd, array.get(zoneBounds, i) - gap + buffer, bgcolor=bullCol, border_width=0))
  270. array.set(redBoxes, i, box.new(greenEnd, array.get(zoneBounds, i) - buffer, redEnd, array.get(zoneBounds, i) - gap + buffer, bgcolor=bearCol, border_width=0))
  271. else if dispMode == 'Mode 1'
  272. array.set(greenBoxes, i, box.new(int(leftMax), array.get(zoneBounds, i) - buffer, greenEnd, array.get(zoneBounds, i) - gap + buffer, bgcolor=bullCol, border_width=0))
  273. else
  274. array.set(greenBoxes, i, box.new(int(leftMax), array.get(zoneBounds, i) - buffer, greenEnd, array.get(zoneBounds, i) - gap + buffer, bgcolor=bullCol, border_width=0))
  275. array.set(redBoxes, i, box.new(int(leftMax)-redEnd+greenEnd, array.get(zoneBounds, i) - buffer, int(leftMax), array.get(zoneBounds, i) - gap + buffer, bgcolor=bearCol, border_width=0))
  276.  
  277. outBox := box.new(int(leftMax), profHigh, bar_index-1, profLow, chart.fg_color, boxWid, line.style_dashed, bgcolor=boxBg)
  278.  
  279.  
  280. poc = pocLevel()
  281. [val, vah] = valueLevels(poc)
  282. if showPoc
  283. line.delete(pocLine)
  284. pocLine := line.new(int(leftMax), poc, bar_index-1, poc, color=pocCol, width=pocWid)
  285. if showVA
  286. line.delete(vahLine)
  287. line.delete(valLine)
  288. vahLine := line.new(int(leftMax), vah, bar_index-1, vah, color=vahCol, width=vahWid)
  289. valLine := line.new(int(leftMax), val, bar_index-1, val, color=valCol, width=valWid)
  290. if showVAb
  291. box.new(int(leftMax), vah, bar_index-1, val, border_color=color.rgb(54, 58, 69, 100), bgcolor=VAbCol)
  292.  
  293. if delete
  294. box.delete(outBox)
  295. line.delete(pocLine)
  296. line.delete(vahLine)
  297. line.delete(valLine)
  298. for i = 0 to array.size(greenBoxes)-1
  299. box.delete(array.get(greenBoxes, i))
  300. for i = 0 to array.size(redBoxes)-1
  301. box.delete(array.get(redBoxes, i))
  302.  
  303. drawForexBox(startBar, title, top, bottom) =>
  304. box.new(int(startBar), top, bar_index-1, bottom, chart.fg_color, boxWid, line.style_dashed, bgcolor=boxBg)
  305. if showLabels
  306. label.new((bar_index - 1 + int(startBar))/2, top, title, color=color.rgb(0,0,0,100), textcolor=chart.fg_color)
  307.  
  308.  
  309. combArray(arr1, arr2) =>
  310. out = array.copy(arr1)
  311. if array.size(arr2) > 0
  312. for i = 0 to array.size(arr2) - 1
  313. array.push(out, array.get(arr2, i))
  314. out
  315.  
  316. updateIntra(o, h, l, c, v) =>
  317. if array.size(o) > 0
  318. for i = 0 to array.size(o) - 1
  319. array.push(ltfOpen, array.get(o, i))
  320. array.push(ltfHigh,array.get(h, i))
  321. array.push(ltfLow,array.get(l, i))
  322. array.push(ltfClose,array.get(c, i))
  323. array.push(ltfVolume,array.get(v, i))
  324.  
  325.  
  326. //==========================
  327. //Calculations
  328. //==========================
  329. //Detecting different start dates
  330. newDaily = dayofweek != dayofweek[1]
  331. newWeekly = weekofyear != weekofyear[1]
  332. newMonthly = (dayofmonth != dayofmonth[1] + 1) and (dayofmonth != dayofmonth[1])
  333. newYearly = year != year[1]
  334. newQuarterly = month != month[1] and (month - 1) % 3 == 0
  335.  
  336. utcHour = hour(time(timeframe.period, '0000-2400', 'GMT'), 'GMT')
  337.  
  338. newTokyo = utcHour != utcHour[1] + 1 and utcHour != utcHour[1]
  339. endTokyo = utcHour >= 9 and utcHour[1] < 9
  340.  
  341. newLondon = utcHour >= 7 and utcHour[1] < 7
  342. endLondon = utcHour >= 16 and utcHour[1] < 16
  343.  
  344. newNewYork = utcHour >= 13 and utcHour[1] < 13
  345. endNewYork = utcHour >= 22 and utcHour[1] < 22
  346.  
  347. newSession = switch sessionType
  348. 'Tokyo' => newTokyo
  349. 'London' => newLondon
  350. 'New York' => newNewYork
  351. 'Daily' => newDaily
  352. 'Weekly' => newWeekly
  353. 'Monthly' => newMonthly
  354. 'Yearly' => newYearly
  355. 'Quarterly' => newQuarterly
  356. => newDaily
  357.  
  358. zoneEnd = switch sessionType
  359. 'Tokyo' => endTokyo
  360. 'London' => endLondon
  361. 'New York' => endNewYork
  362. 'Daily' => newDaily
  363. 'Weekly' => newWeekly
  364. 'Monthly' => newMonthly
  365. 'Yearly' => newYearly
  366. 'Quarterly' => newQuarterly
  367. => newDaily
  368.  
  369. isForex = showFx
  370.  
  371. //Re calculating and drawing zones
  372. calcSession(zoneEnd or (barstate.islast and showCur))
  373. drawNewZone(zoneEnd)
  374. drawCurZone(barstate.islast and not zoneEnd and showCur and activeZone, zoneEnd)
  375.  
  376. //Reseting profie at start of new zone
  377. resetProfile(newSession)
  378.  
  379. //Updating data arrays
  380. updateIntra(dO, dH, dL, dC, dV)
  381.  
  382. //Reseting zone start value
  383. if zoneEnd
  384. activeZone := false
  385.  
  386. if newSession
  387. zoneStart := bar_index
  388. activeZone := true
  389.  
  390. if newLondon
  391. londonStart := bar_index
  392. if newTokyo
  393. tokyoStart := bar_index
  394. if newNewYork
  395. nyStart := bar_index
  396.  
  397. londonHigh = ta.highest(high, bar_index-londonStart+1)
  398. tokyoHigh = ta.highest(high, bar_index-tokyoStart+1)
  399. nyHigh = ta.highest(high, bar_index-nyStart+1)
  400.  
  401. londonLow = ta.lowest(low, bar_index-londonStart+1)
  402. tokyoLow = ta.lowest(low, bar_index-tokyoStart+1)
  403. nyLow = ta.lowest(low, bar_index-nyStart+1)
  404.  
  405. if endLondon and isForex
  406. drawForexBox(londonStart, 'London', londonHigh, londonLow)
  407. if endNewYork and isForex
  408. drawForexBox(nyStart, 'New York', nyHigh, nyLow)
  409. if endTokyo and isForex
  410. drawForexBox(tokyoStart, 'Tokyo', tokyoHigh, tokyoLow)
  411.  
Advertisement
Add Comment
Please, Sign In to add comment