AgentSkillsCN

btc-trading-bot

比特币交易模拟,包含技术分析(EMA/RSI/布林带)、蒙特卡洛预测和Telegram提醒。重点关注柬埔寨市场(USD/KHR 4050)。 触发词:BTC回测、指标计算、恐惧与贪婪整合、加密策略开发、CoinGecko/Alternative.me API、投资组合模拟、追踪止损优化、夏普/最大回撤指标。 入口点:btc_trader.py(365天回测)、btc_simulation.py(60天蒙特卡洛)、backtest_runner.py(高级指标)。

SKILL.md
--- frontmatter
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

code
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

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

Strategy Matrix

ConditionElite (btc_trader)Pro (btc_simulation)
Trend EntryEMA12>26 ∧ RSI∈[50,70] ∧ FNG<80EMA12>26 ∧ RSI∈[50,75]
ContrarianPrice<BB_lower ∧ RSI<35 ∧ FNG<25
Exit: ReversalEMA12<26EMA12<26
Exit: Blow-offPrice>BB_upper ∧ RSI>75 ∧ FNG>80
Exit: Stop5% trailing5% trailing

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

Indicators

python
# 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

APIEndpointRate LimitTimeout
CoinGecko/coins/bitcoin/market_chart?vs_currency=usd&days=N~30/min10s
Alternative.me/fng/?limit=NGenerous10s

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

python
# 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.

python
# 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.

python
# 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.

python
# 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:

python
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:

code
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

python
# 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

python
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

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

Timezone-Safe Datetime

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

API with Retry

python
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

PitfallStatusFix
Lookahead bias✅ OKUses .shift() for signals
Survivorship bias✅ N/ASingle asset
Slippage/fees❌ MissingAdd 0.1% per trade
Position sizing❌ 100% alwaysImplement Kelly or fixed-fraction
Out-of-sample❌ MissingSplit train/test periods
python
# 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

FileRead When
references/strategies.mdStrategy modification, threshold tuning
references/indicators.mdAdding new indicators, formula verification
references/apis.mdAPI debugging, response schema lookup
scripts/utils.pyData 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