Advertisement
NKactive

Untitled

Aug 5th, 2023
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.08 KB | None | 0 0
  1. // Liquidations by volume
  2. // Description: Shows actual liquidations on a per-candle basis, by using the difference in volume between spot and futures perpetuals markets.
  3. // i.e. volume on a futures market will be much higher than spot market if there are many liquidations.
  4. //
  5. // Hence, this indicator can approximate the amount of liquidations (ie, bars where there were a lot more liquidations than others) from the differenc between futures and spot volumes,
  6. // but it cannot distinguish the proportion of shorts versus longs liquidations, it is instead approximated with the current price bar's color,
  7. // which naturally suggests where the majority of liquidations happened (ie, if a price bar closes above open and hence in green, then we can suppose that
  8. // a majority of liquiditations were on shorts, since we know longs won). This explains why there is only one liquidation bar but colored, and not two, since we cannot separate longs or shorts liquidations.
  9. //
  10. // Long liquidation data should in theory be more accurate than short liquidation data due to the inability to short on a spot market.
  11. //
  12. // This indicator should be able to help identify trends by determining liquidation points in the chart. Focus first on the magnitude (ie, finding bars of unusually high liquidations), and only after consider the color.
  13. //
  14. // Notes:
  15. // - Script now removes any negative values, these values are not relevant to the indicators purpose
  16. // - Added an option to remove below average values to help indentify high points on the histogram
  17. // - Added options to plot both market volumes (spot and perpetuals) seperately
  18. // - Can autodetect the spot and futures markets automatically for the currently selected ticker in TradingView. It always uses the USDT spot versus USDT perpetuals for the current symbol, even if the source ticker is USD, USDC, etc. The only requirement is that USD is written in the ticker string (thanks to hamiissah for the idea to search for USD).
  19. // - The exchange providing the data is not specified so the script can switch to any exchange that can provide perpetuals futures data for the current pair, but in practice it is almost always Binance, and if you want, you can enable an option to ensure we always use Binance as a source, to avoid unintended data switching.
  20. // - Ticker autodetection also works on composite tickers (eg, BINANCE:BTCUSD+KRAKEN:BTCUSD)/2 ). The first symbol will be extracted and used, so if the composite ticker is not a simple average of the same symbol across multiple exchanges, obviously the liquidations will be wrong, but anyway there is no source of data for liquidations over composite tickers by definition.
  21. //
  22. // This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
  23. // Original Code © Thomas_Davison
  24. // Modifications © NK.active
  25. // Extended by Tartigradia to automatically detect the symbol and add multi-timeframe support (MTF)
  26. //
  27.  
  28. //@version=5
  29. strategy("Liquidations by volume (TG fork) Adapted Analysis", shorttitle='Liquidations by vol (TG)', format=format.volume, precision=2)
  30.  
  31. import EliCobra/CobraMetrics/4 as cobra
  32. //// PLOT DATA
  33. disp_ind = input.string ("None" , title = "Display Curve" , tooltip = "Choose which data you would like to display", options=["Strategy", "Equity", "Open Profit", "Gross Profit", "Net Profit", "None"], group = "🐍 𝓒𝓸𝓫𝓻𝓪 𝓜𝓮𝓽𝓻𝓲𝓬𝓼 🐍")
  34. pos_table = input.string("Middle Left", "Table Position", options = ["Top Left", "Middle Left", "Bottom Left", "Top Right", "Middle Right", "Bottom Right", "Top Center", "Bottom Center"], group = "🐍 𝓒𝓸𝓫𝓻𝓪 𝓜𝓮𝓽𝓻𝓲𝓬𝓼 🐍")
  35. type_table = input.string("None", "Table Type", options = ["Full", "Simple", "None"], group = "🐍 𝓒𝓸𝓫𝓻𝓪 𝓜𝓮𝓽𝓻𝓲𝓬𝓼 🐍")
  36. plot(cobra.curve(disp_ind))
  37. cobra.cobraTable(type_table, pos_table)
  38.  
  39. // uses the difference in volume between a spot market and a futures market to determine possible liquidations that might have taken place
  40.  
  41. // the calculation is simple: histogram bar value = futures volume - spot volume
  42.  
  43. // NOTES: - markets used should have the same volume equivalent i.e. volume for BTCUSDT should be measured in BTC for both spot and futures markets, some futures markets use contracts worth different amounts meaning values will differ greatly.
  44. // - negative values will been removed as they dont show relevant data to this indicator
  45. // - all values while calculated accurately, are given to interpretation, as not all of the volume difference seen on a futures market is due to liquidations. Traders making trades within a single candle time period will skew the data.
  46.  
  47. // INPUTS
  48. //
  49. grp1 = 'Resolution'
  50. tf = input.timeframe('', title='Timeframe Resolution', group=grp1)
  51. lookBack = input.int(defval=10,title="Biggest Bar LookBack", tooltip="Select how many bars to lookback over to find the biggest bar", group=grp1)
  52. tf_gaps = input.bool(false, title='Timeframe gaps?', group=grp1)
  53.  
  54. grp2 = 'Ticker autodetect'
  55. ticker_autodetect = input.bool(true, 'Ticker Autodetect: use current chart symbol to try to autodetect the perpetual markets?', tooltip='If enabled, will try to detect the spot and futures markets for the current symbol, by detecting where USD is written in the ticker symbol and then extract what is before as the target ticker we want, then append USDT and USDTPERP. So this only works for crypto assets listed on perpetuals markets, and it always uses USDT as the target markets, although the input ticker can be USD, USDC, etc.', group=grp2)
  56. ticker_autodetect_alwaysbinance = input.bool(false, 'Always use Binance?', tooltip='If false, the exchange providing the data is not specified so the script can switch to any exchange that can provide perpetuals futures data for the current pair, but in practice it is almost always Binance, and if you want, you can enable an option to ensure we always use Binance as a source, to avoid unintended data switching. This only works if Ticker Autodetect is enabled.', group=grp2)
  57.  
  58. grp3 = 'Ticker manual selection'
  59. assetSpot_user = input.symbol(title="Spot symbol", defval = "binance:btcusdt", tooltip='Will be used if ticker autodetect is disabled.', group=grp3)
  60. assetFutures_user = input.symbol(title="Futures symbol", defval = "binance:btcusdtperp", tooltip='Will be used if ticker autodetect is disabled.', group=grp3)
  61.  
  62. grp4 = 'Aesthetics'
  63. longLiqCol = input.color(title="Long liquidations color", defval = color.red, tooltip='Some people prefer to display long liquidations in red to show that bears won, others prefer to display them in green to show that longs lost. By default, they are displayed in red.', group=grp4)
  64. shortLiqCol = input.color(title="Short liquidations color", defval = color.green, group=grp4)
  65. removeBelowMean = input.bool(title="Remove below average volume differences?", defval = true, group=grp4)
  66. timePeriodMean = input.int(title="Lookback period to calculate mean", defval = 100, tooltip='Works only if Remove below mean volume differences is enabled.', group=grp4)
  67. plotSpot = input.bool(title="Plot spot market volume?", defval = false, tooltip="If disabled, spot price will still be shown in the status bar.", group=grp4)
  68. spotVolCol = input.color(title="Spot volume color", defval = color.yellow, group=grp4)
  69. plotFutures = input.bool(title="Plot futures market volume?", defval = false, group=grp4)
  70. futuresVolCol = input.color(title="Futures volume color", defval = color.purple, tooltip="If disabled, futures price will still be shown in the status bar.", group=grp4)
  71.  
  72. // DATA LOADING
  73. //
  74.  
  75. // Autodetect ticker
  76. current_ticker = ticker.standard(syminfo.tickerid) // cannot use syminfo.ticker for aggregate/composite tickers (eg, calculations to calculate the average across multiple exchanges), then we need to use other functions such as syminfo.description or ticker.standard(syminfo.tickerid) to get the full composite ticker
  77. usd_start_location = str.pos(current_ticker, 'USD') // autodetect where USD is located in the ticker symbol string
  78. ticker_target = str.substring(current_ticker, 0, usd_start_location) // extract substring before USD as the target ticker we want to find on perpetuals
  79. ticker_exchange = ticker_autodetect_alwaysbinance ? 'binance:' : '' // set binance as the static exchange source for the perp data if this option is enabled
  80. regexclean = "(?<=:)[a-zA-Z1-9]+" // clean up the extracted substring, as it can cointain other characters, such as math operators and parenthesis, we only keep letters and numbers, and only after a comma if one is specified (so we remove the exchange, because anyway we have to use Binance for perpetuals), eg, if it's an average of tickers of the same symbol at various exchanges
  81. ticker_target_clean = str.match(ticker_target, regexclean) // apply the cleaning regex on the ticker target (the target symbol)
  82. ticker_spot = ticker_exchange + ticker_target_clean + 'USDT' // concatenate previous strings and append 'USDT' for the spot market
  83. ticker_futures = ticker_exchange + ticker_target_clean + 'USDTPERP' // same but append 'USDTPERP' for the futures perpetuals market
  84.  
  85. // Define tickers we fetch, either use autodetected ones or manually set ones by user
  86. assetSpot = ticker_autodetect ? ticker_spot : assetSpot_user
  87. assetFutures = ticker_autodetect ? ticker_futures : assetFutures_user
  88.  
  89. // Fetch data
  90. spotVolume = request.security(assetSpot, timeframe=(tf == 'Chart' ? timeframe.period : tf), expression=volume, gaps=tf_gaps ? barmerge.gaps_on : barmerge.gaps_off)
  91. futuresVolume = request.security(assetFutures, timeframe=(tf == 'Chart' ? timeframe.period : tf), expression=volume, gaps=tf_gaps ? barmerge.gaps_on : barmerge.gaps_off)
  92.  
  93. // Calculate liquidations as the difference between futures volume and spot volume shortLiqCol is green
  94. // NK.active => Check why colour is based on the chart close and open instead of the futuresVolume and spotVolume
  95. difference = futuresVolume - spotVolume
  96. // direction = futuresVolume > spotVolume ? shortLiqCol : longLiqCol // close > open ? shortLiqCol : longLiqCol
  97. direction = close > open ? shortLiqCol : longLiqCol
  98. // directionBool used later one to determine if its a long position (1) or short (0) => added ny NK.active
  99. // directionBool = close > open ? 1 : 0
  100.  
  101. differenceSum = math.sum(difference, timePeriodMean)
  102. differenceMean = differenceSum / timePeriodMean
  103.  
  104. if removeBelowMean and difference < differenceMean or difference < 0
  105. difference := 0
  106.  
  107. // PLOT
  108. //
  109. plot(difference, color=direction, title='Liquidations', linewidth=2, style=plot.style_histogram)
  110. plot(spotVolume, color=spotVolCol, title='Spot volume', display=plotSpot ? display.all : display.status_line)
  111. plot(futuresVolume, color=futuresVolCol, title='Futures volume', display=plotFutures ? display.all : display.status_line)
  112. //
  113. // Show current market used as a label
  114. // We use `var` to only initialize the table on the first bar.
  115. // Also we use a table instead of a label because table do not rescale the chart, so that the chart's scale is maximized to the metrics, not the text.
  116. // Removed to put the cobra tate table
  117. // var table textDisplay = table.new(position.top_right, 1, 1, bgcolor=color.new(color.gray, 85))
  118. // if barstate.islast
  119. // table.cell(textDisplay, 0, 0, text='Spot: ' + assetSpot + '\nFutures: ' + assetFutures, text_color=color.gray, text_halign=text.align_left)
  120.  
  121. // Code added by NK.active
  122. // Add code to put in buy and sell directions
  123. // ------------------------------------------
  124. // difference = futuresVolume - spotVolume // (defined above)
  125. // Average last 10 bars for buySignal
  126. // replace maxClose maxOpen with an array populated by the red and the green liquidations respectively
  127. //. use directionBool to see if its green or red signal
  128. // workout buySignal and sellSignal based on the current day being bigger than the last 10
  129.  
  130. // From Certified_Weeb but changed to ta.highest
  131. highest_bar_offset = ta.highest(difference, lookBack)
  132. plot(highest_bar_offset, title= "Test highest_bar_offset")
  133.  
  134. //buySignal = close > open // still to add (and) next code from loop to check last 10 bars AND THEN change close>open to futuresVolume > spotVolume
  135. //sellSignal = close < open // still to add (and) next code from loop to check last 10 bars AND THEN change close<open to futuresVolume < spotVolume
  136. buySignal = close > open and difference >= highest_bar_offset
  137. sellSignal = close < open and difference >= highest_bar_offset
  138.  
  139. // plotshape(maCrossUnder, title="Lower Close", style=shape.arrowdown, color=color.yellow)
  140. plotshape(buySignal,style=shape.triangleup,location=location.belowbar, color=direction, title = "Buy Signal")
  141. if (buySignal)
  142. strategy.entry("My Long Entry Id", strategy.long)
  143. plotshape(sellSignal,style=shape.triangledown,location=location.belowbar, color=direction, title = "Sell Signal")
  144. if (sellSignal)
  145. strategy.entry("My Short Entry Id", strategy.short)
  146. myLabel = barstate.islast ? label.new(bar_index, high, text="Difference", tooltip = "Max10Pos" + str.tostring(highest_bar_offset)+"\n Current"+str.tostring(difference)) : na
  147. //plotshape(barstate.islast,style=shape.labeldown,location=location.abovebar, textcolor=color.white)
  148.  
  149. // End of code added by NK.active
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement