OPEN-SOURCE SCRIPT
Обновлено

RSI Weighted Trend System I [InvestorUnknown]

The RSI Weighted Trend System I is an experimental indicator designed to combine both slow-moving trend indicators for stable trend identification and fast-moving indicators to capture potential major turning points in the market. The novelty of this system lies in the dynamic weighting mechanism, where fast indicators receive weight based on the current Relative Strength Index (RSI) value, thus providing a flexible tool for traders seeking to adapt their strategies to varying market conditions.

Dynamic RSI-Based Weighting System
  • The core of the indicator is the dynamic weighting of fast indicators based on the value of the RSI. In essence, the higher the absolute value of the RSI (whether positive or negative), the higher the weight assigned to the fast indicators. This enables the system to capture rapid price movements around potential turning points.


Users can choose between a threshold-based or continuous weight system:
  • Threshold-Based Weighting: Fast indicators are activated only when the absolute RSI value exceeds a user-defined threshold. Below this threshold, fast indicators receive no weight.
  • Continuous Weighting: By setting the weight threshold to zero, the fast indicators always receive some weight, although this can result in more false signals in ranging markets.


// Calculate weight for Fast Indicators based on RSI (Slow Indicator weight is kept to 1 for simplicity)
f_RSI_Weight_System(series float rsi, simple float weight_thre) =>

    float fast_weight   = na
    float slow_weight   = na

    if weight_thre > 0
        if math.abs(rsi) <= weight_thre
            fast_weight := 0
            slow_weight := 1
        else
            fast_weight := 0 + math.sqrt(math.abs(rsi))
            slow_weight := 1
    else
        fast_weight     := 0 + math.sqrt(math.abs(rsi))
        slow_weight     := 1

    [fast_weight, slow_weight]


снимок


Slow and Fast Indicators
Slow Indicators are designed to identify stable trends, remaining constant in weight. These include:
  • DMI (Directional Movement Index) For Loop
  • CCI (Commodity Channel Index) For Loop
  • Aroon For Loop

Fast Indicators are more responsive and designed to spot rapid trend shifts:
  • ZLEMA (Zero-Lag Exponential Moving Average) For Loop
  • IIRF (Infinite Impulse Response Filter) For Loop


Each of these indicators is calculated using a for-loop method to generate a moving average, which captures the trend of a given length range.


RSI Normalization
  • To facilitate the weighting system, the RSI is normalized from its usual 0-100 range to a -1 to 1 range. This allows for easy scaling when calculating weights and helps the system adjust to rapidly changing market conditions.


// Normalize RSI (1 to -1)
f_RSI(series float rsi_src, simple int rsi_len, simple string rsi_wb, simple string ma_type, simple int ma_len) =>
    output = switch rsi_wb
        "RAW RSI"       => ta.rsi(rsi_src, rsi_len)
        "RSI MA"        => ma_type == "EMA" ? (ta.ema(ta.rsi(rsi_src, rsi_len), ma_len)) : (ta.sma(ta.rsi(rsi_src, rsi_len), ma_len))


Signal Calculation
  • The final trading signal is a weighted average of both the slow and fast indicators, depending on the calculated weights from the RSI. This ensures a balanced approach, where slow indicators maintain overall trend guidance, while fast indicators provide timely entries and exits.


// Calculate Signal (as weighted average)
sig = math.round(((DMI*slow_w) + (CCI*slow_w) + (Aroon*slow_w) + (ZLEMA*fast_w) + (IIRF*fast_w)) / (3*slow_w + 2*fast_w), 2)



Backtest Mode and Performance Metrics
This version of the RSI Weighted Trend System includes a comprehensive backtesting mode, allowing users to evaluate the performance of their selected settings against a Buy & Hold strategy. The backtesting includes:
  • Equity calculation based on the signals generated by the indicator.
  • Performance metrics table comparing Buy & Hold strategy metrics with the system’s signals, including: Mean, positive, and negative return percentages, Standard deviations (of all, positive and negative returns), Sharpe Ratio, Sortino Ratio, and Omega Ratio


