This strategy is a multi-timeframe volume price indicator trading strategy. It comprehensively utilizes the Relative Strength Index (RSI), Average True Range (ATR), Simple Moving Average (SMA) and custom volume price conditions to identify potential long signals. When certain oversold, volume price crossover, price breakout and other entry conditions are met, this strategy will establish long positions. It also sets stop loss and take profit levels to control the risk-reward ratio per trade.
The key points of this strategy are:
Specifically, this strategy sets the length and oversold parameters for the RSI indicator and calculates the RSI values based on these parameters. When the RSI stays below the oversold level for multiple successive bars, an oversold signal is triggered.
In addition, the strategy defines 3 volume thresholds and sets up multiple sets of volume price conditions based on data from different timeframes. For example, the volume value of the 90-period is greater than 1.5 times that of the 49-period. When all these volume price conditions are met at the same time, the volume price indicator generates a long signal.
On the price aspect, the strategy calculates the 13-period SMA and counts the number of bars since the price breaks above the SMA. When the price breaks out above the SMA and the number of bars after breakout is less than 5, it is considered a price breakout signal.
For the ATR period parameters, this strategy specifies a small period of 5 and a big period of 14 for the ATR. When the small period ATR is lower than the big period ATR, it signals that the market volatility is accelerating downward and contributes to the long signal.
Finally, the strategy takes into account all the above entry criteria, including oversold, volume price, price breakout and ATR indicators. When all these conditions are met at the same time, the final long signal is triggered and a long position is established.
This strategy has the following advantages:
Multi-timeframe volume price condition judgement improves accuracy. By evaluating multiple sets of volume price data across different timeframes instead of just a single timeframe, the strategy can judge the concentration of trading volumes more precisely.
The triple confirmation mechanism of oversold + volume price + price breakout ensures reliable entry signals. The oversold condition provides the basic timing for entries, while the additional confirmations from volume price and price indicators further ensure the reliability of the long signals.
The stop loss and take profit mechanism strictly controls the risk per trade. The stop loss and take profit parameters can be adjusted based on personal risk appetite to maximize profits while reasonably controlling the risk per trade.
Integrating multiple indicators increases robustness. Even if some indicators fail or malfunction, the strategy can still rely on other indicators for judgement and ensure a certain level of resilience.
There are also some risks with this strategy:
Parameter configuration risk. The parameter settings of indicators directly impact the judgement, and improper parameters may lead to biases in the trading signals. The reasonable parameter values need to be carefully validated.
Limited profit potential. As a strategy integrating multiple indicators for collective judgement, its signals tend to be more conservative with relatively fewer trades per unit time, thus the profit potential has some constraints.
Indicator divergence risk. When some indicators give out long signals while others give out short signals, the strategy cannot determine the optimal decision. Such potential divergence amongst indicators needs to be identified and resolved in advance.
This strategy can be further optimized in the following aspects:
Incorporate machine learning models to aid judgement. Models can be trained on the volume price and volatility features to dynamically tune the manually defined parameters.
Improve the sophistication of take profit strategies, such as trailing stop take profit, partial take profits, etc. to further increase the profit per trade while preventing loss of profit.
Evaluate incorporating order book data. In addition to price & volume chart data, order book data also reveals depth liquidity distribution information to provide supplementary reference signals.
Test combinations with other indicators. This strategy mainly utilizes indicators like RSI, ATR and SMA. Other indicators such as Bollinger Bands and KDJ can also be combined to diversify and optimize the sources of trading signals.
This strategy utilizes a combination of indicators including RSI, ATR, SMA and custom volume price conditions to identify potential long entry opportunities. It has advantages like multi-timeframe volume price evaluation, triple confirmation mechanism and stop loss/take profit risk controls. Nonetheless, risks like parameter configuration, constrained profit potential also need to be noted. In the future, this strategy can be further enhanced via machine learning augmentation, more sophisticated take profit design, incorporation of order book data as well as expanded indicator combinations.
/*backtest start: 2023-10-24 00:00:00 end: 2023-11-23 00:00:00 period: 1h basePeriod: 15m exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ // © Kimply_Tr //@version=5 // Strategy settings and parameters strategy(title='Volume ValueWhen Velocity', overlay=true) // Define the stop-loss and take-profit percentages for the long strategy long_stoploss_value = input.float(defval=3, title='Stop-Loss (SL) %', minval=0, group='▶ Stop Loss/Take Profit => Long-Strategy', inline='2') long_stoploss_percentage = close * (long_stoploss_value / 100) / syminfo.mintick // Calculate long stop-loss percentage long_takeprofit_value = input.float(defval=2, title='Take-Profit (TP) %', minval=0, group='▶ Stop Loss/Take Profit => Long-Strategy', inline='2') long_takeprofit_percentage = close * (long_takeprofit_value / 100) / syminfo.mintick // Calculate long take-profit percentage // Define parameters related to ValueWhen occurrences occurrence_ValueWhen_1 = input.int(title='occurrence_ValueWhen_1', defval=1, maxval=100, step=1, group="▶ ValueWhen",tooltip ="Its value must be smaller than (occurrence_ValueWhen_2)") occurrence_ValueWhen_2 = input.int(title='occurrence_ValueWhen_2', defval=5, maxval=100, step=1, group="▶ ValueWhen" ,tooltip="Its value must be greater than (occurrence_ValueWhen_1)") distance_value=input.int(title='distance_value_occurrence', defval=170, maxval=5000, step=1, group="▶ ValueWhen" ,tooltip="It indicates the minimum distance between the occurrences of 1 and 2, i.e. the difference between the occurrences of 1 and 2 is greater than (distance_value_occurrence)") // Define RSI-related parameters rsi_over_sold = input.int(defval=60, minval=1, title='Oversold Level', group='▶ RSI',inline ='2') // Input for oversold level in RSI rsi_length = input.int(defval=40, minval=1, title='RSI Length', group='▶ RSI',inline ='2') // Input for RSI length rsi = ta.rsi(close, rsi_length) // Calculate RSI // Define volume thresholds volume_threshold1 = input.float(title='volume_threshold_1', defval=0.5, maxval=10, step=0.1, group="▶ Volume") volume_threshold2 = input.float(title='volume_threshold_2', defval=0.4, maxval=10, step=0.1, group="▶ Volume") volume_threshold3 = input.float(title='volume_threshold_3', defval=0.62, maxval=10, step=0.1, group="▶ Volume") // ATR (Average True Range) // Define ATR parameters atr_small = input.int(title='ATR_Small', defval=5, maxval=500, step=1, group="▶ Atr",inline ='2') atr_big = input.int(title='ATR_Big ', defval=14, maxval=500, step=1, group="▶ Atr",inline ='2') atr_value3 = ta.atr(15) // Calculate ATR value 3 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Date Range // Define the date range for back-testing start_date = input.int(title='Start Day', defval=1, minval=1, maxval=31, group='▶ Time-Period for Back-Testing', inline='1') // Input for start day end_date = input.int(title='until Day', defval=1, minval=1, maxval=31, group='▶ Time-Period for Back-Testing', inline='1') // Input for end day start_month = input.int(title='Start Month', defval=7, minval=1, maxval=12, group='▶ Time-Period for Back-Testing', inline='2') // Input for start month end_month = input.int(title='until Month', defval=1, minval=1, maxval=12, group='▶ Time-Period for Back-Testing', inline='2') // Input for end month start_year = input.int(title='Start Year', defval=2022, minval=1800, maxval=3000, group='▶ Time-Period for Back-Testing', inline='3') // Input for start year end_year = input.int(title='until Year', defval=2077, minval=1800, maxval=3000, group='▶ Time-Period for Back-Testing', inline='3') // Input for end year in_date_range = time >= timestamp(syminfo.timezone, start_year, start_month, start_date, 0, 0) and time < timestamp(syminfo.timezone, end_year, end_month, end_date, 0, 0) // Check if the current time is within the specified date range //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// was_over_sold = ta.barssince(rsi <= rsi_over_sold) <= 10 // Check if RSI was oversold in the last 10 bars //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// getVolume(symbol, bar) => request.security(syminfo.tickerid, "D", volume)[bar] // Function to get volume data for a specific symbol and bar getVolume2(symbol, bar) => request.security(syminfo.tickerid, "39", volume)[bar] // Function to get volume data for a specific symbol and bar 2 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// firstCandleColor1 = request.security(syminfo.tickerid, "D", close[2] > open[1] ? 1 : 0) firstCandleColor2 = request.security(syminfo.tickerid, "1", close[2] > open[0] ? 1 : 0) firstCandleColor3 = request.security(syminfo.tickerid, "W", close[1] > open[1] ? 1 : 0) firstCandleColor= ((firstCandleColor1+firstCandleColor2)) > firstCandleColor3 ? 1 : 0 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// sma = ta.sma(close, 13) // Calculate the simple moving average (SMA) of the close price over 13 periods numCandles = ta.barssince(close > sma) // Count the number of candles since the close price crossed above the SMA atr1=request.security(syminfo.tickerid, "30", ta.atr(atr_small)<ta.atr(atr_big)) // Get the ATR value for the specific security and timeframe (30 minutes) and check if ATR_small is less than ATR_big prevClose = ta.valuewhen(close > sma, close, occurrence_ValueWhen_1) // Get the close price when it first crosses above the SMA based on occurrence_ValueWhen_1 prevCloseBarsAgo = ta.valuewhen(close > sma, close, occurrence_ValueWhen_2) // Get the close price when it first crosses above the SMA based on occurrence_ValueWhen_2 prevCloseChange = (prevCloseBarsAgo - prevClose ) // Calculate the change in the close price between the occurrences of crossing above the SMA atrval=(atr_value3>140) or (atr_value3 < 123) // Check if atr_value3 is either greater than 140 or less than 123 Condition = getVolume(syminfo.tickerid, 90) > volume_threshold1 * getVolume(syminfo.tickerid, 49) and getVolume(syminfo.tickerid, 110) > volume_threshold3 * getVolume(syminfo.tickerid, 49) and getVolume2(syminfo.tickerid, 30) > volume_threshold2 * getVolume2(syminfo.tickerid, 55) and getVolume2(syminfo.tickerid, 7) > volume_threshold2 * getVolume2(syminfo.tickerid, 3) // Check multiple volume conditions buy_signal=Condition and atrval and firstCandleColor==0 and was_over_sold and prevCloseChange> distance_value and atr1 and numCandles<5 // Determine if the buy signal is generated based on various conditions //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Long Strategy // Enter long position if the buy signal conditions are met and within the specified date range if buy_signal and in_date_range strategy.entry('Long', strategy.long, alert_message='Open Long Position') // Enter long position strategy.exit('Long SL/TP', from_entry='Long', loss=long_stoploss_percentage, profit=long_takeprofit_percentage, alert_message='Your SL/TP-Limit for the Long-Strategy has been activated.') // Exit long position with stop-loss and take-profit