STH Unrealized Profit/Loss Ratio (STH-NUPL) | [DeV]STH-NUPL
The Short-Term Holder Net Unrealized Profit/Loss Ratio (STH-NUPL) is an analytical tool designed to approximate the unrealized profit or loss of Bitcoin’s short-term holders (STHs)—typically those holding coins for less than 155 days—within the constraints of PulseWire’s price-based environment. Drawing inspiration from the canonical STH-NUPL metric, which assesses the difference between the market value and realized value of STH-held coins, this indicator adapts the concept into a normalized ratio using Bitcoin’s price data as a proxy. It offers a window into the sentiment and behavior of short-term market participants, who are often more sensitive to price fluctuations than long-term holders.
In its raw form, STH-NUPL oscillates around a break-even threshold of 0, where positive values indicate aggregate unrealized profits for STHs (market value exceeds realized value), and negative values suggest losses. This inflection point frequently acts as a key level: in bear markets, it can signal capitulation as STHs sell at break-even or below, while in bull markets, it may reflect reluctance to realize losses, providing support. The indicator enhances this metric with smoothing, a moving average overlay, and sophisticated visualization options, delivering a statistically informed perspective on short-term holder dynamics tailored for institutional-grade analysis.
STH-NUPL Settings -
Lookback Length (Default: 150 days): Defines the SMA period for estimating realized value. This 150-day window aligns with traditional STH definitions (e.g., <155 days), capturing a broad yet relevant historical cost basis for short-term holders, ideal for assessing cyclical behavior.
Smoothing Period (Default: 5 days): Applies an EMA to the raw STH-NUPL ratio, with a short default period to maintain responsiveness to recent price shifts while filtering out daily volatility. This setting is particularly suited for tactical analysis.
Moving Average Settings -
MA Lookback Length (Default: 90 days): Sets the period for the STH-NUPL’s moving average, offering a medium-term trend signal that contrasts with the 150-day lookback, enabling detection of momentum shifts within broader market phases.
MA Type (Default: EMA): Provides six moving average types, from the straightforward SMA to the volume-sensitive VWMA. The default EMA balances smoothness and reactivity, while options like HMA or VWMA cater to specialized needs, such as emphasizing recent action or volume trends.
Display Settings -
Show Moving Average (Default: True): Toggles the visibility of the STH-NUPL MA plot, allowing users to focus solely on the smoothed ratio when desired.
Show Background Colors (Default: True): Activates dynamic background shading to visually reinforce market regimes.
Background Color Source (Default: STH-NUPL): Enables users to tie the background to either the STH-NUPL’s midline (reflecting sthNupl > 0) or the MA’s trend direction (maNupl > maNupl ), aligning the visual context with the chosen analytical focus.
Analytical Applications -
Bear Market Capitulation: When the smoothed STH-NUPL approaches or falls below zero, it often signals loss realization among STHs, a precursor to capitulation in downtrends. A declining MA crossing zero can confirm this selling pressure.
Bull Market Support: Positive STH-NUPL values with a rising MA indicate STHs are in profit and reluctant to sell at a loss, forming support zones in uptrends as sell pressure wanes.
Sentiment Extremes: Significant deviations above or below zero highlight over-optimism or despair among STHs, offering contrarian opportunities when paired with price action or other on-chain metrics.
**Limitations**
As a PulseWire-based approximation, this indicator uses price data (close) rather than true on-chain STH supply and realized price, which are available through providers like Glassnode. The 150-day SMA for realized value simplifies the cost basis, potentially underrepresenting the diversity of STH transactions. Despite this, the smoothed ratio and moving average overlay provide a practical proxy for tracking STH sentiment within PulseWire’s ecosystem.
Indicator