f_PerformanceMetrics(series float base, int Lookback, simple float startDate, bool Annualize = true) =>
    // Initialize variables for positive and negative returns
    pos_sum = 0.0
    neg_sum = 0.0
    pos_count = 0
    neg_count = 0
    returns_sum = 0.0
    returns_squared_sum = 0.0
    pos_returns_squared_sum = 0.0
    neg_returns_squared_sum = 0.0
    // Loop through the past 'Lookback' bars to calculate sums and counts
    if (time >= startDate)
        for i = 0 to Lookback - 1
            r = (base - base[i + 1]) / base[i + 1]
            returns_sum += r
            returns_squared_sum += r * r
            if r > 0
                pos_sum += r
                pos_count += 1
                pos_returns_squared_sum += r * r
            if r < 0
                neg_sum += r
                neg_count += 1
                neg_returns_squared_sum += r * r

    float [] export_array = array.new_float(12)

    // Calculate means
    mean_all = math.round((returns_sum / Lookback) * 100, 2)
    mean_pos = math.round((pos_count != 0 ? pos_sum / pos_count : na) * 100, 2)
    mean_neg = math.round((neg_count != 0 ? neg_sum / neg_count : na) * 100, 2)

    // Calculate standard deviations
    stddev_all = math.round((math.sqrt((returns_squared_sum - (returns_sum * returns_sum) / Lookback) / Lookback)) * 100, 2)
    stddev_pos = math.round((pos_count != 0 ? math.sqrt((pos_returns_squared_sum - (pos_sum * pos_sum) / pos_count) / pos_count) : na) * 100, 2)
    stddev_neg = math.round((neg_count != 0 ? math.sqrt((neg_returns_squared_sum - (neg_sum * neg_sum) / neg_count) / neg_count) : na) * 100, 2)

    // Calculate probabilities
    prob_pos = math.round((pos_count / Lookback) * 100, 2)
    prob_neg = math.round((neg_count / Lookback) * 100, 2)
    prob_neu = math.round(((Lookback - pos_count - neg_count) / Lookback) * 100, 2)

    // Calculate ratios
    sharpe_ratio = math.round(mean_all / stddev_all * (Annualize ? math.sqrt(Lookback) : 1), 2)
    sortino_ratio = math.round(mean_all / stddev_neg * (Annualize ? math.sqrt(Lookback) : 1), 2)
    omega_ratio = math.round(pos_sum / math.abs(neg_sum), 2)

    // Set values in the array
    array.set(export_array, 0, mean_all),       array.set(export_array, 1, mean_pos),           array.set(export_array, 2, mean_neg),
    array.set(export_array, 3, stddev_all),     array.set(export_array, 4, stddev_pos),         array.set(export_array, 5, stddev_neg),
    array.set(export_array, 6, prob_pos),       array.set(export_array, 7, prob_neu),           array.set(export_array, 8, prob_neg),
    array.set(export_array, 9, sharpe_ratio),   array.set(export_array, 10, sortino_ratio),     array.set(export_array, 11, omega_ratio)

    // Export the array
    export_array


The metrics help traders assess the effectiveness of their strategy over time and can be used to optimize their settings.

снимок


Calibration Mode
  • A calibration mode is included to assist users in tuning the indicator to their specific needs. In this mode, traders can focus on a specific indicator (e.g., DMI, CCI, Aroon, ZLEMA, IIRF, or RSI) and fine-tune it without interference from other signals.
  • The calibration plot visualizes the chosen indicator's performance against a zero line, making it easy to see how changes in the indicator’s settings affect its trend detection.



Customization and Default Settings
  • Important Note: The default settings provided are not optimized for any particular market or asset. They serve as a starting point for experimentation. Traders are encouraged to calibrate the system to suit their own trading strategies and preferences.
  • The indicator allows deep customization, from selecting which indicators to use, adjusting the lengths of each indicator, smoothing parameters, and the RSI weight system.



Alerts
Traders can set alerts for both long and short signals when the indicator flips, allowing for automated monitoring of potential trading opportunities.
Информация о релизе
- Fixed issue with indicator giving errors on lower timeframes (the issue may still persist if you are using backtest mode on lower timeframes and referencing more than 5000 bars, in which case you will have to change the Backtest Start Date for the backtest tool to work.)
Информация о релизе
// Added max_bars_back = 5000 to avoid some errors related to the backtest mode.
Информация о релизе
Updated the code to pinescript v6, added backtesting library v2 with more backtesting functions and removed old backtesting functions from the code

Отказ от ответственности