Kelly Position Size CalculatorThis position sizing calculator implements the Kelly Criterion, developed by John L. Kelly Jr. at Bell Laboratories in 1956, to determine mathematically optimal position sizes for maximizing long-term wealth growth. Unlike arbitrary position sizing methods, this tool provides a scientifically solution based on your strategy's actual performance statistics and incorporates modern refinements from over six decades of academic research.
The Kelly Criterion addresses a fundamental question in capital allocation: "What fraction of capital should be allocated to each opportunity to maximize growth while avoiding ruin?" This question has profound implications for financial markets, where traders and investors constantly face decisions about optimal capital allocation (Van Tharp, 2007).
Theoretical Foundation
The Kelly Criterion for binary outcomes is expressed as f* = (bp - q) / b, where f* represents the optimal fraction of capital to allocate, b denotes the risk-reward ratio, p indicates the probability of success, and q represents the probability of loss (Kelly, 1956). This formula maximizes the expected logarithm of wealth, ensuring maximum long-term growth rate while avoiding the risk of ruin.
The mathematical elegance of Kelly's approach lies in its derivation from information theory. Kelly's original work was motivated by Claude Shannon's information theory (Shannon, 1948), recognizing that maximizing the logarithm of wealth is equivalent to maximizing the rate of information transmission. This connection between information theory and wealth accumulation provides a deep theoretical foundation for optimal position sizing.
The logarithmic utility function underlying the Kelly Criterion naturally embodies several desirable properties for capital management. It exhibits decreasing marginal utility, penalizes large losses more severely than it rewards equivalent gains, and focuses on geometric rather than arithmetic mean returns, which is appropriate for compounding scenarios (Thorp, 2006).
Scientific Implementation
This calculator extends beyond basic Kelly implementation by incorporating state of the art refinements from academic research:
Parameter Uncertainty Adjustment: Following Michaud (1989), the implementation applies Bayesian shrinkage to account for parameter estimation error inherent in small sample sizes. The adjustment formula f_adjusted = f_kelly × confidence_factor + f_conservative × (1 - confidence_factor) addresses the overconfidence bias documented by Baker and McHale (2012), where the confidence factor increases with sample size and the conservative estimate equals 0.25 (quarter Kelly).
Sample Size Confidence: The reliability of Kelly calculations depends critically on sample size. Research by Browne and Whitt (1996) provides theoretical guidance on minimum sample requirements, suggesting that at least 30 independent observations are necessary for meaningful parameter estimates, with 100 or more trades providing reliable estimates for most trading strategies.
Universal Asset Compatibility: The calculator employs intelligent asset detection using TradingView's built-in symbol information, automatically adapting calculations for different asset classes without manual configuration.
ASSET SPECIFIC IMPLEMENTATION
Equity Markets: For stocks and ETFs, position sizing follows the calculation Shares = floor(Kelly Fraction × Account Size / Share Price). This straightforward approach reflects whole share constraints while accommodating fractional share trading capabilities.
Foreign Exchange Markets: Forex markets require lot-based calculations following Lot Size = Kelly Fraction × Account Size / (100,000 × Base Currency Value). The calculator automatically handles major currency pairs with appropriate pip value calculations, following industry standards described by Archer (2010).
Futures Markets: Futures position sizing accounts for leverage and margin requirements through Contracts = floor(Kelly Fraction × Account Size / Margin Requirement). The calculator estimates margin requirements as a percentage of contract notional value, with specific adjustments for micro-futures contracts that have smaller sizes and reduced margin requirements (Kaufman, 2013).
Index and Commodity Markets: These markets combine characteristics of both equity and futures markets. The calculator automatically detects whether instruments are cash-settled or futures-based, applying appropriate sizing methodologies with correct point value calculations.
Risk Management Integration
The calculator integrates sophisticated risk assessment through two primary modes:
Stop Loss Integration: When fixed stop-loss levels are defined, risk calculation follows Risk per Trade = Position Size × Stop Loss Distance. This ensures that the Kelly fraction accounts for actual risk exposure rather than theoretical maximum loss, with stop-loss distance measured in appropriate units for each asset class.
Strategy Drawdown Assessment: For discretionary exit strategies, risk estimation uses maximum historical drawdown through Risk per Trade = Position Value × (Maximum Drawdown / 100). This approach assumes that individual trade losses will not exceed the strategy's historical maximum drawdown, providing a reasonable estimate for strategies with well-defined risk characteristics.
Fractional Kelly Approaches
Pure Kelly sizing can produce substantial volatility, leading many practitioners to adopt fractional Kelly approaches. MacLean, Sanegre, Zhao, and Ziemba (2004) analyze the trade-offs between growth rate and volatility, demonstrating that half-Kelly typically reduces volatility by approximately 75% while sacrificing only 25% of the growth rate.
The calculator provides three primary Kelly modes to accommodate different risk preferences and experience levels. Full Kelly maximizes growth rate while accepting higher volatility, making it suitable for experienced practitioners with strong risk tolerance and robust capital bases. Half Kelly offers a balanced approach popular among professional traders, providing optimal risk-return balance by reducing volatility significantly while maintaining substantial growth potential. Quarter Kelly implements a conservative approach with low volatility, recommended for risk-averse traders or those new to Kelly methodology who prefer gradual introduction to optimal position sizing principles.
Empirical Validation and Performance
Extensive academic research supports the theoretical advantages of Kelly sizing. Hakansson and Ziemba (1995) provide a comprehensive review of Kelly applications in finance, documenting superior long-term performance across various market conditions and asset classes. Estrada (2008) analyzes Kelly performance in international equity markets, finding that Kelly-based strategies consistently outperform fixed position sizing approaches over extended periods across 19 developed markets over a 30-year period.
Several prominent investment firms have successfully implemented Kelly-based position sizing. Pabrai (2007) documents the application of Kelly principles at Berkshire Hathaway, noting Warren Buffett's concentrated portfolio approach aligns closely with Kelly optimal sizing for high-conviction investments. Quantitative hedge funds, including Renaissance Technologies and AQR, have incorporated Kelly-based risk management into their systematic trading strategies.
Practical Implementation Guidelines
Successful Kelly implementation requires systematic application with attention to several critical factors:
Parameter Estimation: Accurate parameter estimation represents the greatest challenge in practical Kelly implementation. Brown (1976) notes that small errors in probability estimates can lead to significant deviations from optimal performance. The calculator addresses this through Bayesian adjustments and confidence measures.
Sample Size Requirements: Users should begin with conservative fractional Kelly approaches until achieving sufficient historical data. Strategies with fewer than 30 trades may produce unreliable Kelly estimates, regardless of adjustments. Full confidence typically requires 100 or more independent trade observations.
Market Regime Considerations: Parameters that accurately describe historical performance may not reflect future market conditions. Ziemba (2003) recommends regular parameter updates and conservative adjustments when market conditions change significantly.
Professional Features and Customization
The calculator provides comprehensive customization options for professional applications:
Multiple Color Schemes: Eight professional color themes (Gold, EdgeTools, Behavioral, Quant, Ocean, Fire, Matrix, Arctic) with dark and light theme compatibility ensure optimal visibility across different trading environments.
Flexible Display Options: Adjustable table size and position accommodate various chart layouts and user preferences, while maintaining analytical depth and clarity.
Comprehensive Results: The results table presents essential information including asset specifications, strategy statistics, Kelly calculations, sample confidence measures, position values, risk assessments, and final position sizes in appropriate units for each asset class.
Limitations and Considerations
Like any analytical tool, the Kelly Criterion has important limitations that users must understand:
Stationarity Assumption: The Kelly Criterion assumes that historical strategy statistics represent future performance characteristics. Non-stationary market conditions may invalidate this assumption, as noted by Lo and MacKinlay (1999).
Independence Requirement: Each trade should be independent to avoid correlation effects. Many trading strategies exhibit serial correlation in returns, which can affect optimal position sizing and may require adjustments for portfolio applications.
Parameter Sensitivity: Kelly calculations are sensitive to parameter accuracy. Regular calibration and conservative approaches are essential when parameter uncertainty is high.
Transaction Costs: The implementation incorporates user-defined transaction costs but assumes these remain constant across different position sizes and market conditions, following Ziemba (2003).
Advanced Applications and Extensions
Multi-Asset Portfolio Considerations: While this calculator optimizes individual position sizes, portfolio-level applications require additional considerations for correlation effects and aggregate risk management. Simplified portfolio approaches include treating positions independently with correlation adjustments.
Behavioral Factors: Behavioral finance research reveals systematic biases that can interfere with Kelly implementation. Kahneman and Tversky (1979) document loss aversion, overconfidence, and other cognitive biases that lead traders to deviate from optimal strategies. Successful implementation requires disciplined adherence to calculated recommendations.
Time-Varying Parameters: Advanced implementations may incorporate time-varying parameter models that adjust Kelly recommendations based on changing market conditions, though these require sophisticated econometric techniques and substantial computational resources.
Comprehensive Usage Instructions and Practical Examples
Implementation begins with loading the calculator on your desired trading instrument's chart. The system automatically detects asset type across stocks, forex, futures, and cryptocurrency markets while extracting current price information. Navigation to the indicator settings allows input of your specific strategy parameters.
Strategy statistics configuration requires careful attention to several key metrics. The win rate should be calculated from your backtest results using the formula of winning trades divided by total trades multiplied by 100. Average win represents the sum of all profitable trades divided by the number of winning trades, while average loss calculates the sum of all losing trades divided by the number of losing trades, entered as a positive number. The total historical trades parameter requires the complete number of trades in your backtest, with a minimum of 30 trades recommended for basic functionality and 100 or more trades optimal for statistical reliability. Account size should reflect your available trading capital, specifically the risk capital allocated for trading rather than total net worth.
Risk management configuration adapts to your specific trading approach. The stop loss setting should be enabled if you employ fixed stop-loss exits, with the stop loss distance specified in appropriate units depending on the asset class. For stocks, this distance is measured in dollars, for forex in pips, and for futures in ticks. When stop losses are not used, the maximum strategy drawdown percentage from your backtest provides the risk assessment baseline. Kelly mode selection offers three primary approaches: Full Kelly for aggressive growth with higher volatility suitable for experienced practitioners, Half Kelly for balanced risk-return optimization popular among professional traders, and Quarter Kelly for conservative approaches with reduced volatility.
Display customization ensures optimal integration with your trading environment. Eight professional color themes provide optimization for different chart backgrounds and personal preferences. Table position selection allows optimal placement within your chart layout, while table size adjustment ensures readability across different screen resolutions and viewing preferences.
Detailed Practical Examples
Example 1: SPY Swing Trading Strategy
Consider a professionally developed swing trading strategy for SPY (S&P 500 ETF) with backtesting results spanning 166 total trades. The strategy achieved 110 winning trades, representing a 66.3% win rate, with an average winning trade of $2,200 and average losing trade of $862. The maximum drawdown reached 31.4% during the testing period, and the available trading capital amounts to $25,000. This strategy employs discretionary exits without fixed stop losses.
Implementation requires loading the calculator on the SPY daily chart and configuring the parameters accordingly. The win rate input receives 66.3, while average win and loss inputs receive 2200 and 862 respectively. Total historical trades input requires 166, with account size set to 25000. The stop loss function remains disabled due to the discretionary exit approach, with maximum strategy drawdown set to 31.4%. Half Kelly mode provides the optimal balance between growth and risk management for this application.
The calculator generates several key outputs for this scenario. The risk-reward ratio calculates automatically to 2.55, while the Kelly fraction reaches approximately 53% before scientific adjustments. Sample confidence achieves 100% given the 166 trades providing high statistical confidence. The recommended position settles at approximately 27% after Half Kelly and Bayesian adjustment factors. Position value reaches approximately $6,750, translating to 16 shares at a $420 SPY price. Risk per trade amounts to approximately $2,110, representing 31.4% of position value, with expected value per trade reaching approximately $1,466. This recommendation represents the mathematically optimal balance between growth potential and risk management for this specific strategy profile.
Example 2: EURUSD Day Trading with Stop Losses
A high-frequency EURUSD day trading strategy demonstrates different parameter requirements compared to swing trading approaches. This strategy encompasses 89 total trades with a 58% win rate, generating an average winning trade of $180 and average losing trade of $95. The maximum drawdown reached 12% during testing, with available capital of $10,000. The strategy employs fixed stop losses at 25 pips and take profit targets at 45 pips, providing clear risk-reward parameters.
Implementation begins with loading the calculator on the EURUSD 1-hour chart for appropriate timeframe alignment. Parameter configuration includes win rate at 58, average win at 180, and average loss at 95. Total historical trades input receives 89, with account size set to 10000. The stop loss function is enabled with distance set to 25 pips, reflecting the fixed exit strategy. Quarter Kelly mode provides conservative positioning due to the smaller sample size compared to the previous example.
Results demonstrate the impact of smaller sample sizes on Kelly calculations. The risk-reward ratio calculates to 1.89, while the Kelly fraction reaches approximately 32% before adjustments. Sample confidence achieves 89%, providing moderate statistical confidence given the 89 trades. The recommended position settles at approximately 7% after Quarter Kelly application and Bayesian shrinkage adjustment for the smaller sample. Position value amounts to approximately $700, translating to 0.07 standard lots. Risk per trade reaches approximately $175, calculated as 25 pips multiplied by lot size and pip value, with expected value per trade at approximately $49. This conservative position sizing reflects the smaller sample size, with position sizes expected to increase as trade count surpasses 100 and statistical confidence improves.
Example 3: ES1! Futures Systematic Strategy
Systematic futures trading presents unique considerations for Kelly criterion application, as demonstrated by an E-mini S&P 500 futures strategy encompassing 234 total trades. This systematic approach achieved a 45% win rate with an average winning trade of $1,850 and average losing trade of $720. The maximum drawdown reached 18% during the testing period, with available capital of $50,000. The strategy employs 15-tick stop losses with contract specifications of $50 per tick, providing precise risk control mechanisms.
Implementation involves loading the calculator on the ES1! 15-minute chart to align with the systematic trading timeframe. Parameter configuration includes win rate at 45, average win at 1850, and average loss at 720. Total historical trades receives 234, providing robust statistical foundation, with account size set to 50000. The stop loss function is enabled with distance set to 15 ticks, reflecting the systematic exit methodology. Half Kelly mode balances growth potential with appropriate risk management for futures trading.
Results illustrate how favorable risk-reward ratios can support meaningful position sizing despite lower win rates. The risk-reward ratio calculates to 2.57, while the Kelly fraction reaches approximately 16%, lower than previous examples due to the sub-50% win rate. Sample confidence achieves 100% given the 234 trades providing high statistical confidence. The recommended position settles at approximately 8% after Half Kelly adjustment. Estimated margin per contract amounts to approximately $2,500, resulting in a single contract allocation. Position value reaches approximately $2,500, with risk per trade at $750, calculated as 15 ticks multiplied by $50 per tick. Expected value per trade amounts to approximately $508. Despite the lower win rate, the favorable risk-reward ratio supports meaningful position sizing, with single contract allocation reflecting appropriate leverage management for futures trading.
Example 4: MES1! Micro-Futures for Smaller Accounts
Micro-futures contracts provide enhanced accessibility for smaller trading accounts while maintaining identical strategy characteristics. Using the same systematic strategy statistics from the previous example but with available capital of $15,000 and micro-futures specifications of $5 per tick with reduced margin requirements, the implementation demonstrates improved position sizing granularity.
Kelly calculations remain identical to the full-sized contract example, maintaining the same risk-reward dynamics and statistical foundations. However, estimated margin per contract reduces to approximately $250 for micro-contracts, enabling allocation of 4-5 micro-contracts. Position value reaches approximately $1,200, while risk per trade calculates to $75, derived from 15 ticks multiplied by $5 per tick. This granularity advantage provides better position size precision for smaller accounts, enabling more accurate Kelly implementation without requiring large capital commitments.
Example 5: Bitcoin Swing Trading
Cryptocurrency markets present unique challenges requiring modified Kelly application approaches. A Bitcoin swing trading strategy on BTCUSD encompasses 67 total trades with a 71% win rate, generating average winning trades of $3,200 and average losing trades of $1,400. Maximum drawdown reached 28% during testing, with available capital of $30,000. The strategy employs technical analysis for exits without fixed stop losses, relying on price action and momentum indicators.
Implementation requires conservative approaches due to cryptocurrency volatility characteristics. Quarter Kelly mode is recommended despite the high win rate to account for crypto market unpredictability. Expected position sizing remains reduced due to the limited sample size of 67 trades, requiring additional caution until statistical confidence improves. Regular parameter updates are strongly recommended due to cryptocurrency market evolution and changing volatility patterns that can significantly impact strategy performance characteristics.
Advanced Usage Scenarios
Portfolio position sizing requires sophisticated consideration when running multiple strategies simultaneously. Each strategy should have its Kelly fraction calculated independently to maintain mathematical integrity. However, correlation adjustments become necessary when strategies exhibit related performance patterns. Moderately correlated strategies should receive individual position size reductions of 10-20% to account for overlapping risk exposure. Aggregate portfolio risk monitoring ensures total exposure remains within acceptable limits across all active strategies. Professional practitioners often consider using lower fractional Kelly approaches, such as Quarter Kelly, when running multiple strategies simultaneously to provide additional safety margins.
Parameter sensitivity analysis forms a critical component of professional Kelly implementation. Regular validation procedures should include monthly parameter updates using rolling 100-trade windows to capture evolving market conditions while maintaining statistical relevance. Sensitivity testing involves varying win rates by ±5% and average win/loss ratios by ±10% to assess recommendation stability under different parameter assumptions. Out-of-sample validation reserves 20% of historical data for parameter verification, ensuring that optimization doesn't create curve-fitted results. Regime change detection monitors actual performance against expected metrics, triggering parameter reassessment when significant deviations occur.
Risk management integration requires professional overlay considerations beyond pure Kelly calculations. Daily loss limits should cease trading when daily losses exceed twice the calculated risk per trade, preventing emotional decision-making during adverse periods. Maximum position limits should never exceed 25% of account value in any single position regardless of Kelly recommendations, maintaining diversification principles. Correlation monitoring reduces position sizes when holding multiple correlated positions that move together during market stress. Volatility adjustments consider reducing position sizes during periods of elevated VIX above 25 for equity strategies, adapting to changing market conditions.
Troubleshooting and Optimization
Professional implementation often encounters specific challenges requiring systematic troubleshooting approaches. Zero position size displays typically result from insufficient capital for minimum position sizes, negative expected values, or extremely conservative Kelly calculations. Solutions include increasing account size, verifying strategy statistics for accuracy, considering Quarter Kelly mode for conservative approaches, or reassessing overall strategy viability when fundamental issues exist.
Extremely high Kelly fractions exceeding 50% usually indicate underlying problems with parameter estimation. Common causes include unrealistic win rates, inflated risk-reward ratios, or curve-fitted backtest results that don't reflect genuine trading conditions. Solutions require verifying backtest methodology, including all transaction costs in calculations, testing strategies on out-of-sample data, and using conservative fractional Kelly approaches until parameter reliability improves.
Low sample confidence below 50% reflects insufficient historical trades for reliable parameter estimation. This situation demands gathering additional trading data, using Quarter Kelly approaches until reaching 100 or more trades, applying extra conservatism in position sizing, and considering paper trading to build statistical foundations without capital risk.
Inconsistent results across similar strategies often stem from parameter estimation differences, market regime changes, or strategy degradation over time. Professional solutions include standardizing backtest methodology across all strategies, updating parameters regularly to reflect current conditions, and monitoring live performance against expectations to identify deteriorating strategies.
Position sizes that appear inappropriately large or small require careful validation against traditional risk management principles. Professional standards recommend never risking more than 2-3% per trade regardless of Kelly calculations. Calibration should begin with Quarter Kelly approaches, gradually increasing as comfort and confidence develop. Most institutional traders utilize 25-50% of full Kelly recommendations to balance growth with prudent risk management.
Market condition adjustments require dynamic approaches to Kelly implementation. Trending markets may support full Kelly recommendations when directional momentum provides favorable conditions. Ranging or volatile markets typically warrant reducing to Half or Quarter Kelly to account for increased uncertainty. High correlation periods demand reducing individual position sizes when multiple positions move together, concentrating risk exposure. News and event periods often justify temporary position size reductions during high-impact releases that can create unpredictable market movements.
Performance monitoring requires systematic protocols to ensure Kelly implementation remains effective over time. Weekly reviews should compare actual versus expected win rates and average win/loss ratios to identify parameter drift or strategy degradation. Position size efficiency and execution quality monitoring ensures that calculated recommendations translate effectively into actual trading results. Tracking correlation between calculated and realized risk helps identify discrepancies between theoretical and practical risk exposure.
Monthly calibration provides more comprehensive parameter assessment using the most recent 100 trades to maintain statistical relevance while capturing current market conditions. Kelly mode appropriateness requires reassessment based on recent market volatility and performance characteristics, potentially shifting between Full, Half, and Quarter Kelly approaches as conditions change. Transaction cost evaluation ensures that commission structures, spreads, and slippage estimates remain accurate and current.
Quarterly strategic reviews encompass comprehensive strategy performance analysis comparing long-term results against expectations and identifying trends in effectiveness. Market regime assessment evaluates parameter stability across different market conditions, determining whether strategy characteristics remain consistent or require fundamental adjustments. Strategic modifications to position sizing methodology may become necessary as markets evolve or trading approaches mature, ensuring that Kelly implementation continues supporting optimal capital allocation objectives.
Professional Applications
This calculator serves diverse professional applications across the financial industry. Quantitative hedge funds utilize the implementation for systematic position sizing within algorithmic trading frameworks, where mathematical precision and consistent application prove essential for institutional capital management. Professional discretionary traders benefit from optimized position management that removes emotional bias while maintaining flexibility for market-specific adjustments. Portfolio managers employ the calculator for developing risk-adjusted allocation strategies that enhance returns while maintaining prudent risk controls across diverse asset classes and investment strategies.
Individual traders seeking mathematical optimization of capital allocation find the calculator provides institutional-grade methodology previously available only to professional money managers. The Kelly Criterion establishes theoretical foundation for optimal capital allocation across both single strategies and multiple trading systems, offering significant advantages over arbitrary position sizing methods that rely on intuition or fixed percentage approaches. Professional implementation ensures consistent application of mathematically sound principles while adapting to changing market conditions and strategy performance characteristics.
Conclusion
The Kelly Criterion represents one of the few mathematically optimal solutions to fundamental investment problems. When properly understood and carefully implemented, it provides significant competitive advantage in financial markets. This calculator implements modern refinements to Kelly's original formula while maintaining accessibility for practical trading applications.
Success with Kelly requires ongoing learning, systematic application, and continuous refinement based on market feedback and evolving research. Users who master Kelly principles and implement them systematically can expect superior risk-adjusted returns and more consistent capital growth over extended periods.
The extensive academic literature provides rich resources for deeper study, while practical experience builds the intuition necessary for effective implementation. Regular parameter updates, conservative approaches with limited data, and disciplined adherence to calculated recommendations are essential for optimal results.
References
Archer, M. D. (2010). Getting Started in Currency Trading: Winning in Today's Forex Market (3rd ed.). John Wiley & Sons.
Baker, R. D., & McHale, I. G. (2012). An empirical Bayes approach to optimising betting strategies. Journal of the Royal Statistical Society: Series D (The Statistician), 61(1), 75-92.
Breiman, L. (1961). Optimal gambling systems for favorable games. In J. Neyman (Ed.), Proceedings of the Fourth Berkeley Symposium on Mathematical Statistics and Probability (pp. 65-78). University of California Press.
Brown, D. B. (1976). Optimal portfolio growth: Logarithmic utility and the Kelly criterion. In W. T. Ziemba & R. G. Vickson (Eds.), Stochastic Optimization Models in Finance (pp. 1-23). Academic Press.
Browne, S., & Whitt, W. (1996). Portfolio choice and the Bayesian Kelly criterion. Advances in Applied Probability, 28(4), 1145-1176.
Estrada, J. (2008). Geometric mean maximization: An overlooked portfolio approach? The Journal of Investing, 17(4), 134-147.
Hakansson, N. H., & Ziemba, W. T. (1995). Capital growth theory. In R. A. Jarrow, V. Maksimovic, & W. T. Ziemba (Eds.), Handbooks in Operations Research and Management Science (Vol. 9, pp. 65-86). Elsevier.
Kahneman, D., & Tversky, A. (1979). Prospect theory: An analysis of decision under risk. Econometrica, 47(2), 263-291.
Kaufman, P. J. (2013). Trading Systems and Methods (5th ed.). John Wiley & Sons.
Kelly Jr, J. L. (1956). A new interpretation of information rate. Bell System Technical Journal, 35(4), 917-926.
Lo, A. W., & MacKinlay, A. C. (1999). A Non-Random Walk Down Wall Street. Princeton University Press.
MacLean, L. C., Sanegre, E. O., Zhao, Y., & Ziemba, W. T. (2004). Capital growth with security. Journal of Economic Dynamics and Control, 28(4), 937-954.
MacLean, L. C., Thorp, E. O., & Ziemba, W. T. (2011). The Kelly Capital Growth Investment Criterion: Theory and Practice. World Scientific.
Michaud, R. O. (1989). The Markowitz optimization enigma: Is 'optimized' optimal? Financial Analysts Journal, 45(1), 31-42.
Pabrai, M. (2007). The Dhandho Investor: The Low-Risk Value Method to High Returns. John Wiley & Sons.
Shannon, C. E. (1948). A mathematical theory of communication. Bell System Technical Journal, 27(3), 379-423.
Tharp, V. K. (2007). Trade Your Way to Financial Freedom (2nd ed.). McGraw-Hill.
Thorp, E. O. (2006). The Kelly criterion in blackjack sports betting, and the stock market. In L. C. MacLean, E. O. Thorp, & W. T. Ziemba (Eds.), The Kelly Capital Growth Investment Criterion: Theory and Practice (pp. 789-832). World Scientific.
Van Tharp, K. (2007). Trade Your Way to Financial Freedom (2nd ed.). McGraw-Hill Education.
Vince, R. (1992). The Mathematics of Money Management: Risk Analysis Techniques for Traders. John Wiley & Sons.
Vince, R., & Zhu, H. (2015). Optimal betting under parameter uncertainty. Journal of Statistical Planning and Inference, 161, 19-31.
Ziemba, W. T. (2003). The Stochastic Programming Approach to Asset, Liability, and Wealth Management. The Research Foundation of AIMR.
Further Reading
For comprehensive understanding of Kelly Criterion applications and advanced implementations:
MacLean, L. C., Thorp, E. O., & Ziemba, W. T. (2011). The Kelly Capital Growth Investment Criterion: Theory and Practice. World Scientific.
Vince, R. (1992). The Mathematics of Money Management: Risk Analysis Techniques for Traders. John Wiley & Sons.
Thorp, E. O. (2017). A Man for All Markets: From Las Vegas to Wall Street. Random House.
Cover, T. M., & Thomas, J. A. (2006). Elements of Information Theory (2nd ed.). John Wiley & Sons.
Ziemba, W. T., & Vickson, R. G. (Eds.). (2006). Stochastic Optimization Models in Finance. World Scientific.
Wyszukaj w skryptach "美股标普500指数基金中国"
Drawdown Distribution Analysis (DDA) ACADEMIC FOUNDATION AND RESEARCH BACKGROUND
The Drawdown Distribution Analysis indicator implements quantitative risk management principles, drawing upon decades of academic research in portfolio theory, behavioral finance, and statistical risk modeling. This tool provides risk assessment capabilities for traders and portfolio managers seeking to understand their current position within historical drawdown patterns.
The theoretical foundation of this indicator rests on modern portfolio theory as established by Markowitz (1952), who introduced the fundamental concepts of risk-return optimization that continue to underpin contemporary portfolio management. Sharpe (1966) later expanded this framework by developing risk-adjusted performance measures, most notably the Sharpe ratio, which remains a cornerstone of performance evaluation in financial markets.
The specific focus on drawdown analysis builds upon the work of Chekhlov, Uryasev and Zabarankin (2005), who provided the mathematical framework for incorporating drawdown measures into portfolio optimization. Their research demonstrated that traditional mean-variance optimization often fails to capture the full risk profile of investment strategies, particularly regarding sequential losses. More recent work by Goldberg and Mahmoud (2017) has brought these theoretical concepts into practical application within institutional risk management frameworks.
Value at Risk methodology, as comprehensively outlined by Jorion (2007), provides the statistical foundation for the risk measurement components of this indicator. The coherent risk measures framework developed by Artzner et al. (1999) ensures that the risk metrics employed satisfy the mathematical properties required for sound risk management decisions. Additionally, the focus on downside risk follows the framework established by Sortino and Price (1994), while the drawdown-adjusted performance measures implement concepts introduced by Young (1991).
MATHEMATICAL METHODOLOGY
The core calculation methodology centers on a peak-tracking algorithm that continuously monitors the maximum price level achieved and calculates the percentage decline from this peak. The drawdown at any time t is defined as DD(t) = (P(t) - Peak(t)) / Peak(t) × 100, where P(t) represents the asset price at time t and Peak(t) represents the running maximum price observed up to time t.
Statistical distribution analysis forms the analytical backbone of the indicator. The system calculates key percentiles using the ta.percentile_nearest_rank() function to establish the 5th, 10th, 25th, 50th, 75th, 90th, and 95th percentiles of the historical drawdown distribution. This approach provides a complete picture of how the current drawdown compares to historical patterns.
Statistical significance assessment employs standard deviation bands at one, two, and three standard deviations from the mean, following the conventional approach where the upper band equals μ + nσ and the lower band equals μ - nσ. The Z-score calculation, defined as Z = (DD - μ) / σ, enables the identification of statistically extreme events, with thresholds set at |Z| > 2.5 for extreme drawdowns and |Z| > 3.0 for severe drawdowns, corresponding to confidence levels exceeding 99.4% and 99.7% respectively.
ADVANCED RISK METRICS
The indicator incorporates several risk-adjusted performance measures that extend beyond basic drawdown analysis. The Sharpe ratio calculation follows the standard formula Sharpe = (R - Rf) / σ, where R represents the annualized return, Rf represents the risk-free rate, and σ represents the annualized volatility. The system supports dynamic sourcing of the risk-free rate from the US 10-year Treasury yield or allows for manual specification.
The Sortino ratio addresses the limitation of the Sharpe ratio by focusing exclusively on downside risk, calculated as Sortino = (R - Rf) / σd, where σd represents the downside deviation computed using only negative returns. This measure provides a more accurate assessment of risk-adjusted performance for strategies that exhibit asymmetric return distributions.
The Calmar ratio, defined as Annual Return divided by the absolute value of Maximum Drawdown, offers a direct measure of return per unit of drawdown risk. This metric proves particularly valuable for comparing strategies or assets with different risk profiles, as it directly relates performance to the maximum historical loss experienced.
Value at Risk calculations provide quantitative estimates of potential losses at specified confidence levels. The 95% VaR corresponds to the 5th percentile of the drawdown distribution, while the 99% VaR corresponds to the 1st percentile. Conditional VaR, also known as Expected Shortfall, estimates the average loss in the worst 5% of scenarios, providing insight into tail risk that standard VaR measures may not capture.
To enable fair comparison across assets with different volatility characteristics, the indicator calculates volatility-adjusted drawdowns using the formula Adjusted DD = Raw DD / (Volatility / 20%). This normalization allows for meaningful comparison between high-volatility assets like cryptocurrencies and lower-volatility instruments like government bonds.
The Risk Efficiency Score represents a composite measure ranging from 0 to 100 that combines the Sharpe ratio and current percentile rank to provide a single metric for quick asset assessment. Higher scores indicate superior risk-adjusted performance relative to historical patterns.
COLOR SCHEMES AND VISUALIZATION
The indicator implements eight distinct color themes designed to accommodate different analytical preferences and market contexts. The EdgeTools theme employs a corporate blue palette that matches the design system used throughout the edgetools.org platform, ensuring visual consistency across analytical tools.
The Gold theme specifically targets precious metals analysis with warm tones that complement gold chart analysis, while the Quant theme provides a grayscale scheme suitable for analytical environments that prioritize clarity over aesthetic appeal. The Behavioral theme incorporates psychology-based color coding, using green to represent greed-driven market conditions and red to indicate fear-driven environments.
Additional themes include Ocean, Fire, Matrix, and Arctic schemes, each designed for specific market conditions or user preferences. All themes function effectively with both dark and light mode trading platforms, ensuring accessibility across different user interface configurations.
PRACTICAL APPLICATIONS
Asset allocation and portfolio construction represent primary use cases for this analytical framework. When comparing multiple assets such as Bitcoin, gold, and the S&P 500, traders can examine Risk Efficiency Scores to identify instruments offering superior risk-adjusted performance. The 95% VaR provides worst-case scenario comparisons, while volatility-adjusted drawdowns enable fair comparison despite varying volatility profiles.
The practical decision framework suggests that assets with Risk Efficiency Scores above 70 may be suitable for aggressive portfolio allocations, scores between 40 and 70 indicate moderate allocation potential, and scores below 40 suggest defensive positioning or avoidance. These thresholds should be adjusted based on individual risk tolerance and market conditions.
Risk management and position sizing applications utilize the current percentile rank to guide allocation decisions. When the current drawdown ranks above the 75th percentile of historical data, indicating that current conditions are better than 75% of historical periods, position increases may be warranted. Conversely, when percentile rankings fall below the 25th percentile, indicating elevated risk conditions, position reductions become advisable.
Institutional portfolio monitoring applications include hedge fund risk dashboard implementations where multiple strategies can be monitored simultaneously. Sharpe ratio tracking identifies deteriorating risk-adjusted performance across strategies, VaR monitoring ensures portfolios remain within established risk limits, and drawdown duration tracking provides valuable information for investor reporting requirements.
Market timing applications combine the statistical analysis with trend identification techniques. Strong buy signals may emerge when risk levels register as "Low" in conjunction with established uptrends, while extreme risk levels combined with downtrends may indicate exit or hedging opportunities. Z-scores exceeding 3.0 often signal statistically oversold conditions that may precede trend reversals.
STATISTICAL SIGNIFICANCE AND VALIDATION
The indicator provides 95% confidence intervals around current drawdown levels using the standard formula CI = μ ± 1.96σ. This statistical framework enables users to assess whether current conditions fall within normal market variation or represent statistically significant departures from historical patterns.
Risk level classification employs a dynamic assessment system based on percentile ranking within the historical distribution. Low risk designation applies when current drawdowns perform better than 50% of historical data, moderate risk encompasses the 25th to 50th percentile range, high risk covers the 10th to 25th percentile range, and extreme risk applies to the worst 10% of historical drawdowns.
Sample size considerations play a crucial role in statistical reliability. For daily data, the system requires a minimum of 252 trading days (approximately one year) but performs better with 500 or more observations. Weekly data analysis benefits from at least 104 weeks (two years) of history, while monthly data requires a minimum of 60 months (five years) for reliable statistical inference.
IMPLEMENTATION BEST PRACTICES
Parameter optimization should consider the specific characteristics of different asset classes. Equity analysis typically benefits from 500-day lookback periods with 21-day smoothing, while cryptocurrency analysis may employ 365-day lookback periods with 14-day smoothing to account for higher volatility patterns. Fixed income analysis often requires longer lookback periods of 756 days with 34-day smoothing to capture the lower volatility environment.
Multi-timeframe analysis provides hierarchical risk assessment capabilities. Daily timeframe analysis supports tactical risk management decisions, weekly analysis informs strategic positioning choices, and monthly analysis guides long-term allocation decisions. This hierarchical approach ensures that risk assessment occurs at appropriate temporal scales for different investment objectives.
Integration with complementary indicators enhances the analytical framework. Trend indicators such as RSI and moving averages provide directional bias context, volume analysis helps confirm the severity of drawdown conditions, and volatility measures like VIX or ATR assist in market regime identification.
ALERT SYSTEM AND AUTOMATION
The automated alert system monitors five distinct categories of risk events. Risk level changes trigger notifications when drawdowns move between risk categories, enabling proactive risk management responses. Statistical significance alerts activate when Z-scores exceed established threshold levels of 2.5 or 3.0 standard deviations.
New maximum drawdown alerts notify users when historical maximum levels are exceeded, indicating entry into uncharted risk territory. Poor risk efficiency alerts trigger when the composite risk efficiency score falls below 30, suggesting deteriorating risk-adjusted performance. Sharpe ratio decline alerts activate when risk-adjusted performance turns negative, indicating that returns no longer compensate for the risk undertaken.
TRADING STRATEGIES
Conservative risk parity strategies can be implemented by monitoring Risk Efficiency Scores across a diversified asset portfolio. Monthly rebalancing maintains equal risk contribution from each asset, with allocation reductions triggered when risk levels reach "High" status and complete exits executed when "Extreme" risk levels emerge. This approach typically results in lower overall portfolio volatility, improved risk-adjusted returns, and reduced maximum drawdown periods.
Tactical asset rotation strategies compare Risk Efficiency Scores across different asset classes to guide allocation decisions. Assets with scores exceeding 60 receive overweight allocations, while assets scoring below 40 receive underweight positions. Percentile rankings provide timing guidance for allocation adjustments, creating a systematic approach to asset allocation that responds to changing risk-return profiles.
Market timing strategies with statistical edges can be constructed by entering positions when Z-scores fall below -2.5, indicating statistically oversold conditions, and scaling out when Z-scores exceed 2.5, suggesting overbought conditions. The 95% VaR serves as a stop-loss reference point, while trend confirmation indicators provide additional validation for position entry and exit decisions.
LIMITATIONS AND CONSIDERATIONS
Several statistical limitations affect the interpretation and application of these risk measures. Historical bias represents a fundamental challenge, as past drawdown patterns may not accurately predict future risk characteristics, particularly during structural market changes or regime shifts. Sample dependence means that results can be sensitive to the selected lookback period, with shorter periods providing more responsive but potentially less stable estimates.
Market regime changes can significantly alter the statistical parameters underlying the analysis. During periods of structural market evolution, historical distributions may provide poor guidance for future expectations. Additionally, many financial assets exhibit return distributions with fat tails that deviate from normal distribution assumptions, potentially leading to underestimation of extreme event probabilities.
Practical limitations include execution risk, where theoretical signals may not translate directly into actual trading results due to factors such as slippage, timing delays, and market impact. Liquidity constraints mean that risk metrics assume perfect liquidity, which may not hold during stressed market conditions when risk management becomes most critical.
Transaction costs are not incorporated into risk-adjusted return calculations, potentially overstating the attractiveness of strategies that require frequent trading. Behavioral factors represent another limitation, as human psychology may override statistical signals, particularly during periods of extreme market stress when disciplined risk management becomes most challenging.
TECHNICAL IMPLEMENTATION
Performance optimization ensures reliable operation across different market conditions and timeframes. All technical analysis functions are extracted from conditional statements to maintain Pine Script compliance and ensure consistent execution. Memory efficiency is achieved through optimized variable scoping and array usage, while computational speed benefits from vectorized calculations where possible.
Data quality requirements include clean price data without gaps or errors that could distort distribution analysis. Sufficient historical data is essential, with a minimum of 100 bars required and 500 or more preferred for reliable statistical inference. Time alignment across related assets ensures meaningful comparison when conducting multi-asset analysis.
The configuration parameters are organized into logical groups to enhance usability. Core settings include the Distribution Analysis Period (100-2000 bars), Drawdown Smoothing Period (1-50 bars), and Price Source selection. Advanced metrics settings control risk-free rate sourcing, either from live market data or fixed rate specification, along with toggles for various risk-adjusted metric calculations.
Display options provide flexibility in visual presentation, including color theme selection from eight available schemes, automatic dark mode optimization, and control over table display, position lines, percentile bands, and standard deviation overlays. These options ensure that the indicator can be adapted to different analytical workflows and visual preferences.
CONCLUSION
The Drawdown Distribution Analysis indicator provides risk management tools for traders seeking to understand their current position within historical risk patterns. By combining established statistical methodology with practical usability features, the tool enables evidence-based risk assessment and portfolio optimization decisions.
The implementation draws upon established academic research while providing practical features that address real-world trading requirements. Dynamic risk-free rate integration ensures accurate risk-adjusted performance calculations, while multiple color schemes accommodate different analytical preferences and use cases.
Academic compliance is maintained through transparent methodology and acknowledgment of limitations. The tool implements peer-reviewed statistical techniques while clearly communicating the constraints and assumptions underlying the analysis. This approach ensures that users can make informed decisions about the appropriate application of the risk assessment framework within their broader trading and investment processes.
BIBLIOGRAPHY
Artzner, P., Delbaen, F., Eber, J.M. and Heath, D. (1999) 'Coherent Measures of Risk', Mathematical Finance, 9(3), pp. 203-228.
Chekhlov, A., Uryasev, S. and Zabarankin, M. (2005) 'Drawdown Measure in Portfolio Optimization', International Journal of Theoretical and Applied Finance, 8(1), pp. 13-58.
Goldberg, L.R. and Mahmoud, O. (2017) 'Drawdown: From Practice to Theory and Back Again', Journal of Risk Management in Financial Institutions, 10(2), pp. 140-152.
Jorion, P. (2007) Value at Risk: The New Benchmark for Managing Financial Risk. 3rd edn. New York: McGraw-Hill.
Markowitz, H. (1952) 'Portfolio Selection', Journal of Finance, 7(1), pp. 77-91.
Sharpe, W.F. (1966) 'Mutual Fund Performance', Journal of Business, 39(1), pp. 119-138.
Sortino, F.A. and Price, L.N. (1994) 'Performance Measurement in a Downside Risk Framework', Journal of Investing, 3(3), pp. 59-64.
Young, T.W. (1991) 'Calmar Ratio: A Smoother Tool', Futures, 20(1), pp. 40-42.
Pivot and Wick Boxes with Break Signals█ OVERVIEW
This Pine Script® indicator draws support and resistance levels based on high and low pivot points and the wicks of pivot candles. When the price breaks these levels, breakout signals are generated, with an optional volume filter for greater precision. The indicator is fully customizable, allowing users to adjust box styles, pivot length, and signal settings.
█ CONCEPTS
The indicator relies on several key elements to identify and visualize important price levels and trading signals:
Pivot Identification
High and low pivots are detected using the ta.pivothigh and ta.pivotlow functions with a configurable pivot length. Boxes are drawn based on the pivot level and the wick of the pivot candle (top for high pivots, bottom for low pivots).
List of Features
1 — High and Low Pivot Boxes: The indicator draws boxes based on high pivot candles (red) and low pivot candles (green) and their wicks, with options to customize colors, border styles, and background gradient. Boxes are limited to 500 bars back, meaning support and resistance levels older than 500 candles are not displayed to maintain chart clarity.
2 — Breakout Signals: When the price closes above the upper edge of a high pivot box, a breakout signal is generated (green triangle below the bar). When the price closes below the lower edge of a low pivot box, a breakout signal is generated (red triangle above the bar).
Signals can be filtered using volume, requiring the volume at the breakout to exceed the average volume multiplied by a configurable multiplier.
3 — Box Management: The indicator limits the number of displayed boxes (default is 15 for high pivots and 15 for low pivots), removing the oldest boxes when the limit is reached. Boxes older than 500 bars are automatically removed.
Volume Filtering
An optional volume filter allows users to require breakout signals to be confirmed by volume exceeding the moving average of volume (calculated over a selected period, default is 20 days).
█ OTHER SECTIONS
FEATURES
• Show High/Low Pivot Boxes: Enables or disables the display of boxes for high and low pivots.
• Pivot Length: Specifies the number of bars back and forward for detecting pivots (default is 5).
• Max Boxes: Sets the maximum number of boxes for high and low pivots (default is 15).
• Volume Filter: Enables a volume filter for breakout signals, with a configurable multiplier and average period.
• Box Style: Allows customization of border color, background gradient, border width, and border style (solid, dashed, dotted).
HOW TO USE
1 — Add the indicator to your TradingView chart by selecting “Pivot and Wick Boxes with Break Signals” from the indicators list.
2 — Configure the settings in the indicator’s dialog window, adjusting pivot length, maximum number of boxes, colors, and style.
3 — Enable the volume filter if you want signals to be confirmed by high volume.
4 — Monitor breakout signals (green triangles below bars for upward breakouts, red triangles above bars for downward breakouts) on the chart.
LIMITATIONS
• New pivots are detected with a delay equal to the set pivot length. A lower pivot length value results in faster pivot detection but produces pivots with less significance as support or resistance levels compared to those generated with a longer value.
• Breakout signals may produce false signals in volatile market conditions, especially without the volume filter.
• Boxes are limited to 500 bars back, which may exclude older pivots on long-term charts.
3D Surface Modeling [PhenLabs]📊 3D Surface Modeling
Version: PineScript™ v6
📌 Description
The 3D Surface Modeling indicator revolutionizes technical analysis by generating three-dimensional visualizations of multiple technical indicators across various timeframes. This advanced analytical tool processes and renders complex indicator data through a sophisticated matrix-based calculation system, creating an intuitive 3D surface representation of market dynamics.
The indicator employs array-based computations to simultaneously analyze multiple instances of selected technical indicators, mapping their behavior patterns across different temporal dimensions. This unique approach enables traders to identify complex market patterns and relationships that may be invisible in traditional 2D charts.
🚀 Points of Innovation
Matrix-Based Computation Engine: Processes up to 500 concurrent indicator calculations in real-time
Dynamic 3D Rendering System: Creates depth perception through sophisticated line arrays and color gradients
Multi-Indicator Integration: Seamlessly combines VWAP, Hurst, RSI, Stochastic, CCI, MFI, and Fractal Dimension analyses
Adaptive Scaling Algorithm: Automatically adjusts visualization parameters based on indicator type and market conditions
🔧 Core Components
Indicator Processing Module: Handles real-time calculation of multiple technical indicators using array-based mathematics
3D Visualization Engine: Converts indicator data into three-dimensional surfaces using line arrays and color mapping
Dynamic Scaling System: Implements custom normalization algorithms for different indicator types
Color Gradient Generator: Creates depth perception through programmatic color transitions
🔥 Key Features
Multi-Indicator Support: Comprehensive analysis across seven different technical indicators
Customizable Visualization: User-defined color schemes and line width parameters
Real-time Processing: Continuous calculation and rendering of 3D surfaces
Cross-Timeframe Analysis: Simultaneous visualization of indicator behavior across multiple periods
🎨 Visualization
Surface Plot: Three-dimensional representation using up to 500 lines with dynamic color gradients
Depth Indicators: Color intensity variations showing indicator value magnitude
Pattern Recognition: Visual identification of market structures across multiple timeframes
📖 Usage Guidelines
Indicator Selection
Type: VWAP, Hurst, RSI, Stochastic, CCI, MFI, Fractal Dimension
Default: VWAP
Starting Length: Minimum 5 periods
Default: 10
Step Size: Interval between calculations
Range: 1-10
Visualization Parameters
Color Scheme: Green, Red, Blue options
Line Width: 1-5 pixels
Surface Resolution: Up to 500 lines
✅ Best Use Cases
Multi-timeframe market analysis
Pattern recognition across different technical indicators
Trend strength assessment through 3D visualization
Market behavior study across multiple periods
⚠️ Limitations
High computational resource requirements
Maximum 500 line restriction
Requires substantial historical data
Complex visualization learning curve
🔬 How It Works
1. Data Processing:
Calculates selected indicator values across multiple timeframes
Stores results in multi-dimensional arrays
Applies custom scaling algorithms
2. Visualization Generation:
Creates line arrays for 3D surface representation
Applies color gradients based on value magnitude
Renders real-time updates to surface plot
3. Display Integration:
Synchronizes with chart timeframe
Updates surface plot dynamically
Maintains visual consistency across updates
🌟 Credits:
Inspired by LonesomeTheBlue (modified for multiple indicator types with scaling fixes and additional unique mappings)
💡 Note:
Optimal performance requires sufficient computing resources and historical data. Users should start with default settings and gradually adjust parameters based on their analysis requirements and system capabilities.
FVG Premium [no1x]█ OVERVIEW
This indicator provides a comprehensive toolkit for identifying, visualizing, and tracking Fair Value Gaps (FVGs) across three distinct timeframes (current chart, a user-defined Medium Timeframe - MTF, and a user-defined High Timeframe - HTF). It is designed to offer traders enhanced insight into FVG dynamics through detailed state monitoring (formation, partial fill, full mitigation, midline touch), extensive visual customization for FVG representation, and a rich alert system for timely notifications on FVG-related events.
█ CONCEPTS
This indicator is built upon the core concept of Fair Value Gaps (FVGs) and their significance in price action analysis, offering a multi-layered approach to their detection and interpretation across different timeframes.
Fair Value Gaps (FVGs)
A Fair Value Gap (FVG), also known as an imbalance, represents a range in price delivery where one side of the market (buying or selling) was more aggressive, leaving an inefficiency or an "imbalance" in the price action. This concept is prominently featured within Smart Money Concepts (SMC) and Inner Circle Trader (ICT) methodologies, where such gaps are often interpreted as footprints left by "smart money" due to rapid, forceful price movements. These methodologies suggest that price may later revisit these FVG zones to rebalance a prior inefficiency or to seek liquidity before continuing its path. These gaps are typically identified by a three-bar pattern:
Bullish FVG : This is a three-candle formation where the second candle shows a strong upward move. The FVG is the space created between the high of the first candle (bottom of FVG) and the low of the third candle (top of FVG). This indicates a strong upward impulsive move.
Bearish FVG : This is a three-candle formation where the second candle shows a strong downward move. The FVG is the space created between the low of the first candle (top of FVG) and the high of the third candle (bottom of FVG). This indicates a strong downward impulsive move.
FVGs are often watched by traders as potential areas where price might return to "rebalance" or find support/resistance.
Multi-Timeframe (MTF) Analysis
The indicator extends FVG detection beyond the current chart's timeframe (Low Timeframe - LTF) to two higher user-defined timeframes: Medium Timeframe (MTF) and High Timeframe (HTF). This allows traders to:
Identify FVGs that might be significant on a broader market structure.
Observe how FVGs from different timeframes align or interact.
Gain a more comprehensive perspective on potential support and resistance zones.
FVG State and Lifecycle Management
The indicator actively tracks the lifecycle of each detected FVG:
Formation : The initial identification of an FVG.
Partial Fill (Entry) : When price enters but does not completely pass through the FVG. The indicator updates the "current" top/bottom of the FVG to reflect the filled portion.
Midline (Equilibrium) Touch : When price touches the 50% level of the FVG.
Full Mitigation : When price completely trades through the FVG, effectively "filling" or "rebalancing" the gap. The indicator records the mitigation time.
This state tracking is crucial for understanding how price interacts with these zones.
FVG Classification (Large FVG)
FVGs can be optionally classified as "Large FVGs" (LV) if their size (top to bottom range) exceeds a user-defined multiple of the Average True Range (ATR) for that FVG's timeframe. This helps distinguish FVGs that are significantly larger relative to recent volatility.
Visual Customization and Information Delivery
A key concept is providing extensive control over how FVGs are displayed. This control is achieved through a centralized set of visual parameters within the indicator, allowing users to configure numerous aspects (colors, line styles, visibility of boxes, midlines, mitigation lines, labels, etc.) for each timeframe. Additionally, an on-chart information panel summarizes the nearest unmitigated bullish and bearish FVG levels for each active timeframe, providing a quick glance at key price points.
█ FEATURES
This indicator offers a rich set of features designed to provide a highly customizable and comprehensive Fair Value Gap (FVG) analysis experience. Users can tailor the FVG detection, visual representation, and alerting mechanisms across three distinct timeframes: the current chart (Low Timeframe - LTF), a user-defined Medium Timeframe (MTF), and a user-defined High Timeframe (HTF).
Multi-Timeframe FVG Detection and Display
The core strength of this indicator lies in its ability to identify and display FVGs from not only the current chart's timeframe (LTF) but also from two higher, user-selectable timeframes (MTF and HTF).
Timeframe Selection: Users can specify the exact MTF (e.g., "60", "240") and HTF (e.g., "D", "W") through dedicated inputs in the "MTF (Medium Timeframe)" and "HTF (High Timeframe)" settings groups. The visibility of FVGs from these higher timeframes can be toggled independently using the "Show MTF FVGs" and "Show HTF FVGs" checkboxes.
Consistent Detection Logic: The FVG detection logic, based on the classic three-bar imbalance pattern detailed in the 'Concepts' section, is applied consistently across all selected timeframes (LTF, MTF, HTF)
Timeframe-Specific Visuals: Each timeframe's FVGs (LTF, MTF, HTF) can be customized with unique colors for bullish/bearish states and their mitigated counterparts. This allows for easy visual differentiation of FVGs originating from different market perspectives.
Comprehensive FVG Visualization Options
The indicator provides extensive control over how FVGs are visually represented on the chart for each timeframe (LTF, MTF, HTF).
FVG Boxes:
Visibility: Main FVG boxes can be shown or hidden per timeframe using the "Show FVG Boxes" (for LTF), "Show Boxes" (for MTF/HTF) inputs.
Color Customization: Colors for bullish, bearish, active, and mitigated FVG boxes (including Large FVGs, if classified) are fully customizable for each timeframe.
Box Extension & Length: FVG boxes can either be extended to the right indefinitely ("Extend Boxes Right") or set to a fixed length in bars ("Short Box Length" or "Box Length" equivalent inputs).
Box Labels: Optional labels can display the FVG's timeframe and fill percentage on the box. These labels are configurable for all timeframes (LTF, MTF, and HTF). Please note: If FVGs are positioned very close to each other on the chart, their respective labels may overlap. This can potentially lead to visual clutter, and it is a known behavior in the current version of the indicator.
Box Borders: Visibility, width, style (solid, dashed, dotted), and color of FVG box borders are customizable per timeframe.
Midlines (Equilibrium/EQ):
Visibility: The 50% level (midline or EQ) of FVGs can be shown or hidden for each timeframe.
Style Customization: Width, style, and color of the midline are customizable per timeframe. The indicator tracks if this midline has been touched by price.
Mitigation Lines:
Visibility: Mitigation lines (representing the FVG's opening level that needs to be breached for full mitigation) can be shown or hidden for each timeframe. If shown, these lines are always extended to the right.
Style Customization: Width, style, and color of the mitigation line are customizable per timeframe.
Mitigation Line Labels: Optional price labels can be displayed on mitigation lines, with a customizable horizontal bar offset for positioning. For optimal label placement, the following horizontal bar offsets are recommended: 4 for LTF, 8 for MTF, and 12 for HTF.
Persistence After Mitigation: Users can choose to keep mitigation lines visible even after an FVG is fully mitigated, with a distinct color for such lines. Importantly, this option is only effective if the general setting 'Hide Fully Mitigated FVGs' is disabled, as otherwise, the entire FVG and its lines will be removed upon mitigation.
FVG State Management and Behavior
The indicator tracks and visually responds to changes in FVG states.
Hide Fully Mitigated FVGs: This option, typically found in the indicator's general settings, allows users to automatically remove all visual elements of an FVG from the chart once price has fully mitigated it. This helps maintain chart clarity by focusing on active FVGs.
Partial Fill Visualization: When price enters an FVG, the indicator offers a dynamic visual representation: the portion of the FVG that has been filled is shown as a "mitigated box" (typically with a distinct color), while the original FVG box shrinks to clearly highlight the remaining, unfilled portion. This two-part display provides an immediate visual cue about how much of the FVG's imbalance has been addressed and what potential remains within the gap.
Visual Filtering by ATR Proximity: To help users focus on the most relevant price action, FVGs can be dynamically hidden if they are located further from the current price than a user-defined multiple of the Average True Range (ATR). This behavior is controlled by the "Filter Band Width (ATR Multiple)" input; setting this to zero disables the filter entirely, ensuring all detected FVGs remain visible regardless of their proximity to price.
Alternative Usage Example: Mitigation Lines as Key Support/Resistance Levels
For traders preferring a minimalist chart focused on key Fair Value Gap (FVG) levels, the indicator's visualization settings can be customized to display only FVG mitigation lines. This approach leverages these lines as potential support and resistance zones, reflecting areas where price might revisit to address imbalances.
To configure this view:
Disable FVG Boxes: Turn off "Show FVG Boxes" (for LTF) or "Show Boxes" (for MTF/HTF) for the desired timeframes.
Hide Midlines: Disable the visibility of the 50% FVG Midlines (Equilibrium/EQ).
Ensure Mitigation Lines are Visible: Keep "Mitigation Lines" enabled.
Retain All Mitigation Lines:
Disable the "Hide Fully Mitigated FVGs" option in the general settings.
Enable the feature to "keep mitigation lines visible even after an FVG is fully mitigated". This ensures lines from all FVGs (active or fully mitigated) remain on the chart, which is only effective if "Hide Fully Mitigated FVGs" is disabled.
This setup offers:
A Decluttered Chart: Focuses solely on the FVG opening levels.
Precise S/R Zones: Treats mitigation lines as specific points for potential price reactions.
Historical Level Analysis: Includes lines from past, fully mitigated FVGs for a comprehensive view of significant price levels.
For enhanced usability with this focused view, consider these optional additions:
The on-chart Information Panel can be activated to display a quick summary of the nearest unmitigated FVG levels.
Mitigation Line Labels can also be activated for clear price level identification. A customizable horizontal bar offset is available for positioning these labels; for example, offsets of 4 for LTF, 8 for MTF, and 12 for HTF can be effective.
FVG Classification (Large FVG)
This feature allows for distinguishing FVGs based on their size relative to market volatility.
Enable Classification: Users can enable "Classify FVG (Large FVG)" to identify FVGs that are significantly larger than average.
ATR-Based Threshold: An FVG is classified as "Large" if its height (price range) is greater than or equal to the Average True Range (ATR) of its timeframe multiplied by a user-defined "Large FVG Threshold (ATR Multiple)". The ATR period for this calculation is also configurable.
Dedicated Colors: Large FVGs (both bullish/bearish and active/mitigated) can be assigned unique colors, making them easily distinguishable on the chart.
Panel Icon: Large FVGs are marked with a special icon in the Info Panel.
Information Panel
An on-chart panel provides a quick summary of the nearest unmitigated FVG levels.
Visibility and Position: The panel can be shown/hidden and positioned in any of the nine standard locations on the chart (e.g., Top Right, Middle Center).
Content: It displays the price levels of the nearest unmitigated bullish and bearish FVGs for LTF, MTF (if active), and HTF (if active). It also indicates if these nearest FVGs are Large FVGs (if classification is enabled) using a selectable icon.
Styling: Text size, border color, header background/text colors, default text color, and "N/A" cell background color are customizable.
Highlighting: Background and text colors for the cells displaying the overall nearest bullish and bearish FVG levels (across all active timeframes) can be customized to draw attention to the most proximate FVG.
Comprehensive Alert System
The indicator offers a granular alert system for various FVG-related events, configurable for each timeframe (LTF, MTF, HTF) independently. Users can enable alerts for:
New FVG Formation: Separate alerts for new bullish and new bearish FVG formations.
FVG Entry/Partial Fill: Separate alerts for price entering a bullish FVG or a bearish FVG.
FVG Full Mitigation: Separate alerts for full mitigation of bullish and bearish FVGs.
FVG Midline (EQ) Touch: Separate alerts for price touching the midline of a bullish or bearish FVG.
Alert messages are detailed, providing information such as the timeframe, FVG type (bull/bear, Large FVG), relevant price levels, and timestamps.
█ NOTES
This section provides additional information regarding the indicator's usage, performance considerations, and potential interactions with the TradingView platform. Understanding these points can help users optimize their experience and troubleshoot effectively.
Performance and Resource Management
Maximum FVGs to Track : The "Max FVGs to Track" input (defaulting to 25) limits the number of FVG objects processed for each category (e.g., LTF Bullish, MTF Bearish). Increasing this value significantly can impact performance due to more objects being iterated over and potentially drawn, especially when multiple timeframes are active.
Drawing Object Limits : To manage performance, this script sets its own internal limits on the number of drawing objects it displays. While it allows for up to approximately 500 lines (max_lines_count=500) and 500 labels (max_labels_count=500), the number of FVG boxes is deliberately restricted to a maximum of 150 (max_boxes_count=150). This specific limit for boxes is a key performance consideration: displaying too many boxes can significantly slow down the indicator, and a very high number is often not essential for analysis. Enabling all visual elements for many FVGs across all three timeframes can cause the indicator to reach these internal limits, especially the stricter box limit
Optimization Strategies : To help you manage performance, reduce visual clutter, and avoid exceeding drawing limits when using this indicator, I recommend the following strategies:
Maintain or Lower FVG Tracking Count: The "Max FVGs to Track" input defaults to 25. I find this value generally sufficient for effective analysis and balanced performance. You can keep this default or consider reducing it further if you experience performance issues or prefer a less dense FVG display.
Utilize Proximity Filtering: I suggest activating the "Filter Band Width (ATR Multiple)" option (found under "General Settings") to display only those FVGs closer to the current price. From my experience, a value of 5 for the ATR multiple often provides a good starting point for balanced performance, but you should feel free to adjust this based on market volatility and your specific trading needs.
Hide Fully Mitigated FVGs: I strongly recommend enabling the "Hide Fully Mitigated FVGs" option. This setting automatically removes all visual elements of an FVG from the chart once it has been fully mitigated by price. Doing so significantly reduces the number of active drawing objects, lessens computational load, and helps maintain chart clarity by focusing only on active, relevant FVGs.
Disable FVG Display for Unused Timeframes: If you are not actively monitoring certain higher timeframes (MTF or HTF) for FVG analysis, I advise disabling their display by unchecking "Show MTF FVGs" or "Show HTF FVGs" respectively. This can provide a significant performance boost.
Simplify Visual Elements: For active FVGs, consider hiding less critical visual elements if they are not essential for your specific analysis. This could include box labels, borders, or even entire FVG boxes if, for example, only the mitigation lines are of interest for a particular timeframe.
Settings Changes and Platform Limits : This indicator is comprehensive and involves numerous calculations and drawings. When multiple settings are changed rapidly in quick succession, it is possible, on occasion, for TradingView to issue a "Runtime error: modify_study_limit_exceeding" or similar. This can cause the indicator to temporarily stop updating or display errors.
Recommended Approach : When adjusting settings, it is advisable to wait a brief moment (a few seconds) after each significant change. This allows the indicator to reprocess and update on the chart before another change is made
Error Recovery : Should such a runtime error occur, making a minor, different adjustment in the settings (e.g., toggling a checkbox off and then on again) and waiting briefly will typically allow the indicator to recover and resume correct operation. This behavior is related to platform limitations when handling complex scripts with many inputs and drawing objects.
Multi-Timeframe (MTF/HTF) Data and Behavior
HTF FVG Confirmation is Essential: : For an FVG from a higher timeframe (MTF or HTF) to be identified and displayed on your current chart (LTF), the three-bar pattern forming the FVG on that higher timeframe must consist of fully closed bars. The indicator does not draw speculative FVGs based on incomplete/forming bars from higher timeframes.
Data Retrieval and LTF Processing: The indicator may use techniques like lookahead = barmerge.lookahead_on for timely data retrieval from higher timeframes. However, the actual detection of an FVG occurs after all its constituent bars on the HTF have closed.
Appearance Timing on LTF (1 LTF Candle Delay): As a natural consequence of this, an FVG that is confirmed on an HTF (i.e., its third bar closes) will typically become visible on your LTF chart one LTF bar after its confirmation on the HTF.
Example: Assume an FVG forms on a 30-minute chart at 15:30 (i.e., with the close of the 30-minute bar that covers the 15:00-15:30 period). If you are monitoring this FVG on a 15-minute chart, the indicator will detect this newly formed 30-minute FVG while processing the data for the 15-minute bar that starts at 15:30 and closes at 15:45. Therefore, the 30-minute FVG will become visible on your 15-minute chart at the earliest by 15:45 (i.e., with the close of that relevant 15-minute LTF candle). This means the HTF FVG is reflected on the LTF chart with a delay equivalent to one LTF candle.
FVG Detection and Display Logic
Fair Value Gaps (FVGs) on the current chart timeframe (LTF) are detected based on barstate.isconfirmed. This means the three-bar pattern must be complete with closed bars before an FVG is identified. This confirmation method prevents FVGs from being prematurely identified on the forming bar.
Alerts
Alert Setup : To receive alerts from this indicator, you must first ensure you have enabled the specific alert conditions you are interested in within the indicator's own settings (see 'Comprehensive Alert System' under the 'FEATURES' section). Once configured, open TradingView's 'Create Alert' dialog. In the 'Condition' tab, select this indicator's name, and crucially, choose the 'Any alert() function call' option from the dropdown list. This setup allows the indicator to trigger alerts based on the precise event conditions you have activated in its settings
Alert Frequency : Alerts are designed to trigger once per bar close (alert.freq_once_per_bar_close) for the specific event.
User Interface (UI) Tips
Settings Group Icons: In the indicator settings menu, timeframe-specific groups are marked with star icons for easier navigation: 🌟 for LTF (Current Chart Timeframe), 🌟🌟 for MTF (Medium Timeframe), and 🌟🌟🌟 for HTF (High Timeframe).
Dependent Inputs: Some input settings are dependent on others being enabled. These dependencies are visually indicated in the settings menu using symbols like "↳" (dependent setting on the next line), "⟷" (mutually exclusive inline options), or "➜" (directly dependent inline option).
Settings Layout Overview: The indicator settings are organized into logical groups for ease of use. Key global display controls – such as toggles for MTF FVGs, HTF FVGs (along with their respective timeframe selectors), and the Information Panel – are conveniently located at the very top within the '⚙️ General Settings' group. This placement allows for quick access to frequently adjusted settings. Other sections provide detailed customization options for each timeframe (LTF, MTF, HTF), specific FVG components, and alert configurations.
█ FOR Pine Script® CODERS
This section provides a high-level overview of the FVG Premium indicator's internal architecture, data flow, and the interaction between its various library components. It is intended for Pine Script™ programmers who wish to understand the indicator's design, potentially extend its functionality, or learn from its structure.
System Architecture and Modular Design
The indicator is architected moduarly, leveraging several custom libraries to separate concerns and enhance code organization and reusability. Each library has a distinct responsibility:
FvgTypes: Serves as the foundational data definition layer. It defines core User-Defined Types (UDTs) like fvgObject (for storing all attributes of an FVG) and drawSettings (for visual configurations), along with enumerations like tfType.
CommonUtils: Provides utility functions for common tasks like mapping user string inputs (e.g., "Dashed" for line style) to their corresponding Pine Script™ constants (e.g., line.style_dashed) and formatting timeframe strings for display.
FvgCalculations: Contains the core logic for FVG detection (both LTF and MTF/HTF via requestMultiTFBarData), FVG classification (Large FVGs based on ATR), and checking FVG interactions with price (mitigation, partial fill).
FvgObject: Implements an object-oriented approach by attaching methods to the fvgObject UDT. These methods manage the entire visual lifecycle of an FVG on the chart, including drawing, updating based on state changes (e.g., mitigation), and deleting drawing objects. It's responsible for applying the visual configurations defined in drawSettings.
FvgPanel: Manages the creation and dynamic updates of the on-chart information panel, which displays key FVG levels.
The main indicator script acts as the orchestrator, initializing these libraries, managing user inputs, processing data flow between libraries, and handling the main event loop (bar updates) for FVG state management and alerts.
Core Data Flow and FVG Lifecycle Management
The general data flow and FVG lifecycle can be summarized as follows:
Input Processing: User inputs from the "Settings" dialog are read by the main indicator script. Visual style inputs (colors, line styles, etc.) are consolidated into a types.drawSettings object (defined in FvgTypes). Other inputs (timeframes, filter settings, alert toggles) control the behavior of different modules. CommonUtils assists in mapping some string inputs to Pine constants.
FVG Detection:
For the current chart timeframe (LTF), FvgCalculations.detectFvg() identifies potential FVGs based on bar patterns.
For MTF/HTF, the main indicator script calls FvgCalculations.requestMultiTFBarData() to fetch necessary bar data from higher timeframes, then FvgCalculations.detectMultiTFFvg() identifies FVGs.
Newly detected FVGs are instantiated as types.fvgObject and stored in arrays within the main script. These objects also undergo classification (e.g., Large FVG) by FvgCalculations.
State Update & Interaction: On each bar, the main indicator script iterates through active FVG objects to manage their state based on price interaction:
Initially, the main script calls FvgCalculations.fvgInteractionCheck() to efficiently determine if the current bar's price might be interacting with a given FVG.
If a potential interaction is flagged, the main script then invokes methods directly on the fvgObject instance (e.g., updateMitigation(), updatePartialFill(), checkMidlineTouch(), which are part of FvgObject).
These fvgObject methods are responsible for the detailed condition checking and the actual modification of the FVG's state. For instance, the updateMitigation() and updatePartialFill() methods internally utilize specific helper functions from FvgCalculations (like checkMitigation() and checkPartialMitigation()) to confirm the precise nature of the interaction before updating the fvgObject’s state fields (such as isMitigated, currentTop, currentBottom, or isMidlineTouched).
Visual Rendering:
The FvgObject.updateDrawings() method is called for each fvgObject. This method is central to drawing management; it creates, updates, or deletes chart drawings (boxes, lines, labels) based on the FVG's current state, its prev_* (previous bar state) fields for optimization, and the visual settings passed via the drawSettings object.
Information Panel Update: The main indicator script determines the nearest FVG levels, populates a panelData object (defined in FvgPanelLib), and calls FvgPanel.updatePanel() to refresh the on-chart display.
Alert Generation: Based on the updated FVG states and user-enabled alert settings, the main indicator script constructs and triggers alerts using Pine Script's alert() function."
Key Design Considerations
UDT-Centric Design: The fvgObject UDT is pivotal, acting as a stateful container for all information related to a single FVG. Most operations revolve around creating, updating, or querying these objects.
State Management: To optimize drawing updates and manage FVG lifecycles, fvgObject instances store their previous bar's state (e.g., prevIsVisible, prevCurrentTop). The FvgObject.updateDrawings() method uses this to determine if a redraw is necessary, minimizing redundant drawing calls.
Settings Object: A drawSettings object is populated once (or when inputs change) and passed to drawing functions. This avoids repeatedly reading numerous input() values on every bar or within loops, improving performance.
Dynamic Arrays for FVG Storage: Arrays are used to store collections of fvgObject instances, allowing for dynamic management (adding new FVGs, iterating for updates).
Nef33-Volume Footprint ApproximationDescription of the "Volume Footprint Approximation" Indicator
Purpose
The "Volume Footprint Approximation" indicator is a tool designed to assist traders in analyzing market volume dynamics and anticipating potential trend changes in price. It is inspired by the concept of a volume footprint chart, which visualizes the distribution of trading volume across different price levels. However, since TradingView does not provide detailed intrabar data for all users, this indicator approximates the behavior of a footprint chart by using available volume and price data (open, close, volume) to classify volume as buy or sell, calculate volume delta, detect imbalances, and generate trend change signals.
The indicator is particularly useful for identifying areas of high buying or selling activity, imbalances between supply and demand, delta divergences, and potential reversal points in the market. It provides specific signals for bullish and bearish trend changes, making it suitable for traders looking to trade reversals or confirm trends.
How It Works
The indicator uses volume and price data from each candlestick to perform the following calculations:
Volume Classification:
Classifies the volume of each candlestick as "buy" or "sell" based on price movement:
If the closing price is higher than the opening price (close > open), the volume is classified as "buy."
If the closing price is lower than the opening price (close < open), the volume is classified as "sell."
If the closing price equals the opening price (close == open), it compares with the previous close to determine the direction:
If the current close is higher than the previous close, it is classified as "buy."
If the current close is lower than the previous close, it is classified as "sell."
If the current close equals the previous close, the classification from the previous bar is used.
Delta Calculation:
Calculates the volume delta as the difference between buy volume and sell volume (buyVolume - sellVolume).
A positive delta indicates more buy volume; a negative delta indicates more sell volume.
Imbalance Detection:
Identifies imbalances between buy and sell volume:
A buy imbalance occurs when buy volume exceeds sell volume by a defined percentage (default is 300%).
A sell imbalance occurs when sell volume exceeds buy volume by the same percentage.
Delta Divergence Detection:
Positive Delta Divergence: Occurs when the price is falling (for at least 2 bars) but the delta is increasing or becomes positive, indicating that buyers are entering despite the price decline.
Negative Delta Divergence: Occurs when the price is rising (for at least 2 bars) but the delta is decreasing or becomes negative, indicating that sellers are entering despite the price increase.
Trend Change Signals:
Bullish Signal (trendChangeBullish): Generated when the following conditions are met:
There is a positive delta divergence.
The delta has moved from a negative value (e.g., -500) to a positive value (e.g., +200) over the last 3 bars.
There is a buy imbalance.
The price is near a historical support level (approximated as the lowest low of the last 50 bars).
Bearish Signal (trendChangeBearish): Generated when the following conditions are met:
There is a negative delta divergence.
The delta has moved from a positive value (e.g., +500) to a negative value (e.g., -200) over the last 3 bars.
There is a sell imbalance.
The price is near a historical resistance level (approximated as the highest high of the last 50 bars).
Visual Elements
The indicator is displayed in a separate panel below the price chart (overlay=false) and includes the following elements:
Volume Histograms:
Buy Volume: Represented by a green histogram. Shows the volume classified as "buy."
Sell Volume: Represented by a red histogram. Shows the volume classified as "sell."
Note: The histograms overlap, and the last plotted histogram (red) takes visual precedence, meaning the sell volume may cover the buy volume if it is larger.
Delta Line:
Delta Volume: Represented by a blue line. Shows the difference between buy and sell volume.
A line above zero indicates more buy volume; a line below zero indicates more sell volume.
A dashed gray horizontal line marks the zero level for easier interpretation.
Imbalance Backgrounds:
Buy Imbalance: Light green background when buy volume exceeds sell volume by the defined percentage.
Sell Imbalance: Light red background when sell volume exceeds buy volume by the defined percentage.
Divergence Backgrounds:
Positive Delta Divergence: Lime green background when a positive delta divergence is detected.
Negative Delta Divergence: Fuchsia background when a negative delta divergence is detected.
Trend Change Signals:
Bullish Signal: Green label with the text "Bullish Trend Change" when the conditions for a bullish trend change are met.
Bearish Signal: Red label with the text "Bearish Trend Change" when the conditions for a bearish trend change are met.
Information Labels:
Below each bar, a label displays:
Total Vol: The total volume of the bar.
Delta: The delta volume value.
Alerts
The indicator generates the following alerts:
Positive Delta Divergence: "Positive Delta Divergence Detected! Price is falling, but delta is increasing."
Negative Delta Divergence: "Negative Delta Divergence Detected! Price is rising, but delta is decreasing."
Bullish Trend Change Signal: "Bullish Trend Change Signal! Positive Delta Divergence, Delta Rise, Buy Imbalance, and Near Support."
Bearish Trend Change Signal: "Bearish Trend Change Signal! Negative Delta Divergence, Delta Drop, Sell Imbalance, and Near Resistance."
These alerts can be configured in TradingView to receive real-time notifications.
Adjustable Parameters
The indicator allows customization of the following parameters:
Imbalance Threshold (%): The percentage required to detect an imbalance between buy and sell volume (default is 300%).
Lookback Period for Divergence: Number of bars to look back for detecting price and delta trends (default is 2 bars).
Support/Resistance Lookback Period: Number of bars to look back for identifying historical support and resistance levels (default is 50 bars).
Delta High Threshold (Bearish): Minimum delta value 2 bars ago for the bearish signal (default is +500).
Delta Low Threshold (Bearish): Maximum delta value in the current bar for the bearish signal (default is -200).
Delta Low Threshold (Bullish): Maximum delta value 2 bars ago for the bullish signal (default is -500).
Delta High Threshold (Bullish): Minimum delta value in the current bar for the bullish signal (default is +200).
Practical Use
The indicator is useful for the following purposes:
Identifying Trend Changes:
The trend change signals (trendChangeBullish and trendChangeBearish) indicate potential price reversals. For example, a bullish signal near a support level may be an opportunity to enter a long position.
Detecting Divergences:
Delta divergences (positive and negative) can anticipate trend changes by showing a disagreement between price movement and underlying buying/selling pressure.
Finding Key Levels:
Imbalances (green and red backgrounds) often coincide with support and resistance levels, helping to identify areas where the market might react.
Confirming Trends:
A consistently positive delta in an uptrend or a negative delta in a downtrend can confirm the strength of the trend.
Identifying Failed Auctions:
Although not detected automatically, you can manually identify failed auctions by observing a price move to new highs/lows with decreasing volume in the direction of the move.
Limitations
Intrabar Data: It does not use detailed intrabar data, making it less precise than a native footprint chart.
Approximations: Volume classification and support/resistance detection are approximations, which may lead to false signals.
Volume Dependency: It requires reliable volume data, so it may be less effective on assets with inaccurate volume data (e.g., some forex pairs).
False Signals: Divergences and imbalances do not always indicate a trend change, especially in strongly trending markets.
Recommendations
Combine with Other Indicators: Use tools like RSI, MACD, support/resistance levels, or candlestick patterns to confirm signals.
Trade on Higher Timeframes: Signals are more reliable on higher timeframes like 1-hour or 4-hour charts.
Perform Backtesting: Evaluate the indicator's accuracy on historical data to adjust parameters and improve effectiveness.
Adjust Parameters: Modify thresholds (e.g., imbalanceThreshold or supportResistanceLookback) based on the asset and timeframe you are trading.
Conclusion
The "Volume Footprint Approximation" indicator is a powerful tool for analyzing volume dynamics and anticipating price trend changes. By classifying volume, calculating delta, detecting imbalances and divergences, and generating trend change signals, it provides traders with valuable insights into market buying and selling pressure. While it has limitations due to the lack of intrabar data, it can be highly effective when used in combination with other technical analysis tools and on assets with reliable volume data.
IPO Date ScreenerThis script, the IPO Date Screener, allows traders to visually identify stocks that are relatively new, based on the number of bars (days) since their IPO. The user can set a custom threshold for the number of days (bars) after the IPO, and the script will highlight new stocks that fall below that threshold.
Key Features:
Customizable IPO Days Threshold: Set the threshold for considering a stock as "new." Since Pine screener limits number bars to 500, it will work for stocks having trading days below 500 since IPO which almost 2 years.
Column Days since IPO: Sort this column from low to high to see newest to oldest STOCK with 500 days of trading.
Since a watchlist is limited to 1000 stocks, use this pines script to screen stocks within the watch list having trading days below 500 or user can select lower number of days from settings.
This is not helpful to add on chart, this is to use on pine screener as utility.
Non-Psychological Levels🟩 Non-Psychological Levels is a structural analysis tool that segments price action into objective ranges, identifying Broken and Unbroken levels without relying on psychological or time-based assumptions. By emphasizing mechanically derived price behavior, it provides traders with a clear framework for analyzing support and resistance in a consistent and unbiased manner across various market conditions.
This indicator introduces a new approach to understanding market structure by focusing on price movement within defined segments, free from behavioral patterns, round numbers, or specific time intervals. While the indicator is time-agnostic in design, it works within the natural time progression of the chart, ensuring that segmentation aligns with the inherent structure of price movement. Broken levels, where price has breached a structural boundary, and Unbroken levels, which remain intact, are visualized with horizontal lines. These structural zones are complemented by dynamically boxed segments that contextualize both historical and ongoing price behavior.
By offering an objective perspective, the Non-Psychological Levels indicator complements psychology-based tools, helping traders explore market dynamics from multiple angles. When structural levels align with psychological zones, they reinforce critical price areas; when they differ, they provide opportunities to analyze price behavior from an alternative lens. This indicator is designed as both an educational framework and a practical tool, encouraging a deeper understanding of structural price behavior in technical analysis.
⭕ THEORY AND CONCEPT ⭕
The Non-Psychological Levels indicator is grounded in the principle of analyzing price behavior without reliance on psychological assumptions or time-based factors. Its primary purpose is to provide a structural framework for identifying support and resistance levels by focusing solely on price movement within mechanically defined segments. By removing external influences such as sentiment, time intervals, or market sessions, the indicator offers an unbiased lens through which traders can observe price dynamics.
Non-psychology, as defined here, refers to an approach that excludes behavioral and emotional patterns—like fear, greed, or herd mentality—from price analysis. Traditional tools often depend on these patterns to identify zones such as pivots or Fibonacci retracements, but these methods can be inconsistent in volatile markets. In contrast, the Non-Psychological Levels indicator focuses entirely on what price is doing, free from assumptions about trader behavior or external time constraints.
The indicator’s time-agnostic and mechanically driven design segments price action into consistent ranges, highlighting "Broken" levels (where price breaches structural boundaries) and "Unbroken" levels (where price holds). These structural zones remain unaffected by subjective or external influences, ensuring clarity and consistency across different markets and timeframes. By doing so, the indicator reveals a pure view of price structure, independent of psychological biases.
Importantly, the Non-Psychological Levels indicator is not intended to replace psychology-based tools but to complement them. When its structural levels align with psychological zones like round numbers or session highs/lows, the significance of these areas is reinforced. Conversely, when the levels differ, the contrast provides traders with alternative insights into market dynamics. This dual perspective—blending mechanical objectivity with behavioral analysis—enhances the depth and flexibility of market evaluation.
The following principles outline the theoretical foundation of the indicator and its unique contribution to structural price analysis:
Time-Agnostic Design : The indicator avoids reliance on time-based factors like daily opens, session intervals, or specific events. Instead, it segments price action using bar indexes, ensuring that structural levels are identified independently of external time variables. While the x-axis of a chart inherently represents time, this indicator abstracts away its influence, allowing traders to focus purely on price movement without the bias of temporal context.
Mechanical and Neutral Framework : Every calculation within the indicator is predetermined by a set of mechanical rules, ensuring no subjective input or interpretation affects the results. This objectivity guarantees that levels are derived solely from observed price behavior, providing a reliable framework that traders can trust to remain consistent across different assets, timeframes, and market conditions.
Broken and Unbroken Levels : Broken levels represent zones where price has breached a structural boundary, while Unbroken levels highlight areas where price has consistently respected its range. This distinction provides a clear and systematic method for identifying key support and resistance levels, offering insights into where future price interactions are most likely to occur.
Neutral Price Behavior : By dividing price action into equal segments, the indicator removes the influence of external factors like trader sentiment or psychological expectations. Each segment independently determines significant levels based purely on price action, enabling a structural view of the market that abstracts away behavioral or emotional biases.
Complement to Psychological Tools : While the indicator itself avoids behavioral assumptions, its levels can align with psychological zones like round numbers, pivots, or Fibonacci levels. When these structural and psychological levels overlap, it reinforces the importance of key areas, while divergences offer opportunities to examine price behavior from a new perspective.
Educational Value : The indicator encourages traders to explore the contrast between structural and psychological analysis. By introducing a framework that isolates price behavior from external influences, it challenges traditional methods of technical analysis, fostering deeper insights into market structure and behavior.
🔍 UNDERSTANDING STRUCTURAL LEVELS 🔍
The Non-Psychological Levels indicator offers a straightforward yet powerful way to understand market structure by segmenting price action into mechanically defined ranges. This segmentation highlights two key elements: "Broken" levels, where price has breached structural boundaries, and "Unbroken" levels, which remain intact and respected by price action. Together, these components create a framework for identifying potential areas of support and resistance.
Broken Levels : These are structural boundaries that price has surpassed, indicating areas where previous support or resistance failed. Broken levels often signal transitions in price behavior, such as shifts in momentum or the start of trending movements. They provide insight into zones where price has already tested and moved beyond.
Unbroken Levels : These levels remain intact within a given price segment, marking areas where price has consistently respected boundaries. Unbroken levels are particularly useful for identifying potential reversal points or zones of continued support or resistance. Their persistence across price action often makes them reliable indicators of market structure.
The visual segmentation of price action into distinct ranges allows traders to observe how price transitions between structural zones. For example:
- Clusters of Unbroken levels near the current price may suggest strong support or resistance, offering areas of interest for reversals or breakouts.
- Gaps between Unbroken levels highlight areas of price inefficiency or low interaction, which may become significant if revisited.
By focusing solely on structural price behavior, the Non-Psychological Levels indicator enables traders to analyze price independently of time or psychological factors. This makes it a valuable tool for understanding price dynamics objectively, whether used on its own or alongside other indicators.
🛠️ SETTINGS 🛠️
The Non-Psychological Levels indicator offers various customizable settings to help users tailor its visualization to their specific trading style and market conditions. These settings allow adjustments to sensitivity, level projection, and the source of price calculations (e.g., wicks or closing prices). Below, we outline each setting and its impact on the chart, along with examples to illustrate their functionality.
Custom Settings
Sensitivity : This setting adjusts the balance between detailed and broader structural levels by controlling the number of segments. Higher values result in more segments, revealing finer price levels, while lower values consolidate segments to highlight major price movements.
Source : Allows the user to choose between 'Wick' or 'Close' for detecting levels. Selecting 'Wick' emphasizes the absolute highs and lows of price action, while 'Close' focuses on closing prices within each segment.
Level Labels : Configures the visual representation of price levels, allowing users to toggle between price values, symbols (▲ ▼), or disabling labels altogether. This setting ensures clarity in how Broken and Unbroken levels are displayed on the chart.
Unbroken Levels : - - - Users can customize the colors and label styles for Unbroken levels, which highlight areas where price has respected structural boundaries.
Broken Levels : -|- Similar to Unbroken levels, users can specify the visual appearance of Broken levels, including color customization for Broken highs and lows. These settings help distinguish areas where price has breached a structural boundary.
Projection Options : This setting allows users to control how broken and unbroken levels are visually extended on the chart. The Future option projects lines forward to the right of the current price, showing potential future relevance of levels. The All option extends lines both forward and backward, providing a comprehensive view of how levels align with historical and potential future price action. The None option disables projections, keeping the chart focused solely on current segment levels without any extensions.
Segments : Includes options for customizing the segment visualization:
- Live Segment : Toggles the display of a highlighted box representing the current developing segment, helping users focus on ongoing price action.
- Boxes : Allows users to display filled boxes around each segment for additional visual emphasis.
- Segment Colors : Users can define separate colors for support (lower) and resistance (upper) segments, making it easier to interpret directional trends.
- Boundaries : Enables or disables vertical lines to mark segment boundaries, providing a clearer view of structural divisions.
Repaint : This setting allows users to enable or disable triangle labels within the live segment. When enabled, the triangles dynamically update to reflect real-time price behavior during the live bar but will repaint until the bar is fully confirmed. Disabling this option prevents the triangles from appearing during the live bar, reducing potential confusion as they may otherwise flash on and off during price updates. This setting ensures users can choose their preferred visualization while maintaining clarity in real-time analysis.
Color Settings : Offers extensive customization for all visual elements, including Broken and Unbroken levels, segment boundaries, and live segments. These settings ensure the indicator can adapt to individual preferences for chart readability.
🖼️ CHART EXAMPLES 🖼️
The following chart examples illustrate different configurations and features of the Non-Psychological Levels indicator. These examples highlight how the indicator’s settings influence the visualization of structural price behavior, helping traders understand its functionality in various scenarios.
Broken and Unbroken Levels : Orange prices are Broken HIghs. Blue prices are Broken Lows. Green and Red are Unbroken.
Boundaries : Enable Boundaries to visualize segments.
High Sensitivity Setting : A high sensitivity setting produces fewer segments and levels, emphasizing broader price ranges and major structural zones. This configuration is better suited for higher timeframes or identifying overarching trends.
Low Sensitivity Setting : A low sensitivity setting results in a greater number of segments and levels, offering a granular view of price structure. This configuration is ideal for analyzing detailed price movements on lower timeframes.
Live Segment with Triangles Enabled : This example shows the live segment box with triangle labels enabled. These triangles update dynamically during the live bar but may repaint until the bar is confirmed, helping traders observe real-time price behavior.
Broken and Unbroken Levels : This example highlights Broken levels (where price has breached structural boundaries and are drawn through subsequent price action) and Unbroken levels (where price has respected structural boundaries). These distinctions visually identify areas of potential support and resistance.
Broken and Unbroken Levels with Projection: All : This example demonstrates the "Project All" feature, where broken and unbroken levels are extended both forward and backward on the chart. This visualization highlights historical and potential future support and resistance zones, helping traders better understand how price interacts with these structural levels over time.
Segment Boxes with Boundaries : Filled boxes around individual segments visually distinguish each price interval, offering clarity in observing structural price transitions.
📊 SUMMARY 📊
The Non-Psychological Levels indicator provides a unique framework for analyzing structural price behavior through the identification of Broken and Unbroken levels. These levels act as a mechanical representation of support and resistance, independent of psychological biases or time-based factors. By focusing purely on price movement within defined segments, the indicator offers a neutral and consistent approach to understanding market dynamics.
This method complements traditional tools by providing an unbiased perspective. When structural levels align with psychological zones—such as round numbers or session-based highs and lows—they reinforce the significance of these areas as key price zones. When they diverge, the indicator introduces an alternative view, prompting further exploration of price behavior. This dual perspective enhances the depth of analysis by combining the mechanical and behavioral aspects of price action.
The Non-Psychological Levels indicator is not designed to generate trading signals or predict future price movements but serves as a visual and educational tool. Its adaptability across all markets and timeframes allows traders to integrate it into their broader strategies. By highlighting structural price dynamics, the indicator offers a fresh perspective on market analysis while remaining compatible with other technical tools.
⚙️ COMPATIBILITY AND LIMITATIONS ⚙️
Asset Compatibility :
The Non-Psychological Levels indicator is compatible with all asset classes, including cryptocurrencies, forex, stocks, and commodities. It can be applied to any chart or timeframe, making it a flexible tool for structural price analysis. Users should adjust the Sensitivity setting to ensure the segmentation aligns with the price behavior of the specific asset being analyzed. For instance, higher sensitivity values are more suitable for assets with large price ranges, while lower values work well for assets with tighter ranges.
Visual Range Dependency :
The indicator is optimized to perform calculations only within the visible range of the chart. This is a significant advantage, as it prevents unnecessary calculations and maintains efficient performance. However, because of this dependency, levels may appear to "recalculate" when the chart is zoomed in or out quickly or shifted abruptly. While this does not affect the integrity of the levels, it may cause a temporary lag as the indicator adjusts to the new visual range.
Persistence of Levels Beyond Visibility :
Even if levels are not visible on the chart due to zoom or scroll settings, they still exist in the background and are recalculated when revisited. This ensures that the structural price analysis remains consistent, regardless of the chart view.
Box Limitations in Pine Script :
The indicator is subject to Pine Script's inherent limitation of 500 boxes. This means that no more than 500 segments or level boxes can be drawn on the chart simultaneously. For most configurations, this limitation is mitigated by focusing on the visual range, but users employing very low sensitivity settings may exceed the limit. In such cases, only the most recent 500 boxes will be displayed, potentially omitting earlier segments.
Lag with Low Sensitivity Settings :
When sensitivity is set to a low value, the indicator creates many more segments, resulting in finer granularity and a higher number of boxes. While this provides detailed structural levels, it may increase the likelihood of exceeding Pine Script’s 500-box limit or cause a temporary lag when rendering a dense set of boxes over a wide visual range. Users should adjust sensitivity to balance detail with performance, especially on assets with high volatility or broad price ranges.
Live Segment Caution :
The live segment box updates in real time to reflect price movements as the segment is still developing. Since the segment high and segment low are not yet finalized, users should interpret this feature as a dynamic visualization of current price behavior rather than a definitive structural analysis. This ensures clarity during ongoing price action while maintaining the integrity of the indicator's framework.
Cross-Market Versatility :
The indicator’s time-agnostic and mechanical design ensures that it functions identically across all markets and timeframes. However, users should consider the unique characteristics of different markets when interpreting the results, as certain assets (e.g., highly volatile cryptocurrencies) may require sensitivity adjustments for optimal segmentation.
Visual Range Dependency: Levels recalculate efficiently within the chart's visible range but may lag temporarily when zooming or scrolling quickly.
These considerations ensure that the Non-Psychological Levels indicator remains robust and versatile while highlighting some inherent limitations of Pine Script and real-time recalculations. Users can mitigate these constraints by carefully adjusting sensitivity and understanding how the visual range dependency affects performance.
⚠️ DISCLAIMER ⚠️
The Non-Psychological Levels indicator is a visual analysis tool and is not designed as a predictive or trading signal indicator. Its primary purpose is to highlight structural price levels, providing an objective framework for understanding support and resistance within mechanically segmented price action.
The indicator operates within the visible range of the chart to ensure efficiency and adaptiveness, but this recalculation should not be interpreted as a forecast of future price behavior. While the structural levels may align with significant price zones in hindsight, they are purely a reflection of observed price dynamics and should not be used as standalone trading signals.
This indicator is intended as an educational and visual aid to complement other analysis methods. Users are encouraged to integrate it into a broader trading strategy and make adjustments to the settings based on their individual needs and market conditions.
🧠 BEYOND THE CODE 🧠
The Non-Psychological Levels indicator, like other xxattaxx indicators , is designed with education and community collaboration in mind. Its open-source nature encourages exploration, experimentation, and the development of new approaches to price analysis. By focusing on structural price behavior rather than psychological or time-based factors, this indicator introduces a fresh perspective for users to study.
Beyond its visual utility, the indicator serves as an educational framework for understanding the concept of non-psychological analysis. It offers traders an opportunity to explore price dynamics in a purely mechanical way, challenging conventional methods and fostering deeper insights into structural behavior. This approach is especially valuable for those interested in exploring new concepts or seeking alternative perspectives on market analysis.
Your comments, suggestions, and discussions are invaluable in shaping the future of this project. We actively encourage your feedback and contributions, which will directly help us refine and improve the Non-Psychological Levels indicator. We look forward to seeing the creative ways in which you use and enhance this tool. MVS
Industry Group StrengthThe Industry Group Strength indicator is designed to help traders identify the best-performing stocks within specific industry groups. The movement of individual stocks is often closely tied to the overall performance of their industry. By focusing on industry groups, this indicator allows you to find the top-performing stocks within an industry.
Thanks to a recent Pine Script update, an indicator like this is now possible. Special thanks to @PineCoders for introducing the dynamic requests feature.
How this indicator works:
The indicator contains predefined lists of stocks for each industry group. To be included in these lists, stocks must meet the following basic filters:
Market capitalization over 2B
Price greater than $10
Primary listing status
Once the relevant stocks are filtered, the indicator automatically recognizes the industry group of the current stock displayed on the chart. It then retrieves and displays data for that entire industry group.
Data Points Available:
The user can choose between three different data points to rank and compare stocks:
YTD (Year-To-Date) Return: Measures how much a stock has gained or lost since the start of the year.
RS Rating: A relative strength rating for a user-selected lookback period (explained below).
% Return: The percentage return over a user-selected lookback period.
Stock Ranking:
Stocks are ranked based on their performance within their respective industry groups, allowing users to easily identify which stocks are leading or lagging behind others in the same sector.
Visualization:
The indicator presents stocks in a table format, with performance metrics displayed both as text labels and color-coded lines. The color gradient represents the percentile rank, making it visually clear which stocks are outperforming or underperforming within their industry group.
Relative Strength (RS):
Relative Strength (RS) measures a stock’s performance relative to a benchmark, typically the S&P 500 (the default setting). It is calculated by dividing the closing price of the stock by the closing price of the S&P 500.
If the stock rises while the S&P 500 falls, or if the stock rises more sharply than the S&P 500, the RS value increases. Conversely, if the stock falls while the S&P 500 rises, the RS value decreases. This indicator normalizes the RS value into a range from 1 to 99, allowing for easier comparison across different stocks, regardless of their raw performance. This normalized RS value helps traders quickly assess how a stock is performing relative to others.
SP500 RatiosThe "SP500 Ratios" indicator is a powerful tool developed for the TradingView platform, allowing users to access a variety of financial ratios and inflation-adjusted data related to the S&P 500 index. This indicator integrates with Nasdaq Data Link (formerly known as Quandl) to retrieve historical data, providing a comprehensive overview of key financial metrics associated with the S&P 500.
Key Features
Price to Sales Ratio: Quarterly ratio of price to sales (revenue) for the S&P 500.
Dividend Yield: Monthly dividend yield based on 12-month dividend per share.
Price Earnings Ratio (PE Ratio): Monthly price-to-earnings ratio based on trailing twelve-month reported earnings.
CAPE Ratio (Shiller PE Ratio): Monthly cyclically adjusted PE ratio, based on average inflation-adjusted earnings over the past ten years.
Earnings Yield: Monthly earnings yield, the inverse of the PE ratio.
Price to Book Ratio: Quarterly ratio of price to book value.
Inflation Adjusted S&P 500: Monthly S&P 500 level adjusted for inflation.
Revenue Per Share: Quarterly trailing twelve-month sales per share, not adjusted for inflation.
Earnings Per Share: Monthly real earnings per share, adjusted for inflation.
User Configuration
The indicator offers flexibility through user-configurable options. You can choose to display or hide each metric according to your analysis needs. Users can also adjust the line width for better visibility on the chart.
Visualization
The selected data is plotted on the chart with distinct colors for each metric, facilitating visual analysis. A dynamic legend table is also generated in the top-right corner of the chart, listing the currently displayed metrics with their associated colors.
This indicator is ideal for traders and analysts seeking detailed insights into the financial performance and valuations of the S&P 500, while benefiting from the customization flexibility offered by TradingView.
Volatility Projection Levels (VPL)### Indicator Name: **Volatility Projection Levels (VPL)**
### Description:
The **Volatility Projection Levels (VPL)** indicator is a powerful tool designed to help traders anticipate key support and resistance levels for the E-mini S&P 500 (ES) by leveraging the CBOE Volatility Index (^VIX). This indicator utilizes historical volatility data to project potential price movements for the upcoming month, offering clear visual cues that enhance swing trading strategies.
### Key Features:
- **Volatility-Based Projections**: The VPL indicator uses the previous month’s closing value of the VIX, normalizing it for monthly analysis by dividing by the square root of 12. This calculated percentage is then applied to the E-mini S&P 500’s closing price from the last day of the previous month.
- **Upper and Lower Projection Levels**: The indicator calculates two essential levels:
- **Upper Projection Level**: The previous month’s closing price of the E-mini S&P 500 plus the calculated volatility percentage.
- **Lower Projection Level**: The previous month’s closing price of the E-mini S&P 500 minus the calculated volatility percentage.
- **Continuous Visualization**: The VPL indicator plots these projection levels on the chart throughout the entire month, providing traders with a consistent reference for potential support and resistance zones. This continuous visualization allows for better anticipation of market movements.
- **Previous Month's Close Reference**: Additionally, the indicator plots the previous month’s closing price as a reference point, offering further context for current price action.
### Use Cases:
- **Swing Trading**: The VPL indicator is ideal for swing traders looking to exploit predicted price ranges within a monthly timeframe.
- **Support & Resistance Identification**: It aids traders in identifying critical levels where the market may encounter support or resistance, thus informing entry and exit decisions.
- **Risk Management**: By forecasting potential price levels, traders can set more strategic stop-loss and take-profit levels, enhancing risk management.
### Summary:
The **Volatility Projection Levels (VPL)** indicator equips traders with a forward-looking tool that incorporates volatility data into market analysis. By projecting key price levels based on historical VIX data, the VPL indicator enhances decision-making, helping traders anticipate market movements and optimize their trading strategies.
Made by Serpenttrading
Market Breadth - AsymmetrikMarket Breadth - Asymmetrik User Manual
Overview
The Market Breadth - Asymmetrik is a script designed to provide insights into the overall market condition by plotting three key indicators based on stocks within the S&P 500 index. It helps traders assess market momentum and strength through visual cues and is especially useful for understanding the proportion of stocks trading above their respective moving averages.
Features
1. Market Breadth Indicators:
- Breadth 20D (green line): Represents the percentage of stocks in the S&P 500 that are above their 20-day moving average.
- Breadth 50D (yellow line): Represents the percentage of stocks in the S&P 500 that are above their 50-day moving average.
- Breadth 100D (red line): Represents the percentage of stocks in the S&P 500 that are above their 100-day moving average.
2. Horizontal Lines for Context:
- Green line at 10%
- Lighter green line at 20%
- Grey line at 50%
- Light red line at 80%
- Dark red line at 90%
3. Background Color Alerts:
- Green background when all three indicators are under 20%, indicating a potential oversold market condition.
- Red background when all three indicators are over 80%, indicating a potential overbought market condition.
Interpreting the Indicator
- Market Breadth Lines: Observe the plotted lines to assess the percentage of stocks above their moving averages.
- Horizontal Lines: Use the horizontal lines to quickly identify important threshold levels.
- Background Colors: Pay attention to background colors for quick insights:
- Green: All indicators suggest a potentially oversold market condition (below 20).
- Red: All indicators suggest a potentially overbought market condition (above 80).
Troubleshooting
- If the indicator does not appear as expected, please contact me.
- This indicator works only on daily and weekly timeframes.
Conclusion
This Market Breadth Indicator offers a visual representation of market momentum and strength through three key indicators, helping you identify potential buying and selling zones.
Earnings Yield & Dividend Yield (vs SP500, treasury, IG)# What's this script?
I created this because I wanted to compare the Earnings/Dividend yield of SP500 and the symbol with the time period of the chart.
Plot the following yields.
Earnings Yield of S&P500.
Calculated using S&P 500 Earnings by Month provided by Nasdaq date link.
(data.nasdaq.com)
Dividend Yield of S&P500.
Calculated using S&P 500 Dividend by Month provided by Nasdaq date link.
(data.nasdaq.com)
Earnings Yield of the displayed symbol.
Dividend Yield of the displayed symbol.
Treasury constant maturity rate. default is 10Y(FRED:DGS10).
Investment grade corporate bond yields by Moody's.
Grades from Aaa to Baa are represented by color bands.
Investment grade bond yields by BofA.
Grades from AAA to BBB are represented by color bands.
-----------
◇これなに?
request.quandl()を用いてSP500の益回りと配当利回りが得られますが
月間データなのでチャートの時間間隔でみたかったのと、
SP500とシンボルの益回りや配当利回りを比較したかったのでつくりました。
下記を表示します
- SP500の益回りと配当利回り
- 表示シンボルの益回りや配当利回り
- 設定画面で指定した財務省債券(デフォルトは10年)
- 投資適格社債(MoodysとBofAでかなり違ったので両方)をカラーバンドで表示
かんたんなものですけど、おやくにたてればさいわいです
Rsi strategy for BTC with (Rsi SPX)
I hope this strategy is just an idea and a starting point, I use the correlation of the Sp500 with the Btc, this does not mean that this correlation will exist forever!. I love Trading view and I'm learning to program, I find correlations very interesting and here is a simple strategy.
This is a trading strategy script written in Pine Script language for use in TradingView. Here is a brief overview of the strategy:
The script uses the RSI (Relative Strength Index) technical indicator with a period of 14 on two securities: the S&P 500 (SPX) and the symbol corresponding to the current chart (presumably Bitcoin, based on the variable name "Btc_1h_fixed"). The RSI is plotted on the chart for both securities.
The script then sets up two trading conditions using the RSI values:
A long entry condition: when the RSI for the current symbol crosses above the RSI for the S&P 500, a long trade is opened using the "strategy.entry" function.
A short entry condition: when the RSI for the current symbol crosses below the RSI for the S&P 500, a short trade is opened using the "strategy.entry" function.
The script also includes a take profit input parameter that allows the user to set a percentage profit target for closing the trade. The take profit is set using the "strategy.exit" function.
Overall, the strategy aims to take advantage of divergences in RSI values between the current symbol and the S&P 500 by opening long or short trades accordingly. The take profit parameter allows the user to set a specific profit target for each trade. However, the script does not include any stop loss or risk management features, which should be considered when implementing the strategy in a real trading scenario.
BTC/USD - RSIIF RSI (14) reaches 68 ... sell 1 lot size ( with TP 250 points and SL 500 points)
IF RSI (14) reaches 27 ... buy 1 lot size ( with TP 250points and SL 500 points)
IF RSI (14) reaches 80 ... sell 1 lot size ( with TP 250 points and SL 500 points)
IF RSI (14) reaches 18 ... buy 1 lot size ( with TP 250points and SL 500 points)
VIX MTF MomentumSweet little momentum gadget to track the VIX Index.
What is the VIX?
The CBOE S&P 500 Volatility Index (VIX) is known as the 'Fear Index' which can measure how worried traders are that the S&P 500 might suddenly drop within the next 30 days.
When the VIX starts moving higher, it is telling you that traders are getting nervous. When the VIX starts moving lower, it is telling you that traders are gaining confidence.
VIX calculation?
The Chicago Board of Options Exchange Market Volatility Index (VIX) is a measure of implied volatility (Of the S&P 500 securities options), based on the prices of a basket of S&P 500 Index options with 30 days to expiration.
How to use:
If VIX Momentum is above 0 (RED) traders are getting nervous.
If VIX Momentum is below 0 (GREEN) traders are gaining confidence.
Follow to get updates and new scripts: www.tradingview.com
Open Interest Rank-BuschiEnglish:
One part of the "Commitment of Traders-Report" is the Open Interest which is shown in this indicator (source: Quandl database).
Unlike my also published indicator "Open Interest-Buschi", the values here are not absolute but in a ranking system from 0 to 100 with individual time frames-
The following futures are included:
30-year Bonds (ZB)
10-year Notes ( ZN )
Soybeans (ZS)
Soybean Meal (ZM)
Soybean Oil (ZL)
Corn ( ZC )
Soft Red Winter Wheat (ZW)
Hard Red Winter Wheat (KE)
Lean Hogs (HE)
Live Cattle ( LE )
Gold ( GC )
Silver (SI)
Copper (HG)
Crude Oil ( CL )
Heating Oil (HO)
RBOB Gasoline ( RB )
Natural Gas ( NG )
Australian Dollar (A6)
British Pound (B6)
Canadian Dollar (D6)
Euro (E6)
Japanese Yen (J6)
Swiss Franc (S6)
Sugar ( SB )
Coffee (KC)
Cocoa ( CC )
Cotton ( CT )
S&P 500 E-Mini (ES)
Russell 2000 E-Mini (RTY)
Dow Jones Industrial Mini (YM)
Nasdaq 100 E-Mini (NQ)
Platin (PL)
Palladium (PA)
Aluminium (AUP)
Steel ( HRC )
Ethanol (AEZ)
Brent Crude Oil (J26)
Rice (ZR)
Oat (ZO)
Milk (DL)
Orange Juice (JO)
Lumber (LS)
Feeder Cattle (GF)
S&P 500 ( SP )
Dow Jones Industrial Average Index (DJIA)
New Zealand Dollar (N6)
Deutsch:
Ein Bestandteil des "Commitment of Traders-Report" ist das Open Interest, das in diesem Indikator dargestellt wird (Quelle: Quandl Datenbank).
Anders als in meinem ebenfalls veröffentlichten Indikator "Open Interest-Buschi" werden hier nicht die absoluten Werte dargestellt, sondern in einem Ranking-System von 0 bis 100 mit individuellen Zeitrahmen.
Folgende Futures sind enthalten:
30-jährige US-Staatsanleihen (ZB)
10-jährige US-Staatsanleihen ( ZN )
Sojabohnen(ZS)
Sojabohnen-Mehl (ZM)
Sojabohnen-Öl (ZL)
Mais( ZC )
Soft Red Winter-Weizen (ZW)
Hard Red Winter-Weizen (KE)
Magerschweine (HE)
Lebendrinder ( LE )
Gold ( GC )
Silber (SI)
Kupfer(HG)
Rohöl ( CL )
Heizöl (HO)
Benzin ( RB )
Erdgas ( NG )
Australischer Dollar (A6)
Britisches Pfund (B6)
Kanadischer Dollar (D6)
Euro (E6)
Japanischer Yen (J6)
Schweizer Franken (S6)
Zucker ( SB )
Kaffee (KC)
Kakao ( CC )
Baumwolle ( CT )
S&P 500 E-Mini (ES)
Russell 2000 E-Mini (RTY)
Dow Jones Industrial Mini (YM)
Nasdaq 100 E-Mini (NQ)
Platin (PL)
Palladium (PA)
Aluminium (AUP)
Stahl ( HRC )
Ethanol (AEZ)
Brent Rohöl (J26)
Reis (ZR)
Hafer (ZO)
Milch (DL)
Orangensaft (JO)
Holz (LS)
Mastrinder (GF)
S&P 500 ( SP )
Dow Jones Industrial Average Index (DJIA)
Neuseeland Dollar (N6)
Open Interest-Buschi
English:
One part of the "Commitment of Traders-Report" is the Open Interest which is shown in this indicator (source: Quandl database).
The following futures are included:
30-year Bonds (ZB)
10-year Notes (ZN)
Soybeans (ZS)
Soybean Meal (ZM)
Soybean Oil (ZL)
Corn (ZC)
Soft Red Winter Wheat (ZW)
Hard Red Winter Wheat(KE)
Lean Hogs (HE)
Live Cattle (LE)
Gold (GC)
Silver (SI)
Copper (HG)
Crude Oil (CL)
Heating Oil (HO)
RBOB Gasoline (RB)
Natural Gas (NG)
Australian Dollar (A6)
British Pound (B6)
Canadian Dollar (D6)
Euro (E6)
Japanese Yen (J6)
Swiss Franc (S6)
Sugar (SB)
Coffee (KC)
Cocoa (CC)
Cotton (CT)
S&P 500 E-Mini (ES)
Russell 2000 E-Mini (RTY)
Dow Jones Industrial Mini (YM)
Nasdaq 100 E-Mini (NQ)
Platin (PL)
Palladium (PA)
Aluminium (AUP)
Steel (HRC)
Ethanol (AEZ)
Brent Crude Oil (J26)
Rice (ZR)
Oat (ZO)
Milk (DL)
Orange Juice (JO)
Lumber (LS)
Feeder Cattle (GF)
S&P 500 (SP)
Dow Jones Industrial Average Index (DJIA)
New Zealand Dollar (N6)
Deutsch:
Ein Bestandteil des "Commitment of Traders-Report" ist das Open Interest, das in diesem Indikator dargestellt wird (Quelle: Quandl Datenbank).
Folgende Futures sind enthalten:
30-jährige US-Staatsanleihen (ZB)
10-jährige US-Staatsanleihen (ZN)
Sojabohnen(ZS)
Sojabohnen-Mehl (ZM)
Sojabohnen-Öl (ZL)
Mais(ZC)
Soft Red Winter-Weizen (ZW)
Hard Red Winter-Weizen (KE)
Magerschweine (HE)
Lebendrinder (LE)
Gold (GC)
Silber (SI)
Kupfer(HG)
Rohöl (CL)
Heizöl (HO)
Benzin (RB)
Erdgas (NG)
Australischer Dollar (A6)
Britisches Pfund (B6)
Kanadischer Dollar (D6)
Euro (E6)
Japanischer Yen (J6)
Schweizer Franken (S6)
Zucker (SB)
Kaffee (KC)
Kakao (CC)
Baumwolle (CT)
S&P 500 E-Mini (ES)
Russell 2000 E-Mini (RTY)
Dow Jones Industrial Mini (YM)
Nasdaq 100 E-Mini (NQ)
Platin (PL)
Palladium (PA)
Aluminium (AUP)
Stahl (HRC)
Ethanol (AEZ)
Brent Rohöl (J26)
Reis (ZR)
Hafer (ZO)
Milch (DL)
Orangensaft (JO)
Holz (LS)
Mastrinder (GF)
S&P 500 (SP)
Dow Jones Industrial Average Index (DJIA)
Neuseeland Dollar (N6)
HSM KILLZONE//@version=5
indicator('HSM KILLZONE', 'HSM KILLZONE', overlay=true, max_bars_back=500, explicit_plot_zorder=true)
import boitoki/AwesomeColor/4 as ac
import boitoki/Utilities/3 as util
///////////////
// Groups
///////////////
g0 = 'GENERAL'
g1_01 = '♯1 SESSION'
g1_02 = '♯2 SESSION'
g1_03 = '♯3 SESSION'
g1_04 = '♯4 SESSION'
g4 = 'BOX'
g6 = 'LABELS'
g5 = 'OPENING RANGE'
g7 = 'FIBONACCI LEVELS'
g8 = 'OPTIONS'
g11 = 'CANDLE'
g10 = 'Alerts visualized'
///////////////
// Defined
///////////////
max_bars = 500
option_yes = 'Yes'
option_no = '× No'
option_extend1 = 'Yes'
option_hide = '× Hide'
option_border_style1 = '────'
option_border_style2 = '- - - - - -'
option_border_style3 = '•••••••••'
option_chart_x = '× No'
option_chart_1 = 'Bar color'
option_chart_2 = 'Candles'
fmt_price = '{0,number,#.#####}'
fmt_pips = '{0,number,#.#}'
icon_separator = ' • '
color_none = color.new(color.black, 100)
color_text = color.new(color.white, 0)
///////////////
// Functions
///////////////
f_get_time_by_bar(bar_count) => timeframe.multiplier * bar_count * 60 * 1000
f_border_style (_style) =>
switch _style
option_border_style1 => line.style_solid
option_border_style2 => line.style_dashed
option_border_style3 => line.style_dotted
=> _style
f_get_period (_session, _start, _lookback) =>
result = math.max(_start, 1)
for i = result to _lookback
if na(_session ) and _session
result := i+1
break
result
f_get_label_position (_y, _side) =>
switch _y
'top' => _side == 'outside' ? label.style_label_lower_left : label.style_label_upper_left
'bottom' => _side == 'outside' ? label.style_label_upper_left : label.style_label_lower_left
f_get_started (_session) => na(_session ) and _session
f_get_ended (_session) => na(_session) and _session
f_message_limit_bars (_v) => '⚠️ This box\'s right position exceeds 500 bars(' + str.tostring(_v) + '). This box is not displayed correctly.'
f_set_line_x1 (_line, _x) =>
if (line.get_x1(_line) != _x)
line.set_x1(_line, _x)
f_set_line_x2 (_line, _x) =>
if (line.get_x2(_line) != _x)
line.set_x2(_line, _x)
f_set_box_right (_box, _x) =>
if box.get_right(_box) != _x
box.set_right(_box, _x)
///////////////
// Inputs
///////////////
// Timezone
i_tz = input.string('GMT-4', title='Timezone', options= , tooltip='e.g. \'America/New_York\', \'Asia/Tokyo\', \'GMT-4\', \'GMT+9\'...', group=g0)
i_history_period = input.int(10, 'History', minval=0, group=g0)
i_show = i_history_period > 0
i_lookback = 12 * 60
// Sessions
i_show_sess1 = input.bool(true, 'Session 1 ', group=g1_01, inline='session1_1') and i_show
i_sess1_label = input.string('New York AM', '', group=g1_01, inline='session1_1')
i_sess1_color = input.color(#0a0a0a, '', group=g1_01, inline='session1_1')
i_sess1_barcolor1 = input.color(#0a0a0a, '•', group=g1_01, inline='session1_1')
i_sess1_barcolor2 = input.color(#0a0a0a, '', group=g1_01, inline='session1_1')
i_sess1 = input.session('0700-1100', 'Time', group=g1_01)
i_sess1_extend = input.string(option_no, 'Extend', options= , group=g1_01)
i_sess1_fib = input.string(option_no, 'Fibonacci levels', group=g1_01, options= ) != option_no
i_sess1_op = input.string(option_no, 'Opening range', group=g1_01, options= ) != option_no and i_show
i_sess1_chart = input.string(option_chart_x, 'Bar', options= , group=g1_01)
i_sess1_barcolor = i_sess1_chart == option_chart_1
i_sess1_plotcandle = i_sess1_chart == option_chart_2
i_show_sess2 = input.bool(true, 'Session 2 ', group=g1_02, inline='session2_1') and i_show
i_sess2_label = input.string('New York PM', '', group=g1_02, inline='session2_1')
i_sess2_color = input.color(#0a0a0a, '', group=g1_02, inline='session2_1')
i_sess2_barcolor1 = input.color(#0a0a0a, '•', group=g1_02, inline='session2_1')
i_sess2_barcolor2 = input.color(#0a0a0a, '', group=g1_02, inline='session2_1')
i_sess2 = input.session('1300-1600', 'Time', group=g1_02)
i_sess2_extend = input.string(option_no, 'Extend', options= , group=g1_02)
i_sess2_fib = input.string(option_no, 'Fibonacci levels', group=g1_02, options= ) != option_no
i_sess2_op = input.string(option_no, 'Opening range', group=g1_02, options= ) != option_no and i_show
i_sess2_chart = input.string(option_chart_x, 'Bar', options= , group=g1_02)
i_sess2_barcolor = i_sess2_chart == option_chart_1
i_sess2_plotcandle = i_sess2_chart == option_chart_2
i_show_sess3 = input.bool(true, 'Session 3 ', group=g1_03, inline='session3_1') and i_show
i_sess3_label = input.string('Asian Sesh', '', group=g1_03, inline='session3_1')
i_sess3_color = input.color(#0a0a0a, '', group=g1_03, inline='session3_1')
i_sess3_barcolor1 = input.color(#0a0a0a, '•', group=g1_03, inline='session3_1')
i_sess3_barcolor2 = input.color(#0a0a0a, '', group=g1_03, inline='session3_1')
i_sess3 = input.session('2000-0000', 'Time', group=g1_03)
i_sess3_extend = input.string(option_no, 'Extend', options= , group=g1_03)
i_sess3_fib = input.string(option_no, 'Fibonacci levels', group=g1_03, options= ) != option_no
i_sess3_op = input.string(option_no, 'Opening range', group=g1_03, options= ) != option_no and i_show
i_sess3_chart = input.string(option_chart_x, 'Bar', options= , group=g1_03)
i_sess3_barcolor = i_sess3_chart == option_chart_1
i_sess3_plotcandle = i_sess3_chart == option_chart_2
i_show_sess4 = input.bool(true, 'Session 4 ', group=g1_04, inline='session4_1') and i_show
i_sess4_label = input.string('London', '', group=g1_04, inline='session4_1')
i_sess4_color = input.color(#0a0a0a, '', group=g1_04, inline='session4_1')
i_sess4_barcolor1 = input.color(#0a0a0a, '•', group=g1_04, inline='session4_1')
i_sess4_barcolor2 = input.color(#0a0a0a, '', group=g1_04, inline='session4_1')
i_sess4 = input.session('0200-0500', 'Time', group=g1_04)
i_sess4_extend = input.string(option_no, 'Extend', options= , group=g1_04)
i_sess4_fib = input.string(option_no, 'Fibonacci levels', group=g1_04, options= ) != option_no
i_sess4_op = input.string(option_no, 'Opening range', group=g1_04, options= ) != option_no and i_show
i_sess4_chart = input.string(option_chart_x, 'Bar', options= , group=g1_04)
i_sess4_barcolor = i_sess4_chart == option_chart_1
i_sess4_plotcandle = i_sess4_chart == option_chart_2
// Show & Styles
i_sess_box_style = input.string('Box', 'Style', options= , group=g4)
i_sess_border_style = f_border_style(input.string(option_border_style2, 'Line style', options= , group=g4))
i_sess_border_width = input.int(1, 'Thickness', minval=0, group=g4)
i_sess_bgopacity = input.int(94, 'Transp', minval=0, maxval=100, step=1, group=g4, tooltip='Setting the 100 is no background color')
// Candle
option_candle_body = 'OC'
option_candle_wick = 'OHLC'
i_candle = input.string(option_hide, 'Display', options= , group=g11)
i_candle_border_width = input.int(2, 'Thickness', minval=0, group=g11)
i_show_candle = (i_candle != option_hide) and (i_candle_border_width > 0)
i_show_candle_wick = i_candle == option_candle_wick
option_candle_color1 = 'Session\'s'
option_candle_color2 = 'Red • Green'
i_candle_color = input.string(option_candle_color2, 'Color ', options= , group=g11, inline='candle_color')
i_candle_color_g = input.color(#A6E22E, '', group=g11, inline='candle_color')
i_candle_color_r = input.color(#F92672, '', group=g11, inline='candle_color')
// Labels
i_label_show = input.bool(true, 'Labels', inline='label_show', group=g6) and i_show
i_label_size = str.lower(input.string('Small', '', options= , inline='label_show', group=g6))
i_label_position_y = str.lower(input.string('Top', '', options= , inline='label_show', group=g6))
i_label_position_s = str.lower(input.string('Outside', '', options= , inline='label_show', group=g6))
i_label_position = f_get_label_position(i_label_position_y, i_label_position_s)
i_label_format_name = input.bool(true, 'Name', inline='label_format', group=g6)
i_label_format_day = input.bool(false, 'Day', inline='label_format', group=g6)
i_label_format_price = input.bool(false, 'Price', inline='label_format', group=g6)
i_label_format_pips = input.bool(false, 'Pips', inline='label_format', group=g6)
// Fibonacci levels
i_f_linestyle = f_border_style(input.string(option_border_style1, title="Style", options= , group=g7))
i_f_linewidth = input.int(1, title="Thickness", minval=1, group=g7)
// Opening range
i_o_minutes = input.int(15, title='Periods (minutes)', minval=1, step=1, group=g5)
i_o_minutes := math.max(i_o_minutes, timeframe.multiplier + 1)
i_o_transp = input.int(88, title='Transp', minval=0, maxval=100, step=1, group=g5)
// Alerts
i_alert1_show = input.bool(false, 'Alerts - Sessions stard/end', group=g10)
i_alert2_show = input.bool(false, 'Alerts - Opening range breakouts', group=g10)
i_alert3_show = input.bool(false, 'Alerts - Price crossed session\'s High/Low after session closed', group=g10)
// ------------------------
// Drawing labels
// ------------------------
f_render_label (_show, _session, _is_started, _color, _top, _bottom, _text, _labels) =>
var label my_label = na
var int start_time = na
v_position_y = (i_label_position_y == 'top') ? _top : _bottom
v_label = array.new_string()
v_chg = _top - _bottom
if _is_started
start_time := time
if i_label_format_name and not na(_text)
array.push(v_label, _text)
if i_label_format_day
array.push(v_label, util.get_day(dayofweek(start_time, i_tz)))
if i_label_format_price
array.push(v_label, str.format(fmt_price, v_chg))
if i_label_format_pips
array.push(v_label, str.format(fmt_pips, util.toPips(v_chg)) + ' pips')
if _show
if _is_started
my_label := label.new(bar_index, v_position_y, array.join(v_label, icon_separator), textcolor=_color, color=color_none, size=i_label_size, style=i_label_position)
array.push(_labels, my_label)
util.clear_labels(_labels, i_history_period)
else if _session
label.set_y(my_label, v_position_y)
label.set_text(my_label, array.join(v_label, icon_separator))
// ------------------------
// Drawing Fibonacci levels
// ------------------------
f_render_fibonacci (_show, _session, _is_started, _x1, _x2, _color, _top, _bottom, _level, _width, _style, _is_extend, _lines) =>
var line my_line = na
if _show
y = (_top - _bottom) * _level + _bottom
if _is_started
my_line := line.new(_x1, y, _x2, y, width=_width, color=color.new(_color, 30), style=_style)
array.push(_lines, my_line)
if _is_extend
line.set_extend(my_line, extend.right)
else if _session
line.set_y1(my_line, y)
line.set_y2(my_line, y)
f_set_line_x2(my_line, _x2)
// ------------------------
// Drawing Opening range
// ------------------------
f_render_oprange (_show, _session, _is_started, _x1, _x2, _color, _max, _is_extend, _boxes) =>
var int start_time = na
var box my_box = na
top = ta.highest(high, _max)
bottom = ta.lowest(low, _max)
is_crossover = ta.crossover(close, box.get_top(my_box))
is_crossunder = ta.crossunder(close, box.get_bottom(my_box))
if _show
if _is_started
util.clear_boxes(_boxes, math.max(0, i_history_period - 1))
start_time := time
my_box := na
else if _session
time_op = start_time + (i_o_minutes * 60 * 1000)
time_op_delay = time_op - f_get_time_by_bar(1)
if time <= time_op and time > time_op_delay
my_box := box.new(_x1, top, _x2, bottom, border_width=0, bgcolor=color.new(_color, i_o_transp))
array.push(_boxes, my_box)
if _is_extend
box.set_extend(my_box, extend.right)
my_box
else
f_set_box_right(my_box, _x2)
if is_crossover
alert('Price crossed over the opening range', alert.freq_once_per_bar)
if i_alert2_show
label.new(bar_index, box.get_top(my_box), "×", color=color.blue, textcolor=ac.tradingview('blue'), style=label.style_none, size=size.large)
if is_crossunder
alert('Price crossed under the opening range', alert.freq_once_per_bar)
if i_alert2_show
label.new(bar_index, box.get_bottom(my_box), "×", color=color.red, textcolor=ac.tradingview('red'), style=label.style_none, size=size.large)
my_box
// ------------------------
// Drawing candle
// ------------------------
f_render_candle (_show, _session, _is_started, _is_ended, _color, _top, _bottom, _open, _x1, _x2, _boxes, _lines) =>
var box body = na
var line wick1 = na
var line wick2 = na
border_width = i_candle_border_width
cx = math.round(math.avg(_x2, _x1)) - math.round(border_width / 2)
body_color = i_candle_color == option_candle_color2 ? close > _open ? i_candle_color_g : i_candle_color_r : _color
if _show
if _is_started
body := box.new(_x1, _top, _x2, _bottom, body_color, border_width, line.style_solid, bgcolor=color.new(color.black, 100))
wick1 := i_show_candle_wick ? line.new(cx, _top, cx, _top, color=_color, width=border_width, style=line.style_solid) : na
wick2 := i_show_candle_wick ? line.new(cx, _bottom, cx, _bottom, color=_color, width=border_width, style=line.style_solid) : na
array.push(_boxes, body)
array.push(_lines, wick1)
array.push(_lines, wick2)
util.clear_boxes(_boxes, i_history_period)
util.clear_lines(_lines, i_history_period * 2)
else if _session
top = math.max(_open, close)
bottom = math.min(_open, close)
box.set_top(body, top)
box.set_bottom(body, bottom)
box.set_right(body, _x2)
box.set_border_color(body, body_color)
line.set_y1(wick1, _top)
line.set_y2(wick1, top)
f_set_line_x1(wick1, cx)
f_set_line_x2(wick1, cx)
line.set_color(wick1, body_color)
line.set_y1(wick2, _bottom)
line.set_y2(wick2, bottom)
f_set_line_x1(wick2, cx)
f_set_line_x2(wick2, cx)
line.set_color(wick2, body_color)
else if _is_ended
box.set_right(body, bar_index)
// ------------------------
// Rendering limit message
// ------------------------
f_render_limitmessage (_show, _session, _is_started, _is_ended, _x, _y, _rightbars) =>
var label my_note = na
if _show
if _is_started
if _rightbars > max_bars
my_note := label.new(_x, _y, f_message_limit_bars(_rightbars), style=label.style_label_upper_left, color=color.yellow, textalign=text.align_left, yloc=yloc.price)
else if _session
if _rightbars > max_bars
label.set_y(my_note, _y)
label.set_text(my_note, f_message_limit_bars(_rightbars))
else
label.delete(my_note)
else if _is_ended
label.delete(my_note)
true
// Rendering session
//
f_render_sessionrange (_show, _session, _is_started, _is_ended, _color, _top, _bottom, _x1, _x2, _is_extend, _lines) =>
var line above_line = na
var line below_line = na
if _show
if _is_started
above_line := line.new(_x1, _top, _x2, _top, width=i_sess_border_width, style=i_sess_border_style, color=_color)
below_line := line.new(_x1, _bottom, _x2, _bottom, width=i_sess_border_width, style=i_sess_border_style, color=_color)
linefill.new(above_line, below_line, color.new(_color, i_sess_bgopacity))
array.push(_lines, above_line)
array.push(_lines, below_line)
util.clear_lines(_lines, i_history_period * 2)
if _is_extend
line.set_extend(above_line, extend.right)
line.set_extend(below_line, extend.right)
else if _session
line.set_y1(above_line, _top)
line.set_y2(above_line, _top)
line.set_x2(above_line, _x2)
line.set_y1(below_line, _bottom)
line.set_y2(below_line, _bottom)
line.set_x2(below_line, _x2)
true
else if _is_ended
true
true
// ------------------------
// Rendering session box
// ------------------------
f_render_session (_show, _session, _is_started, _is_ended, _color, _top, _bottom, _x1, _x2, _is_extend, _boxes) =>
var box my_box = na
if _show
if _is_started
my_box := box.new(_x1, _top, _x2, _bottom, _color, i_sess_border_width, i_sess_border_style, bgcolor=color.new(_color, i_sess_bgopacity))
array.push(_boxes, my_box)
util.clear_boxes(_boxes, i_history_period)
if _is_extend
box.set_extend(my_box, extend.right)
else if _session
box.set_top(my_box, _top)
box.set_bottom(my_box, _bottom)
f_set_box_right(my_box, _x2)
else if _is_ended
box.set_right(my_box, bar_index)
my_box
// ------------------------
// Drawing market
// ------------------------
f_render_main (_show, _session, _is_started, _is_ended, _color, _top, _bottom) =>
var box my_box = na
var label my_note = na
var x1 = 0
var x2 = 0
var session_open = 0.0
var session_high = 0.0
var session_low = 0.0
x0_1 = ta.valuewhen(na(_session ) and _session, bar_index, 1)
x0_2 = ta.valuewhen(na(_session) and _session , bar_index, 0)
x0_d = math.abs(x0_2 - x0_1)
limit_bars = max_bars
rightbars = x0_d
if _show
if _is_started
x1 := bar_index
x2 := bar_index + (math.min(x0_d, limit_bars))
session_open := open
session_high := _top
session_low := _bottom
else if _session
true_x2 = x1 + x0_d
rightbars := true_x2 - bar_index
limit_bars := bar_index + max_bars
x2 := math.min(true_x2, limit_bars)
session_high := _top
session_low := _bottom
else if _is_ended
session_open := na
// ------------------------
// Drawing
// ------------------------
draw (_show, _session, _color, _label, _extend, _show_fib, _show_op, _lookback, _boxes_session, _lines_session, _boxes_candle_body, _lines_candle_wick, _boxes_op, _lines_fib, _labels) =>
max = f_get_period(_session, 1, _lookback)
top = ta.highest(high, max)
bottom = ta.lowest(low, max)
is_started = f_get_started(_session)
is_ended = f_get_ended(_session)
is_extend = _extend != option_no
= f_render_main(_show, _session, is_started, is_ended, _color, top, bottom)
if i_sess_box_style == 'Box'
f_render_session(_show, _session, is_started, is_ended, _color, top, bottom, x1, x2, is_extend, _boxes_session)
if i_sess_box_style == 'Sandwich'
f_render_sessionrange(_show, _session, is_started, is_ended, _color, top, bottom, x1, x2, is_extend, _lines_session)
if i_show_candle
f_render_candle(_show, _session, is_started, is_ended, _color, top, bottom, _open, x1, x2, _boxes_candle_body, _lines_candle_wick)
if i_label_show
f_render_label(_show, _session, is_started, _color, top, bottom, _label, _labels)
if _show_op
f_render_oprange(_show, _session, is_started, x1, x2, _color, max, is_extend, _boxes_op)
if _show_fib
f_render_fibonacci(_show, _session, is_started, x1, x2, _color, top, bottom, 0.500, 2, line.style_solid, is_extend, _lines_fib)
f_render_fibonacci(_show, _session, is_started, x1, x2, _color, top, bottom, 0.628, i_f_linewidth, i_f_linestyle, is_extend, _lines_fib)
f_render_fibonacci(_show, _session, is_started, x1, x2, _color, top, bottom, 0.382, i_f_linewidth, i_f_linestyle, is_extend, _lines_fib)
util.clear_lines(_lines_fib, i_history_period * 3)
f_render_limitmessage(_show, _session, is_started, is_ended, x1, bottom, _rightbars)
///////////////////
// Calculating
///////////////////
string tz = (i_tz == option_no or i_tz == '') ? na : i_tz
int sess1 = time(timeframe.period, i_sess1, tz)
int sess2 = time(timeframe.period, i_sess2, tz)
int sess3 = time(timeframe.period, i_sess3, tz)
int sess4 = time(timeframe.period, i_sess4, tz)
///////////////////
// Plotting
///////////////////
var sess1_box = array.new()
var sess2_box = array.new()
var sess3_box = array.new()
var sess4_box = array.new()
var sess1_line = array.new()
var sess2_line = array.new()
var sess3_line = array.new()
var sess4_line = array.new()
var sess1_op = array.new()
var sess2_op = array.new()
var sess3_op = array.new()
var sess4_op = array.new()
var sess1_fib = array.new()
var sess2_fib = array.new()
var sess3_fib = array.new()
var sess4_fib = array.new()
var sess1_candle_body = array.new()
var sess2_candle_body = array.new()
var sess3_candle_body = array.new()
var sess4_candle_body = array.new()
var sess1_candle_wick = array.new()
var sess2_candle_wick = array.new()
var sess3_candle_wick = array.new()
var sess4_candle_wick = array.new()
var sess1_labels = array.new()
var sess2_labels = array.new()
var sess3_labels = array.new()
var sess4_labels = array.new()
= draw(i_show_sess1, sess1, i_sess1_color, i_sess1_label, i_sess1_extend, i_sess1_fib, i_sess1_op, i_lookback, sess1_box, sess1_line, sess1_candle_body, sess1_candle_wick, sess1_op, sess1_fib, sess1_labels)
= draw(i_show_sess2, sess2, i_sess2_color, i_sess2_label, i_sess2_extend, i_sess2_fib, i_sess2_op, i_lookback, sess2_box, sess2_line, sess2_candle_body, sess2_candle_wick, sess2_op, sess2_fib, sess2_labels)
= draw(i_show_sess3, sess3, i_sess3_color, i_sess3_label, i_sess3_extend, i_sess3_fib, i_sess3_op, i_lookback, sess3_box, sess3_line, sess3_candle_body, sess3_candle_wick, sess3_op, sess3_fib, sess3_labels)
= draw(i_show_sess4, sess4, i_sess4_color, i_sess4_label, i_sess4_extend, i_sess4_fib, i_sess4_op, i_lookback, sess4_box, sess4_line, sess4_candle_body, sess4_candle_wick, sess4_op, sess4_fib, sess4_labels)
is_positive_bar = close > open
color c_barcolor = na
color c_plotcandle = na
c_sess1_barcolor = (is_sess1) ? (is_positive_bar ? i_sess1_barcolor1 : i_sess1_barcolor2) : na
c_sess2_barcolor = (is_sess2) ? (is_positive_bar ? i_sess2_barcolor1 : i_sess2_barcolor2) : na
c_sess3_barcolor = (is_sess3) ? (is_positive_bar ? i_sess3_barcolor1 : i_sess3_barcolor2) : na
c_sess4_barcolor = (is_sess4) ? (is_positive_bar ? i_sess4_barcolor1 : i_sess4_barcolor2) : na
if (i_sess1_chart != option_chart_x) and is_sess1
c_barcolor := i_sess1_barcolor ? c_sess1_barcolor : na
c_plotcandle := i_sess1_plotcandle ? c_sess1_barcolor : na
if (i_sess2_chart != option_chart_x) and is_sess2
c_barcolor := i_sess2_barcolor ? c_sess2_barcolor : na
c_plotcandle := i_sess2_plotcandle ? c_sess2_barcolor : na
if (i_sess3_chart != option_chart_x) and is_sess3
c_barcolor := i_sess3_barcolor ? c_sess3_barcolor : na
c_plotcandle := i_sess3_plotcandle ? c_sess3_barcolor : na
if (i_sess4_chart != option_chart_x) and is_sess4
c_barcolor := i_sess4_barcolor ? c_sess4_barcolor : na
c_plotcandle := i_sess4_plotcandle ? c_sess4_barcolor : na
barcolor(c_barcolor)
plotcandle(open, high, low, close, color=is_positive_bar ? color_none : c_plotcandle, bordercolor=c_plotcandle, wickcolor=c_plotcandle)
////////////////////
// Alerts
////////////////////
// Session alerts
sess1_started = is_sess1 and not is_sess1 , sess1_ended = not is_sess1 and is_sess1
sess2_started = is_sess2 and not is_sess2 , sess2_ended = not is_sess2 and is_sess2
sess3_started = is_sess3 and not is_sess3 , sess3_ended = not is_sess3 and is_sess3
sess4_started = is_sess4 and not is_sess4 , sess4_ended = not is_sess4 and is_sess4
alertcondition(sess1_started, 'Session #1 started')
alertcondition(sess1_ended, 'Session #1 ended')
alertcondition(sess2_started, 'Session #2 started')
alertcondition(sess2_ended, 'Session #2 ended')
alertcondition(sess3_started, 'Session #3 started')
alertcondition(sess3_ended, 'Session #3 ended')
alertcondition(sess4_started, 'Session #4 started')
alertcondition(sess4_ended, 'Session #4 ended')
alertcondition((not is_sess1) and ta.crossover(close, sess1_high), 'Session #1 High crossed (after session closed)')
alertcondition((not is_sess1) and ta.crossunder(close, sess1_low), 'Session #1 Low crossed (after session closed)')
alertcondition((not is_sess2) and ta.crossover(close, sess2_high), 'Session #2 High crossed (after session closed)')
alertcondition((not is_sess2) and ta.crossunder(close, sess2_low), 'Session #2 Low crossed (after session closed)')
alertcondition((not is_sess3) and ta.crossover(close, sess3_high), 'Session #3 High crossed (after session closed)')
alertcondition((not is_sess3) and ta.crossunder(close, sess3_low), 'Session #3 Low crossed (after session closed)')
alertcondition((not is_sess4) and ta.crossover(close, sess4_high), 'Session #4 High crossed (after session closed)')
alertcondition((not is_sess4) and ta.crossunder(close, sess4_low), 'Session #4 Low crossed (after session closed)')
// Alerts visualized
if i_alert1_show
if i_show_sess1
if sess1_started
label.new(bar_index, close, 'Start', yloc=yloc.abovebar, color=i_sess1_color, textcolor=color_text, size=size.small, style=label.style_label_down)
if sess1_ended
label.new(bar_index, close, 'End' , yloc=yloc.abovebar, color=i_sess1_color, textcolor=color_text, size=size.small, style=label.style_label_down)
if i_show_sess2
if sess2_started
label.new(bar_index, close, 'Start', yloc=yloc.abovebar, color=i_sess2_color, textcolor=color_text, size=size.small, style=label.style_label_down)
if sess2_ended
label.new(bar_index, close, 'End' , yloc=yloc.abovebar, color=i_sess2_color, textcolor=color_text, size=size.small, style=label.style_label_down)
if i_show_sess3
if sess3_started
label.new(bar_index, close, 'Start', yloc=yloc.abovebar, color=i_sess3_color, textcolor=color_text, size=size.small, style=label.style_label_down)
if sess3_ended
label.new(bar_index, close, 'End' , yloc=yloc.abovebar, color=i_sess3_color, textcolor=color_text, size=size.small, style=label.style_label_down)
if i_show_sess4
if sess4_started
label.new(bar_index, close, 'Start', yloc=yloc.abovebar, color=i_sess4_color, textcolor=color_text, size=size.small, style=label.style_label_down)
if sess4_ended
label.new(bar_index, close, 'End' , yloc=yloc.abovebar, color=i_sess4_color, textcolor=color_text, size=size.small, style=label.style_label_down)
plot(i_alert3_show ? sess1_high : na, 'sess1_high', style=plot.style_linebr, color=i_sess1_color)
plot(i_alert3_show ? sess1_low : na, 'sess1_low' , style=plot.style_linebr, color=i_sess1_color, linewidth=2)
plot(i_alert3_show ? sess2_high : na, 'sess2_high', style=plot.style_linebr, color=i_sess2_color)
plot(i_alert3_show ? sess2_low : na, 'sess2_low' , style=plot.style_linebr, color=i_sess2_color, linewidth=2)
plot(i_alert3_show ? sess3_high : na, 'sess3_high', style=plot.style_linebr, color=i_sess3_color)
plot(i_alert3_show ? sess3_low : na, 'sess3_low' , style=plot.style_linebr, color=i_sess3_color, linewidth=2)
plot(i_alert3_show ? sess4_high : na, 'sess4_high', style=plot.style_linebr, color=i_sess4_color)
plot(i_alert3_show ? sess4_low : na, 'sess4_low' , style=plot.style_linebr, color=i_sess4_color, linewidth=2)
plotshape(i_alert3_show and (not is_sess1) and ta.crossover(close, sess1_high) ? sess1_high : na, 'cross sess1_high', color=i_sess1_color, style=shape.triangleup, location=location.absolute, size=size.tiny)
plotshape(i_alert3_show and (not is_sess1) and ta.crossunder(close, sess1_low) ? sess1_low : na, 'cross sess1_low', color=i_sess1_color, style=shape.triangledown, location=location.absolute, size=size.tiny)
plotshape(i_alert3_show and (not is_sess2) and ta.crossover(close, sess2_high) ? sess2_high : na, 'cross sess2_high', color=i_sess2_color, style=shape.triangleup, location=location.absolute, size=size.tiny)
plotshape(i_alert3_show and (not is_sess2) and ta.crossunder(close, sess2_low) ? sess2_low : na, 'cross sess2_low', color=i_sess2_color, style=shape.triangledown, location=location.absolute, size=size.tiny)
plotshape(i_alert3_show and (not is_sess3) and ta.crossover(close, sess3_high) ? sess3_high : na, 'cross sess3_high', color=i_sess3_color, style=shape.triangleup, location=location.absolute, size=size.tiny)
plotshape(i_alert3_show and (not is_sess3) and ta.crossunder(close, sess3_low) ? sess3_low : na, 'cross sess3_low', color=i_sess3_color, style=shape.triangledown, location=location.absolute, size=size.tiny)
plotshape(i_alert3_show and (not is_sess4) and ta.crossover(close, sess4_high) ? sess4_high : na, 'cross sess4_high', color=i_sess4_color, style=shape.triangleup, location=location.absolute, size=size.tiny)
plotshape(i_alert3_show and (not is_sess4) and ta.crossunder(close, sess4_low) ? sess4_low : na, 'cross sess4_low', color=i_sess4_color, style=shape.triangledown, location=location.absolute, size=size.tiny)
HSM MACROS//@version=5
indicator('HSM MACROS', 'HSM MACROS', overlay=true, max_bars_back=500, explicit_plot_zorder=true)
import boitoki/AwesomeColor/4 as ac
import boitoki/Utilities/3 as util
///////////////
// Groups
///////////////
g0 = 'GENERAL'
g1_01 = '♯1 SESSION'
g1_02 = '♯2 SESSION'
g1_03 = '♯3 SESSION'
g1_04 = '♯4 SESSION'
g4 = 'BOX'
g6 = 'LABELS'
g5 = 'OPENING RANGE'
g7 = 'FIBONACCI LEVELS'
g8 = 'OPTIONS'
g11 = 'CANDLE'
g10 = 'Alerts visualized'
///////////////
// Defined
///////////////
max_bars = 500
option_yes = 'Yes'
option_no = '× No'
option_extend1 = 'Yes'
option_hide = '× Hide'
option_border_style1 = '────'
option_border_style2 = '- - - - - -'
option_border_style3 = '•••••••••'
option_chart_x = '× No'
option_chart_1 = 'Bar color'
option_chart_2 = 'Candles'
fmt_price = '{0,number,#.#####}'
fmt_pips = '{0,number,#.#}'
icon_separator = ' • '
color_none = color.new(color.black, 100)
color_text = color.new(color.white, 0)
///////////////
// Functions
///////////////
f_get_time_by_bar(bar_count) => timeframe.multiplier * bar_count * 60 * 1000
f_border_style (_style) =>
switch _style
option_border_style1 => line.style_solid
option_border_style2 => line.style_dashed
option_border_style3 => line.style_dotted
=> _style
f_get_period (_session, _start, _lookback) =>
result = math.max(_start, 1)
for i = result to _lookback
if na(_session ) and _session
result := i+1
break
result
f_get_label_position (_y, _side) =>
switch _y
'top' => _side == 'outside' ? label.style_label_lower_left : label.style_label_upper_left
'bottom' => _side == 'outside' ? label.style_label_upper_left : label.style_label_lower_left
f_get_started (_session) => na(_session ) and _session
f_get_ended (_session) => na(_session) and _session
f_message_limit_bars (_v) => '⚠️ This box\'s right position exceeds 500 bars(' + str.tostring(_v) + '). This box is not displayed correctly.'
f_set_line_x1 (_line, _x) =>
if (line.get_x1(_line) != _x)
line.set_x1(_line, _x)
f_set_line_x2 (_line, _x) =>
if (line.get_x2(_line) != _x)
line.set_x2(_line, _x)
f_set_box_right (_box, _x) =>
if box.get_right(_box) != _x
box.set_right(_box, _x)
///////////////
// Inputs
///////////////
// Timezone
i_tz = input.string('GMT-4', title='Timezone', options= , tooltip='e.g. \'America/New_York\', \'Asia/Tokyo\', \'GMT-4\', \'GMT+9\'...', group=g0)
i_history_period = input.int(10, 'History', minval=0, group=g0)
i_show = i_history_period > 0
i_lookback = 12 * 60
// Sessions
i_show_sess1 = input.bool(true, 'Session 1 ', group=g1_01, inline='session1_1') and i_show
i_sess1_label = input.string('MC1', '', group=g1_01, inline='session1_1')
i_sess1_color = input.color(#0a0a0a, '', group=g1_01, inline='session1_1')
i_sess1_barcolor1 = input.color(#0a0a0a, '•', group=g1_01, inline='session1_1')
i_sess1_barcolor2 = input.color(#0a0a0a, '', group=g1_01, inline='session1_1')
i_sess1 = input.session('0820-0830', 'Time', group=g1_01)
i_sess1_extend = input.string(option_no, 'Extend', options= , group=g1_01)
i_sess1_fib = input.string(option_no, 'Fibonacci levels', group=g1_01, options= ) != option_no
i_sess1_op = input.string(option_no, 'Opening range', group=g1_01, options= ) != option_no and i_show
i_sess1_chart = input.string(option_chart_x, 'Bar', options= , group=g1_01)
i_sess1_barcolor = i_sess1_chart == option_chart_1
i_sess1_plotcandle = i_sess1_chart == option_chart_2
i_show_sess2 = input.bool(true, 'Session 2 ', group=g1_02, inline='session2_1') and i_show
i_sess2_label = input.string('MC2', '', group=g1_02, inline='session2_1')
i_sess2_color = input.color(#0a0a0a, '', group=g1_02, inline='session2_1')
i_sess2_barcolor1 = input.color(#0a0a0a, '•', group=g1_02, inline='session2_1')
i_sess2_barcolor2 = input.color(#0a0a0a, '', group=g1_02, inline='session2_1')
i_sess2 = input.session('0920-0930', 'Time', group=g1_02)
i_sess2_extend = input.string(option_no, 'Extend', options= , group=g1_02)
i_sess2_fib = input.string(option_no, 'Fibonacci levels', group=g1_02, options= ) != option_no
i_sess2_op = input.string(option_no, 'Opening range', group=g1_02, options= ) != option_no and i_show
i_sess2_chart = input.string(option_chart_x, 'Bar', options= , group=g1_02)
i_sess2_barcolor = i_sess2_chart == option_chart_1
i_sess2_plotcandle = i_sess2_chart == option_chart_2
i_show_sess3 = input.bool(true, 'Session 3 ', group=g1_03, inline='session3_1') and i_show
i_sess3_label = input.string('MC3', '', group=g1_03, inline='session3_1')
i_sess3_color = input.color(#0a0a0a, '', group=g1_03, inline='session3_1')
i_sess3_barcolor1 = input.color(#0a0a0a, '•', group=g1_03, inline='session3_1')
i_sess3_barcolor2 = input.color(#0a0a0a, '', group=g1_03, inline='session3_1')
i_sess3 = input.session('0950-1010', 'Time', group=g1_03)
i_sess3_extend = input.string(option_no, 'Extend', options= , group=g1_03)
i_sess3_fib = input.string(option_no, 'Fibonacci levels', group=g1_03, options= ) != option_no
i_sess3_op = input.string(option_no, 'Opening range', group=g1_03, options= ) != option_no and i_show
i_sess3_chart = input.string(option_chart_x, 'Bar', options= , group=g1_03)
i_sess3_barcolor = i_sess3_chart == option_chart_1
i_sess3_plotcandle = i_sess3_chart == option_chart_2
i_show_sess4 = input.bool(true, 'Session 4 ', group=g1_04, inline='session4_1') and i_show
i_sess4_label = input.string('MC4', '', group=g1_04, inline='session4_1')
i_sess4_color = input.color(#0a0a0a, '', group=g1_04, inline='session4_1')
i_sess4_barcolor1 = input.color(#0a0a0a, '•', group=g1_04, inline='session4_1')
i_sess4_barcolor2 = input.color(#0a0a0a, '', group=g1_04, inline='session4_1')
i_sess4 = input.session('1050-1110', 'Time', group=g1_04)
i_sess4_extend = input.string(option_no, 'Extend', options= , group=g1_04)
i_sess4_fib = input.string(option_no, 'Fibonacci levels', group=g1_04, options= ) != option_no
i_sess4_op = input.string(option_no, 'Opening range', group=g1_04, options= ) != option_no and i_show
i_sess4_chart = input.string(option_chart_x, 'Bar', options= , group=g1_04)
i_sess4_barcolor = i_sess4_chart == option_chart_1
i_sess4_plotcandle = i_sess4_chart == option_chart_2
// Show & Styles
i_sess_box_style = input.string('Box', 'Style', options= , group=g4)
i_sess_border_style = f_border_style(input.string(option_border_style2, 'Line style', options= , group=g4))
i_sess_border_width = input.int(1, 'Thickness', minval=0, group=g4)
i_sess_bgopacity = input.int(94, 'Transp', minval=0, maxval=100, step=1, group=g4, tooltip='Setting the 100 is no background color')
// Candle
option_candle_body = 'OC'
option_candle_wick = 'OHLC'
i_candle = input.string(option_hide, 'Display', options= , group=g11)
i_candle_border_width = input.int(2, 'Thickness', minval=0, group=g11)
i_show_candle = (i_candle != option_hide) and (i_candle_border_width > 0)
i_show_candle_wick = i_candle == option_candle_wick
option_candle_color1 = 'Session\'s'
option_candle_color2 = 'Red • Green'
i_candle_color = input.string(option_candle_color2, 'Color ', options= , group=g11, inline='candle_color')
i_candle_color_g = input.color(#A6E22E, '', group=g11, inline='candle_color')
i_candle_color_r = input.color(#F92672, '', group=g11, inline='candle_color')
// Labels
i_label_show = input.bool(true, 'Labels', inline='label_show', group=g6) and i_show
i_label_size = str.lower(input.string('Small', '', options= , inline='label_show', group=g6))
i_label_position_y = str.lower(input.string('Top', '', options= , inline='label_show', group=g6))
i_label_position_s = str.lower(input.string('Outside', '', options= , inline='label_show', group=g6))
i_label_position = f_get_label_position(i_label_position_y, i_label_position_s)
i_label_format_name = input.bool(true, 'Name', inline='label_format', group=g6)
i_label_format_day = input.bool(false, 'Day', inline='label_format', group=g6)
i_label_format_price = input.bool(false, 'Price', inline='label_format', group=g6)
i_label_format_pips = input.bool(false, 'Pips', inline='label_format', group=g6)
// Fibonacci levels
i_f_linestyle = f_border_style(input.string(option_border_style1, title="Style", options= , group=g7))
i_f_linewidth = input.int(1, title="Thickness", minval=1, group=g7)
// Opening range
i_o_minutes = input.int(15, title='Periods (minutes)', minval=1, step=1, group=g5)
i_o_minutes := math.max(i_o_minutes, timeframe.multiplier + 1)
i_o_transp = input.int(88, title='Transp', minval=0, maxval=100, step=1, group=g5)
// Alerts
i_alert1_show = input.bool(false, 'Alerts - Sessions stard/end', group=g10)
i_alert2_show = input.bool(false, 'Alerts - Opening range breakouts', group=g10)
i_alert3_show = input.bool(false, 'Alerts - Price crossed session\'s High/Low after session closed', group=g10)
// ------------------------
// Drawing labels
// ------------------------
f_render_label (_show, _session, _is_started, _color, _top, _bottom, _text, _labels) =>
var label my_label = na
var int start_time = na
v_position_y = (i_label_position_y == 'top') ? _top : _bottom
v_label = array.new_string()
v_chg = _top - _bottom
if _is_started
start_time := time
if i_label_format_name and not na(_text)
array.push(v_label, _text)
if i_label_format_day
array.push(v_label, util.get_day(dayofweek(start_time, i_tz)))
if i_label_format_price
array.push(v_label, str.format(fmt_price, v_chg))
if i_label_format_pips
array.push(v_label, str.format(fmt_pips, util.toPips(v_chg)) + ' pips')
if _show
if _is_started
my_label := label.new(bar_index, v_position_y, array.join(v_label, icon_separator), textcolor=_color, color=color_none, size=i_label_size, style=i_label_position)
array.push(_labels, my_label)
util.clear_labels(_labels, i_history_period)
else if _session
label.set_y(my_label, v_position_y)
label.set_text(my_label, array.join(v_label, icon_separator))
// ------------------------
// Drawing Fibonacci levels
// ------------------------
f_render_fibonacci (_show, _session, _is_started, _x1, _x2, _color, _top, _bottom, _level, _width, _style, _is_extend, _lines) =>
var line my_line = na
if _show
y = (_top - _bottom) * _level + _bottom
if _is_started
my_line := line.new(_x1, y, _x2, y, width=_width, color=color.new(_color, 30), style=_style)
array.push(_lines, my_line)
if _is_extend
line.set_extend(my_line, extend.right)
else if _session
line.set_y1(my_line, y)
line.set_y2(my_line, y)
f_set_line_x2(my_line, _x2)
// ------------------------
// Drawing Opening range
// ------------------------
f_render_oprange (_show, _session, _is_started, _x1, _x2, _color, _max, _is_extend, _boxes) =>
var int start_time = na
var box my_box = na
top = ta.highest(high, _max)
bottom = ta.lowest(low, _max)
is_crossover = ta.crossover(close, box.get_top(my_box))
is_crossunder = ta.crossunder(close, box.get_bottom(my_box))
if _show
if _is_started
util.clear_boxes(_boxes, math.max(0, i_history_period - 1))
start_time := time
my_box := na
else if _session
time_op = start_time + (i_o_minutes * 60 * 1000)
time_op_delay = time_op - f_get_time_by_bar(1)
if time <= time_op and time > time_op_delay
my_box := box.new(_x1, top, _x2, bottom, border_width=0, bgcolor=color.new(_color, i_o_transp))
array.push(_boxes, my_box)
if _is_extend
box.set_extend(my_box, extend.right)
my_box
else
f_set_box_right(my_box, _x2)
if is_crossover
alert('Price crossed over the opening range', alert.freq_once_per_bar)
if i_alert2_show
label.new(bar_index, box.get_top(my_box), "×", color=color.blue, textcolor=ac.tradingview('blue'), style=label.style_none, size=size.large)
if is_crossunder
alert('Price crossed under the opening range', alert.freq_once_per_bar)
if i_alert2_show
label.new(bar_index, box.get_bottom(my_box), "×", color=color.red, textcolor=ac.tradingview('red'), style=label.style_none, size=size.large)
my_box
// ------------------------
// Drawing candle
// ------------------------
f_render_candle (_show, _session, _is_started, _is_ended, _color, _top, _bottom, _open, _x1, _x2, _boxes, _lines) =>
var box body = na
var line wick1 = na
var line wick2 = na
border_width = i_candle_border_width
cx = math.round(math.avg(_x2, _x1)) - math.round(border_width / 2)
body_color = i_candle_color == option_candle_color2 ? close > _open ? i_candle_color_g : i_candle_color_r : _color
if _show
if _is_started
body := box.new(_x1, _top, _x2, _bottom, body_color, border_width, line.style_solid, bgcolor=color.new(color.black, 100))
wick1 := i_show_candle_wick ? line.new(cx, _top, cx, _top, color=_color, width=border_width, style=line.style_solid) : na
wick2 := i_show_candle_wick ? line.new(cx, _bottom, cx, _bottom, color=_color, width=border_width, style=line.style_solid) : na
array.push(_boxes, body)
array.push(_lines, wick1)
array.push(_lines, wick2)
util.clear_boxes(_boxes, i_history_period)
util.clear_lines(_lines, i_history_period * 2)
else if _session
top = math.max(_open, close)
bottom = math.min(_open, close)
box.set_top(body, top)
box.set_bottom(body, bottom)
box.set_right(body, _x2)
box.set_border_color(body, body_color)
line.set_y1(wick1, _top)
line.set_y2(wick1, top)
f_set_line_x1(wick1, cx)
f_set_line_x2(wick1, cx)
line.set_color(wick1, body_color)
line.set_y1(wick2, _bottom)
line.set_y2(wick2, bottom)
f_set_line_x1(wick2, cx)
f_set_line_x2(wick2, cx)
line.set_color(wick2, body_color)
else if _is_ended
box.set_right(body, bar_index)
// ------------------------
// Rendering limit message
// ------------------------
f_render_limitmessage (_show, _session, _is_started, _is_ended, _x, _y, _rightbars) =>
var label my_note = na
if _show
if _is_started
if _rightbars > max_bars
my_note := label.new(_x, _y, f_message_limit_bars(_rightbars), style=label.style_label_upper_left, color=color.yellow, textalign=text.align_left, yloc=yloc.price)
else if _session
if _rightbars > max_bars
label.set_y(my_note, _y)
label.set_text(my_note, f_message_limit_bars(_rightbars))
else
label.delete(my_note)
else if _is_ended
label.delete(my_note)
true
// Rendering session
//
f_render_sessionrange (_show, _session, _is_started, _is_ended, _color, _top, _bottom, _x1, _x2, _is_extend, _lines) =>
var line above_line = na
var line below_line = na
if _show
if _is_started
above_line := line.new(_x1, _top, _x2, _top, width=i_sess_border_width, style=i_sess_border_style, color=_color)
below_line := line.new(_x1, _bottom, _x2, _bottom, width=i_sess_border_width, style=i_sess_border_style, color=_color)
linefill.new(above_line, below_line, color.new(_color, i_sess_bgopacity))
array.push(_lines, above_line)
array.push(_lines, below_line)
util.clear_lines(_lines, i_history_period * 2)
if _is_extend
line.set_extend(above_line, extend.right)
line.set_extend(below_line, extend.right)
else if _session
line.set_y1(above_line, _top)
line.set_y2(above_line, _top)
line.set_x2(above_line, _x2)
line.set_y1(below_line, _bottom)
line.set_y2(below_line, _bottom)
line.set_x2(below_line, _x2)
true
else if _is_ended
true
true
// ------------------------
// Rendering session box
// ------------------------
f_render_session (_show, _session, _is_started, _is_ended, _color, _top, _bottom, _x1, _x2, _is_extend, _boxes) =>
var box my_box = na
if _show
if _is_started
my_box := box.new(_x1, _top, _x2, _bottom, _color, i_sess_border_width, i_sess_border_style, bgcolor=color.new(_color, i_sess_bgopacity))
array.push(_boxes, my_box)
util.clear_boxes(_boxes, i_history_period)
if _is_extend
box.set_extend(my_box, extend.right)
else if _session
box.set_top(my_box, _top)
box.set_bottom(my_box, _bottom)
f_set_box_right(my_box, _x2)
else if _is_ended
box.set_right(my_box, bar_index)
my_box
// ------------------------
// Drawing market
// ------------------------
f_render_main (_show, _session, _is_started, _is_ended, _color, _top, _bottom) =>
var box my_box = na
var label my_note = na
var x1 = 0
var x2 = 0
var session_open = 0.0
var session_high = 0.0
var session_low = 0.0
x0_1 = ta.valuewhen(na(_session ) and _session, bar_index, 1)
x0_2 = ta.valuewhen(na(_session) and _session , bar_index, 0)
x0_d = math.abs(x0_2 - x0_1)
limit_bars = max_bars
rightbars = x0_d
if _show
if _is_started
x1 := bar_index
x2 := bar_index + (math.min(x0_d, limit_bars))
session_open := open
session_high := _top
session_low := _bottom
else if _session
true_x2 = x1 + x0_d
rightbars := true_x2 - bar_index
limit_bars := bar_index + max_bars
x2 := math.min(true_x2, limit_bars)
session_high := _top
session_low := _bottom
else if _is_ended
session_open := na
// ------------------------
// Drawing
// ------------------------
draw (_show, _session, _color, _label, _extend, _show_fib, _show_op, _lookback, _boxes_session, _lines_session, _boxes_candle_body, _lines_candle_wick, _boxes_op, _lines_fib, _labels) =>
max = f_get_period(_session, 1, _lookback)
top = ta.highest(high, max)
bottom = ta.lowest(low, max)
is_started = f_get_started(_session)
is_ended = f_get_ended(_session)
is_extend = _extend != option_no
= f_render_main(_show, _session, is_started, is_ended, _color, top, bottom)
if i_sess_box_style == 'Box'
f_render_session(_show, _session, is_started, is_ended, _color, top, bottom, x1, x2, is_extend, _boxes_session)
if i_sess_box_style == 'Sandwich'
f_render_sessionrange(_show, _session, is_started, is_ended, _color, top, bottom, x1, x2, is_extend, _lines_session)
if i_show_candle
f_render_candle(_show, _session, is_started, is_ended, _color, top, bottom, _open, x1, x2, _boxes_candle_body, _lines_candle_wick)
if i_label_show
f_render_label(_show, _session, is_started, _color, top, bottom, _label, _labels)
if _show_op
f_render_oprange(_show, _session, is_started, x1, x2, _color, max, is_extend, _boxes_op)
if _show_fib
f_render_fibonacci(_show, _session, is_started, x1, x2, _color, top, bottom, 0.500, 2, line.style_solid, is_extend, _lines_fib)
f_render_fibonacci(_show, _session, is_started, x1, x2, _color, top, bottom, 0.628, i_f_linewidth, i_f_linestyle, is_extend, _lines_fib)
f_render_fibonacci(_show, _session, is_started, x1, x2, _color, top, bottom, 0.382, i_f_linewidth, i_f_linestyle, is_extend, _lines_fib)
util.clear_lines(_lines_fib, i_history_period * 3)
f_render_limitmessage(_show, _session, is_started, is_ended, x1, bottom, _rightbars)
///////////////////
// Calculating
///////////////////
string tz = (i_tz == option_no or i_tz == '') ? na : i_tz
int sess1 = time(timeframe.period, i_sess1, tz)
int sess2 = time(timeframe.period, i_sess2, tz)
int sess3 = time(timeframe.period, i_sess3, tz)
int sess4 = time(timeframe.period, i_sess4, tz)
///////////////////
// Plotting
///////////////////
var sess1_box = array.new()
var sess2_box = array.new()
var sess3_box = array.new()
var sess4_box = array.new()
var sess1_line = array.new()
var sess2_line = array.new()
var sess3_line = array.new()
var sess4_line = array.new()
var sess1_op = array.new()
var sess2_op = array.new()
var sess3_op = array.new()
var sess4_op = array.new()
var sess1_fib = array.new()
var sess2_fib = array.new()
var sess3_fib = array.new()
var sess4_fib = array.new()
var sess1_candle_body = array.new()
var sess2_candle_body = array.new()
var sess3_candle_body = array.new()
var sess4_candle_body = array.new()
var sess1_candle_wick = array.new()
var sess2_candle_wick = array.new()
var sess3_candle_wick = array.new()
var sess4_candle_wick = array.new()
var sess1_labels = array.new()
var sess2_labels = array.new()
var sess3_labels = array.new()
var sess4_labels = array.new()
= draw(i_show_sess1, sess1, i_sess1_color, i_sess1_label, i_sess1_extend, i_sess1_fib, i_sess1_op, i_lookback, sess1_box, sess1_line, sess1_candle_body, sess1_candle_wick, sess1_op, sess1_fib, sess1_labels)
= draw(i_show_sess2, sess2, i_sess2_color, i_sess2_label, i_sess2_extend, i_sess2_fib, i_sess2_op, i_lookback, sess2_box, sess2_line, sess2_candle_body, sess2_candle_wick, sess2_op, sess2_fib, sess2_labels)
= draw(i_show_sess3, sess3, i_sess3_color, i_sess3_label, i_sess3_extend, i_sess3_fib, i_sess3_op, i_lookback, sess3_box, sess3_line, sess3_candle_body, sess3_candle_wick, sess3_op, sess3_fib, sess3_labels)
= draw(i_show_sess4, sess4, i_sess4_color, i_sess4_label, i_sess4_extend, i_sess4_fib, i_sess4_op, i_lookback, sess4_box, sess4_line, sess4_candle_body, sess4_candle_wick, sess4_op, sess4_fib, sess4_labels)
is_positive_bar = close > open
color c_barcolor = na
color c_plotcandle = na
c_sess1_barcolor = (is_sess1) ? (is_positive_bar ? i_sess1_barcolor1 : i_sess1_barcolor2) : na
c_sess2_barcolor = (is_sess2) ? (is_positive_bar ? i_sess2_barcolor1 : i_sess2_barcolor2) : na
c_sess3_barcolor = (is_sess3) ? (is_positive_bar ? i_sess3_barcolor1 : i_sess3_barcolor2) : na
c_sess4_barcolor = (is_sess4) ? (is_positive_bar ? i_sess4_barcolor1 : i_sess4_barcolor2) : na
if (i_sess1_chart != option_chart_x) and is_sess1
c_barcolor := i_sess1_barcolor ? c_sess1_barcolor : na
c_plotcandle := i_sess1_plotcandle ? c_sess1_barcolor : na
if (i_sess2_chart != option_chart_x) and is_sess2
c_barcolor := i_sess2_barcolor ? c_sess2_barcolor : na
c_plotcandle := i_sess2_plotcandle ? c_sess2_barcolor : na
if (i_sess3_chart != option_chart_x) and is_sess3
c_barcolor := i_sess3_barcolor ? c_sess3_barcolor : na
c_plotcandle := i_sess3_plotcandle ? c_sess3_barcolor : na
if (i_sess4_chart != option_chart_x) and is_sess4
c_barcolor := i_sess4_barcolor ? c_sess4_barcolor : na
c_plotcandle := i_sess4_plotcandle ? c_sess4_barcolor : na
barcolor(c_barcolor)
plotcandle(open, high, low, close, color=is_positive_bar ? color_none : c_plotcandle, bordercolor=c_plotcandle, wickcolor=c_plotcandle)
////////////////////
// Alerts
////////////////////
// Session alerts
sess1_started = is_sess1 and not is_sess1 , sess1_ended = not is_sess1 and is_sess1
sess2_started = is_sess2 and not is_sess2 , sess2_ended = not is_sess2 and is_sess2
sess3_started = is_sess3 and not is_sess3 , sess3_ended = not is_sess3 and is_sess3
sess4_started = is_sess4 and not is_sess4 , sess4_ended = not is_sess4 and is_sess4
alertcondition(sess1_started, 'Session #1 started')
alertcondition(sess1_ended, 'Session #1 ended')
alertcondition(sess2_started, 'Session #2 started')
alertcondition(sess2_ended, 'Session #2 ended')
alertcondition(sess3_started, 'Session #3 started')
alertcondition(sess3_ended, 'Session #3 ended')
alertcondition(sess4_started, 'Session #4 started')
alertcondition(sess4_ended, 'Session #4 ended')
alertcondition((not is_sess1) and ta.crossover(close, sess1_high), 'Session #1 High crossed (after session closed)')
alertcondition((not is_sess1) and ta.crossunder(close, sess1_low), 'Session #1 Low crossed (after session closed)')
alertcondition((not is_sess2) and ta.crossover(close, sess2_high), 'Session #2 High crossed (after session closed)')
alertcondition((not is_sess2) and ta.crossunder(close, sess2_low), 'Session #2 Low crossed (after session closed)')
alertcondition((not is_sess3) and ta.crossover(close, sess3_high), 'Session #3 High crossed (after session closed)')
alertcondition((not is_sess3) and ta.crossunder(close, sess3_low), 'Session #3 Low crossed (after session closed)')
alertcondition((not is_sess4) and ta.crossover(close, sess4_high), 'Session #4 High crossed (after session closed)')
alertcondition((not is_sess4) and ta.crossunder(close, sess4_low), 'Session #4 Low crossed (after session closed)')
// Alerts visualized
if i_alert1_show
if i_show_sess1
if sess1_started
label.new(bar_index, close, 'Start', yloc=yloc.abovebar, color=i_sess1_color, textcolor=color_text, size=size.small, style=label.style_label_down)
if sess1_ended
label.new(bar_index, close, 'End' , yloc=yloc.abovebar, color=i_sess1_color, textcolor=color_text, size=size.small, style=label.style_label_down)
if i_show_sess2
if sess2_started
label.new(bar_index, close, 'Start', yloc=yloc.abovebar, color=i_sess2_color, textcolor=color_text, size=size.small, style=label.style_label_down)
if sess2_ended
label.new(bar_index, close, 'End' , yloc=yloc.abovebar, color=i_sess2_color, textcolor=color_text, size=size.small, style=label.style_label_down)
if i_show_sess3
if sess3_started
label.new(bar_index, close, 'Start', yloc=yloc.abovebar, color=i_sess3_color, textcolor=color_text, size=size.small, style=label.style_label_down)
if sess3_ended
label.new(bar_index, close, 'End' , yloc=yloc.abovebar, color=i_sess3_color, textcolor=color_text, size=size.small, style=label.style_label_down)
if i_show_sess4
if sess4_started
label.new(bar_index, close, 'Start', yloc=yloc.abovebar, color=i_sess4_color, textcolor=color_text, size=size.small, style=label.style_label_down)
if sess4_ended
label.new(bar_index, close, 'End' , yloc=yloc.abovebar, color=i_sess4_color, textcolor=color_text, size=size.small, style=label.style_label_down)
plot(i_alert3_show ? sess1_high : na, 'sess1_high', style=plot.style_linebr, color=i_sess1_color)
plot(i_alert3_show ? sess1_low : na, 'sess1_low' , style=plot.style_linebr, color=i_sess1_color, linewidth=2)
plot(i_alert3_show ? sess2_high : na, 'sess2_high', style=plot.style_linebr, color=i_sess2_color)
plot(i_alert3_show ? sess2_low : na, 'sess2_low' , style=plot.style_linebr, color=i_sess2_color, linewidth=2)
plot(i_alert3_show ? sess3_high : na, 'sess3_high', style=plot.style_linebr, color=i_sess3_color)
plot(i_alert3_show ? sess3_low : na, 'sess3_low' , style=plot.style_linebr, color=i_sess3_color, linewidth=2)
plot(i_alert3_show ? sess4_high : na, 'sess4_high', style=plot.style_linebr, color=i_sess4_color)
plot(i_alert3_show ? sess4_low : na, 'sess4_low' , style=plot.style_linebr, color=i_sess4_color, linewidth=2)
plotshape(i_alert3_show and (not is_sess1) and ta.crossover(close, sess1_high) ? sess1_high : na, 'cross sess1_high', color=i_sess1_color, style=shape.triangleup, location=location.absolute, size=size.tiny)
plotshape(i_alert3_show and (not is_sess1) and ta.crossunder(close, sess1_low) ? sess1_low : na, 'cross sess1_low', color=i_sess1_color, style=shape.triangledown, location=location.absolute, size=size.tiny)
plotshape(i_alert3_show and (not is_sess2) and ta.crossover(close, sess2_high) ? sess2_high : na, 'cross sess2_high', color=i_sess2_color, style=shape.triangleup, location=location.absolute, size=size.tiny)
plotshape(i_alert3_show and (not is_sess2) and ta.crossunder(close, sess2_low) ? sess2_low : na, 'cross sess2_low', color=i_sess2_color, style=shape.triangledown, location=location.absolute, size=size.tiny)
plotshape(i_alert3_show and (not is_sess3) and ta.crossover(close, sess3_high) ? sess3_high : na, 'cross sess3_high', color=i_sess3_color, style=shape.triangleup, location=location.absolute, size=size.tiny)
plotshape(i_alert3_show and (not is_sess3) and ta.crossunder(close, sess3_low) ? sess3_low : na, 'cross sess3_low', color=i_sess3_color, style=shape.triangledown, location=location.absolute, size=size.tiny)
plotshape(i_alert3_show and (not is_sess4) and ta.crossover(close, sess4_high) ? sess4_high : na, 'cross sess4_high', color=i_sess4_color, style=shape.triangleup, location=location.absolute, size=size.tiny)
plotshape(i_alert3_show and (not is_sess4) and ta.crossunder(close, sess4_low) ? sess4_low : na, 'cross sess4_low', color=i_sess4_color, style=shape.triangledown, location=location.absolute, size=size.tiny)
HSM BULLET//@version=5
indicator('HSM BULLET', 'HSM BULLET', overlay=true, max_bars_back=500, explicit_plot_zorder=true)
import boitoki/AwesomeColor/4 as ac
import boitoki/Utilities/3 as util
///////////////
// Groups
///////////////
g0 = 'GENERAL'
g1_01 = '♯1 SESSION'
g1_02 = '♯2 SESSION'
g1_03 = '♯3 SESSION'
g1_04 = '♯4 SESSION'
g4 = 'BOX'
g6 = 'LABELS'
g5 = 'OPENING RANGE'
g7 = 'FIBONACCI LEVELS'
g8 = 'OPTIONS'
g11 = 'CANDLE'
g10 = 'Alerts visualized'
///////////////
// Defined
///////////////
max_bars = 500
option_yes = 'Yes'
option_no = '× No'
option_extend1 = 'Yes'
option_hide = '× Hide'
option_border_style1 = '────'
option_border_style2 = '- - - - - -'
option_border_style3 = '•••••••••'
option_chart_x = '× No'
option_chart_1 = 'Bar color'
option_chart_2 = 'Candles'
fmt_price = '{0,number,#.#####}'
fmt_pips = '{0,number,#.#}'
icon_separator = ' • '
color_none = color.new(color.black, 100)
color_text = color.new(color.white, 0)
///////////////
// Functions
///////////////
f_get_time_by_bar(bar_count) => timeframe.multiplier * bar_count * 60 * 1000
f_border_style (_style) =>
switch _style
option_border_style1 => line.style_solid
option_border_style2 => line.style_dashed
option_border_style3 => line.style_dotted
=> _style
f_get_period (_session, _start, _lookback) =>
result = math.max(_start, 1)
for i = result to _lookback
if na(_session ) and _session
result := i+1
break
result
f_get_label_position (_y, _side) =>
switch _y
'top' => _side == 'outside' ? label.style_label_lower_left : label.style_label_upper_left
'bottom' => _side == 'outside' ? label.style_label_upper_left : label.style_label_lower_left
f_get_started (_session) => na(_session ) and _session
f_get_ended (_session) => na(_session) and _session
f_message_limit_bars (_v) => '⚠️ This box\'s right position exceeds 500 bars(' + str.tostring(_v) + '). This box is not displayed correctly.'
f_set_line_x1 (_line, _x) =>
if (line.get_x1(_line) != _x)
line.set_x1(_line, _x)
f_set_line_x2 (_line, _x) =>
if (line.get_x2(_line) != _x)
line.set_x2(_line, _x)
f_set_box_right (_box, _x) =>
if box.get_right(_box) != _x
box.set_right(_box, _x)
///////////////
// Inputs
///////////////
// Timezone
i_tz = input.string('GMT-4', title='Timezone', options= , tooltip='e.g. \'America/New_York\', \'Asia/Tokyo\', \'GMT-4\', \'GMT+9\'...', group=g0)
i_history_period = input.int(10, 'History', minval=0, group=g0)
i_show = i_history_period > 0
i_lookback = 12 * 60
// Sessions
i_show_sess1 = input.bool(true, 'Session 1 ', group=g1_01, inline='session1_1') and i_show
i_sess1_label = input.string('London Silver', '', group=g1_01, inline='session1_1')
i_sess1_color = input.color(#0a0a0a, '', group=g1_01, inline='session1_1')
i_sess1_barcolor1 = input.color(#0a0a0a, '•', group=g1_01, inline='session1_1')
i_sess1_barcolor2 = input.color(#0a0a0a, '', group=g1_01, inline='session1_1')
i_sess1 = input.session('0300-0400', 'Time', group=g1_01)
i_sess1_extend = input.string(option_no, 'Extend', options= , group=g1_01)
i_sess1_fib = input.string(option_no, 'Fibonacci levels', group=g1_01, options= ) != option_no
i_sess1_op = input.string(option_no, 'Opening range', group=g1_01, options= ) != option_no and i_show
i_sess1_chart = input.string(option_chart_x, 'Bar', options= , group=g1_01)
i_sess1_barcolor = i_sess1_chart == option_chart_1
i_sess1_plotcandle = i_sess1_chart == option_chart_2
i_show_sess2 = input.bool(true, 'Session 2 ', group=g1_02, inline='session2_1') and i_show
i_sess2_label = input.string('NY AM Bullet', '', group=g1_02, inline='session2_1')
i_sess2_color = input.color(#0a0a0a, '', group=g1_02, inline='session2_1')
i_sess2_barcolor1 = input.color(#0a0a0a, '•', group=g1_02, inline='session2_1')
i_sess2_barcolor2 = input.color(#0a0a0a, '', group=g1_02, inline='session2_1')
i_sess2 = input.session('1000-1100', 'Time', group=g1_02)
i_sess2_extend = input.string(option_no, 'Extend', options= , group=g1_02)
i_sess2_fib = input.string(option_no, 'Fibonacci levels', group=g1_02, options= ) != option_no
i_sess2_op = input.string(option_no, 'Opening range', group=g1_02, options= ) != option_no and i_show
i_sess2_chart = input.string(option_chart_x, 'Bar', options= , group=g1_02)
i_sess2_barcolor = i_sess2_chart == option_chart_1
i_sess2_plotcandle = i_sess2_chart == option_chart_2
i_show_sess3 = input.bool(true, 'Session 3 ', group=g1_03, inline='session3_1') and i_show
i_sess3_label = input.string('NY PM Bullet', '', group=g1_03, inline='session3_1')
i_sess3_color = input.color(#0a0a0a, '', group=g1_03, inline='session3_1')
i_sess3_barcolor1 = input.color(#0a0a0a, '•', group=g1_03, inline='session3_1')
i_sess3_barcolor2 = input.color(#0a0a0a, '', group=g1_03, inline='session3_1')
i_sess3 = input.session('1400-1500', 'Time', group=g1_03)
i_sess3_extend = input.string(option_no, 'Extend', options= , group=g1_03)
i_sess3_fib = input.string(option_no, 'Fibonacci levels', group=g1_03, options= ) != option_no
i_sess3_op = input.string(option_no, 'Opening range', group=g1_03, options= ) != option_no and i_show
i_sess3_chart = input.string(option_chart_x, 'Bar', options= , group=g1_03)
i_sess3_barcolor = i_sess3_chart == option_chart_1
i_sess3_plotcandle = i_sess3_chart == option_chart_2
i_show_sess4 = input.bool(true, 'Session 4 ', group=g1_04, inline='session4_1') and i_show
i_sess4_label = input.string(' ', '', group=g1_04, inline='session4_1')
i_sess4_color = input.color(#0a0a0a, '', group=g1_04, inline='session4_1')
i_sess4_barcolor1 = input.color(#0a0a0a, '•', group=g1_04, inline='session4_1')
i_sess4_barcolor2 = input.color(#0a0a0a, '', group=g1_04, inline='session4_1')
i_sess4 = input.session('1000-1000', 'Time', group=g1_04)
i_sess4_extend = input.string(option_no, 'Extend', options= , group=g1_04)
i_sess4_fib = input.string(option_no, 'Fibonacci levels', group=g1_04, options= ) != option_no
i_sess4_op = input.string(option_no, 'Opening range', group=g1_04, options= ) != option_no and i_show
i_sess4_chart = input.string(option_chart_x, 'Bar', options= , group=g1_04)
i_sess4_barcolor = i_sess4_chart == option_chart_1
i_sess4_plotcandle = i_sess4_chart == option_chart_2
// Show & Styles
i_sess_box_style = input.string('Box', 'Style', options= , group=g4)
i_sess_border_style = f_border_style(input.string(option_border_style2, 'Line style', options= , group=g4))
i_sess_border_width = input.int(1, 'Thickness', minval=0, group=g4)
i_sess_bgopacity = input.int(94, 'Transp', minval=0, maxval=100, step=1, group=g4, tooltip='Setting the 100 is no background color')
// Candle
option_candle_body = 'OC'
option_candle_wick = 'OHLC'
i_candle = input.string(option_hide, 'Display', options= , group=g11)
i_candle_border_width = input.int(2, 'Thickness', minval=0, group=g11)
i_show_candle = (i_candle != option_hide) and (i_candle_border_width > 0)
i_show_candle_wick = i_candle == option_candle_wick
option_candle_color1 = 'Session\'s'
option_candle_color2 = 'Red • Green'
i_candle_color = input.string(option_candle_color2, 'Color ', options= , group=g11, inline='candle_color')
i_candle_color_g = input.color(#A6E22E, '', group=g11, inline='candle_color')
i_candle_color_r = input.color(#F92672, '', group=g11, inline='candle_color')
// Labels
i_label_show = input.bool(true, 'Labels', inline='label_show', group=g6) and i_show
i_label_size = str.lower(input.string('Small', '', options= , inline='label_show', group=g6))
i_label_position_y = str.lower(input.string('Top', '', options= , inline='label_show', group=g6))
i_label_position_s = str.lower(input.string('Outside', '', options= , inline='label_show', group=g6))
i_label_position = f_get_label_position(i_label_position_y, i_label_position_s)
i_label_format_name = input.bool(true, 'Name', inline='label_format', group=g6)
i_label_format_day = input.bool(false, 'Day', inline='label_format', group=g6)
i_label_format_price = input.bool(false, 'Price', inline='label_format', group=g6)
i_label_format_pips = input.bool(false, 'Pips', inline='label_format', group=g6)
// Fibonacci levels
i_f_linestyle = f_border_style(input.string(option_border_style1, title="Style", options= , group=g7))
i_f_linewidth = input.int(1, title="Thickness", minval=1, group=g7)
// Opening range
i_o_minutes = input.int(15, title='Periods (minutes)', minval=1, step=1, group=g5)
i_o_minutes := math.max(i_o_minutes, timeframe.multiplier + 1)
i_o_transp = input.int(88, title='Transp', minval=0, maxval=100, step=1, group=g5)
// Alerts
i_alert1_show = input.bool(false, 'Alerts - Sessions stard/end', group=g10)
i_alert2_show = input.bool(false, 'Alerts - Opening range breakouts', group=g10)
i_alert3_show = input.bool(false, 'Alerts - Price crossed session\'s High/Low after session closed', group=g10)
// ------------------------
// Drawing labels
// ------------------------
f_render_label (_show, _session, _is_started, _color, _top, _bottom, _text, _labels) =>
var label my_label = na
var int start_time = na
v_position_y = (i_label_position_y == 'top') ? _top : _bottom
v_label = array.new_string()
v_chg = _top - _bottom
if _is_started
start_time := time
if i_label_format_name and not na(_text)
array.push(v_label, _text)
if i_label_format_day
array.push(v_label, util.get_day(dayofweek(start_time, i_tz)))
if i_label_format_price
array.push(v_label, str.format(fmt_price, v_chg))
if i_label_format_pips
array.push(v_label, str.format(fmt_pips, util.toPips(v_chg)) + ' pips')
if _show
if _is_started
my_label := label.new(bar_index, v_position_y, array.join(v_label, icon_separator), textcolor=_color, color=color_none, size=i_label_size, style=i_label_position)
array.push(_labels, my_label)
util.clear_labels(_labels, i_history_period)
else if _session
label.set_y(my_label, v_position_y)
label.set_text(my_label, array.join(v_label, icon_separator))
// ------------------------
// Drawing Fibonacci levels
// ------------------------
f_render_fibonacci (_show, _session, _is_started, _x1, _x2, _color, _top, _bottom, _level, _width, _style, _is_extend, _lines) =>
var line my_line = na
if _show
y = (_top - _bottom) * _level + _bottom
if _is_started
my_line := line.new(_x1, y, _x2, y, width=_width, color=color.new(_color, 30), style=_style)
array.push(_lines, my_line)
if _is_extend
line.set_extend(my_line, extend.right)
else if _session
line.set_y1(my_line, y)
line.set_y2(my_line, y)
f_set_line_x2(my_line, _x2)
// ------------------------
// Drawing Opening range
// ------------------------
f_render_oprange (_show, _session, _is_started, _x1, _x2, _color, _max, _is_extend, _boxes) =>
var int start_time = na
var box my_box = na
top = ta.highest(high, _max)
bottom = ta.lowest(low, _max)
is_crossover = ta.crossover(close, box.get_top(my_box))
is_crossunder = ta.crossunder(close, box.get_bottom(my_box))
if _show
if _is_started
util.clear_boxes(_boxes, math.max(0, i_history_period - 1))
start_time := time
my_box := na
else if _session
time_op = start_time + (i_o_minutes * 60 * 1000)
time_op_delay = time_op - f_get_time_by_bar(1)
if time <= time_op and time > time_op_delay
my_box := box.new(_x1, top, _x2, bottom, border_width=0, bgcolor=color.new(_color, i_o_transp))
array.push(_boxes, my_box)
if _is_extend
box.set_extend(my_box, extend.right)
my_box
else
f_set_box_right(my_box, _x2)
if is_crossover
alert('Price crossed over the opening range', alert.freq_once_per_bar)
if i_alert2_show
label.new(bar_index, box.get_top(my_box), "×", color=color.blue, textcolor=ac.tradingview('blue'), style=label.style_none, size=size.large)
if is_crossunder
alert('Price crossed under the opening range', alert.freq_once_per_bar)
if i_alert2_show
label.new(bar_index, box.get_bottom(my_box), "×", color=color.red, textcolor=ac.tradingview('red'), style=label.style_none, size=size.large)
my_box
// ------------------------
// Drawing candle
// ------------------------
f_render_candle (_show, _session, _is_started, _is_ended, _color, _top, _bottom, _open, _x1, _x2, _boxes, _lines) =>
var box body = na
var line wick1 = na
var line wick2 = na
border_width = i_candle_border_width
cx = math.round(math.avg(_x2, _x1)) - math.round(border_width / 2)
body_color = i_candle_color == option_candle_color2 ? close > _open ? i_candle_color_g : i_candle_color_r : _color
if _show
if _is_started
body := box.new(_x1, _top, _x2, _bottom, body_color, border_width, line.style_solid, bgcolor=color.new(color.black, 100))
wick1 := i_show_candle_wick ? line.new(cx, _top, cx, _top, color=_color, width=border_width, style=line.style_solid) : na
wick2 := i_show_candle_wick ? line.new(cx, _bottom, cx, _bottom, color=_color, width=border_width, style=line.style_solid) : na
array.push(_boxes, body)
array.push(_lines, wick1)
array.push(_lines, wick2)
util.clear_boxes(_boxes, i_history_period)
util.clear_lines(_lines, i_history_period * 2)
else if _session
top = math.max(_open, close)
bottom = math.min(_open, close)
box.set_top(body, top)
box.set_bottom(body, bottom)
box.set_right(body, _x2)
box.set_border_color(body, body_color)
line.set_y1(wick1, _top)
line.set_y2(wick1, top)
f_set_line_x1(wick1, cx)
f_set_line_x2(wick1, cx)
line.set_color(wick1, body_color)
line.set_y1(wick2, _bottom)
line.set_y2(wick2, bottom)
f_set_line_x1(wick2, cx)
f_set_line_x2(wick2, cx)
line.set_color(wick2, body_color)
else if _is_ended
box.set_right(body, bar_index)
// ------------------------
// Rendering limit message
// ------------------------
f_render_limitmessage (_show, _session, _is_started, _is_ended, _x, _y, _rightbars) =>
var label my_note = na
if _show
if _is_started
if _rightbars > max_bars
my_note := label.new(_x, _y, f_message_limit_bars(_rightbars), style=label.style_label_upper_left, color=color.yellow, textalign=text.align_left, yloc=yloc.price)
else if _session
if _rightbars > max_bars
label.set_y(my_note, _y)
label.set_text(my_note, f_message_limit_bars(_rightbars))
else
label.delete(my_note)
else if _is_ended
label.delete(my_note)
true
// Rendering session
//
f_render_sessionrange (_show, _session, _is_started, _is_ended, _color, _top, _bottom, _x1, _x2, _is_extend, _lines) =>
var line above_line = na
var line below_line = na
if _show
if _is_started
above_line := line.new(_x1, _top, _x2, _top, width=i_sess_border_width, style=i_sess_border_style, color=_color)
below_line := line.new(_x1, _bottom, _x2, _bottom, width=i_sess_border_width, style=i_sess_border_style, color=_color)
linefill.new(above_line, below_line, color.new(_color, i_sess_bgopacity))
array.push(_lines, above_line)
array.push(_lines, below_line)
util.clear_lines(_lines, i_history_period * 2)
if _is_extend
line.set_extend(above_line, extend.right)
line.set_extend(below_line, extend.right)
else if _session
line.set_y1(above_line, _top)
line.set_y2(above_line, _top)
line.set_x2(above_line, _x2)
line.set_y1(below_line, _bottom)
line.set_y2(below_line, _bottom)
line.set_x2(below_line, _x2)
true
else if _is_ended
true
true
// ------------------------
// Rendering session box
// ------------------------
f_render_session (_show, _session, _is_started, _is_ended, _color, _top, _bottom, _x1, _x2, _is_extend, _boxes) =>
var box my_box = na
if _show
if _is_started
my_box := box.new(_x1, _top, _x2, _bottom, _color, i_sess_border_width, i_sess_border_style, bgcolor=color.new(_color, i_sess_bgopacity))
array.push(_boxes, my_box)
util.clear_boxes(_boxes, i_history_period)
if _is_extend
box.set_extend(my_box, extend.right)
else if _session
box.set_top(my_box, _top)
box.set_bottom(my_box, _bottom)
f_set_box_right(my_box, _x2)
else if _is_ended
box.set_right(my_box, bar_index)
my_box
// ------------------------
// Drawing market
// ------------------------
f_render_main (_show, _session, _is_started, _is_ended, _color, _top, _bottom) =>
var box my_box = na
var label my_note = na
var x1 = 0
var x2 = 0
var session_open = 0.0
var session_high = 0.0
var session_low = 0.0
x0_1 = ta.valuewhen(na(_session ) and _session, bar_index, 1)
x0_2 = ta.valuewhen(na(_session) and _session , bar_index, 0)
x0_d = math.abs(x0_2 - x0_1)
limit_bars = max_bars
rightbars = x0_d
if _show
if _is_started
x1 := bar_index
x2 := bar_index + (math.min(x0_d, limit_bars))
session_open := open
session_high := _top
session_low := _bottom
else if _session
true_x2 = x1 + x0_d
rightbars := true_x2 - bar_index
limit_bars := bar_index + max_bars
x2 := math.min(true_x2, limit_bars)
session_high := _top
session_low := _bottom
else if _is_ended
session_open := na
// ------------------------
// Drawing
// ------------------------
draw (_show, _session, _color, _label, _extend, _show_fib, _show_op, _lookback, _boxes_session, _lines_session, _boxes_candle_body, _lines_candle_wick, _boxes_op, _lines_fib, _labels) =>
max = f_get_period(_session, 1, _lookback)
top = ta.highest(high, max)
bottom = ta.lowest(low, max)
is_started = f_get_started(_session)
is_ended = f_get_ended(_session)
is_extend = _extend != option_no
= f_render_main(_show, _session, is_started, is_ended, _color, top, bottom)
if i_sess_box_style == 'Box'
f_render_session(_show, _session, is_started, is_ended, _color, top, bottom, x1, x2, is_extend, _boxes_session)
if i_sess_box_style == 'Sandwich'
f_render_sessionrange(_show, _session, is_started, is_ended, _color, top, bottom, x1, x2, is_extend, _lines_session)
if i_show_candle
f_render_candle(_show, _session, is_started, is_ended, _color, top, bottom, _open, x1, x2, _boxes_candle_body, _lines_candle_wick)
if i_label_show
f_render_label(_show, _session, is_started, _color, top, bottom, _label, _labels)
if _show_op
f_render_oprange(_show, _session, is_started, x1, x2, _color, max, is_extend, _boxes_op)
if _show_fib
f_render_fibonacci(_show, _session, is_started, x1, x2, _color, top, bottom, 0.500, 2, line.style_solid, is_extend, _lines_fib)
f_render_fibonacci(_show, _session, is_started, x1, x2, _color, top, bottom, 0.628, i_f_linewidth, i_f_linestyle, is_extend, _lines_fib)
f_render_fibonacci(_show, _session, is_started, x1, x2, _color, top, bottom, 0.382, i_f_linewidth, i_f_linestyle, is_extend, _lines_fib)
util.clear_lines(_lines_fib, i_history_period * 3)
f_render_limitmessage(_show, _session, is_started, is_ended, x1, bottom, _rightbars)
///////////////////
// Calculating
///////////////////
string tz = (i_tz == option_no or i_tz == '') ? na : i_tz
int sess1 = time(timeframe.period, i_sess1, tz)
int sess2 = time(timeframe.period, i_sess2, tz)
int sess3 = time(timeframe.period, i_sess3, tz)
int sess4 = time(timeframe.period, i_sess4, tz)
///////////////////
// Plotting
///////////////////
var sess1_box = array.new()
var sess2_box = array.new()
var sess3_box = array.new()
var sess4_box = array.new()
var sess1_line = array.new()
var sess2_line = array.new()
var sess3_line = array.new()
var sess4_line = array.new()
var sess1_op = array.new()
var sess2_op = array.new()
var sess3_op = array.new()
var sess4_op = array.new()
var sess1_fib = array.new()
var sess2_fib = array.new()
var sess3_fib = array.new()
var sess4_fib = array.new()
var sess1_candle_body = array.new()
var sess2_candle_body = array.new()
var sess3_candle_body = array.new()
var sess4_candle_body = array.new()
var sess1_candle_wick = array.new()
var sess2_candle_wick = array.new()
var sess3_candle_wick = array.new()
var sess4_candle_wick = array.new()
var sess1_labels = array.new()
var sess2_labels = array.new()
var sess3_labels = array.new()
var sess4_labels = array.new()
= draw(i_show_sess1, sess1, i_sess1_color, i_sess1_label, i_sess1_extend, i_sess1_fib, i_sess1_op, i_lookback, sess1_box, sess1_line, sess1_candle_body, sess1_candle_wick, sess1_op, sess1_fib, sess1_labels)
= draw(i_show_sess2, sess2, i_sess2_color, i_sess2_label, i_sess2_extend, i_sess2_fib, i_sess2_op, i_lookback, sess2_box, sess2_line, sess2_candle_body, sess2_candle_wick, sess2_op, sess2_fib, sess2_labels)
= draw(i_show_sess3, sess3, i_sess3_color, i_sess3_label, i_sess3_extend, i_sess3_fib, i_sess3_op, i_lookback, sess3_box, sess3_line, sess3_candle_body, sess3_candle_wick, sess3_op, sess3_fib, sess3_labels)
= draw(i_show_sess4, sess4, i_sess4_color, i_sess4_label, i_sess4_extend, i_sess4_fib, i_sess4_op, i_lookback, sess4_box, sess4_line, sess4_candle_body, sess4_candle_wick, sess4_op, sess4_fib, sess4_labels)
is_positive_bar = close > open
color c_barcolor = na
color c_plotcandle = na
c_sess1_barcolor = (is_sess1) ? (is_positive_bar ? i_sess1_barcolor1 : i_sess1_barcolor2) : na
c_sess2_barcolor = (is_sess2) ? (is_positive_bar ? i_sess2_barcolor1 : i_sess2_barcolor2) : na
c_sess3_barcolor = (is_sess3) ? (is_positive_bar ? i_sess3_barcolor1 : i_sess3_barcolor2) : na
c_sess4_barcolor = (is_sess4) ? (is_positive_bar ? i_sess4_barcolor1 : i_sess4_barcolor2) : na
if (i_sess1_chart != option_chart_x) and is_sess1
c_barcolor := i_sess1_barcolor ? c_sess1_barcolor : na
c_plotcandle := i_sess1_plotcandle ? c_sess1_barcolor : na
if (i_sess2_chart != option_chart_x) and is_sess2
c_barcolor := i_sess2_barcolor ? c_sess2_barcolor : na
c_plotcandle := i_sess2_plotcandle ? c_sess2_barcolor : na
if (i_sess3_chart != option_chart_x) and is_sess3
c_barcolor := i_sess3_barcolor ? c_sess3_barcolor : na
c_plotcandle := i_sess3_plotcandle ? c_sess3_barcolor : na
if (i_sess4_chart != option_chart_x) and is_sess4
c_barcolor := i_sess4_barcolor ? c_sess4_barcolor : na
c_plotcandle := i_sess4_plotcandle ? c_sess4_barcolor : na
barcolor(c_barcolor)
plotcandle(open, high, low, close, color=is_positive_bar ? color_none : c_plotcandle, bordercolor=c_plotcandle, wickcolor=c_plotcandle)
////////////////////
// Alerts
////////////////////
// Session alerts
sess1_started = is_sess1 and not is_sess1 , sess1_ended = not is_sess1 and is_sess1
sess2_started = is_sess2 and not is_sess2 , sess2_ended = not is_sess2 and is_sess2
sess3_started = is_sess3 and not is_sess3 , sess3_ended = not is_sess3 and is_sess3
sess4_started = is_sess4 and not is_sess4 , sess4_ended = not is_sess4 and is_sess4
alertcondition(sess1_started, 'Session #1 started')
alertcondition(sess1_ended, 'Session #1 ended')
alertcondition(sess2_started, 'Session #2 started')
alertcondition(sess2_ended, 'Session #2 ended')
alertcondition(sess3_started, 'Session #3 started')
alertcondition(sess3_ended, 'Session #3 ended')
alertcondition(sess4_started, 'Session #4 started')
alertcondition(sess4_ended, 'Session #4 ended')
alertcondition((not is_sess1) and ta.crossover(close, sess1_high), 'Session #1 High crossed (after session closed)')
alertcondition((not is_sess1) and ta.crossunder(close, sess1_low), 'Session #1 Low crossed (after session closed)')
alertcondition((not is_sess2) and ta.crossover(close, sess2_high), 'Session #2 High crossed (after session closed)')
alertcondition((not is_sess2) and ta.crossunder(close, sess2_low), 'Session #2 Low crossed (after session closed)')
alertcondition((not is_sess3) and ta.crossover(close, sess3_high), 'Session #3 High crossed (after session closed)')
alertcondition((not is_sess3) and ta.crossunder(close, sess3_low), 'Session #3 Low crossed (after session closed)')
alertcondition((not is_sess4) and ta.crossover(close, sess4_high), 'Session #4 High crossed (after session closed)')
alertcondition((not is_sess4) and ta.crossunder(close, sess4_low), 'Session #4 Low crossed (after session closed)')
// Alerts visualized
if i_alert1_show
if i_show_sess1
if sess1_started
label.new(bar_index, close, 'Start', yloc=yloc.abovebar, color=i_sess1_color, textcolor=color_text, size=size.small, style=label.style_label_down)
if sess1_ended
label.new(bar_index, close, 'End' , yloc=yloc.abovebar, color=i_sess1_color, textcolor=color_text, size=size.small, style=label.style_label_down)
if i_show_sess2
if sess2_started
label.new(bar_index, close, 'Start', yloc=yloc.abovebar, color=i_sess2_color, textcolor=color_text, size=size.small, style=label.style_label_down)
if sess2_ended
label.new(bar_index, close, 'End' , yloc=yloc.abovebar, color=i_sess2_color, textcolor=color_text, size=size.small, style=label.style_label_down)
if i_show_sess3
if sess3_started
label.new(bar_index, close, 'Start', yloc=yloc.abovebar, color=i_sess3_color, textcolor=color_text, size=size.small, style=label.style_label_down)
if sess3_ended
label.new(bar_index, close, 'End' , yloc=yloc.abovebar, color=i_sess3_color, textcolor=color_text, size=size.small, style=label.style_label_down)
if i_show_sess4
if sess4_started
label.new(bar_index, close, 'Start', yloc=yloc.abovebar, color=i_sess4_color, textcolor=color_text, size=size.small, style=label.style_label_down)
if sess4_ended
label.new(bar_index, close, 'End' , yloc=yloc.abovebar, color=i_sess4_color, textcolor=color_text, size=size.small, style=label.style_label_down)
plot(i_alert3_show ? sess1_high : na, 'sess1_high', style=plot.style_linebr, color=i_sess1_color)
plot(i_alert3_show ? sess1_low : na, 'sess1_low' , style=plot.style_linebr, color=i_sess1_color, linewidth=2)
plot(i_alert3_show ? sess2_high : na, 'sess2_high', style=plot.style_linebr, color=i_sess2_color)
plot(i_alert3_show ? sess2_low : na, 'sess2_low' , style=plot.style_linebr, color=i_sess2_color, linewidth=2)
plot(i_alert3_show ? sess3_high : na, 'sess3_high', style=plot.style_linebr, color=i_sess3_color)
plot(i_alert3_show ? sess3_low : na, 'sess3_low' , style=plot.style_linebr, color=i_sess3_color, linewidth=2)
plot(i_alert3_show ? sess4_high : na, 'sess4_high', style=plot.style_linebr, color=i_sess4_color)
plot(i_alert3_show ? sess4_low : na, 'sess4_low' , style=plot.style_linebr, color=i_sess4_color, linewidth=2)
plotshape(i_alert3_show and (not is_sess1) and ta.crossover(close, sess1_high) ? sess1_high : na, 'cross sess1_high', color=i_sess1_color, style=shape.triangleup, location=location.absolute, size=size.tiny)
plotshape(i_alert3_show and (not is_sess1) and ta.crossunder(close, sess1_low) ? sess1_low : na, 'cross sess1_low', color=i_sess1_color, style=shape.triangledown, location=location.absolute, size=size.tiny)
plotshape(i_alert3_show and (not is_sess2) and ta.crossover(close, sess2_high) ? sess2_high : na, 'cross sess2_high', color=i_sess2_color, style=shape.triangleup, location=location.absolute, size=size.tiny)
plotshape(i_alert3_show and (not is_sess2) and ta.crossunder(close, sess2_low) ? sess2_low : na, 'cross sess2_low', color=i_sess2_color, style=shape.triangledown, location=location.absolute, size=size.tiny)
plotshape(i_alert3_show and (not is_sess3) and ta.crossover(close, sess3_high) ? sess3_high : na, 'cross sess3_high', color=i_sess3_color, style=shape.triangleup, location=location.absolute, size=size.tiny)
plotshape(i_alert3_show and (not is_sess3) and ta.crossunder(close, sess3_low) ? sess3_low : na, 'cross sess3_low', color=i_sess3_color, style=shape.triangledown, location=location.absolute, size=size.tiny)
plotshape(i_alert3_show and (not is_sess4) and ta.crossover(close, sess4_high) ? sess4_high : na, 'cross sess4_high', color=i_sess4_color, style=shape.triangleup, location=location.absolute, size=size.tiny)
plotshape(i_alert3_show and (not is_sess4) and ta.crossunder(close, sess4_low) ? sess4_low : na, 'cross sess4_low', color=i_sess4_color, style=shape.triangledown, location=location.absolute, size=size.tiny)
Advanced Volume Profile Pro Delta + POC + VAH/VAL# Advanced Volume Profile Pro - Delta + POC + VAH/VAL Analysis System
## WHAT THIS SCRIPT DOES
This script creates a comprehensive volume profile analysis system that combines traditional volume-at-price distribution with delta volume calculations, Point of Control (POC) identification, and Value Area (VAH/VAL) analysis. Unlike standard volume indicators that show only total volume over time, this script analyzes volume distribution across price levels and estimates buying vs selling pressure using multiple calculation methods to provide deeper market structure insights.
## WHY THIS COMBINATION IS ORIGINAL AND USEFUL
**The Problem Solved:** Traditional volume indicators show when volume occurs but not where price finds acceptance or rejection. Standalone volume profiles lack directional bias information, while basic delta calculations don't provide structural context. Traders need to understand both volume distribution AND directional sentiment at key price levels.
**The Solution:** This script implements an integrated approach that:
- Maps volume distribution across price levels using configurable row density
- Estimates delta (buying vs selling pressure) using three different methodologies
- Identifies Point of Control (highest volume price level) for key support/resistance
- Calculates Value Area boundaries where 70% of volume traded
- Provides real-time alerts for key level interactions and volume imbalances
**Unique Features:**
1. **Developing POC Visualization**: Real-time tracking of Point of Control migration throughout the session via blue dotted trail, revealing institutional accumulation/distribution patterns before they complete
2. **Multi-Method Delta Calculation**: Price Action-based, Bid/Ask estimation, and Cumulative methods for different market conditions
3. **Adaptive Timeframe System**: Auto-adjusts calculation parameters based on chart timeframe for optimal performance
4. **Flexible Profile Types**: N Bars Back (precise control), Days Back (calendar-based), and Session-based analysis modes
5. **Advanced Imbalance Detection**: Identifies and highlights significant buying/selling imbalances with configurable thresholds
6. **Comprehensive Alert System**: Monitors POC touches, Value Area entry/exit, and major volume imbalances
## HOW THE SCRIPT WORKS TECHNICALLY
### Core Volume Profile Methodology:
**1. Price Level Distribution:**
- Divides price range into user-defined rows (10-50 configurable)
- Calculates row height: `(Highest Price - Lowest Price) / Number of Rows`
- Distributes each bar's volume across price levels it touched proportionally
**2. Delta Volume Calculation Methods:**
**Price Action Method:**
```
Price Range = High - Low
Buy Pressure = (Close - Low) / Price Range
Sell Pressure = (High - Close) / Price Range
Buy Volume = Total Volume × Buy Pressure
Sell Volume = Total Volume × Sell Pressure
Delta = Buy Volume - Sell Volume
```
**Bid/Ask Estimation Method:**
```
Average Price = (High + Low + Close) / 3
Buy Volume = Close > Average ? Volume × 0.6 : Volume × 0.4
Sell Volume = Total Volume - Buy Volume
```
**Cumulative Method:**
```
Buy Volume = Close > Open ? Volume : Volume × 0.3
Sell Volume = Close ≤ Open ? Volume : Volume × 0.3
```
**3. Point of Control (POC) Identification:**
- Scans all price levels to find maximum volume concentration
- POC represents the price level with highest trading activity
- Acts as significant support/resistance level
- **Developing POC Feature**: Tracks POC evolution in real-time via blue dotted trail, showing how institutional interest migrates throughout the session. Upward POC migration indicates accumulation patterns, downward migration suggests distribution, providing early trend signals before price confirmation.
**4. Value Area Calculation:**
- Starts from POC and expands up/down to encompass 70% of total volume
- VAH (Value Area High): Upper boundary of value area
- VAL (Value Area Low): Lower boundary of value area
- Expansion algorithm prioritizes direction with higher volume
**5. Adaptive Range Selection:**
Based on profile type and timeframe optimization:
- **N Bars Back**: Fixed lookback period with performance optimization (20-500 bars)
- **Days Back**: Calendar-based analysis with automatic timeframe adjustment (1-365 days)
- **Session**: Current trading session or custom session times
### Performance Optimization Features:
- **Sampling Algorithm**: Reduces calculation load on large datasets while maintaining accuracy
- **Memory Management**: Clears previous drawings to prevent performance degradation
- **Safety Constraints**: Prevents excessive memory usage with configurable limits
## HOW TO USE THIS SCRIPT
### Initial Setup:
1. **Profile Configuration**: Select profile type based on trading style:
- N Bars Back: Precise control over data range
- Days Back: Intuitive calendar-based analysis
- Session: Real-time session development
2. **Row Density**: Set number of rows (30 default) - more rows = higher resolution, slower performance
3. **Delta Method**: Choose calculation method based on market type:
- Price Action: Best for trending markets
- Bid/Ask Estimate: Good for ranging markets
- Cumulative: Smoothed approach for volatile markets
4. **Visual Settings**: Configure colors, position (left/right), and display options
### Reading the Profile:
**Volume Bars:**
- **Length**: Represents relative volume at that price level
- **Color**: Green = net buying pressure, Red = net selling pressure
- **Intensity**: Darker colors indicate volume imbalances above threshold
**Key Levels:**
- **POC (Blue Line)**: Highest volume price - major support/resistance
- **VAH (Purple Dashed)**: Value Area High - upper boundary of fair value
- **VAL (Orange Dashed)**: Value Area Low - lower boundary of fair value
- **Value Area Fill**: Shaded region showing main trading range
**Developing POC Trail:**
- **Blue Dotted Lines**: Show real-time POC evolution throughout the session
- **Migration Patterns**: Upward trail indicates bullish accumulation, downward trail suggests bearish distribution
- **Early Signals**: POC movement often precedes price movement, providing advance warning of institutional activity
- **Institutional Footprints**: Reveals where smart money concentrated volume before final POC establishment
### Trading Applications:
**Support/Resistance Analysis:**
- POC acts as magnetic price level - expect reactions
- VAH/VAL provide intermediate support/resistance levels
- Profile edges show areas of low volume acceptance
**Developing POC Analysis:**
- **Upward Migration**: POC moving higher = institutional accumulation, bullish bias
- **Downward Migration**: POC moving lower = institutional distribution, bearish bias
- **Stable POC**: Tight clustering = balanced market, range-bound conditions
- **Early Trend Detection**: POC direction change often precedes price breakouts
**Entry Strategies:**
- Buy at VAL with POC as target (in uptrends)
- Sell at VAH with POC as target (in downtrends)
- Breakout plays above/below profile extremes
**Volume Imbalance Trading:**
- Strong buying imbalance (>60% threshold) suggests continued upward pressure
- Strong selling imbalance suggests continued downward pressure
- Imbalances near key levels provide high-probability setups
**Multi-Timeframe Context:**
- Use higher timeframe profiles for major levels
- Lower timeframe profiles for precise entries
- Session profiles for intraday trading structure
## SCRIPT SETTINGS EXPLANATION
### Volume Profile Settings:
- **Profile Type**: Determines data range for calculation
- N Bars Back: Exact number of bars (20-500 range)
- Days Back: Calendar days with timeframe adaptation (1-365 days)
- Session: Trading session-based (intraday focus)
- **Number of Rows**: Profile resolution (10-50 range)
- **Profile Width**: Visual width as chart percentage (10-50%)
- **Value Area %**: Volume percentage for VA calculation (50-90%, 70% standard)
- **Auto-Adjust**: Automatically optimizes for different timeframes
### Delta Volume Settings:
- **Show Delta Volume**: Enable/disable delta calculations
- **Delta Calculation Method**: Choose methodology based on market conditions
- **Highlight Imbalances**: Visual emphasis for significant volume imbalances
- **Imbalance Threshold**: Percentage for imbalance detection (50-90%)
### Session Settings:
- **Session Type**: Daily, Weekly, Monthly, or Custom periods
- **Custom Session Time**: Define specific trading hours
- **Previous Sessions**: Number of historical sessions to display
### Days Back Settings:
- **Lookback Days**: Number of calendar days to analyze (1-365)
- **Automatic Calculation**: Script automatically converts days to bars based on timeframe:
- Intraday: Accounts for 6.5 trading hours per day
- Daily: 1 bar per day
- Weekly/Monthly: Proportional adjustment
### N Bars Back Settings:
- **Lookback Bars**: Exact number of bars to analyze (20-500)
- **Precise Control**: Best for systematic analysis and backtesting
### Visual Customization:
- **Colors**: Bullish (green), Bearish (red), and level colors
- **Profile Position**: Left or Right side of chart
- **Profile Offset**: Distance from current price action
- **Labels**: Show/hide level labels and values
- **Smooth Profile Bars**: Enhanced visual appearance
### Alert Configuration:
- **POC Touch**: Alerts when price interacts with Point of Control
- **VA Entry/Exit**: Alerts for Value Area boundary interactions
- **Major Imbalance**: Alerts for significant volume imbalances
## VISUAL FEATURES
### Profile Display:
- **Horizontal Bars**: Volume distribution across price levels
- **Color Coding**: Delta-based coloring for directional bias
- **Smooth Rendering**: Optional smoothing for cleaner appearance
- **Transparency**: Configurable opacity for chart readability
### Level Lines:
- **POC**: Solid blue line with optional label
- **VAH/VAL**: Dashed colored lines with value displays
- **Extension**: Lines extend across relevant time periods
- **Value Area Fill**: Optional shaded region between VAH/VAL
### Information Table:
- **Current Values**: Real-time POC, VAH, VAL prices
- **VA Range**: Value Area width calculation
- **Positioning**: Multiple table positions available
- **Text Sizing**: Adjustable for different screen sizes
## IMPORTANT USAGE NOTES
**Realistic Expectations:**
- Volume profile analysis provides structural context, not trading signals
- Delta calculations are estimations based on price action, not actual order flow
- Past volume distribution does not guarantee future price behavior
- Combine with other analysis methods for comprehensive market view
**Best Practices:**
- Use appropriate profile types for your trading style:
- Day Trading: Session or Days Back (1-5 days)
- Swing Trading: Days Back (10-30 days) or N Bars Back
- Position Trading: Days Back (60-180 days)
- Consider market context (trending vs ranging conditions)
- Verify key levels with additional technical analysis
- Monitor profile development for changing market structure
**Performance Considerations:**
- Higher row counts increase calculation complexity
- Large lookback periods may affect chart performance
- Auto-adjust feature optimizes for most use cases
- Consider using session profiles for intraday efficiency
**Limitations:**
- Delta calculations are estimations, not actual transaction data
- Profile accuracy depends on available price/volume history
- Effectiveness varies across different instruments and market conditions
- Requires understanding of volume profile concepts for optimal use
**Data Requirements:**
- Requires volume data for accurate calculations
- Works best on liquid instruments with consistent volume
- May be less effective on very low volume or exotic instruments
This script serves as a comprehensive volume analysis tool for traders who need detailed market structure information with integrated directional bias analysis and real-time POC development tracking for informed trading decisions.
Active PMI Support/Resistance Levels [EdgeTerminal]The PMI Support & Resistance indicator revolutionizes traditional technical analysis by using Pointwise Mutual Information (PMI) - a statistical measure from information theory - to objectively identify support and resistance levels. Unlike conventional methods that rely on visual pattern recognition, this indicator provides mathematically rigorous, quantifiable evidence of price levels where significant market activity occurs.
- The Mathematical Foundation: Pointwise Mutual Information
Pointwise Mutual Information measures how much more likely two events are to occur together compared to if they were statistically independent. In our context:
Event A: Volume spikes occurring (high trading activity)
Event B: Price being at specific levels
The PMI formula calculates: PMI = log(P(A,B) / (P(A) × P(B)))
Where:
P(A,B) = Probability of volume spikes occurring at specific price levels
P(A) = Probability of volume spikes occurring anywhere
P(B) = Probability of price being at specific levels
High PMI scores indicate that volume spikes and certain price levels co-occur much more frequently than random chance would predict, revealing genuine support and resistance zones.
- Why PMI Outperforms Traditional Methods
Subjective interpretation: What one trader sees as significant, another might ignore
Confirmation bias: Tendency to see patterns that confirm existing beliefs
Inconsistent criteria: No standardized definition of "significant" volume or price action
Static analysis: Doesn't adapt to changing market conditions
No strength measurement: Can't quantify how "strong" a level truly is
PMI Advantages:
✅ Objective & Quantifiable: Mathematical proof of significance, not visual guesswork
✅ Statistical Rigor: Levels backed by information theory and probability
✅ Strength Scoring: PMI scores rank levels by statistical significance
✅ Adaptive: Automatically adjusts to different market volatility regimes
✅ Eliminates Bias: Computer-calculated, removing human interpretation errors
✅ Market Structure Aware: Reveals the underlying order flow concentrations
- How It Works
Data Processing Pipeline:
Volume Analysis: Identifies volume spikes using configurable thresholds
Price Binning: Divides price range into discrete levels for analysis
Co-occurrence Calculation: Measures how often volume spikes happen at each price level
PMI Computation: Calculates statistical significance for each price level
Level Filtering: Shows only levels exceeding minimum PMI thresholds
Dynamic Updates: Refreshes levels periodically while maintaining historical traces
Visual System:
Current Levels: Bright, thick lines with PMI scores - your actionable levels
Historical Traces: Faded previous levels showing market structure evolution
Strength Tiers: Line styles indicate PMI strength (solid/dashed/dotted)
Color Coding: Green for support, red for resistance
Info Table: Real-time display of strongest levels with scores
- Indicator Settings:
Core Parameters
Lookback Period (Default: 200)
Lower (50-100): More responsive to recent price action, catches short-term levels
Higher (300-500): Focuses on major historical levels, more stable but less responsive
Best for: Day trading (100-150), Swing trading (200-300), Position trading (400-500)
Volume Spike Threshold (Default: 1.5)
Lower (1.2-1.4): More sensitive, catches smaller volume increases, more levels detected
Higher (2.0-3.0): Only major volume surges count, fewer but stronger signals
Market dependent: High-volume stocks may need higher thresholds (2.0+), low-volume stocks lower (1.2-1.3)
Price Bins (Default: 50)
Lower (20-30): Broader price zones, less precise but captures wider areas
Higher (70-100): More granular levels, precise but may be overly specific
Volatility dependent: High volatility assets benefit from more bins (70+)
Minimum PMI Score (Default: 0.5)
Lower (0.2-0.4): Shows more levels including weaker ones, comprehensive view
Higher (1.0-2.0): Only statistically strong levels, cleaner chart
Progressive filtering: Start with 0.5, increase if too cluttered
Max Levels to Show (Default: 8)
Fewer (3-5): Clean chart focusing on strongest levels only
More (10-15): Comprehensive view but may clutter chart
Strategy dependent: Scalpers prefer fewer (3-5), swing traders more (8-12)
Historical Tracking Settings
Update Frequency (Default: 20 bars)
Lower (5-10): More frequent updates, captures rapid market changes
Higher (50-100): Less frequent updates, focuses on major structural shifts
Timeframe scaling: 1-minute charts need lower frequency (5-10), daily charts higher (50+)
Show Historical Levels (Default: True)
Enables the "breadcrumb trail" effect showing evolution of support/resistance
Disable for cleaner charts focusing only on current levels
Max Historical Marks (Default: 50)
Lower (20-30): Less memory usage, shorter history
Higher (100-200): Longer historical context but more resource intensive
Fade Strength (Default: 0.8)
Lower (0.5-0.6): Historical levels more visible
Higher (0.9-0.95): Historical levels very subtle
Visual Settings
Support/Resistance Colors: Choose colors that contrast well with your chart theme Line Width: Thicker lines (3-4) for better visibility on busy charts Show PMI Scores: Toggle labels showing statistical strength Label Size: Adjust based on screen resolution and chart zoom level
- Most Effective Usage Strategies
For Day Trading:
Setup: Lookback 100-150, Volume Threshold 1.8-2.2, Update Frequency 10-15
Use PMI levels as bounce/rejection points for scalp entries
Higher PMI scores (>1.5) offer better probability setups
Watch for volume spike confirmations at levels
For Swing Trading:
Setup: Lookback 200-300, Volume Threshold 1.5-2.0, Update Frequency 20-30
Enter on pullbacks to high PMI support levels
Target next resistance level with PMI score >1.0
Hold through minor levels, exit at major PMI levels
For Position Trading:
Setup: Lookback 400-500, Volume Threshold 2.0+, Update Frequency 50+
Focus on PMI scores >2.0 for major structural levels
Use for portfolio entry/exit decisions
Combine with fundamental analysis for timing
- Trading Applications:
Entry Strategies:
PMI Bounce Trades
Price approaches high PMI support level (>1.0)
Wait for volume spike confirmation (orange triangles)
Enter long on bullish price action at the level
Stop loss just below the PMI level
Target: Next PMI resistance level
PMI Breakout Trades
Price consolidates near high PMI level
Volume increases (watch for orange triangles)
Enter on decisive break with volume
Previous resistance becomes new support
Target: Next major PMI level
PMI Rejection Trades
Price approaches PMI resistance with momentum
Watch for rejection signals and volume spikes
Enter short on failure to break through
Stop above the PMI level
Target: Next PMI support level
Risk Management:
Stop Loss Placement
Place stops 0.1-0.5% beyond PMI levels (adjust for volatility)
Higher PMI scores warrant tighter stops
Use ATR-based stops for volatile assets
Position Sizing
Larger positions at PMI levels >2.0 (highest conviction)
Smaller positions at PMI levels 0.5-1.0 (lower conviction)
Scale out at multiple PMI targets
- Key Warning Signs & What to Watch For
Red Flags:
🚨 Very Low PMI Scores (<0.3): Weak statistical significance, avoid trading
🚨 No Volume Confirmation: PMI level without recent volume spikes may be stale
🚨 Overcrowded Levels: Too many levels close together suggests poor parameter tuning
🚨 Outdated Levels: Historical traces are reference only, not tradeable
Optimization Tips:
✅ Regular Recalibration: Adjust parameters monthly based on market regime changes
✅ Volume Context: Always check for recent volume activity at PMI levels
✅ Multiple Timeframes: Confirm PMI levels across different timeframes
✅ Market Conditions: Higher thresholds during high volatility periods
Interpreting PMI Scores
PMI Score Ranges:
0.5-1.0: Moderate statistical significance, proceed with caution
1.0-1.5: Good significance, reliable for most trading strategies
1.5-2.0: Strong significance, high-confidence trade setups
2.0+: Very strong significance, institutional-grade levels
Historical Context: The historical trace system shows how support and resistance evolve over time. When current levels align with multiple historical traces, it indicates persistent market memory at those prices, significantly increasing the level's reliability.