analytics_tablesLibrary "analytics_tables"
📝 Description
This library provides the implementation of several performance-related statistics and metrics, presented in the form of tables.
The metrics shown in the afforementioned tables where developed during the past years of my in-depth analalysis of various strategies in an atempt to reason about the performance of each strategy.
The visualization and some statistics where inspired by the existing implementations of the "Seasonality" script, and the performance matrix implementations of @QuantNomad and @ZenAndTheArtOfTrading scripts.
While this library is meant to be used by my strategy framework "Template Trailing Strategy (Backtester)" script, I wrapped it in a library hoping this can be usefull for other community strategy scripts that will be released in the future.
🤔 How to Guide
To use the functionality this library provides in your script you have to import it first!
Copy the import statement of the latest release by pressing the copy button below and then paste it into your script. Give a short name to this library so you can refer to it later on. The import statement should look like this:
import jason5480/analytics_tables/1 as ant
There are three types of tables provided by this library in the initial release. The stats table the metrics table and the seasonality table.
Each one shows different kinds of performance statistics.
The table UDT shall be initialized once using the `init()` method.
They can be updated using the `update()` method where the updated data UDT object shall be passed.
The data UDT can also initialized and get updated on demend depending on the use case
A code example for the StatsTable is the following:
var ant.StatsData statsData = ant.StatsData.new()
statsData.update(SideStats.new(), SideStats.new(), 0)
if (barstate.islastconfirmedhistory or (barstate.isrealtime and barstate.isconfirmed))
var statsTable = ant.StatsTable.new().init(ant.getTablePos('TOP', 'RIGHT'))
statsTable.update(statsData)
A code example for the MetricsTable is the following:
var ant.StatsData statsData = ant.StatsData.new()
statsData.update(ant.SideStats.new(), ant.SideStats.new(), 0)
if (barstate.islastconfirmedhistory or (barstate.isrealtime and barstate.isconfirmed))
var metricsTable = ant.MetricsTable.new().init(ant.getTablePos('BOTTOM', 'RIGHT'))
metricsTable.update(statsData, 10)
A code example for the SeasonalityTable is the following:
var ant.SeasonalData seasonalData = ant.SeasonalData.new().init(Seasonality.monthOfYear)
seasonalData.update()
if (barstate.islastconfirmedhistory or (barstate.isrealtime and barstate.isconfirmed))
var seasonalTable = ant.SeasonalTable.new().init(seasonalData, ant.getTablePos('BOTTOM', 'LEFT'))
seasonalTable.update(seasonalData)
🏋️♂️ Please refer to the "EXAMPLE" regions of the script for more advanced and up to date code examples!
Special thanks to @Mrcrbw for the proposal to develop this library and @DCNeu for the constructive feedback 🏆.
getTablePos(ypos, xpos)
Get table position compatible string
Parameters:
ypos (simple string) : The position on y axise
xpos (simple string) : The position on x axise
Returns: The position to be passed to the table
method init(this, pos, height, width, positiveTxtColor, negativeTxtColor, neutralTxtColor, positiveBgColor, negativeBgColor, neutralBgColor)
Initialize the stats table object with the given colors in the given position
Namespace types: StatsTable
Parameters:
this (StatsTable) : The stats table object
pos (simple string) : The table position string
height (simple float) : The height of the table as a percentage of the charts height. By default, 0 auto-adjusts the height based on the text inside the cells
width (simple float) : The width of the table as a percentage of the charts height. By default, 0 auto-adjusts the width based on the text inside the cells
positiveTxtColor (simple color) : The text color when positive
negativeTxtColor (simple color) : The text color when negative
neutralTxtColor (simple color) : The text color when neutral
positiveBgColor (simple color) : The background color with transparency when positive
negativeBgColor (simple color) : The background color with transparency when negative
neutralBgColor (simple color) : The background color with transparency when neutral
method init(this, pos, height, width, neutralBgColor)
Initialize the metrics table object with the given colors in the given position
Namespace types: MetricsTable
Parameters:
this (MetricsTable) : The metrics table object
pos (simple string) : The table position string
height (simple float) : The height of the table as a percentage of the charts height. By default, 0 auto-adjusts the height based on the text inside the cells
width (simple float) : The width of the table as a percentage of the charts width. By default, 0 auto-adjusts the width based on the text inside the cells
neutralBgColor (simple color) : The background color with transparency when neutral
method init(this, seas)
Initialize the seasonal data
Namespace types: SeasonalData
Parameters:
this (SeasonalData) : The seasonal data object
seas (simple Seasonality) : The seasonality of the matrix data
method init(this, data, pos, maxNumOfYears, height, width, extended, neutralTxtColor, neutralBgColor)
Initialize the seasonal table object with the given colors in the given position
Namespace types: SeasonalTable
Parameters:
this (SeasonalTable) : The seasonal table object
data (SeasonalData) : The seasonality data of the table
pos (simple string) : The table position string
maxNumOfYears (simple int) : The maximum number of years that fit into the table
height (simple float) : The height of the table as a percentage of the charts height. By default, 0 auto-adjusts the height based on the text inside the cells
width (simple float) : The width of the table as a percentage of the charts width. By default, 0 auto-adjusts the width based on the text inside the cells
extended (simple bool) : The seasonal table with extended columns for performance
neutralTxtColor (simple color) : The text color when neutral
neutralBgColor (simple color) : The background color with transparency when neutral
method update(this, wins, losses, numOfInconclusiveExits)
Update the strategy info data of the strategy
Namespace types: StatsData
Parameters:
this (StatsData) : The strategy statistics object
wins (SideStats)
losses (SideStats)
numOfInconclusiveExits (int) : The number of inconclusive trades
method update(this, stats, positiveTxtColor, negativeTxtColor, negativeBgColor, neutralBgColor)
Update the stats table object with the given data
Namespace types: StatsTable
Parameters:
this (StatsTable) : The stats table object
stats (StatsData) : The stats data to update the table
positiveTxtColor (simple color) : The text color when positive
negativeTxtColor (simple color) : The text color when negative
negativeBgColor (simple color) : The background color with transparency when negative
neutralBgColor (simple color) : The background color with transparency when neutral
method update(this, stats, buyAndHoldPerc, positiveTxtColor, negativeTxtColor, positiveBgColor, negativeBgColor)
Update the metrics table object with the given data
Namespace types: MetricsTable
Parameters:
this (MetricsTable) : The metrics table object
stats (StatsData) : The stats data to update the table
buyAndHoldPerc (float) : The buy and hold percetage
positiveTxtColor (simple color) : The text color when positive
negativeTxtColor (simple color) : The text color when negative
positiveBgColor (simple color) : The background color with transparency when positive
negativeBgColor (simple color) : The background color with transparency when negative
method update(this)
Update the seasonal data based on the season and eon timeframe
Namespace types: SeasonalData
Parameters:
this (SeasonalData) : The seasonal data object
method update(this, data, positiveTxtColor, negativeTxtColor, neutralTxtColor, positiveBgColor, negativeBgColor, neutralBgColor, timeBgColor)
Update the seasonal table object with the given data
Namespace types: SeasonalTable
Parameters:
this (SeasonalTable) : The seasonal table object
data (SeasonalData) : The seasonal cell data to update the table
positiveTxtColor (simple color) : The text color when positive
negativeTxtColor (simple color) : The text color when negative
neutralTxtColor (simple color) : The text color when neutral
positiveBgColor (simple color) : The background color with transparency when positive
negativeBgColor (simple color) : The background color with transparency when negative
neutralBgColor (simple color) : The background color with transparency when neutral
timeBgColor (simple color) : The background color of the time gradient
SideStats
Object that represents the strategy statistics data of one side win or lose
Fields:
numOf (series int)
sumFreeProfit (series float)
freeProfitStDev (series float)
sumProfit (series float)
profitStDev (series float)
sumGain (series float)
gainStDev (series float)
avgQuantityPerc (series float)
avgCapitalRiskPerc (series float)
avgTPExecutedCount (series float)
avgRiskRewardRatio (series float)
maxStreak (series int)
StatsTable
Object that represents the stats table
Fields:
table (series table) : The actual table
rows (series int) : The number of rows of the table
columns (series int) : The number of columns of the table
StatsData
Object that represents the statistics data of the strategy
Fields:
wins (SideStats)
losses (SideStats)
numOfInconclusiveExits (series int)
avgFreeProfitStr (series string)
freeProfitStDevStr (series string)
lossFreeProfitStDevStr (series string)
avgProfitStr (series string)
profitStDevStr (series string)
lossProfitStDevStr (series string)
avgQuantityStr (series string)
MetricsTable
Object that represents the metrics table
Fields:
table (series table) : The actual table
rows (series int) : The number of rows of the table
columns (series int) : The number of columns of the table
SeasonalData
Object that represents the seasonal table dynamic data
Fields:
seasonality (series Seasonality)
eonToMatrixRow (map)
numOfEons (series int)
mostRecentMatrixRow (series int)
balances (matrix)
returnPercs (matrix)
maxDDs (matrix)
eonReturnPercs (array)
eonCAGRs (array)
eonMaxDDs (array)
SeasonalTable
Object that represents the seasonal table
Fields:
table (series table) : The actual table
headRows (series int) : The number of head rows of the table
headColumns (series int) : The number of head columns of the table
eonRows (series int) : The number of eon rows of the table
seasonColumns (series int) : The number of season columns of the table
statsRows (series int)
statsColumns (series int) : The number of stats columns of the table
rows (series int) : The number of rows of the table
columns (series int) : The number of columns of the table
extended (series bool) : Whether the table has additional performance statistics Library

