Claude Code Plugins

Community-maintained marketplace

Feedback

btc-trading-bot

@khopilot/bit-trand
0
0

|

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name btc-trading-bot
description Bitcoin trading simulation with technical analysis (EMA/RSI/Bollinger), Monte Carlo projections, and Telegram alerts. Cambodian market focus (USD/KHR 4050). TRIGGERS: BTC backtesting, indicator calculations, Fear & Greed integration, crypto strategy development, CoinGecko/Alternative.me APIs, portfolio simulation, trailing stop optimization, Sharpe/drawdown metrics. ENTRY POINTS: btc_trader.py (365d backtest), btc_simulation.py (60d Monte Carlo), backtest_runner.py (advanced metrics).

BTC Trading Bot

Architecture

btc_trader.py ──────────────────► Telegram / Console
     │                              ▲
     │ imports                      │
     ▼                              │
backtest_runner.py ─────────────────┘
     
btc_simulation.py (self-contained, duplicates core functions)

Critical: btc_simulation.py duplicates functions. Refactor target.

Execution

python btc_trader.py        # 365d backtest → Telegram
python btc_simulation.py    # 60d GBM Monte Carlo
python backtest_runner.py   # Sharpe, drawdown, win rate
# Optional Telegram (falls back to stdout)
export TELEGRAM_BOT_TOKEN="..."
export TELEGRAM_CHAT_ID="..."

Strategy Matrix

Condition Elite (btc_trader) Pro (btc_simulation)
Trend Entry EMA12>26 ∧ RSI∈[50,70] ∧ FNG<80 EMA12>26 ∧ RSI∈[50,75]
Contrarian Price<BB_lower ∧ RSI<35 ∧ FNG<25
Exit: Reversal EMA12<26 EMA12<26
Exit: Blow-off Price>BB_upper ∧ RSI>75 ∧ FNG>80
Exit: Stop 5% trailing 5% trailing

⚠️ 5% trailing stop is dangerously tight for crypto. BTC routinely swings 3-5% intraday. See ATR-based stop.

Indicators

# All calculations in calculate_indicators(df)
EMA_12  = Close.ewm(span=12, adjust=False).mean()
EMA_26  = Close.ewm(span=26, adjust=False).mean()
RSI_14  = 100 - (100 / (1 + avg_gain / avg_loss.replace(0, ε)))  # ε prevents div/0
BB_MID  = Close.rolling(20).mean()
BB_STD  = Close.rolling(20).std()
BB_UP   = BB_MID + 2σ
BB_LOW  = BB_MID - 2σ

Warmup period: First 26 rows are garbage (NaN propagation). Drop or backfill.

Data Sources

API Endpoint Rate Limit Timeout
CoinGecko /coins/bitcoin/market_chart?vs_currency=usd&days=N ~30/min 10s
Alternative.me /fng/?limit=N Generous 10s

FNG Fallback: Silently returns 50 on failure. This masks API issues. Add logging.

# Proper FNG fetch with warning
try:
    fng_data = requests.get(url, timeout=10).json()
except Exception as e:
    logging.warning(f"FNG API failed: {e}, defaulting to 50")
    return pd.DataFrame({'Date': dates, 'FNG_Value': 50})

Critical Bugs

1. Ledger Parser Format Mismatch

backtest_runner.py:47-60 regex expects Elite format, breaks on Pro.

# Elite: "2025-01-15: BUY at $42,500.00"
# Pro:   "Day 0 (2025-01-01): BUY at $42,500.00"

# FIX: Universal parser
import re
def parse_trade(entry: str) -> dict:
    patterns = [
        r'(\d{4}-\d{2}-\d{2}): (BUY|SELL) at \$([\d,]+\.?\d*)',           # Elite
        r'Day \d+ \((\d{4}-\d{2}-\d{2})\): (BUY|SELL) at \$([\d,]+\.?\d*)' # Pro
    ]
    for p in patterns:
        if m := re.match(p, entry):
            return {'date': m[1], 'action': m[2], 'price': float(m[3].replace(',', ''))}
    raise ValueError(f"Unknown format: {entry}")

2. Unrealized P&L at Backtest End

Open positions must be marked-to-market at final close price.

# End of run_elite_strategy()
if position_open:
    unrealized = btc_held * df.iloc[-1]['Close']
    portfolio_value = cash + unrealized

3. Timezone Inconsistency

CoinGecko returns UTC timestamps. FNG returns Unix timestamps. Merge carefully.

# Always normalize to UTC date
df['Date'] = pd.to_datetime(df['Date']).dt.tz_localize(None).dt.normalize()

Dynamic Trailing Stop

Replace fixed 5% with ATR-based volatility adjustment:

def calculate_atr(df: pd.DataFrame, period: int = 14) -> pd.Series:
    tr = pd.concat([
        df['High'] - df['Low'],
        (df['High'] - df['Close'].shift()).abs(),
        (df['Low'] - df['Close'].shift()).abs()
    ], axis=1).max(axis=1)
    return tr.rolling(period).mean()

# Dynamic stop: 2× ATR below entry (or highest since entry)
stop_price = highest_since_entry - (2 * current_atr)

