Crypto Regime Detection with a Local AI Agent: Bull vs Bear vs Sideways
The biggest mistake most crypto traders make isn't picking bad coins — it's using a bull market strategy in a bear market. Or holding through a sideways chop when they should be flat. The market has distinct regimes, and your strategy needs to know which one it's in.
Regime detection used to require expensive quant tools or years of statistics experience. With a local AI agent and a few Python libraries, you can do it yourself — for free, running on your own machine, in real-time.
Not financial advice. Paper trading only.
What Is a Market Regime?
A market regime is the dominant behavior pattern of an asset over a period of time. For crypto, there are three that matter:
Bull Regime — Sustained upward trend. Higher highs, higher lows. Breakouts hold. Dips are bought. Momentum strategies work.
Bear Regime — Sustained downward trend. Lower highs, lower lows. Bounces get sold. Mean reversion is dangerous. Defensive positioning is key.
Sideways/Ranging Regime — No clear trend. Price oscillates between support and resistance. Mean reversion strategies outperform. Trend-following fails.
Each regime rewards different strategies. Using the wrong strategy in the wrong regime is like wearing snow boots at the beach — technically functional, completely wrong for the context.
Why AI Helps With Regime Detection
Classic approaches to regime detection use:
- Moving average crossovers (simple but lag-heavy)
- ADX (Average Directional Index) for trend strength
- Volatility regimes (low vol = trending, high vol = chaotic)
- Hidden Markov Models (powerful but complex)
A local LLM adds a layer that pure indicators miss: contextual reasoning. You can feed your agent a set of indicators and ask it to synthesize them the way an experienced analyst would.
More importantly: you can do this without sending your data to any external API. Everything runs locally.
Building the Regime Detection System
Step 1: Fetch Multi-Timeframe Data
Regime detection works better with multiple timeframes. A coin can be in a bull regime on the daily but ranging on the hourly.
import ccxt
import pandas as pd
import ta
def fetch_ohlcv(symbol, timeframe, limit=200):
exchange = ccxt.binance({"enableRateLimit": True})
data = exchange.fetch_ohlcv(symbol, timeframe, limit=limit)
df = pd.DataFrame(data, columns=["ts","open","high","low","close","volume"])
df["datetime"] = pd.to_datetime(df["ts"], unit="ms")
df.set_index("datetime", inplace=True)
return df
# Pull 4H and Daily
df_4h = fetch_ohlcv("BTC/USDT", "4h", 200)
df_1d = fetch_ohlcv("BTC/USDT", "1d", 100)
Step 2: Calculate Regime Indicators
def add_regime_indicators(df):
# Trend direction
df["ema_21"] = ta.trend.EMAIndicator(df["close"], 21).ema_indicator()
df["ema_55"] = ta.trend.EMAIndicator(df["close"], 55).ema_indicator()
df["ema_200"] = ta.trend.EMAIndicator(df["close"], 200).ema_indicator()
# Trend strength
adx_obj = ta.trend.ADXIndicator(df["high"], df["low"], df["close"], 14)
df["adx"] = adx_obj.adx()
df["adx_pos"] = adx_obj.adx_pos() # +DI
df["adx_neg"] = adx_obj.adx_neg() # -DI
# Momentum
df["rsi"] = ta.momentum.RSIIndicator(df["close"], 14).rsi()
# Volatility
bb = ta.volatility.BollingerBands(df["close"], 20, 2)
df["bb_width"] = (bb.bollinger_hband() - bb.bollinger_lband()) / bb.bollinger_mavg()
# Volume trend
df["vol_ema"] = ta.trend.EMAIndicator(df["volume"], 20).ema_indicator()
df["vol_ratio"] = df["volume"] / df["vol_ema"]
return df.dropna()
Step 3: Rule-Based Regime Classifier
Before involving the LLM, build a solid rule-based baseline:
def classify_regime_rules(df):
"""Fast, deterministic regime classification using rules."""
latest = df.iloc[-1]
price = latest["close"]
ema21 = latest["ema_21"]
ema55 = latest["ema_55"]
ema200 = latest["ema_200"]
adx = latest["adx"]
adx_pos = latest["adx_pos"]
adx_neg = latest["adx_neg"]
rsi = latest["rsi"]
bb_width = latest["bb_width"]
# Strong bull conditions
if (price > ema21 > ema55 > ema200 and
adx > 25 and adx_pos > adx_neg and
rsi > 50):
return "BULL", "Strong uptrend: price above all EMAs, ADX trending, RSI bullish"
# Strong bear conditions
if (price < ema21 < ema55 < ema200 and
adx > 25 and adx_neg > adx_pos and
rsi < 50):
return "BEAR", "Strong downtrend: price below all EMAs, ADX trending, RSI bearish"
# Ranging/sideways
if adx < 20 or bb_width < 0.05:
return "SIDEWAYS", f"Low trend strength: ADX={adx:.1f}, BB width={bb_width:.3f}"
# Transitional states
if price > ema55 and ema21 > ema55:
return "BULL_WEAK", "Emerging bull: above medium-term EMAs but not confirmed"
if price < ema55 and ema21 < ema55:
return "BEAR_WEAK", "Emerging bear: below medium-term EMAs but not confirmed"
return "UNCERTAIN", "Mixed signals — no clear regime"
Step 4: LLM Synthesis Layer
Now bring in Ollama for contextual reasoning:
import urllib.request
import json
def classify_regime_llm(df, symbol="BTC/USDT"):
"""Use local LLM to synthesize regime from indicators."""
latest = df.iloc[-1]
prev_week = df.iloc[-42] # ~1 week ago on 4H
price_change_7d = (latest["close"] - prev_week["close"]) / prev_week["close"] * 100
prompt = f"""You are a crypto market analyst. Classify the current market regime for {symbol}.
CURRENT INDICATORS:
- Price: ${latest['close']:,.2f} ({price_change_7d:+.1f}% vs 7 days ago)
- EMA 21: ${latest['ema_21']:,.2f}
- EMA 55: ${latest['ema_55']:,.2f}
- EMA 200: ${latest['ema_200']:,.2f}
- ADX: {latest['adx']:.1f} (>25 = trending, <20 = ranging)
- +DI: {latest['adx_pos']:.1f}, -DI: {latest['adx_neg']:.1f}
- RSI(14): {latest['rsi']:.1f}
- Bollinger Band Width: {latest['bb_width']:.3f}
- Volume vs 20-period avg: {latest['vol_ratio']:.2f}x
Price vs EMAs: {'ABOVE' if latest['close'] > latest['ema_21'] else 'BELOW'} EMA21, \
{'ABOVE' if latest['close'] > latest['ema_55'] else 'BELOW'} EMA55, \
{'ABOVE' if latest['close'] > latest['ema_200'] else 'BELOW'} EMA200
Respond with exactly:
REGIME: [BULL/BEAR/SIDEWAYS]
CONFIDENCE: [HIGH/MEDIUM/LOW]
REASON: [One sentence explanation]
STRATEGY: [What type of strategy works in this regime]
"""
payload = {
"model": "mistral",
"prompt": prompt,
"stream": False,
"options": {"temperature": 0.1} # Low temp for consistency
}
req = urllib.request.Request(
"http://localhost:11434/api/generate",
data=json.dumps(payload).encode(),
headers={"Content-Type": "application/json"}
)
with urllib.request.urlopen(req, timeout=30) as resp:
result = json.loads(resp.read())
return result["response"].strip()
Putting It All Together
def detect_regime(symbol="BTC/USDT"):
"""Full regime detection pipeline."""
print(f"\nAnalyzing regime for {symbol}...")
# Get data
df_4h = fetch_ohlcv(symbol, "4h", 250)
df_4h = add_regime_indicators(df_4h)
# Rule-based check (fast)
regime, reason = classify_regime_rules(df_4h)
print(f"Rule-based: {regime} — {reason}")
# LLM synthesis (deeper)
llm_analysis = classify_regime_llm(df_4h, symbol)
print(f"\nLLM Analysis:\n{llm_analysis}")
return regime, llm_analysis
# Run it
detect_regime("BTC/USDT")
detect_regime("ETH/USDT")
detect_regime("SOL/USDT")
Adapting Your Strategy to the Regime
Once you know the regime, you can dynamically switch strategies:
STRATEGY_MAP = {
"BULL": {
"approach": "trend-following",
"entries": "buy dips to EMA21",
"exits": "trail stop below EMA55",
"leverage": "1-2x max",
},
"BEAR": {
"approach": "defensive/short",
"entries": "sell bounces to EMA21",
"exits": "cover at oversold RSI",
"leverage": "avoid longs",
},
"SIDEWAYS": {
"approach": "mean-reversion",
"entries": "buy at lower BB, sell at upper BB",
"exits": "take profit at opposite band",
"leverage": "none",
},
"UNCERTAIN": {
"approach": "flat",
"entries": "none",
"exits": "reduce exposure",
"leverage": "none",
},
}
Scheduling Regime Checks with OpenClaw
Run regime detection automatically every 4 hours via OpenClaw's heartbeat system:
# In your OpenClaw skill file
def heartbeat():
regime, analysis = detect_regime("BTC/USDT")
send_telegram(f"**BTC Regime Update**\n{analysis}")
Set the heartbeat interval to 4 hours and you'll never miss a regime shift.
What Regime Detection Won't Do
It won't predict tops and bottoms. It won't tell you when a regime will end. It operates on historical data with a lag — the faster your timeframe, the noisier the signal.
The value is in avoiding catastrophic mismatches: running a trend-following bot in a ranging market, or buying dips in a bear trend. Regime detection keeps you in the right mode.
Ready to Automate Your Analysis?
The full regime detection system — including multi-timeframe analysis, Telegram alerts, and integration with paper trading — is in the OpenClaw kit:
👉 OpenClaw Home AI Agent Kit — Full Setup Guide
Know the regime. Trade accordingly.
🛠️ Also check out CryptoClaw Skills Hub — browse and install crypto skills for your OpenClaw agent: https://paarthurnax970-debug.github.io/cryptoclawskills/
Not financial advice. Paper trading only. All strategies should be backtested before any live deployment.
Top comments (0)