← 返回
未分类 Key 中文

Grid Trading

Dynamic grid trading strategy for any token pair on EVM L2 chains via OKX DEX API. Features asymmetric grid steps (buy-dense/sell-wide in bullish, reverse in...
基于OKX DEX API的EVM L2链任意交易对动态网格交易策略。特点为不对称网格步长(牛市时买入密集/卖出宽松,反向...)
synththoughts synththoughts 来源
未分类 clawhub v1.5.3 1 版本 100000 Key: 需要
★ 0
Stars
📥 788
下载
💾 6
安装
1
版本
#base#defi#grid#latest#okx#trading

概述

Dynamic Grid Trading Strategy v1.0

Cron-driven grid bot for EVM L2 chains via onchainos CLI. Features asymmetric grid steps — different spacing for buy vs sell sides based on trend direction, trend intelligence with multi-timeframe analysis, sell optimization, and HODL Alpha tracking.

Every tick: fetch price → MTF analysis → compute grid level → trend-adaptive decision → execute swap → report to Discord.

Asymmetric Grid Steps

Buy and sell sides use different spacing based on trend direction:

TrendBuy SideSell SideEffect
------------------------------------
BullishTighter (accumulate fast)Wider (hold longer)Buy dense, sell sparse → captures uptrend
BearishWider (wait for dip)Tighter (exit fast)Sell dense, buy sparse → reduces downside exposure
Neutral/WeakSymmetricSymmetricSymmetric (default)

Key config: ASYM_FACTOR=0.4 (max asymmetry ratio). Asymmetry scales with trend strength and only activates when strength > 0.3.

New grid dict fields: buy_step, sell_step (backward-compatible step = average). Level prices are now non-uniform: below center spaced by buy_step, above center by sell_step.

Architecture

Cron (5min) → Python script → onchainos CLI → OKX Web3 API → Chain
                  ↓                ↓
            grid_state.json    Wallet (TEE signing)
                  ↓
            ┌─────────────┐
            │ MTF Analysis │ ← price_history (288 bars = 24h)
            │ K-line ATR   │ ← okx-dex-market kline (1H × 24)
            └──────┬──────┘
                   ↓
            Trend-Adaptive Grid Decision
                   ↓
            Discord embed (notification)

OKX Skill Dependencies (command syntax defined in each skill, do not duplicate here):

  • okx-dex-swap — quote, approve, swap execution
  • okx-dex-market — K-line / OHLC data
  • okx-agentic-wallet — wallet switch, balance, contract-call (TEE signing)
  • okx-onchain-gateway — transaction simulation

Pipeline: Execution Steps

CRITICAL RULE: Steps MUST execute in order. Do NOT skip steps or proceed past a gate that has not been satisfied.

Step 1: Data Acquisition

Actions:

  1. Fetch ETH price via okx-dex-swap (swap quote)
  2. Fetch on-chain balances via okx-agentic-wallet (wallet balance)
  3. Update price_history (append, cap at 288 = 24h @ 5min)
  4. Detect external deposits/withdrawals (unexplained balance changes > $100)

Gate (ALL must pass):

  • [ ] Price is non-null and > 0
  • [ ] At least one balance (ETH or USDC) > 0
  • [ ] Circuit breaker not active (consecutive_errors < 5)
  • [ ] Stop not triggered (stop_triggered == null)

Step 2: Multi-Timeframe Analysis

Actions:

  1. Compute short EMA (25min / 5-bar), medium EMA (1h / 12-bar), long EMA (4h / 48-bar)
  2. Detect EMA alignment → trend direction (bullish / bearish / neutral) + strength (0-1)
  3. Detect 8h structure: split into 4 segments, check higher-highs/higher-lows → uptrend / downtrend / ranging
  4. Compute 1h and 4h momentum
  5. Fetch K-line data (1H candles, 24 bars) → compute ATR-based volatility (hourly cache)

Output: mtf dict, kline_vol float

def analyze_multi_timeframe(history, price) -> dict:
    # Returns {trend, strength, momentum_1h, momentum_4h, structure,
    #          ema_short, ema_medium, ema_long}
    # EMA alignment: short > medium > long → bullish
    # Structure: 8h window split into 4 segments
    #   higher-highs + higher-lows → "uptrend"
    #   lower-highs + lower-lows → "downtrend"
    #   else → "ranging"

Gate:

  • [ ] mtf dict has trend and strength fields (graceful fallback to neutral if insufficient history)

Step 3: Grid Decision

Actions:

  1. Calculate dynamic grid with trend-adaptive volatility multiplier:
    • Grid center = EMA(20) on 1H kline (20-hour EMA, fetched via okx-dex-market kline). Falls back to 5min tick history if kline unavailable.
    • Base: VOLATILITY_MULTIPLIER_BASE=2.0
    • In trend (strength > 0.3): blend toward VOLATILITY_MULTIPLIER_TREND=3.0
    • Wider grid in trends → fewer trades → more holding
  2. Check recalibration triggers (breakout / vol shift / age)
  3. Map price → grid level
  4. If level changed: determine direction (BUY if level dropped, SELL if rose)
  5. Safety checks: cooldown, trend-adaptive position limits, repeat guard, consecutive limit
  6. Sell optimization: if SELL in strong uptrend, delay via _should_delay_sell()
  7. Calculate trade size with trend-adaptive sizing

Gate:

  • [ ] Grid is valid (step > 0, levels > 0)
  • [ ] If trade needed: amount >= MIN_TRADE_USD ($5)
  • [ ] All safety checks passed (cooldown, position limits, etc.)

Step 4: Execution

Actions:

  1. Get swap quote + tx data from OKX DEX aggregator
  2. Pre-simulate via okx-onchain-gateway (diagnostic, non-blocking)
  3. For BUY: ensure USDC approval via okx-dex-swap
  4. Sign + broadcast via okx-agentic-wallet contract-call (TEE signing)
  5. On failure: 1 auto-retry with 3s delay and fresh quote
  6. Record trade in state, update grid level ONLY on success

Gate:

  • [ ] Transaction hash received, or failure recorded with retriable flag
  • [ ] Level updated only on success; NOT on failure or skip

Step 5: Notification & Tracking

Actions:

  1. Calculate PnL (USD + ETH denominated)
  2. Calculate HODL Alpha: current_portfolio - (initial_eth × current_price)
  3. Build structured JSON output for AI agent parsing
  4. Send Discord embed (green=SELL, blue=BUY, grey=no-trade, red=stop)
  5. Emit ---JSON--- block with enriched fields

Output: Discord notification + structured JSON

Tunable Parameters

Grid Structure

ParameterDefaultDescription
---------
GRID_LEVELS6Number of grid levels. More = finer, more trades
GRID_TYPE"arithmetic""arithmetic" (fixed $ step) or "geometric" (fixed % step)
EMA_PERIOD20EMA lookback for grid center (applied to 1H kline = 20h)
VOLATILITY_MULTIPLIER_BASE2.0Base grid width = multiplier x stddev
VOLATILITY_MULTIPLIER_TREND3.0Wider grid in trending markets
ASYM_FACTOR0.4Max buy/sell asymmetry ratio. 0=symmetric, 1=fully asymmetric
GRID_RECALIBRATE_HOURS12Max hours before forced recalibration

Multi-Timeframe

ParameterDefaultDescription
---------
MTF_SHORT_PERIOD55-bar EMA (25min @ 5min tick)
MTF_MEDIUM_PERIOD1212-bar EMA (1h @ 5min tick)
MTF_LONG_PERIOD4848-bar EMA (4h @ 5min tick)
MTF_STRUCTURE_PERIOD9696-bar (8h @ 5min tick) for structure detection

Sell Optimization

ParameterDefaultDescription
---------
SELL_TRAIL_TICKS2Wait 2 ticks (10min) of price stability before selling in uptrend
SELL_MOMENTUM_THRESHOLD0.005Skip sell if 1h momentum > 0.5% in strong uptrend

Grid Modes

Arithmetic (等差网格): Each level is a fixed USD distance apart. Good for narrow ranges.

levels = [center - N*step, ..., center, ..., center + N*step]

Geometric (等比网格): Each level is a fixed percentage apart. Better for wide ranges because step size scales with price. The ratio is derived from the arithmetic step: ratio = 1 + (step / center).

# In calc_dynamic_grid(), when GRID_TYPE == "geometric":
ratio = 1 + (step / center)
level_prices = [center * (ratio ** (i - half)) for i in range(GRID_LEVELS + 1)]

Both modes store level_prices in the grid dict for unified level lookup via bisect_right. Asymmetric spacing uses levels below center spaced by buy_step, levels above by sell_step. The _build_level_prices() helper handles both symmetric and asymmetric construction.

Choosing a mode:

MarketRecommendedWhy
---------
Tight range ($1900-$2100)ArithmeticEven spacing, predictable profit per grid
Wide range ($1500-$3000)GeometricSteps scale with price, avoids crowding at low end
High volatilityGeometricNaturally wider steps at higher prices
Stablecoin pairsArithmeticFixed small steps (0.1-0.5%)

Adaptive Step Sizing

Step scales with real-time volatility, modulated by trend strength. Splits into directional buy/sell steps:

vol_mult = VOLATILITY_MULTIPLIER_BASE  (2.0)
if trend_strength > 0.3:
    vol_mult = blend(BASE, TREND, strength)  (up to 3.0)

# Asymmetric steps based on trend direction
asym = ASYM_FACTOR × strength  (if strength > 0.3, else 0)
if bullish:
    buy_mult  = vol_mult × (1 - asym)   # tighter buy
    sell_mult = vol_mult × (1 + asym)   # wider sell
elif bearish:
    buy_mult  = vol_mult × (1 + asym)   # wider buy
    sell_mult = vol_mult × (1 - asym)   # tighter sell

buy_step  = (buy_mult × ATR) / (GRID_LEVELS / 2)
sell_step = (sell_mult × ATR) / (GRID_LEVELS / 2)
# Both clamped to [price × STEP_MIN_PCT, price × STEP_MAX_PCT], floor $5
step = (buy_step + sell_step) / 2  # backward-compatible average
ParameterDefaultDescription
---------
STEP_MIN_PCT0.010Step floor as fraction of price (1.0%)
STEP_MAX_PCT0.060Step cap as fraction of price (6%)
VOL_RECALIBRATE_RATIO0.3Recalibrate if kline ATR shifts >30% from grid's stored ATR

Recalibration triggers (asymmetric):

  1. Downside breakout: Price < grid lower - buy_step → recalibrate immediately (buying dips is grid's edge)
  2. Upside breakout: Price > grid upper + sell_step → require N consecutive ticks confirmation before recalibrating (anti-chase)
  3. Grid age exceeds GRID_RECALIBRATE_HOURS
  4. Current kline ATR deviates >30% from grid's stored ATR
ParameterDefaultDescription
---------
UPSIDE_CONFIRM_TICKS6Ticks (30min @ 5min interval) price must hold above grid before upside recalibration
MAX_CENTER_SHIFT_PCT0.03Max 3% grid center shift per recalibration (prevents chasing spikes)

Anti-chase mechanism:

  • Upside breakout counter resets if price returns to grid range before confirmation
  • Even after confirmation, center shifts are capped to MAX_CENTER_SHIFT_PCT per recalibration
  • Multiple recalibrations can gradually track a true trend, but a single spike cannot drag the grid

Position Sizing Strategies

Controls how much to trade at each grid level.

StrategyDescription
------
"equal"Every grid level trades the same amount
"martingale"BUY more at lower levels, SELL more at higher levels
"anti_martingale"Reduces exposure as price moves further from center
"pyramid"Largest position at grid center, tapering toward edges
"trend_adaptive"(default) In bullish: buy more + sell less. In bearish: sell more + buy less
def _calc_sizing_multiplier(level, grid_levels, direction, mtf=None):
    base_mult = 1.0
    if SIZING_STRATEGY == "trend_adaptive" and mtf:
        trend = mtf.get("trend", "neutral")
        strength = mtf.get("strength", 0)
        if trend == "bullish":
            if direction == "BUY":
                base_mult = 1.0 + strength * (MAX - 1.0)   # buy aggressively
            else:
                base_mult = 1.0 - strength * (1.0 - MIN)   # sell conservatively
        elif trend == "bearish":
            # opposite
            ...
    return clamp(base_mult, SIZING_MULTIPLIER_MIN, SIZING_MULTIPLIER_MAX)

Trade Execution

ParameterDefaultDescription
---------
MAX_TRADE_PCT0.12Max 12% of portfolio per trade (before sizing multiplier)
MIN_TRADE_USD5.0Minimum trade size in USD
SLIPPAGE_PCT1Slippage tolerance for DEX swap
GAS_RESERVE0.003Native token reserved for gas

Risk Controls

Basic Controls

ParameterDefaultDescription
---------
MIN_TRADE_INTERVAL180030min cooldown between same-direction trades
MAX_SAME_DIR_TRADES3Max consecutive same-direction trades
MAX_CONSECUTIVE_ERRORS5Circuit breaker threshold
COOLDOWN_AFTER_ERRORS3600Cooldown after circuit breaker trips
POSITION_MAX_PCT_DEFAULT70Block BUY when ETH > this %
POSITION_MIN_PCT_DEFAULT30Block SELL when ETH < this %
POSITION_MAX_PCT_BULLISH80Allow more ETH in bullish trend
POSITION_MIN_PCT_BEARISH25Allow less ETH in bearish trend

Additional safety guards:

  • Rapid drop protection: skip BUY if price dropped >2% in last 30min (6 ticks)
  • Consecutive same-direction reset: limit resets if grid was recalibrated or >1h since last trade
  • Anti-repeat: skip if same direction + same level boundary as last trade
  • Trend-adaptive position limits: limits shift based on trend direction and strength

Stop-Loss, Trailing Stop & Take-Profit

Three protection mechanisms. When triggered, trading halts and a red Discord alert is sent. Use resume-trading command to clear.

ParameterDefaultDescription
---------
STOP_LOSS_PCT0.15Stop if portfolio drops 15% below cost basis
TRAILING_STOP_PCT0.10Stop if portfolio drops 10% from peak
def _check_stop_conditions(state, total_usd, price):
    cost_basis = initial + deposits
    pnl_pct = (total_usd - cost_basis) / cost_basis
    peak = max(stats["portfolio_peak_usd"], total_usd)
    # Check: stop_loss, trailing_stop, take_profit

Risk Control Flow in tick()

1. If stop_triggered is set → log + Discord red alert + refuse trading + return
2. Check _check_stop_conditions → if triggered, set stop_triggered + alert + return
3. Multi-timeframe analysis → get trend context
4. Normal grid logic (cooldown, trend-adaptive position limits, etc.)
5. If SELL in strong uptrend → _should_delay_sell() check

Core Algorithm

1. Fetch token price
2. Read on-chain balances (ETH + USDC)
3. Multi-timeframe analysis → trend/strength/momentum/structure
4. Fetch K-line ATR volatility (hourly cache)
5. Check if grid needs recalibration (breakout / vol shift / age)
   → calc_dynamic_grid() uses trend-adaptive volatility multiplier
   → asymmetric buy_step/sell_step based on trend direction
6. Map price → grid level
7. If level changed:
   a. Direction: BUY if level dropped, SELL if rose
   b. If SELL in strong uptrend → delay check (trailing + momentum protection)
   c. Safety checks (cooldown, trend-adaptive position limits, repeat guard, consecutive limit)
   d. Calculate trade size (trend-adaptive sizing)
   e. Execute swap via DEX aggregator
   f. Record trade, update level ONLY on success
8. Calculate HODL Alpha
9. Report status (JSON + Discord)

Grid Calculation

def calc_dynamic_grid(price, price_history, mtf=None):
    center = EMA(1H_kline, EMA_PERIOD)  # 20-hour EMA on 1H candles
    atr = calc_kline_volatility(candles)

    # Trend-adaptive multiplier
    vol_mult = VOLATILITY_MULTIPLIER_BASE  # 2.0
    if mtf and mtf["strength"] > 0.3:
        vol_mult = blend(BASE=2.0, TREND=3.0, factor=strength)

    # Asymmetric buy/sell multipliers
    asym = ASYM_FACTOR * strength if strength > 0.3 else 0
    if bullish:
        buy_mult = vol_mult * (1 - asym)   # tighter buy grid
        sell_mult = vol_mult * (1 + asym)   # wider sell grid
    elif bearish:
        buy_mult = vol_mult * (1 + asym)   # wider buy grid
        sell_mult = vol_mult * (1 - asym)   # tighter sell grid

    buy_step = clamp((buy_mult * atr) / half, floor, ceil)
    sell_step = clamp((sell_mult * atr) / half, floor, ceil)

    # Build asymmetric level_prices via _build_level_prices()
    # Below center: spaced by buy_step; Above center: spaced by sell_step
    level_prices = _build_level_prices(center, buy_step, sell_step, half, grid_type)

    return {center, step, buy_step, sell_step, levels, range, vol_pct, type, level_prices}

Examples (at price $2000, ATR=$50):

TrendStrengthbuy_stepsell_stepBuy RangeSell RangeBehavior
---------------------
Neutral0.1$33$33$1901-$2000$2000-$2099Symmetric, normal
Bullish0.6$33$54$1901-$2000$2000-$2162Buy dense + sell wide
Bearish0.6$54$33$1838-$2000$2000-$2099Buy wide + sell dense
Strong Bull0.9$24$66$1928-$2000$2000-$2198Max asymmetry

Sell Optimization Logic

def _should_delay_sell(state, current_level, prev_level, mtf, history):
    """Returns skip reason or None."""

    # 1. Momentum protection: skip sell if 1h momentum > 0.5% in uptrend
    if momentum_1h > SELL_MOMENTUM_THRESHOLD * 100:
        if trend == "bullish" and structure == "uptrend":
            return "trend_hold (momentum +X.X%)"

    # 2. Trailing sell: wait SELL_TRAIL_TICKS (2) before executing
    trail = state["sell_trail_counter"]
    level_key = f"{prev_level}->{current_level}"
    if trail[level_key] < SELL_TRAIL_TICKS:
        trail[level_key] += 1
        return "sell_trail (N/2)"

    # 3. Cleared → proceed with sell
    return None

Trend-Adaptive Position Limits

def _get_position_limits(mtf):
    """Return (max_pct, min_pct) based on trend."""
    if trend == "bullish" and strength > 0.3:
        max_pct = 70 + (80 - 70) * strength  # allow more ETH
        min_pct = 30
    elif trend == "bearish" and strength > 0.3:
        max_pct = 70
        min_pct = 30 - (30 - 25) * strength  # allow less ETH
    else:
        max_pct, min_pct = 70, 30

Trade Size

Returns (amount_in_smallest_unit, failure_info). SELL returns wei (x1e18), BUY returns uUSDC (x1e6).

def calc_trade_amount(direction, eth_bal, usdc_bal, price,
                      current_level=None, grid_levels=None,
                      mtf=None):
    available_eth = eth_bal - GAS_RESERVE_ETH
    total_usd = available_eth * price + usdc_bal
    max_usd = total_usd * MAX_TRADE_PCT

    # Apply trend-adaptive sizing
    multiplier = _calc_sizing_multiplier(level, grid_levels, direction, mtf)
    max_usd *= multiplier

    if direction == "SELL":
        return int(min(max_usd / price, available_eth) * 1e18), None  # wei
    else:
        return int(min(max_usd, usdc_bal * 0.95) * 1e6), None  # uUSDC

Level Update Rule (Critical)

OutcomeUpdate level?Rationale
---------
Trade succeededYesGrid crossing consumed
Trade failedNoRetry on next tick
Trade skipped (cooldown/limit)NoDon't lose the crossing
Sell delayed (trailing/momentum)NoWill retry next tick

PnL Tracking (dual-denominated)

# USD-denominated
total_pnl_usd = current_portfolio_usd - cost_basis
hodl_value_usd = initial_eth_amount × current_price
grid_alpha_usd = current_portfolio_usd - hodl_value_usd

# ETH-denominated
current_eth_equivalent = current_portfolio_usd / current_price
initial_eth_equivalent = cost_basis / initial_price
total_pnl_eth = current_eth_equivalent - initial_eth_equivalent

HODL Alpha (key metric): grid_alpha_usd > 0 means grid outperforms pure ETH holding.

State Schema

{
  "version": 5,
  "grid": {"center": 2000, "step": 43.5, "buy_step": 33.3, "sell_step": 53.7,
           "levels": 6, "range": [1900, 2161], "vol_pct": 2.1,
           "type": "arithmetic",
           "level_prices": [1900, 1933, 1967, 2000, 2054, 2107, 2161]},
  "grid_set_at": "ISO timestamp",
  "current_level": 3,
  "price_history": ["...max 288 (24h at 5min)"],
  "trades": [{"time": "...", "direction": "SELL", "price": 2050,
              "amount_usd": 25, "est_profit": 1.5, "tx": "0x...",
              "grid_from": 2, "grid_to": 3}],
  "stats": {
    "total_trades": 15,
    "realized_pnl": 5.2,
    "grid_profit": 3.8,
    "initial_portfolio_usd": 1000,
    "initial_eth_price": 2000.0,
    "portfolio_peak_usd": 1050.0,
    "total_deposits_usd": 0.0,
    "deposit_history": [],
    "trade_attempts": 10, "trade_successes": 10, "trade_failures": 0,
    "sell_attempts": 5, "sell_successes": 5,
    "buy_attempts": 5, "buy_successes": 5,
    "retry_attempts": 0, "retry_successes": 0,
    "started_at": "ISO timestamp",
    "last_check": "ISO timestamp"
  },
  "stop_triggered": null,
  "last_trade_times": {"BUY": "...", "SELL": "..."},
  "last_failed_trade": null,
  "last_balances": {"eth": 0.134, "usdc": 257.33, "time": "ISO timestamp"},
  "last_quiet_report": "ISO timestamp",
  "upside_breakout_ticks": 0,
  "approved_routers": ["0x..."],
  "errors": {"consecutive": 0, "cooldown_until": null},
  "mtf_cache": null,
  "kline_cache": null,
  "sell_trail_counter": {}
}

Key fields:

  • grid.type + grid.level_prices: geometric/arithmetic grid support (asymmetric spacing)
  • grid.buy_step / grid.sell_step: directional step sizes; grid.step = average for backward compat
  • stats.initial_eth_price: records ETH price at bot start for HODL Alpha calculation
  • stats.portfolio_peak_usd: highest portfolio value (for trailing stop)
  • stop_triggered: string describing trigger condition, or null
  • last_failed_trade: cached for retry command (expires after 10min)
  • upside_breakout_ticks: confirmation counter for upside recalibration
  • approved_routers: USDC approval cache to avoid redundant approvals
  • mtf_cache: cached multi-timeframe analysis result
  • kline_cache: cached K-line data (1h TTL)
  • sell_trail_counter: tracks sell delay tick counts per level transition

Operational Interface

Sub-Commands

CommandPurposeTrigger
---------
tickMain loop: price → MTF → grid → trade → reportCron every 5min
statusPrint current grid state, balances, PnL, trendOn demand
reportGenerate daily performance report (Chinese)Cron daily 08:00 CST
historyShow recent trade historyOn demand
resetReset grid (recalibrate from scratch), keep trade historyManual
retryRetry last failed trade with fresh quote (expires after 10min)AI agent / manual
analyzeOutput detailed market + MTF + round-trip analysis JSONAI agent
depositManually record deposit/withdrawal for PnL trackingManual
resume-tradingClear stop_triggered flag and resume tradingManual / AI agent
COMMANDS = {
    "tick": tick, "status": status, "report": report,
    "history": history_cmd, "reset": reset, "retry": retry,
    "analyze": analyze, "deposit": deposit,
    "resume-trading": resume_trading
}
if __name__ == "__main__":
    cmd = sys.argv[1] if len(sys.argv) > 1 else "tick"
    COMMANDS.get(cmd, tick)()

AI Agent Output Protocol

The tick command outputs a structured JSON block for AI agent parsing:

---JSON---
{
  "version": "1.0",
  "status": "trade_executed" | "no_trade" | "cooldown" | "trade_failed" | ...,
  "market": {
    "price": 2090.45, "ema": 2085.3, "volatility_pct": 1.2,
    "trend": "bullish", "trend_strength": 0.65,
    "momentum_1h": 0.35, "momentum_4h": 1.2,
    "structure": "uptrend",
    "kline_atr_pct": 1.8
  },
  "portfolio": {"eth": 0.134, "usdc": 257.33, "total_usd": 538.0, "eth_pct": 52.1},
  "grid_level": 3,
  "direction": "SELL",
  "tx_hash": "0x...",
  "failure_reason": "...",
  "retriable": true,
  "hodl_alpha": 2.15,
  "success_rate": {"total_attempts": 182, "successes": 182, "rate_pct": 100.0}
}

The analyze command outputs additional fields:

  • multi_timeframe: full MTF data (EMA short/medium/long, momentum, structure)
  • round_trips: trade pair analysis (good / micro / loss classification)

Discord Notification

Two card formats pushed via Discord Bot API:

Trade executed (colored embed):

  • Green = SELL, Blue = BUY
  • Fields: price, level, total value, position, PnL, grid profit, HODL Alpha, BaseScan link

No trade (grey compact card):

  • One-line: price . level . position . PnL . trend . trade count
  • Only sent once per QUIET_INTERVAL (default 1 hour)

Deposit/Withdrawal Detection

Automatically detects external balance changes:

unexplained_change = (current_balance - last_balance) - sum(recorded_trades_since_last)
if abs(unexplained_change) > $100:
    record as deposit or withdrawal → adjust PnL cost basis

Logging

  • File: grid_bot.log in script directory
  • Rotation: simple half-file rotation at 1MB
  • Format: [YYYY-MM-DD HH:MM:SS] message

Adapting to Different Pairs

ConsiderationWhat to adjust
------
Token decimalsUSDC=6, DAI=18, WBTC=8 — affects amount conversion
Typical volatilityBTC lower vol → smaller STEP_MIN/MAX_PCT; meme coins → larger
Liquidity depthLow liquidity → smaller MAX_TRADE_PCT, add price impact check
Gas costsL1 vs L2: adjust GAS_RESERVE and MIN_TRADE_USD
Stablecoin pairTOKEN/USDC pair: STEP_MIN_PCT can be much tighter (0.2%)
Rate limitsAdd 300-500ms delay between consecutive OKX API calls

AI Review & Optimization

AI agent should periodically review trading performance and suggest/apply optimizations. Run weekly or when cumulative PnL stalls.

Step 1: Pull & Pair Trades

Extract recent trades and pair each BUY with its corresponding SELL to form round trips.

# Matching logic: SELL from level A→B matches BUY from level B→A
buy_stack = []
round_trips = []
for trade in trades:
    if trade["direction"] == "BUY":
        buy_stack.append(trade)
    else:  # SELL
        for j in range(len(buy_stack)-1, -1, -1):
            if buy_stack[j]["grid_to"] == trade["grid_from"]:
                matched_buy = buy_stack.pop(j)
                round_trips.append((matched_buy, trade))
                break

Output per round trip:

  • Spread: (sell_price - buy_price) / buy_price x 100%
  • Hold time: minutes between buy and sell
  • Status: profit (spread > 0.3%), micro-profit (0 < spread < 0.3%), loss (spread < 0)

Step 2: Flag Anomalies

FlagConditionMeaning
---------
LOSSspread < 0Bought high, sold low
MICRO0 < spread < 0.3%Profit too small to cover DEX costs
GOODspread >= 0.3%Healthy grid profit

Key metrics: win rate, loss impact, micro-trade ratio (if > 30%, step too small).

Step 3: Root Cause Analysis

LOSS trades:

PatternRoot CauseFix
---------
Buy @high, sell @low after recalibrationGrid chased a spikeIncrease UPSIDE_CONFIRM_TICKS, reduce MAX_CENTER_SHIFT_PCT
Buy @high in trend, sell @low on reversalEMA too reactiveIncrease EMA_PERIOD or GRID_RECALIBRATE_HOURS
Loss during flash crashStop-loss too looseTighten STOP_LOSS_PCT

MICRO trades:

PatternRoot CauseFix
---------
Many trades with < 0.2% spreadStep too smallIncrease STEP_MIN_PCT
Rapid back-and-forth at same levelsLow vol, grid too denseIncrease MIN_TRADE_INTERVAL
Trades cluster in 5-10 min windowsCooldown too shortIncrease MIN_TRADE_INTERVAL

Step 4: Parameter Tuning

STEP_MIN_PCT >= DEX_total_cost x 3
  where DEX_total_cost ~ slippage + price_impact ~ 0.1-0.3% on L2
  → STEP_MIN_PCT >= 0.009 to 0.012

UPSIDE_CONFIRM_TICKS = typical_spike_duration / tick_interval
  e.g., spikes last ~20min, tick=5min → confirm_ticks = 4-6

MAX_CENTER_SHIFT_PCT = step_pct x 2-3

Step 5: Backtest & Apply

Simulate new parameters against historical data, then: backup → patch → recalibrate → monitor 24h → re-run analysis.

Review Checklist (AI Agent Prompt)

1. Read grid_state.json and grid_bot.log
2. Filter trades to review window (default: last 48h)
3. Pair trades into round trips
4. Compute: win_rate, avg_spread, loss_count, micro_count, total_pnl, hodl_alpha
5. If loss_count > 0: trace each loss to recalibration events
6. If micro_ratio > 30%: recommend STEP_MIN_PCT increase
7. Check MTF data for trend alignment during losses
8. Propose specific parameter changes with backtest evidence
9. On user approval: backup → patch → recalibrate → verify

Failure & Rollback

IF Step N fails:
  1. Log failure reason to grid_bot.log
  2. Increment errors.consecutive
  3. If errors.consecutive >= 5: trigger circuit breaker (1h cooldown)
  4. Cache failed trade for retry command (10min expiry)
  5. DO NOT update grid level
  6. Report failure via Discord + JSON output

Anti-Patterns

PatternProblem
------
Recalibrate every tickGrid oscillates, no stable levels
Update level on failure/skipSilently loses grid crossings
No position limitsTrending market → 100% one-sided
Fixed step in volatile marketToo small → over-trades; too large → never triggers
sell - buy as PnLNet cash flow ≠ profit
No cooldownRapid swings cause burst of trades eating slippage
No stop-lossSingle crash wipes out months of grid profits
Martingale without capExponential position growth → liquidation risk
Arithmetic grid on wide range$20 step meaningless at $5000 but huge at $500
Symmetric recalibrationChasing upside spikes = buying high then selling low on reversal
Step floor too lowMicro-profit trades only feed DEX fees, net negative after costs
No center shift capSingle spike can drag grid center 5%+, creating losing positions
Fixed sizing in trendsSelling same size in uptrend = giving away alpha to the market
Selling immediately in uptrendSell delay exists for a reason — let trends play out
Symmetric grid in strong trendsAsymmetric grids accumulate faster on the favorable side
Ignoring buy_step/sell_step in profit calcUse actual level_prices differences, not average step

版本历史

共 1 个版本

  • v1.5.3 当前
    2026-03-30 02:22 安全 安全

安全检测

腾讯云安全 (Keen)

安全,无风险
查看报告

腾讯云安全 (Sanbu)

安全,无风险
查看报告

🔗 相关推荐

business-ops

Cl Lp Rebalancer

synththoughts
Uniswap V3 集中流动性 LP 自动调仓策略。基于波动率自适应范围宽度,低波动收紧提升资本效率,高波动放宽减少调仓和 IL。支持趋势不对称调整、多时间框架分析、全自动 claim/remove/swap/deposit。适用于 EV
★ 0 📥 843
professional

Stock Analysis

udiedrichsen
{"answer":"基于雅虎财经数据,分析股票与加密货币。支持投资组合管理、自选股预警、股息分析、8维评分、热门趋势扫描及传闻/早期信号探测。适用于股票分析、持仓追踪、财报异动、加密监控、热门股追踪或提前发掘非主流传闻。"}
★ 277 📥 57,623
professional

A股量化 AkShare

mbpz
A股量化数据分析工具,基于AkShare库获取A股行情、财务数据、板块信息等。用于回答关于A股股票查询、行情数据、财务分析、选股等问题。
★ 191 📥 62,608