Closed Beta — Demo trading only. No real funds. Help us find bugs!
    BETA
    FeaturesPricingAbout
    Sign InJoin Beta

    Developer Docs

    Getting StartedBot EnginesExchange IntegrationsArchitectureSecurityDatabaseDeploymentTesting

    User Guide

    Getting StartedTrading BotsAI BotDCA BotSignal BotArbitrage BotPump BotScalping BotGrid BotCombo BotTradingDeFiPortfolioMarketplaceSubscriptionsSettingsAdmin

    Bot Engine Deep Dive

    Overview

    BlockbotX supports eight bot types, each with a dedicated execution engine, API routes, and UI dashboard:

    Bot TypeEngine FileDescription
    AI Botbot-executor.tsTechnical analysis with configurable strategies
    DCA Botdca-bot.tsDollar-cost averaging at fixed intervals
    Signal Botsignal-bot.tsExternal signal following (webhook, Telegram)
    Arbitrage Botarbitrage-bot.tsCross-exchange price differential detection
    Pump Botpump-screener.tsVolume spike and price surge detection
    Scalping Botscalping-manager.tsHigh-frequency micro-profit trades
    Grid Botbot-executor.tsGrid trading on price oscillations
    Combo Botbot-executor.tsMulti-strategy orchestration

    All bots execute through a central scheduler (scheduler.ts) that manages execution timing and delegates to the appropriate engine. Redis distributed locks prevent duplicate concurrent executions of the same bot.


    Execution Pipeline

    The full execution flow proceeds as a numbered sequence:

    1. Scheduler polls every 60 seconds. The BotScheduler singleton runs checkAndExecute() on a 60-second setInterval, comparing each bot's nextExecutionAt against the current time.

    2. Identifies bots where nextExecutionAt <= now. The scheduler iterates its in-memory scheduledBots map and collects all bots due for execution.

    3. Acquires Redis lock (bot:execution:lock:{botId}, 120-second TTL). The acquireExecutionLock() function uses redis.set(lockKey, "locked", "EX", 120, "NX"). If the lock cannot be acquired (another instance is already executing), the bot is skipped. If Redis is unavailable, execution proceeds without a lock but logs a warning.

    4. Routes to the appropriate engine by bot type. The executeBot() function normalizes bot.type to lowercase and dispatches:

      • "dca" --> DCABot
      • "arbitrage" --> ArbitrageBot
      • "pump" --> PumpScreener
      • "signal" --> skipped by scheduler (processed via API endpoint)
      • All others --> AI/Strategy bot flow (the default)
    5. Engine executes strategy/scan. Each engine runs its core logic: strategy analysis for AI bots, price scanning for arbitrage, market scanning for pump screener, or scheduled purchase logic for DCA.

    6. Risk validation (pre-trade checks). For AI/Strategy bots, the validateTrade() function checks: max open positions, daily trade limit, daily loss limit, max drawdown, position size, balance sufficiency, and signal confidence.

    7. Trade execution (paper or live). Based on bot.paperTrading, trades execute through either the PaperTradingEngine (simulated) or real exchange APIs (Binance, OKX) via placeMarketOrder().

    8. Position tracking update. New BUY trades create Position records in both the in-memory PositionManager and the database. Existing positions are checked for stop-loss and take-profit triggers.

    9. Execution record saved to database. An Execution record is created with signal action, confidence, reason, price, indicators, and status.

    10. Lock released. The finally block calls releaseLock() to delete the Redis key, ensuring the lock is always released even if an error occurs.


    Bot Types

    AI/Strategy Bot

    The AI/Strategy bot is the most comprehensive bot type. It uses technical analysis strategies to generate BUY, SELL, or HOLD signals.

    Strategy Factory Pattern:

    The createStrategy() function in strategy-factory.ts accepts a BotConfig and returns the appropriate BaseStrategy subclass:

    // lib/bot/strategies/strategy-factory.ts
    export function createStrategy(config: BotConfig): BaseStrategy {
      switch (config.strategy) {
        case "trend_following":
          return new TrendFollowingStrategy(config.strategyParams);
        case "mean_reversion":
          return new MeanReversionStrategy(config.strategyParams);
        case "breakout":
          return new BreakoutStrategy(config.strategyParams);
        default:
          throw new Error(`Unsupported strategy type: ${config.strategy}`);
      }
    }
    

    Each strategy implements an analyze(context: ExecutionContext) method that returns a Signal with action (BUY/SELL/HOLD), confidence (0-100), reason, price, and indicator values.

    Execution Flow (AI/Strategy):

    1. Load bot configuration and normalize strategy name (e.g., "trend following" -> "trend_following").
    2. Check exchange connection availability for live trading.
    3. Decrypt API keys from ExchangeConnection using AES-256-GCM.
    4. Fetch 100 candles from Binance for the configured trading pair and timeframe.
    5. Build ExecutionContext with candles, indicators, positions, and balance.
    6. Check existing positions for stop-loss and take-profit triggers (including trailing stop updates).
    7. Run strategy analysis to generate a Signal.
    8. If signal is BUY or SELL, calculate position size, validate trade against risk rules, and execute.
    9. Record execution and update lastExecutionAt.

    Concurrency Control:

    The executeBots() function processes bots in batches with a configurable concurrency limit (default: 5) to avoid overwhelming exchange rate limits. Batches run in parallel via Promise.allSettled().

    DCA Bot

    Dollar-cost averaging buys a fixed amount of an asset at regular intervals regardless of price.

    Configuration:

    // lib/bot/engine/dca-bot.ts
    export interface DCAConfig {
      tradingPair: string;
      investmentAmount: number;    // Amount in quote currency (e.g., USDT)
      frequency: "hourly" | "daily" | "weekly" | "monthly";
      frequencyValue: number;      // e.g., every 2 weeks
      startDate: string;
      endDate?: string;
      maxTotalInvestment?: number;
      orderType: "market" | "limit";
      limitPriceOffset?: number;
    }
    

    shouldExecute() Checks:

    1. Bot must be active.
    2. Current date must be past startDate.
    3. If endDate is set, current date must not exceed it (auto-stops bot).
    4. If maxTotalInvestment is set, total invested must not exceed it (auto-stops bot).
    5. Time since lastExecutionAt must exceed the configured interval.

    Execution:

    • Fetches current price from the user's Binance connection.
    • Calculates quantity as investmentAmount / price.
    • For paper trading: records trade with 0.1% simulated fee.
    • For live trading: validates order, places market buy using quoteOrderQty (spend a fixed USDT amount), and records the trade with actual fill data.
    • Updates lastExecutionAt on the bot record.

    Arbitrage Bot

    Detects and optionally executes cross-exchange price differentials.

    Configuration:

    // lib/bot/engine/arbitrage-bot.ts
    export interface ArbitrageConfig {
      exchanges: string[];           // e.g., ["binance", "okx"]
      tradingPairs: string[];        // e.g., ["BTCUSDT", "ETHUSDT"]
      minProfitPercent: number;      // Minimum profit threshold
      maxTradeAmount: number;        // Maximum amount per trade
      includeTransferFees: boolean;  // Account for transfer fees
      transferFeePercent: number;    // Average transfer fee
      executionMode: "auto" | "notify";
      checkIntervalSeconds: number;
    }
    

    Price Scanning:

    The scanOnce() method (called by bot-executor.ts during scheduled execution) fetches prices from all configured exchanges and compares every pair of exchanges for each trading pair in both directions.

    • Binance prices: Fetched via the authenticated user client using client.prices().
    • OKX prices: Fetched via the public API (no auth needed) using getOkxPrices(). Symbol format is converted between Binance (BTCUSDT) and OKX (BTC-USDT) using binanceToOkx().

    Opportunity Calculation:

    The calculateOpportunity() method accounts for:

    • 0.1% trading fee per side (buy and sell).
    • Configurable transfer fee percentage (if includeTransferFees is true).
    • Net profit = (sellPrice * (1 - fee)) - (buyPrice * (1 + fee)) - transferFee.
    • Only positive-profit opportunities are returned.

    Execution Modes:

    • notify: Records the opportunity as an execution with signal ARBITRAGE_NOTIFY. No trades are placed.
    • auto: Executes trades via ArbitrageExecutionCoordinator (for live) or records paper trades with simulated buy/sell pairs. Live execution includes an ArbitrageRiskManager circuit breaker with configurable max position size, max daily loss, max consecutive failures, min profit threshold, max slippage, and max execution time.

    Signal Bot

    Receives and executes trading signals from external providers.

    Configuration:

    // lib/bot/engine/signal-bot.ts
    export interface SignalConfig {
      tradingPairs: string[];
      positionSizeType: "fixed" | "percentage";
      positionSize: number;
      maxOpenPositions: number;
      followStopLoss: boolean;
      followTakeProfit: boolean;
      stopLossPercent?: number;
      takeProfitPercent?: number;
      signalProviders: SignalProvider[];
    }
    
    export interface SignalProvider {
      id: string;
      type: "telegram" | "discord" | "manual" | "webhook";
      name: string;
      enabled: boolean;
      config: {
        channelId?: string;
        webhookUrl?: string;
        apiKey?: string;
      };
    }
    

    Signal Processing:

    Signal bots are not executed by the scheduler. Instead, signals arrive via the send-signal API endpoint and are processed by processSignal():

    1. Validate the signal (must have symbol and valid action: BUY, SELL, or CLOSE).
    2. Verify the trading pair is in the bot's allowed list.
    3. For BUY: check maxOpenPositions limit, calculate position size (fixed or percentage of balance), determine stop-loss/take-profit (from signal or config defaults), and execute.
    4. For SELL/CLOSE: find the open position for the symbol, execute the sell, calculate P&L, and close the position record.

    Provider Types:

    • Telegram: Messages are parsed by parseTelegramSignal(), which supports formats like BUY BTCUSDT @ 45000 and LONG BTC Entry: 45000 SL: 44000 TP: 47000.
    • Webhook: External services POST signals directly to the API.
    • Discord: Similar to Telegram with channel-based signal parsing.
    • Manual: User-submitted signals through the UI.

    Position Size Calculation:

    • "fixed": Uses the configured positionSize as the dollar amount.
    • "percentage": Calculates balance * (positionSize / 100) using either the paper trading balance (from database) or the real Binance account balance.

    Pump Screener

    Detects sudden volume spikes and price surges across the market.

    Configuration:

    // lib/bot/engine/pump-screener.ts
    export interface PumpScreenerConfig {
      priceChangePercent: number;    // Minimum price change % to trigger (default: 5)
      volumeMultiplier: number;      // Volume must be X times average (default: 3)
      timeframeMinutes: number;      // Timeframe to measure changes (default: 15)
      minVolume: number;             // Minimum 24h volume in USDT (default: 100000)
      excludeSymbols: string[];
      onlySymbols: string[];         // If set, only monitor these symbols
      autoTrade: boolean;
      tradeAmount: number;           // Amount to trade in USDT
      takeProfitPercent: number;
      stopLossPercent: number;
      checkIntervalSeconds: number;
    }
    

    Detection Logic:

    The scanOnce() method (called by the scheduler):

    1. Fetches 24h ticker data from Binance (dailyStats()).
    2. Filters by: minimum volume, USDT pairs only, exclude/only symbol lists.
    3. Updates an in-memory price history for each symbol.
    4. For each symbol, compares current price to the oldest price in the history window:
      • If priceChangePercent >= config.priceChangePercent and volumeMultiplier >= config.volumeMultiplier, a pump is detected.
    5. Records detection as an execution with signal PUMP_DETECTED and confidence scaled by price change magnitude.

    Auto-Trade:

    When autoTrade is enabled, the screener automatically enters positions on pump detection:

    • Calculates quantity as tradeAmount / currentPrice.
    • Sets stop-loss and take-profit based on configured percentages.
    • Executes via paper or live trading.
    • Creates a position record with SL/TP for monitoring.

    Trading Strategies

    Trend Following

    File: lib/bot/strategies/trend-following.ts

    Uses EMA (Exponential Moving Average) crossovers with volume confirmation and multi-timeframe analysis.

    BUY Signal Logic:

    1. Fast EMA crosses above Slow EMA (bullish crossover).
    2. Volume must be above the threshold multiplier times the 20-period average volume.
    3. Higher timeframe trend must not be bearish (candles are aggregated by 4x factor to synthesize a higher timeframe).
    4. Optional strong uptrend continuation entry: if Fast EMA is more than 1% above Slow EMA with volume confirmation and a consistent uptrend.

    SELL Signal Logic:

    1. Fast EMA crosses below Slow EMA (bearish crossover).
    2. Price drops more than 2% below Slow EMA (trend reversal).

    Confidence Calculation:

    • Base confidence of 60 for crossover detection.
    • Bonuses for: strong EMA spread (>0.5% or >1%), high volume ratio (>1.5x or >2x), consistent uptrend, higher timeframe alignment (+10).
    • Capped at 100.

    Configurable Parameters:

    ParameterDefaultDescription
    fastEMA9Short EMA period
    slowEMA21Long EMA period
    volumeThreshold1.2Volume must be X times 20-bar average
    confirmationCandles1Candles to wait for confirmation

    Mean Reversion

    File: lib/bot/strategies/mean-reversion.ts

    Combines RSI (Relative Strength Index) with Bollinger Bands to identify oversold/overbought conditions.

    BUY Signal Logic:

    1. Primary: RSI below oversold level + price at or below lower Bollinger Band + bounce confirmation (current price > previous close).
    2. Secondary: RSI crossing back above oversold level + price near lower band (%B < 0.2).
    3. Tertiary: Extreme oversold (RSI < oversold - 5) with %B < 0.15.

    SELL Signal Logic:

    1. RSI reaches overbought level (mean reversion target reached).
    2. Price at or above upper Bollinger Band.
    3. Price returns to middle Bollinger Band (conservative exit when RSI > 50).
    4. RSI crosses back above oversold while position is still losing (cut loss).

    Configurable Parameters:

    ParameterDefaultDescription
    rsiPeriod14RSI calculation period
    oversoldLevel30RSI threshold for oversold
    overboughtLevel70RSI threshold for overbought
    bollingerPeriod20Bollinger Bands period
    bollingerStdDev2Standard deviations for bands

    Breakout

    File: lib/bot/strategies/breakout.ts

    Detects Bollinger Band breakouts with volume confirmation and squeeze detection.

    BUY Signal Logic:

    1. Price breaks above the upper Bollinger Band (previous close was below, current is above).
    2. Volume must exceed volumeMultiplier times the 20-period average.
    3. Confirmation candles must show pressure near the upper band.
    4. Bonus confidence for recent Bollinger squeeze (bandwidth < 2%) and trending up.
    5. Continuation entry: price already walking the upper band with sustained volume.

    SELL Signal Logic:

    1. Price breaks below the lower Bollinger Band (aggressive exit, confidence >= 80).
    2. Price drops below the middle Bollinger Band (momentum faded).
    3. Three consecutive declining candles with price retreating from the upper band.

    Configurable Parameters:

    ParameterDefaultDescription
    bollingerPeriod20Bollinger Bands period
    bollingerStdDev2Standard deviations for bands
    volumeMultiplier1.5Volume must be X times 20-bar average
    confirmationCandles1Candles to confirm breakout

    Key Type Definitions

    The following interfaces from lib/bot/types.ts define the core data structures used throughout the bot system.

    BotConfig

    export interface BotConfig {
      strategy: "trend_following" | "mean_reversion" | "breakout";
      tradingPair: string;         // e.g., "BTCUSDT"
      timeframe: "1m" | "5m" | "15m" | "30m" | "1h" | "4h" | "1d";
      paperTrading: boolean;
      strategyParams: StrategyParams;
      executionInterval?: number;  // Minutes between executions, default 5
      enableStopLoss: boolean;
      enableTakeProfit: boolean;
      trailingStop?: boolean;
    }
    

    Signal

    export interface Signal {
      action: "BUY" | "SELL" | "HOLD";
      confidence: number;          // 0-100
      price: number;               // Current market price
      quantity?: number;            // Suggested quantity (optional)
      reason: string;              // Human-readable explanation
      indicators: IndicatorValues; // Indicator values that led to this signal
      metadata?: Record<string, unknown>;
    }
    

    ExecutionContext

    export interface ExecutionContext {
      bot: {
        id: string;
        userId: string;
        name: string;
        config: BotConfig;
        riskSettings: RiskSettings;
      };
      symbol: string;
      timeframe: string;
      candles: Candle[];           // Historical candles (100-500 bars)
      currentPrice: number;
      currentVolume?: number;
      indicators: IndicatorValues;
      positions: Position[];
      balance: {
        asset: string;             // e.g., "USDT"
        free: number;
        locked: number;
        total: number;
      };
      apiKey: string;
      apiSecret: string;
      executionId: string;
      timestamp: Date;
    }
    

    RiskSettings

    export interface RiskSettings {
      positionSizePercent: number;      // % of portfolio per trade
      maxPositionSizePercent: number;   // Max % in a single position
      stopLossPercent: number;          // % below entry for stop loss
      takeProfitPercent: number;        // % above entry for take profit
      maxPositions: number;             // Max concurrent positions
      maxDailyTrades: number;           // Max trades per day
      maxDailyLossPercent: number;      // Pause bot if daily loss exceeds this %
      maxDrawdownPercent: number;       // Pause bot if drawdown exceeds this %
      trailingStopPercent?: number;
      partialTakeProfitPercent?: number;
      partialTakeProfitSize?: number;
    }
    

    Position

    export interface Position {
      id: string;
      botId: string;
      symbol: string;
      side: "BUY" | "SELL";
      entryPrice: number;
      quantity: number;
      currentPrice?: number;
      unrealizedPnL?: number;
      stopLoss: number;
      takeProfit: number;
      highestPrice?: number;   // For trailing stop
      tradeId: string;         // Link to Trade record
      enteredAt: Date;
    }
    

    Technical Indicators

    All indicators are implemented in lib/bot/indicators/ and used by the strategy classes.

    SMA (Simple Moving Average)

    Arithmetic mean of prices over a period. Used internally by Bollinger Bands for the middle band.

    EMA (Exponential Moving Average)

    Weighted moving average that gives more importance to recent prices. Crossovers between fast and slow EMAs form the basis of the trend-following strategy. Key functions:

    • calculateEMA(prices, period): Returns the current EMA value.
    • isBullishEMACrossover(fastEMA, prevFastEMA, slowEMA, prevSlowEMA): Detects fast EMA crossing above slow EMA.
    • isBearishEMACrossover(...): Detects fast EMA crossing below slow EMA.

    RSI (Relative Strength Index)

    Momentum oscillator measuring speed and magnitude of price changes on a 0-100 scale. Used by the mean reversion strategy to identify oversold (< 30) and overbought (> 70) conditions.

    • calculateRSI(prices, period): Returns the current RSI value.

    MACD (Moving Average Convergence Divergence)

    Trend-following momentum indicator showing the relationship between two EMAs. The IndicatorValues type includes MACD line, signal line, and histogram.

    Bollinger Bands

    Volatility bands placed above and below a moving average. Used by both mean reversion and breakout strategies.

    • calculateBollingerBands(prices, period, stdDev, currentPrice?): Returns { upper, middle, lower, bandwidth, percentB }.
    • Bandwidth: Measures the distance between upper and lower bands as a percentage of the middle band. A bandwidth < 2% indicates a "squeeze" (low volatility), which often precedes a breakout.
    • %B: Indicates where the current price sits relative to the bands (0 = at lower band, 1 = at upper band).

    Indicator Caching

    Indicator results are cached using CacheEntry<T> and CacheKey types to avoid redundant calculations within the same execution cycle. Cache keys include symbol, indicator name, period, timeframe, and a timestamp rounded to the nearest minute.


    Risk Management

    Position Sizing

    File: lib/bot/risk/position-sizer.ts

    Uses the Fixed Percentage Risk Model:

    1. Calculate the risk amount: accountBalance * (positionSizePercent / 100).
    2. Calculate the price risk per unit: |entryPrice - stopLossPrice|.
    3. Calculate the base quantity: riskAmount / priceRiskPerUnit.
    4. Apply maximum position size cap: accountBalance * (maxPositionSizePercent / 100) / entryPrice.
    5. Apply minimum order size from the exchange.
    6. Verify sufficient balance.
    7. Round to exchange precision (default: 8 decimal places).

    Example:

    • Account balance: $10,000
    • Risk per trade: 2% = $200
    • Entry price: $50,000, Stop loss at 4% = $48,000
    • Price risk per unit: $2,000
    • Base position: $200 / $2,000 = 0.1 BTC
    • Max position (20%): $2,000 / $50,000 = 0.04 BTC
    • Final position: 0.04 BTC (capped by max)

    The result includes limitApplied indicating which constraint was binding: "none", "max_position", "min_order", or "insufficient_balance".

    Stop-Loss

    File: lib/bot/risk/stop-loss-manager.ts

    Fixed Stop-Loss:

    • Calculated as entryPrice * (1 - stopLossPercent / 100).
    • Triggers when currentPrice <= stopLossPrice.
    • On trigger, the position is closed via market sell and P&L is calculated.

    Trailing Stop-Loss:

    • Follows price upward, locking in gains as the position moves favorably.
    • updateTrailingStopLoss() calculates: newStop = highestPrice * (1 - trailingPercent / 100).
    • The stop only moves up, never down: finalStop = max(newStop, currentStop, entryPrice).
    • The highestPrice is tracked on the Position record and updated each execution cycle.

    Additional Stop-Loss Features:

    • Break-even stop: moves stop to entry price + fees once price rises by a trigger percentage.
    • Time-based stop: closes position if held longer than maxHoldTimeMinutes (default: 1440 = 24 hours).
    • ATR-based stop: adapts to market volatility using entryPrice - (ATR * multiplier).
    • Emergency stop: safety net at 10% loss regardless of configured stop level.

    Take-Profit

    File: lib/bot/risk/take-profit-manager.ts

    • Fixed Take-Profit: Calculated as entryPrice * (1 + takeProfitPercent / 100). Triggers when currentPrice >= takeProfitPrice.
    • Partial Take-Profit: The calculatePartialTakeProfits() function creates multiple levels. For example, with 3 levels and a 15% target: close 33% at 5%, 33% at 10%, and 34% at 15%.

    Drawdown Tracking

    File: lib/bot/risk/drawdown-tracker.ts

    The DrawdownTracker is an in-memory singleton that monitors peak-to-trough decline for each bot:

    • Tracks peakBalance, currentBalance, troughBalance, currentDrawdownPercent, and maxDrawdownPercent.
    • Updated after each position close via drawdownTracker.updateDrawdown(botId, balance, isLoss).
    • State is rebuilt from database trade records on server startup.
    • Issues warnings at configurable thresholds:
      • Warning: drawdown approaching limit.
      • Critical: drawdown at or near limit.
      • Emergency: drawdown exceeded, bot should be paused.
    • The maxDrawdownPercent acts as a circuit breaker -- when exceeded, the risk validator blocks new trades.

    Pre-Trade Validation

    File: lib/bot/risk/risk-validator.ts

    The validateTrade() function performs seven checks before any BUY trade:

    1. Max positions limit: currentPositions.length >= riskSettings.maxPositions.
    2. Daily trade limit: Count of trades today >= riskSettings.maxDailyTrades.
    3. Daily loss limit: Today's P&L loss >= accountBalance * (maxDailyLossPercent / 100).
    4. Max drawdown limit: Current drawdown >= riskSettings.maxDrawdownPercent.
    5. Position size validation: Quantity and value must not be zero.
    6. Max position size: Position value must not exceed accountBalance * (maxPositionSizePercent / 100).
    7. Balance sufficiency: Position value must not exceed available balance.
    8. Signal confidence: Must be >= 50%.

    SELL signals always pass validation (exits are never blocked).

    If any check fails, the trade is rejected with specific violation messages. The shouldPauseBot() function can also auto-pause bots that have exceeded daily loss or drawdown limits.


    Paper Trading

    File: lib/bot/engine/paper-trading.ts

    The PaperTradingEngine simulates order execution without placing real trades on any exchange.

    Key Characteristics:

    • In-memory balance tracking: Maintains Map<botId, Map<asset, PaperBalance>> with free, locked, and total amounts.
    • Default initial balance: $10,000 USDT per bot.
    • Fee simulation: 0.1% trading fee (Binance standard rate).
    • Market order simulation: BUY orders deduct (quantity * price) + fee from quote balance and add quantity to base balance. SELL orders do the inverse.
    • Balance checks: Validates sufficient balance before execution, returning an error with the specific shortfall if insufficient.
    • Persistence: All paper trades are saved to the database Trade table with isPaperTrade: true, enabling identical reporting and analytics as live trades.
    • State rebuild: On server startup, rebuildPaperTradingStates() loads the latest trade for each active paper-trading bot and initializes the in-memory balance from the database.

    Usage:

    The simplified executePaperTrade() function is called by bot-executor.ts and all bot engines when paperTrading is true:

    export async function executePaperTrade(
      botId: string,
      symbol: string,
      side: "BUY" | "SELL",
      quantity: number,
      currentPrice: number
    ): Promise<PaperTradeResult>
    

    Paper trading produces identical tracking and reporting as live trading. It is the recommended mode for strategy testing before committing real capital.


    Backtesting

    File: lib/bot/backtest/backtester.ts

    The backtesting engine replays strategies against historical data to evaluate performance before live deployment.

    Process:

    1. Fetch historical data: fetchHistoricalData() retrieves OHLCV candles for the requested symbol, timeframe, and date range. An additional lookback of 100 periods is added for indicator warmup. Data is cached to avoid redundant API calls.

    2. Validate dataset: validateHistoricalDataset() checks for data completeness and consistency.

    3. Execute backtest: executeBacktest() iterates through candles chronologically, running the configured strategy at each bar and simulating trades with configurable commission (default: 0.1%) and slippage (default: 0.05%).

    4. Generate report: generateBacktestReport() produces a comprehensive report including:

      • Final balance and total return
      • Win rate and trade count
      • Sharpe ratio
      • Max drawdown
      • Profit factor
      • Equity curve data points

    Advanced Backtesting Modes:

    • Parameter Optimization: runParameterOptimization() tests a grid of strategy parameter combinations, sorting results by total return.
    • Walk-Forward Analysis: runWalkForwardAnalysis() tests the strategy across sequential time periods (e.g., 30-day windows), measuring consistency as the percentage of profitable periods.
    • Quick Backtest: quickBacktest() runs a 30-day backtest with a $10,000 initial balance for rapid validation.

    Performance Tracking

    File: lib/bot/performance/performance-tracker.ts

    Metrics

    The PerformanceMetrics interface captures comprehensive trading statistics:

    export interface PerformanceMetrics {
      totalTrades: number;
      winningTrades: number;
      losingTrades: number;
      winRate: number;              // 0-100
      totalProfit: number;
      totalLoss: number;
      netProfit: number;
      netProfitPercent: number;
      profitFactor: number;         // totalProfit / totalLoss
      sharpeRatio: number;          // Risk-adjusted return
      sortinoRatio?: number;        // Downside risk-adjusted return
      avgWin: number;
      avgLoss: number;
      avgTrade: number;
      largestWin: number;
      largestLoss: number;
      avgTradeDuration?: number;    // Hours
      maxDrawdown: number;
      maxDrawdownPercent?: number;
      currentDrawdown: number;
      maxWinStreak: number;
      maxLossStreak: number;
      currentStreak: number;
      startDate: Date;
      endDate: Date;
      totalDays: number;
    }
    

    Snapshots

    recordPerformanceSnapshot() calculates metrics for a bot and saves a PerformanceSnapshot record with:

    • Computed metrics via calculatePerformanceMetrics().
    • Risk score via calculateRiskScore().
    • Rating classification: "excellent", "good", "fair", or "poor" via getPerformanceRating().

    Snapshots are recorded periodically (daily) via recordAllBotSnapshots() for all active bots.

    Trend Analysis

    The getPerformanceHistory() function retrieves historical snapshots and calculates trends using simple linear regression:

    • Return trend: improving, stable, or declining.
    • Win rate trend: improving, stable, or declining.
    • Risk trend: improving, stable, or worsening.

    Alerts

    getPerformanceAlerts() identifies bots with concerning performance:

    • Critical: Profit factor < 1 (losing money) with 10+ trades, or drawdown > 30%.
    • Warning: Risk score > 60, or win rate < 30% with 20+ trades.
    • Info: Fewer than 5 trades (insufficient history).

    Bot Comparison

    compareBots() ranks bots using a weighted composite score:

    • 40% weight on net profit percentage.
    • 30% weight on Sharpe ratio.
    • 20% weight on profit factor.
    • 10% weight on low risk score.

    Position Management

    File: lib/bot/engine/position-manager.ts

    The PositionManager is an in-memory singleton that tracks open positions for all bots.

    Responsibilities:

    • Add/remove positions: Maintains Map<botId, Position[]>.
    • Update prices: updatePosition() sets currentPrice and recalculates unrealizedPnL.
    • Enforce limits: hasReachedMaxPositions() checks against configured position limits.
    • Exposure tracking: getTotalExposure() sums all position values; getTotalUnrealizedPnL() sums unrealized P&L.
    • Trigger detection: checkStopLosses() and checkTakeProfits() scan for triggered levels.
    • Rebuild on startup: rebuildPositions() loads all open trades from the database, groups by bot and symbol, calculates net quantity and average entry price, fetches current prices, and reconstructs Position objects.

    Positions are ephemeral in memory but backed by database Position and Trade records for durability. The in-memory layer exists for performance -- avoiding database queries on every price check during execution cycles.

    AI-powered crypto trading platform in closed beta. 8 bot engines, DeFi integration, and demo trading.

    Product

    • Features
    • Pricing
    • About
    • Join Beta

    Resources

    • Documentation
    • API Reference
    • Support
    • Blog
    • Status

    Legal

    • Terms of Service
    • Privacy Policy
    • Disclaimer

    © 2026 BlockbotX. All rights reserved.

    Built with AI · Powered by Next.js