Inverse Strategy Analysis
I. Strategy Overview
Inverse is a medium-to-long-term trend-following strategy based on the Inverse Fisher Transform of the Commodity Channel Index (CCI). The strategy cleverly applies mathematical transformation technology to convert CCI into more actionable signal indicators, combining multi-timeframe analysis and SSL channel confirmation to construct a complete trend trading system.
The strategy name "Inverse" directly derives from its core technique—the Inverse Fisher Transform. This mathematical transformation maps arbitrarily distributed data into a finite range, effectively smoothing noise signals while preserving key trend reversal characteristics. Through this technique, the strategy successfully converts complex oscillator indicators into clear buy/sell signals.
From a design philosophy perspective, the Inverse strategy belongs to the category combining trend-following and mean-reversion. It captures medium-to-long-term trend continuations while seeking rebound opportunities in oversold zones, achieving dual market opportunity capture. The strategy operates on a 1-hour cycle with 4-hour timeframe trend confirmation, suitable for medium-short-term traders.
II. Theoretical Foundation
2.1 Inverse Fisher Transform Principle
The Fisher Transform was first proposed by J.F. Ehlers as a mathematical method to convert any probability distribution into a normal distribution. Its formula:
Fisher(x) = 0.5 * ln((1 + x) / (1 - x))
The Inverse Fisher Transform is the inverse process of the Fisher Transform:
Inverse Fisher(x) = (exp(2x) - 1) / (exp(2x) + 1)
The core value of this transformation: it maps input data into the fixed range [-1, 1] while enhancing response sensitivity at boundary regions. When input approaches extremes, output changes more drastically—which perfectly meets trading signals' need for inflection point identification.
In the strategy, the Inverse Fisher Transform is applied to the CCI indicator with these processing steps:
- Calculate CCI values (period determined by parameter buy_fisher_length, default 31)
- Scale CCI:
cci_scaled = 0.1 * (cci / 4) - Calculate weighted moving average:
wmacci = WMA(cci_scaled, 9) - Apply Inverse Fisher Transform:
fisher_cci = (exp(2*wmacci) - 1) / (exp(2*wmacci) + 1)
After this processing, Fisher CCI has these advantages:
- Fixed value range [-1, 1], convenient for setting uniform thresholds
- Better smoothness, fewer false signals
- More sensitive to extreme values, identifies reversals faster
2.2 CCI Indicator Characteristics
Commodity Channel Index (CCI), developed by Donald Lambert, is a momentum indicator measuring how far the current price deviates from its historical average:
CCI = (Typical Price - SMA(TP, n)) / (0.015 * Mean Deviation)
Where:
- Typical Price = (High + Low + Close) / 3
- SMA(TP, n) = n-period simple moving average of typical price
- Mean Deviation = Mean absolute deviation of typical price from its moving average
Traditional CCI interpretation:
- CCI > +100: Overbought zone, possible pullback
- CCI < -100: Oversold zone, possible rebound
- CCI within ±100: Normal fluctuation zone
Reasons for choosing CCI as the base indicator:
- CCI has no upper limit, can more truly reflect extreme conditions
- CCI responds quickly to trend changes
- After Inverse Fisher Transform, CCI's overbought/oversold characteristics become more pronounced
2.3 SSL Channels Principle
SSL (SSL Channels) is a trend judgment indicator determining market direction by calculating price's upper and lower channels. The strategy's SSL channel implementation:
def SSLChannels(self, dataframe, length = 7):
df['ATR'] = ATR(dataframe, 14)
df['smaHigh'] = df['high'].rolling(length).mean() + df['ATR']
df['smaLow'] = df['low'].rolling(length).mean() - df['ATR']
df['hlv'] = np.where(df['close'] > df['smaHigh'], 1,
np.where(df['close'] < df['smaLow'], -1, np.NAN))
df['hlv'] = df['hlv'].ffill()
df['sslDown'] = np.where(df['hlv'] < 0, df['smaHigh'], df['smaLow'])
df['sslUp'] = np.where(df['hlv'] < 0, df['smaLow'], df['smaHigh'])
return df['sslDown'], df['sslUp']
SSL channel core logic:
- Calculate SMA high/low channels: Based on price mean ± ATR volatility
- Judge trend state: Close breaks above upper rail for bullish (hlv=1), breaks below lower rail for bearish (hlv=-1)
- Trend state continuation: Use forward fill to maintain trend state until next breakout
- Generate upper/lower rails: Dynamically switch upper/lower rail positions based on trend state
SSL channel advantage: combines trend judgment with volatility adaptation, effectively filtering false signals in ranging markets.
III. Strategy Architecture
3.1 Timeframe Design
The strategy uses a dual-timeframe architecture:
Primary Timeframe (1 hour)
- Generates buy/sell signals
- Calculates granular Fisher CCI indicators
- Executes entry and exit operations
Informative Timeframe (4 hours)
- Confirms trend direction
- Calculates SSL channels and EMA moving averages
- Provides higher-level market context
Advantages of this design:
- Uses 4-hour trend stability to avoid counter-trend trades
- Finds precise entry points on 1-hour timeframe, improving trading efficiency
- When both timeframes align, win rate significantly improves
3.2 Parameter System
The strategy uses a Hyperopt-optimizable parameter system:
Buy Parameters
| Parameter | Default | Optimization Range | Description |
|---|---|---|---|
| buy_fisher_length | 31 | [13, 55] | Fisher CCI calculation period |
| buy_fisher_cci_1 | -0.42 | [-0.6, -0.3] | Primary entry threshold |
| buy_fisher_cci_2 | 0.41 | [0.3, 0.6] | Secondary entry threshold |
Sell Parameters
| Parameter | Default | Optimization Range | Description |
|---|---|---|---|
| sell_fisher_cci_1 | 0.42 | [0.3, 0.6] | Primary exit threshold |
| sell_fisher_cci_2 | -0.34 | [-0.6, -0.3] | Secondary exit threshold |
Stop Loss/Take Profit Parameters
| Parameter | Value | Description |
|---|---|---|
| stoploss | -0.2 | Fixed stop loss 20% |
| trailing_stop | True | Enable trailing stop |
| trailing_stop_positive | 0.078 | Start trailing after 7.8% profit |
| trailing_stop_positive_offset | 0.174 | Trailing stop start offset 17.4% |
| minimal_roi | {"0": 0.10, "30": 0.05, "60": 0.02} | Staged take profit |
3.3 Indicator Calculation Process
The strategy's indicator calculation is divided into two parts:
Informative Timeframe Indicators (4 hours)
def informative_indicators(self, dataframe, metadata):
# EMA system
informative_p['ema_50'] = ta.EMA(informative_p, timeperiod=50)
informative_p['ema_100'] = ta.EMA(informative_p, timeperiod=100)
informative_p['ema_200'] = ta.EMA(informative_p, timeperiod=200)
# SSL channels
ssl_down, ssl_up = self.SSLChannels(informative_p, 20)
informative_p['ssl_down'] = ssl_down
informative_p['ssl_up'] = ssl_up
Primary Timeframe Indicators (1 hour)
def normal_tf_indicators(self, dataframe, metadata):
# Fisher CCI calculation
for cci_length in self.buy_fisher_length.range:
dataframe[f'cci'] = ta.CCI(dataframe, timeperiod=cci_length)
cci = 0.1 * (dataframe[f'cci'] / 4)
wmacci = ta.WMA(cci, timeperiod=9)
dataframe[f'fisher_cci_{cci_length}'] = (numpy.exp(2 * wmacci) - 1) / (numpy.exp(2 * wmacci) + 1)
# Trend confirmation indicators
dataframe['ema_50'] = ta.EMA(dataframe, timeperiod=50)
dataframe['ema_200'] = ta.EMA(dataframe, timeperiod=200)
dataframe['adx'] = ta.ADX(dataframe, timeperiod=3)
dataframe['di_up'] = ta.PLUS_DI(dataframe, timeperiod=3) > ta.MINUS_DI(dataframe, timeperiod=3)
IV. Entry Logic
4.1 Entry Conditions Detailed
The strategy's entry logic uses composite conditions requiring all conditions to be met simultaneously:
Condition Group 1: Fisher CCI Signal
(qtpylib.crossed_above(dataframe[f'fisher_cci_{self.buy_fisher_length.value}'], self.buy_fisher_cci_1.value))
|
(
(qtpylib.crossed_below(dataframe[f'fisher_cci_{self.buy_fisher_length.value}'], self.buy_fisher_cci_2.value).rolling(8).max() == 1) &
(qtpylib.crossed_above(dataframe[f'fisher_cci_{self.buy_fisher_length.value}'], self.buy_fisher_cci_2.value))
)
This includes two entry scenarios:
Scenario A: Oversold Rebound Entry
- Fisher CCI crosses above -0.42 threshold
- Most direct entry signal, capturing rebounds from oversold zones
Scenario B: Trend Confirmation Entry
- Fisher CCI has crossed below 0.41 within the past 8 candles
- Currently Fisher CCI crosses above 0.41
- Captures pullback entries during trend continuation
Condition Group 2: Multi-Timeframe Trend Confirmation
(dataframe[f'ssl_up_{self.info_timeframe}'] > dataframe[f'ssl_down_{self.info_timeframe}']) &
(dataframe['ema_50'] > dataframe['ema_200']) &
(dataframe[f'ema_50_{self.info_timeframe}'] > dataframe[f'ema_100_{self.info_timeframe}']) &
(dataframe[f'ema_50_{self.info_timeframe}'] > dataframe[f'ema_200_{self.info_timeframe}'])
Four trend conditions must all be met simultaneously:
- 4-hour SSL channel bullish: ssl_up > ssl_down, confirms medium-term upward trend
- 1-hour EMA bullish alignment: EMA50 > EMA200, confirms short-term upward trend
- 4-hour EMA bullish alignment (1): EMA50 > EMA100, confirms medium-term momentum
- 4-hour EMA bullish alignment (2): EMA50 > EMA200, confirms medium-term trend
Condition Group 3: Volume Filter
(dataframe['volume'] > 0)
Ensures sufficient market liquidity.
V. Exit Logic
5.1 Sell Signal Conditions
The strategy's exit logic is relatively concise, primarily relying on Fisher CCI inflection signals:
def populate_exit_trend(self, dataframe, metadata):
dataframe.loc[
(
(qtpylib.crossed_below(dataframe[f'fisher_cci_{self.buy_fisher_length.value}'], self.sell_fisher_cci_1.value))
| (qtpylib.crossed_below(dataframe[f'fisher_cci_{self.buy_fisher_length.value}'], self.sell_fisher_cci_2.value))
) &
(dataframe['volume'] > 0)
), 'sell'] = 1
Sell conditions include two scenarios:
Scenario 1: High-Point Reversal Sell
- Fisher CCI crosses below 0.42
- Captures trend reversal from overbought zone
Scenario 2: Trend Weakening Sell
- Fisher CCI crosses below -0.34
- Exits when bullish momentum clearly weakens
5.2 Exit Confirmation Mechanism
The strategy implements a confirm_trade_exit method for secondary confirmation of sell signals:
def confirm_trade_exit(self, pair, trade, order_type, amount, rate, time_in_force, sell_reason, current_time, **kwargs):
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
last_candle = dataframe.iloc[-1]
previous_candle_1 = dataframe.iloc[-2]
if (last_candle is not None):
if (sell_reason in ['sell_signal']):
if last_candle['di_up'] and (last_candle['adx'] > previous_candle_1['adx']):
return False
return True
Exit confirmation logic:
- Only filters sells triggered by sell_signal
- If current DI+ > DI- (bullish momentum dominates) AND ADX rising (trend strength increasing)
- Then reject the sell, continue holding
This is a protection mechanism against being shaken out during strong trends.
5.3 Stop Loss and Take Profit Mechanism
Fixed Stop Loss
- Stop-loss ratio: -20%
- Auto-close when loss reaches 20%
Trailing Stop
trailing_stop = True
trailing_stop_positive = 0.078
trailing_stop_positive_offset = 0.174
trailing_only_offset_is_reached = False
Trailing stop logic:
- When profit reaches 7.8%, activate trailing stop
- Stop line retreats a fixed ratio from the highest point
trailing_only_offset_is_reached = Falsemeans trailing starts immediately without waiting for offset value
Staged Take Profit (ROI)
minimal_roi = {
"0": 0.10, # Effective immediately after opening: 10% target
"30": 0.05, # After 30 minutes: 5% target
"60": 0.02 # After 60 minutes: 2% target
}
ROI mechanism: encourages quick profit-taking, avoids long-holding risk.
VI. Risk Control System
6.1 Multi-Layer Risk Control Architecture
The strategy builds a complete multi-layer risk control system:
Layer 1: Signal Filtering
- Fisher CCI threshold filtering, avoids noisy signals
- Trend confirmation filtering, avoids counter-trend trades
- Volume filtering, ensures liquidity
Layer 2: Trend Confirmation
- Dual-timeframe trend consistency verification
- Multi-dimensional moving average system confirmation
- SSL channel direction confirmation
Layer 3: Position Management
- Fixed stop loss protects principal
- Trailing stop locks in profits
- Staged take profit controls risk exposure
Layer 4: Exit Confirmation
- ADX/DI trend strength filtering
- Prevents being shaken out during strong trends
6.2 Risk Control Parameter Analysis
| Risk Control Type | Parameter Value | Risk Level | Mechanism |
|---|---|---|---|
| Fixed Stop Loss | -20% | Medium-High | Protects principal, prevents large single losses |
| Trailing Activation | 7.8% | Low | Protects after sufficient profit |
| Trailing Offset | 17.4% | Low | Ensures sufficient profit buffer |
| ROI Stage 1 | 10% | Low | Quick profit-taking |
| ROI Stage 2 | 5% | Medium | Reduce expectations after 30 minutes |
| ROI Stage 3 | 2% | Medium | Quick exit after 60 minutes |
6.3 Market Adaptability Analysis
Suitable markets:
- Markets with clear unilateral trends
- Trading instruments with moderate volatility
- Trading pairs with sufficient liquidity
Unsuitable markets:
- Severely oscillating sideways markets
- Low-liquidity small-cap coins
- Extreme conditions (wild spikes or crashes)
VII. Parameter Optimization Space
7.1 Optimizable Parameters
Buy parameter ranges
buy_fisher_length: [13, 55], affects Fisher CCI sensitivitybuy_fisher_cci_1: [-0.6, -0.3], controls oversold entry thresholdbuy_fisher_cci_2: [0.3, 0.6], controls trend pullback entry threshold
Sell parameter ranges
sell_fisher_cci_1: [0.3, 0.6], controls overbought exit thresholdsell_fisher_cci_2: [-0.6, -0.3], controls trend weakening exit threshold
7.2 Optimization Suggestions
- Data preparation: Ensure at least 6 months of historical data, covering different market states
- Optimization method: Use Hyperopt's Sharpe Ratio as objective, set reasonable parameter boundaries
- Out-of-sample verification: Validate parameters on data not used in optimization
VIII. Live Trading Recommendations
8.1 Deployment Preparation
Environment configuration
timeframe = '1h'
startup_candle_count = 200
process_only_new_candles = True
Trading pair selection: Choose mainstream pairs with sufficient liquidity, avoid new coins and low-market-cap coins
8.2 Risk Warnings
- Trend failure risk: May generate consecutive losses at trend turning points—recommend setting circuit breakers after consecutive losses
- Slippage risk: Strategy uses limit orders for buying—in fast markets, may not fill
- Parameter failure risk: Optimized parameters may fail when market conditions change—recommend regular re-optimization
IX. Strategy Strengths and Limitations
9.1 Strategy Strengths
Technical advantages:
- Indicator innovation: Inverse Fisher Transform enhances signal quality
- Multi-timeframe: Uses 4-hour confirmation to reduce false signals
- Composite conditions: Multi-filter conditions improve signal reliability
- Dynamic risk control: Trailing stop and staged take profit
Practical advantages:
- Optimizable: All key parameters support Hyperopt
- Clear logic: Entry/exit rules are explicit, easy to understand and maintain
- Good visualization: Provides plot_config, convenient for analysis
- High computational efficiency: Moderate indicator calculation volume, suitable for real-time trading
9.2 Strategy Limitations
Technical limitations:
- Trend dependency: Underperforms in ranging markets
- Lagging: EMA system has inherent lag
- Parameter sensitivity: Different market environments need different parameters
- Single indicator: Primarily relies on Fisher CCI, lacks multi-indicator verification
Practical limitations:
- Large stop loss: 20% may exceed some traders' risk tolerance
- Aggressive trailing stop: 7.8% trigger threshold may lock in profits too early
- Simple exit: Exit conditions relatively simpler than entry
- No position building mechanism: Doesn't leverage trending advantages to add positions
X. Improvement Directions
10.1 Indicator-Level Improvements
# Suggested additions
dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)
dataframe['macd'] = ta.MACD(dataframe)
dataframe['bb_upperband'] = ta.BBANDS(dataframe, timeperiod=20)['upperband']
10.2 Logic-Level Improvements
Enhanced exit logic: Add RSI divergence detection, MACD death cross confirmation, price pattern recognition
Improved stop-loss mechanism:
# Suggested ATR dynamic stop loss
dataframe['atr'] = ta.ATR(dataframe, timeperiod=14)
stoploss = -2 * dataframe['atr'] / dataframe['close']
Added position management:
# Adjust position size based on ADX strength
position_size = base_size * (adx / 25)
XI. Summary
The Inverse strategy is a well-designed trend-following strategy. Its core innovation—applying the Inverse Fisher Transform to the CCI indicator—effectively enhances signal quality. Through multi-timeframe analysis and composite filtering conditions, the strategy achieves effective capture of trending markets while maintaining signal accuracy.
The strategy's main value:
- Solid mathematical theory: Inverse Fisher Transform has clear mathematical meaning
- Complete risk control: Multi-layer protection safeguards principal and profits
- High optimizability: Parameter system supports Hyperopt automatic optimization
- High live-trading usability: Clear logic, efficient computation
The strategy's main risk lies in its dependence on trending markets—may generate many false signals in oscillating markets. Traders are recommended to:
- Choose trading pairs with strong trends
- Adjust parameters according to market environment
- Strictly control per-trade risk
- Regularly monitor and optimize the strategy
Overall, the Inverse strategy provides a reliable framework for quantitative traders. With appropriate optimization and improvement, its performance across different market environments can be further enhanced.