Recently, I saw an interesting “Volatility Statistical Arbitrage Strategy” shared in the quantitative trading community. Although it is called an arbitrage strategy, after careful study, I found that the core idea of this strategy is actually more like a contrarian trading method, and some people call it “needle tactics”.
The original author’s core point is very simple: When the market falls and volatility is abnormally enlarged, it often means panic selling. At this time, going long against the trend may have good returns. This idea sounds reasonable. After all, we often see that the market will have a technical rebound after extreme panic.
For the purpose of learning, I decided to write a strategy based on this idea to verify it. Although there may be some gaps with the original author’s refined strategy, I think learning classic ideas through manual reproduction is a very valuable process in itself.
The core logic of the strategy is simple, and it can be summarized in a few sentences:
From the perspective of behavioral finance, the strategy captures the extreme state of market sentiment. When price declines are accompanied by high volatility, it often means:
Investors are panicking and may sell irrationally
Overreaction of prices caused by large orders or breaking news
Natural correction needs after technical indicators are oversold
Of course, this is only a theoretical speculation, and the actual effect still needs to be verified by data.
I have used several quantitative platforms before, FMZ’s Pine Script support is better, and it can be connected to multiple exchanges directly, which is convenient for backtesting and live trading.
1. Parameter setting dilemma
What is the appropriate ATR period setting? How large is the multiple threshold? There is no standard answer for these parameters, and you can only find relatively suitable values through repeated testing. Finally, I chose:
2. The importance of risk control
The biggest risk of counter-trend trading is “buying the bottom halfway up the mountain”. So I added several layers of protection:
3. Design of exit mechanism
This is the key part of the strategy. I designed three exit methods:
// Core judgment logic
atr = ta.atr(atr_period)
atr_ma = ta.sma(atr, mean_period)
price_ma = ta.sma(close, mean_period)
// Opening conditions: Downtrend + High volatility
high_volatility = atr > atr_ma * atr_multiplier
price_decline = close < price_ma
long_condition = price_decline and high_volatility
This code is the core of the strategy. The logic is very straightforward and there is nothing fancy. Specifically:
Step 1: Calculate basic indicators
Step 2: Define trigger conditions
The embodiment of the core idea These lines of code reflect the core idea of the strategy: we do not go against the trend at all times, but specifically wait for the moment when “prices are falling, but volatility suddenly soars”. This moment often means that there is an unexpected event or panic, and the price may overreact, providing us with an opportunity to trade against the trend.
XRP Backtest Performance:
ETH backtest performance:
For mainstream stable products, there are fewer opportunities to open positions. For mainstream currencies such as ETH, there are not many times when the conditions are met.
There are more opportunities for small currencies. Coins such as XRP have higher volatility and trigger conditions more frequently.
A 5-minute period is more suitable. Shorter periods have too much noise while longer periods react too slowly.
Transaction fees are a cost that cannot be ignored. Especially for high-frequency trading, transaction fees will significantly affect the final profit.
This strategy replay taught me several important things:
1. Simple logic is often more effective The core logic of this strategy is simple, but it can indeed capture some opportunities in a specific market environment. Complexity does not mean effectiveness, and sometimes simple and direct methods are more practical.
2. Parameter optimization is a technical job The same logic, different parameter settings may lead to completely different results. It requires a lot of testing and in-depth understanding of the market.
3. Risk control is always the first priority Contrarian trading itself is high-risk, and strict risk control measures are necessary. Risk management cannot be ignored because of a certain success.
Through the practice, I also saw some limitations of the strategy:
High dependence on market environment: In a unilateral bear market, you may face continuous losses
High parameter sensitivity: Parameters need to be adjusted according to different products and market environment
Not omnipotent: Only effective under specific market conditions, need to be combined with other strategies
If you want to continue to optimize this strategy, I think you can start from several directions:
Increase market environment judgment: Reduce positions or suspend trading in a clear bear market trend
Dynamic parameter adjustment: Automatically adjust the ATR threshold according to market volatility characteristics
Multi-product combination: Diversify risks and improve strategy stability
Improve exit mechanism: Combine more technical indicators to optimize exit timing
Thank you very much for sharing the original author’s ideas, which gave me a good learning opportunity. Although my implementation may be rough and there is a gap with the original author’s refined strategy, this manual reproduction process has given me a deeper understanding of the mean reversion strategy.
This is how quantitative trading is learned, starting with imitation, thinking in practice, and growing in failure. There is no perfect strategy, only a process of gradually approaching the truth of the market through continuous learning and improvement.
For friends who are also learning quantitative trading, my advice is:
I hope this exploration can help everyone. The market is always changing, and our learning is always on the road.
Strategy source: Volatility spread statistical arbitrage, the principle is announced, the winning rate is extremely high! The profits are too considerable! This article is for learning and communication only and does not constitute investment advice. Quantitative trading is risky, so be cautious when entering the market.
/*backtest
start: 2025-06-17 00:00:00
end: 2025-06-24 00:00:00
period: 5m
basePeriod: 5m
exchanges: [{"eid":"Futures_Binance","currency":"ETH_USDT","tradesMode":"1"}]
args: [["v_input_float_4",0.5],["v_input_float_5",1.5],["RunMode",1,358374]]
*/
//@version=5
strategy(title="Counter-trend short-term mean reversion strategy", overlay=false, pyramiding=5)
// ===== INPUT PARAMETERS =====
// Risk Management Parameters
risk_per_trade = input.float(2.0, title="Risk per transaction (%)", minval=0.1, maxval=10.0, step=0.1)
max_position_size = input.float(10.0, title="Maximum position size (%)", minval=1.0, maxval=50.0, step=1.0)
pyramiding_number = input.int(5, title="Pyramiding times", minval=1, maxval=10)
// ATR and Volatility Parameters
atr_period = input.int(14, title="ATR period", minval=5, maxval=50)
atr_multiplier = input.float(2.0, title="ATR multiple threshold", minval=1.0, maxval=5.0, step=0.1)
mean_period = input.int(20, title="Mean reversion period", minval=5, maxval=100)
// Take Profit and Stop Loss Parameters
use_stop_loss = input.bool(true, title="Use stop loss")
stop_loss_pct = input.float(3.0, title="Stop loss percentage (%)", minval=0.5, maxval=10.0, step=0.1)
use_take_profit = input.bool(true, title="Use take profit")
take_profit_pct = input.float(6.0, title="Take profit percentage (%)", minval=1.0, maxval=20.0, step=0.1)
// ATR regression closing parameters
use_atr_exit = input.bool(true, title="Using ATR regression to close positions")
atr_exit_threshold = input.float(1.0, title="ATR exit threshold", minval=0.5, maxval=3.0, step=0.1)
// ===== CALCULATIONS =====
// ATR calculation
atr = ta.atr(atr_period)
atr_ma = ta.sma(atr, mean_period)
// Price moving average
price_ma = ta.sma(close, mean_period)
// Volatility judgment
high_volatility = atr > atr_ma * atr_multiplier
// Decline judgment
price_decline = close < price_ma
// The price deviation from the moving average
price_deviation = math.abs(close - price_ma) / price_ma
// ===== ENTRY CONDITIONS =====
// Long opening conditions: falling market + high volatility
long_condition = price_decline and high_volatility and strategy.position_size < max_position_size
// ===== EXIT CONDITIONS =====
// ATR reversion to the mean exit condition
atr_mean_reversion = atr <= atr_ma * atr_exit_threshold
// Stop loss and take profit conditions
long_stop_loss = strategy.position_avg_price * (1 - stop_loss_pct / 100)
long_take_profit = strategy.position_avg_price * (1 + take_profit_pct / 100)
// ===== STRATEGY EXECUTION =====
// Open a long position
if long_condition
strategy.entry("Long", strategy.long, qty=risk_per_trade, comment="Go long against the trend")
// Closing conditions
if strategy.position_size > 0
// ATR return to close position
if use_atr_exit and atr_mean_reversion
strategy.close("Long", comment="ATR return to close position")
// Stop loss
if use_stop_loss and close <= long_stop_loss
strategy.close("Long", comment="Stop loss to close position")
// Take profit
if use_take_profit and close >= long_take_profit
strategy.close("Long", comment="Take profit to close position")
// ===== PLOTTING =====
// Plotting Moving Averages
plot(price_ma, color=color.blue, linewidth=2, title="Price moving average", overlay=true)
// Plotting ATR
plotchar(high_volatility, "High volatility", "▲", location.belowbar, color=color.red, size=size.small)
// PLot signals for opening positions
plotshape(long_condition, style=shape.triangleup, location=location.belowbar, color=color.green, size=size.normal, title="Open long signals")
// Plot the stop loss and take profit lines
if strategy.position_size > 0
plot(long_stop_loss, color=color.red, style=plot.style_linebr, linewidth=1, title="Stop loss line")
plot(long_take_profit, color=color.green, style=plot.style_linebr, linewidth=1, title="Take profit line")
// ATR indicator display
plot(atr, color=color.purple, title="ATR")
plot(atr_ma, color=color.orange, title="ATR moving average")
// ===== ALERTS =====
// Open position Reminder
if long_condition
alert("Triggering of the signal to open long positions against the trend", alert.freq_once_per_bar)
// Close position reminder
if strategy.position_size > 0 and atr_mean_reversion
alert("ATR returns, it is recommended to close the position", alert.freq_once_per_bar)