Average SL% Calculator with TP Levels by GorkiAverage Stop Loss And Take Profit Calculator For Futures Trading by Gorki
Description
The "Average SL% Calculator with TP Levels" script, is a simple tool for traders to plan the trades and check how much loss they are going to receive if they run this strategy. This script calculates the average price of up to four entry points, determines the percentage distance to the stop-loss level, and provides potential loss information based on margin and leverage. Additionally, it includes multiple take-profit levels to help traders systematically capture profits. Visual elements such as horizontal lines and labels make it easy to monitor key levels directly on the chart.
Why To Use This Indicator?
Risk Management: Automatically calculates the percentage distance to the stop-loss level, helping you to understand potential losses.
Profit Optimization: Supports up to four take-profit levels, enabling a structured approach to capturing gains.
Visual Clarity: Displays key levels and important information directly on the chart for easy monitoring.
Alerts: Generates alerts when the price crosses specified levels, ensuring you never miss critical trading signals.
How to Use the Script
Add the Script to Your Chart: Apply the script to your PulseWire chart.
Set Input Values: Entry Points: Define up to four limit prices (LIMIT 1, LIMIT 2, LIMIT 3, LIMIT 4).
Stop-Loss: Set your stop-loss price (STOP LOSS).
Take Profits: Specify up to four take-profit levels (Take Profit 1, Take Profit 2, Take Profit 3, Take Profit 4).
Leverage: Input your leverage factor.
Margin: Enter the total margin amount for the trade.
View Calculations: The script will calculate the average entry price, the percentage distance to the stop-loss, and the potential loss based on margin and leverage.
Monitor Levels: Horizontal lines and labels will appear on the chart, showing entry points, stop-loss, and take-profit levels.
Set Alerts: Alerts will trigger when the price crosses your defined levels, helping you to take timely action.
Calculation Details
Average Price: Calculated as the mean of the specified limit prices.
Distance to Stop-Loss: Determined as the percentage difference between the average price and the stop-loss level.
Leveraged Distance: The stop-loss distance percentage multiplied by the leverage factor.
Potential Loss: Calculated by applying the leveraged distance percentage to the margin amount.
Take Profit Percentages: The percentage difference between the average price and each take-profit level.
This comprehensive indicator is a must-have for any trader looking to manage risks effectively while maximizing potential profits. Happy trading! Indicator

Indicator

Strategy

Indicator