Note: CoinGecko /market_chart only returns Close. For ATR, use /ohlc endpoint or exchange API.

Monte Carlo Assumptions

btc_simulation.py uses Geometric Brownian Motion:

dS = μSdt + σSdW

Limitations for crypto:

  • Assumes log-normal returns (BTC has fat tails, kurtosis ~6-10)
  • Ignores regime shifts (bull/bear transitions)
  • Calibrates μ,σ from 60d history (recency bias)

Improvement: Use GARCH(1,1) for volatility clustering or regime-switching model.

Metrics Reference

# Sharpe Ratio (annualized, daily returns)
sharpe = (mean_daily_return / std_daily_return) * sqrt(365)

# Max Drawdown
peak = running_max(portfolio_values)
drawdown = (peak - current) / peak
max_dd = max(drawdown)

# Win Rate
wins = trades.where(pnl > 0).count()
win_rate = wins / total_trades

# Profit Factor
gross_profit = sum(pnl.where(pnl > 0))
gross_loss = abs(sum(pnl.where(pnl < 0)))
profit_factor = gross_profit / gross_loss

Cambodian Market

USD_KHR = 4050

def format_khr(usd: float) -> str:
    return f"៛{usd * USD_KHR:,.0f}"

# Telegram report excerpt
msg = f"""
💰 Portfolio: ${value:,.2f}
🇰🇭 KHR: {format_khr(value)}
"""

Code Patterns

Safe RSI

avg_loss = loss.rolling(14).mean().replace(0, np.finfo(float).eps)

Timezone-Safe Datetime

from datetime import datetime, timezone
now = datetime.now(timezone.utc)

API with Retry

from tenacity import retry, stop_after_attempt, wait_exponential

@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, max=10))
def fetch_with_retry(url: str) -> dict:
    r = requests.get(url, timeout=10)
    r.raise_for_status()
    return r.json()

Backtesting Pitfalls

Pitfall Status Fix
Lookahead bias ✅ OK Uses .shift() for signals
Survivorship bias ✅ N/A Single asset
Slippage/fees ❌ Missing Add 0.1% per trade
Position sizing ❌ 100% always Implement Kelly or fixed-fraction
Out-of-sample ❌ Missing Split train/test periods
# Add transaction cost
SLIPPAGE = 0.001  # 0.1%
def execute_buy(price, capital):
    effective_price = price * (1 + SLIPPAGE)
    return capital / effective_price

def execute_sell(price, btc_held):
    effective_price = price * (1 - SLIPPAGE)
    return btc_held * effective_price

File Reference

File Read When
references/strategies.md Strategy modification, threshold tuning
references/indicators.md Adding new indicators, formula verification
references/apis.md API debugging, response schema lookup
references/PRODUCTION_ARCHITECTURE.md Going live: Full system design, deployment, safety
scripts/utils.py Data validation, metrics calculation, ledger parsing

Quick Fixes Checklist

  • Add FNG warning log on API failure
  • Fix ledger parser for both formats
  • Extract shared module from btc_trader/btc_simulation
  • Add config.yaml for thresholds
  • Implement ATR-based trailing stop
  • Add slippage to backtester
  • Split backtest into train/validation periods

Production Migration

See references/PRODUCTION_ARCHITECTURE.md for complete system design.

TL;DR Architecture

DataService ──► StrategyEngine ──► ExecutorService ──► Exchange
     │               │                    │
     └───────────────┴────────────────────┴──► PostgreSQL
                                               │
                     RiskManager (Watchdog) ◄──┘
                           │
                     TelegramControl

Key Technologies

Component Technology
Exchange API ccxt (107 exchanges)
WebSocket ccxt.pro
Database PostgreSQL
Control Telegram bidirectional
Deployment VPS Singapore + systemd

Safety-First Principles

  1. Testnet firstexchange.set_sandbox_mode(True)
  2. Paper trading mode — Toggle without code changes
  3. Kill switch — Independent watchdog process
  4. Position limits — Max 25% capital per trade
  5. Daily loss limit — Auto-stop at 5% daily loss
  6. Heartbeat monitoring — Alert if bot stops responding

Migration Timeline

Phase Duration Deliverable
Refactor 2 weeks Modular codebase + tests
Exchange 2 weeks ccxt integration + testnet
Real-time 1 week WebSocket data feed
Safety 1 week Risk manager + kill switch
Control 2 weeks Telegram + dashboard
Deploy 1 week VPS + monitoring
Live Ongoing Start with $100

Minimum Viable Production

pip install ccxt python-telegram-bot pyyaml asyncpg
# Simplest live trading loop
async def main():
    exchange = ccxt.binance({'apiKey': KEY, 'secret': SECRET})
    exchange.set_sandbox_mode(True)  # TESTNET!
    
    while True:
        df = await fetch_data()
        signal = strategy.generate_signal(df, position)
        
        if signal.is_entry and risk.check_trade():
            await executor.execute_market_order('buy', quantity)
            telegram.send(f"BUY executed at {price}")
            
        await asyncio.sleep(3600)  # Hourly

Cost

  • Infrastructure: ~$25/month
  • Trading fees: 0.1% per trade
  • Start capital: $100 minimum recommended