Skip to content

Conversation

@birdbathd
Copy link
Contributor

@birdbathd birdbathd commented Dec 10, 2025

Major Feature Update: Comprehensive Dashboard Overhaul

⚠️ Important Notes

This is a significant codebase update with 90 commits, 154 files changed, +31,495/-2,951 lines. It represents several months of development and includes many new features, architectural changes, and bug fixes.

This PR supersedes the following open PRs:

Those features are included in this PR along with many additional improvements.

⚠️ Expect bugs - This is a substantial rewrite with many new features. Thorough testing is recommended before production use.


🔐 Breaking Changes

Authentication System Replaced

  • Removed NextAuth - Replaced with custom JWT-based authentication using jose + bcryptjs
  • Password hashing - Dashboard passwords are now bcrypt hashed (plain text still supported for migration)
  • Cookie changed - Auth cookie is now auth-token instead of next-auth.session-token
  • Why: NextAuth had URL mismatch issues when accessing from different IPs/domains, and compared plain text to hashed passwords incorrectly

Configuration Changes

  • New fields in config.default.json: debugMode, websocketPath, setupComplete, liquidationDatabase
  • setupComplete tracks onboarding state server-side (no longer relies on localStorage)
  • Default paperMode: false and useTradeQualityScoring: false

✨ New Features

1. TradingView-Style Interactive Charts

  • Full candlestick charting with OHLCV data
  • Real-time price updates via WebSocket
  • VWAP overlay with historical line
  • Liquidation markers on chart
  • Order lines for active positions
  • Multiple timeframes (1m, 5m, 15m, 1h, 4h, 1d)
  • Mobile gesture support (pinch zoom, pan)
  • Magnet mode for precise order placement
image

2. Liquidation Discovery Page (/discovery)

  • Analyze liquidation patterns across ALL symbols
  • Volume analysis, frequency metrics, whale detection
  • Symbol recommendations based on activity
  • Market depth visualization
  • Configurable data retention (default 90 days)
  • Add symbols directly to config from discovery
image

3. Trade Quality Scoring System

  • VWAP regime detection (above/below VWAP)
  • Spike velocity analysis
  • Volume trend scoring
  • Quality scores 0-3 affect position sizing (0.5x-1.5x)
  • Passive mode: records scores without filtering trades
  • Historical tracking with SQLite persistence
  • Disabled by default - enable in Global Settings
image

4. Protective Orders with Trailing Take Profit

  • Automatic SL/TP order placement
  • Trailing TP that moves to break-even after partial profit
  • Configurable activation thresholds
  • Works with both long and short positions

5. Dynamic Position Sizing

  • Percentage of balance mode
  • Auto-calculates trade size based on account balance
  • Min/max position limits
  • Quality-adjusted sizing when trade scoring enabled

6. Multi-Tranche Position Management

  • Isolate losing positions while continuing to trade
  • Track multiple entries separately per symbol
  • Configurable max tranches and isolation thresholds
  • Experimental/untested - use with caution

7. Paper Trading Mode

  • Virtual balance simulation
  • No real trades executed
  • Track P&L without risk
  • Experimental - not thoroughly tested

8. Improved Onboarding Flow

  • Step-by-step setup wizard for new users
  • API key configuration
  • Symbol selection with presets (Conservative/Balanced/Aggressive)
  • Dashboard tour
  • State persists server-side (works across devices)

🔧 Improvements

WebSocket Reliability

  • Auto-detect host from browser - No more hardcoded localhost issues
  • Works correctly when accessing via IP, domain, or localhost
  • Better reconnection handling
  • Tab visibility detection - refreshes data when returning to tab

UI/UX Enhancements

  • Mobile-responsive design throughout
  • Pull-to-refresh on mobile
  • Dark/light theme support
  • Improved error notifications
  • Rate limit visualization
  • Session performance tracking

Configuration

  • Per-symbol threshold system toggle (now always visible)
  • Liquidation database retention settings
  • Trade size validation against exchange minimums
  • Safe defaults ($1 USDT trade size for new symbols)

Security

  • Next.js upgraded to 15.5.7 (CVE-2025-66478 fix)
  • Bcrypt password hashing
  • Secure cookie handling
  • Session-based error tracking

🐛 Bug Fixes

  • Fixed stale data when returning to browser tab
  • Fixed WebSocket not connecting from non-localhost access
  • Fixed authentication comparing plain text to hashed passwords
  • Fixed threshold settings not displaying unless already in config
  • Fixed liquidation database settings not persisting
  • Fixed onboarding trade sizes using wrong units (was coin, now USDT)
  • Fixed secure cookies only when actually using HTTPS
  • Fixed FTA Exit Service spamming logs every second (now throttled to 5 min intervals, disabled by default)
  • Fixed various React hooks rule violations
  • Removed deprecated type stub packages

📋 Known Issues / TODO

  • Risk Percentage setting - UI exists but not yet implemented in bot logic
  • Paper Trading - Not thoroughly tested
  • Tranche System - Experimental, needs more testing
  • Trade Quality Scoring - May need tuning for different market conditions

🧪 Testing Recommendations

  1. Fresh install test - Delete config.user.json and go through onboarding
  2. Migration test - Existing users should verify config loads correctly
  3. Multi-device test - Access from different IPs/browsers
  4. Paper mode test - Verify no real trades execute
  5. Discovery page - Check liquidation data collection

📤 Upgrade Guide for Existing Users

  1. Backup your data:

    • config.user.json - Your API keys and symbol settings
    • data/ folder - Contains liquidation history database
  2. Recommended: Rebuild config from new defaults

    • Many new settings won't appear in the UI unless they exist in your config
    • Start fresh with the onboarding wizard, then re-add your API keys and symbols
    • This ensures all new features are accessible
  3. Alternative: Keep existing config

    • Your existing config will still work
    • New fields will be added automatically with defaults
    • Some UI elements may not appear until you re-save settings
  4. After upgrade:

    • Clear browser cache/cookies (auth system changed)
    • Re-login with your dashboard password
    • Verify WebSocket connects (check browser console)

📦 Dependencies

  • Upgraded: next 15.5.4 → 15.5.7
  • Added: jose, bcryptjs, lightweight-charts
  • Removed: @types/uuid, @types/sqlite3 (now included in packages)

🔄 Running with PM2 (Optional)

PM2 is optional but recommended for production use. It provides:

  • Process management and auto-restart on crash
  • System Logs feature in the dashboard (requires PM2)
  • Easy start/stop/restart via dashboard controls

Install PM2

npm install -g pm2

Start with PM2

pm2 start ecosystem.config.js

Without PM2

The bot runs fine without PM2 using:

npm run dev      # Development mode
npm run start    # Production mode

Note: The System Logs section in the dashboard will show "PM2 not detected" if running without PM2. All other features work normally.


🙏 Credits

Built on top of the excellent Aster Lick Hunter by CryptoGnome.

CryptoGnome and others added 30 commits October 12, 2025 17:14
- Treat default "admin" password as unauthenticated access
- Update password check logic in both auth API and login page to exclude "admin" from requiring authentication
- Remove minLength constraint from password input field
- Add clarifying comments about default password handling

This change improves user experience by allowing immediate access when using the default password, while still requiring authentication for custom passwords.
Features:
- Interactive TradingView charts with 7-day kline caching
- Manual and auto-refresh (60s intervals) with optimized updates
- Liquidation markers grouped by configurable time intervals
- Position lines and VWAP indicator
- Recent orders overlay on chart
- Compact, modern chart controls UI

Database Management:
- Configurable liquidation data retention (default: 90 days)
- Automated cleanup scheduler with configurable intervals
- UI controls for database retention settings
- Statistics tracking for stored liquidations

Performance:
- Smart caching system prevents redundant API calls
- Only updates chart when data actually changes
- Efficient incremental updates for new candles
- Optimized state management to prevent unnecessary re-renders
- Automatically loads older candles when scrolling back in time
- Monitors visible time range and loads 500 candles at a time
- Adds endTime parameter support to klines API
- Tracks earliest loaded candle timestamp in cache
- Shows 'Loading history...' indicator during fetch
- Prepends historical data without disrupting current view
- No more 7-day limit - can view unlimited historical data
- Use ref for loadHistoricalData to avoid scope issues
- Remove klineData.length from chart init dependencies to prevent re-initialization
- Chart now initializes correctly and loads historical data on scroll
- Track user interactions (scrolling/zooming) with chart
- Only reset to 2/3 position on initial load
- Maintain view position during auto-refresh and historical data loading
- Reset interaction state when symbol or timeframe changes
- Improves UX by not disrupting user's chosen view
- Add ping/pong keepalive every 30 seconds to detect silent disconnections
- Add inactivity monitor: auto-reconnect if no liquidations received for 5 minutes
- Add proper cleanup of keepalive and inactivity timers on disconnect/stop
- Log warnings when stream becomes inactive
- Broadcast inactivity warnings to UI for visibility

This fixes the issue where the liquidation stream would stop receiving data
without triggering any errors or reconnection attempts.
- Add 'TP/SL' toggle to show/hide position entry and TP/SL lines
- Move 'Liquidations' toggle next to 'Group' setting (they're related)
- Reorganize controls: [Auto-refresh, Orders, TP/SL, VWAP] | [Liquidations, Group] | [Timeframe]
- Fix position lines disappearing when changing chart settings
- Position lines now persist through timeframe/symbol/grouping changes
- Lines are only cleared when toggle is disabled or positions change

This improves chart control organization and fixes the issue where TP/SL
lines would disappear when adjusting chart settings.
Resolved merge conflicts:
- src/bot/index.ts: Added Tranche Manager initialization from dev
- src/lib/bot/hunter.ts: Added tranche creation on order placement
- src/components/SymbolConfigForm.tsx: Updated input handling to allow default values

Accepted new tranche management features from dev:
- Tranche Manager service and database
- Tranche UI components (breakdown, timeline, settings)
- Tranche page for multi-position tracking

Chart features remain independent and functional.
- Reuse Hunter instance instead of creating new one on bot restart
- Remove all event listeners before re-attaching to prevent duplicates
- Clean up thresholdMonitor listeners by event name
- Add detailed logging for liquidation sidebar API loading
- Fix: Hunter now calls removeAllListeners() on stop to clear handlers

This fixes the issue where liquidations would appear multiple times in the UI
due to event listeners accumulating across bot restarts and HMR cycles.
- Add UNIQUE constraint on (symbol, event_time) to liquidations table
- Change INSERT to INSERT OR IGNORE to silently skip duplicate events
- Addresses root cause at database level instead of UI-level workarounds

Testing in progress for duplicate issues and potential bugs.
…y revert

- Restored tranche docs and all related source files from dev branch
- Ensures TradingView feature branch does not remove unrelated tranche features
…unts

- Properly close and remove listeners from old WebSocket before creating new connection
- Add deduplication logic in thresholdMonitor based on eventTime, quantity, and price
- Prevents multiple WebSocket connections from processing the same liquidation event
- Fixes issue where single liquidations were being counted 50+ times due to duplicate events
…n loops

- Add shouldReconnect flag to control automatic reconnection behavior
- Prevent close handler from reconnecting when manually disconnecting
- Track reconnection timeouts to avoid scheduling multiple reconnections
- Temporarily disable auto-reconnect during intentional disconnects (inactivity, config changes)
- Prevents reconnection cascades that could cause duplicate connections
- Maintains deduplication safety mechanisms from previous commit
- Add tranche management fields to SymbolConfig type
- Import and render TrancheSettingsSection in symbol config form
- Add default tranche configuration values
- Allows configuring isolation threshold, max tranches, and recovery settings per symbol
- Add tranche configuration fields to SymbolConfig type
- Integrate TrancheSettingsSection into symbol config form
- Initialize tranche database tables on startup
- Add Tranches page to sidebar navigation with DashboardLayout
- Fix symbol dropdown to show configured symbols from config
- Fix onChange binding and null coalescing for trade size fields

Note: Tranche system is implemented but requires testing with live positions
Configuration:
- Add protective order fields to SymbolConfig type
- Create ProtectiveOrdersSection UI component
- Support breakeven trim with configurable offset
- Support multiple trim levels at different P&L targets

Backend Implementation:
- Create ProtectiveOrderService to manage protective orders
- Place LIMIT orders with 'po_' prefix to avoid TP/SL conflicts
- Integrate with PositionManager for automatic triggers
- Monitor positions and place orders when price levels hit
- Handle order fills and position closures
- Filter protective orders from orphaned order cleanup

Features:
- Breakeven protection: Trim X% when price returns to entry
- Multi-level trims: Set multiple profit/loss targets
- Non-interfering: Uses separate order IDs, won't conflict with TP/SL
- Auto-cleanup: Removes orders when positions close

Note: Untested - requires live position testing
- Fixed log parsing to include proper timestamps with milliseconds
- Generate unique log IDs for each entry
- Added ProtectiveOrderService initialization in bot startup
- Service now starts when any symbol has enableProtectiveOrders=true
- Both TrancheManager and ProtectiveOrderService log their startup status
- Logs now show HH:MM:SS.mmm format for easy reading
…tarts

- Removed enableProtectiveOrders, protectiveBreakeven, protectiveTrimLevels from SymbolConfig types
- Removed ProtectiveOrdersSection from symbol config UI
- Removed automatic protective order checking from PositionManager
- ProtectiveOrderService now starts once in on-demand mode (no monitoring interval)
- Added duplicate start protection to prevent log spam
- Commented out old config-based methods (kept helpers for per-position activation)
- Protective orders now exclusively activated via 'Protect' button on positions
- Use getProtectiveOrderService() instead of proxy export to avoid initialization errors
- Return 503 error if service not available instead of throwing exception
- Provides better error message when bot is not running
…on and disable default TP/SL option

Major Changes:
- Renamed all 'trailing stop' references to 'trailing take profit' (trailing TP)
- Implemented break-even protection: TP never goes below entry price for LONG (never above for SHORT)
- Added 'Disable Default TP/SL' option to scale out settings with intelligent warnings
- Added DCA flag to trailing TP (integrates with existing liq hunter)
- Fixed WebSocket connection error banner flashing on page load (5s grace period)

Trailing TP Enhancements:
- placeTrailingStop() → placeTrailingTakeProfit() with break-even enforcement
- Monitoring enforces Math.max(idealTpPrice, entryPrice) for LONG positions
- Monitoring enforces Math.min(idealTpPrice, entryPrice) for SHORT positions
- Tracking now stores: entryPrice, enableDCA flag alongside trail data
- Method names updated: startTrailingTakeProfitMonitoring(), checkAndAdjustTrailingTakeProfits()
- Log messages updated to reflect 'trailing TP' instead of 'trailing stop'
- UI description: 'Captures upside while protecting profits (exit never falls below break-even)'

Disable Default TP/SL Feature:
- New toggle in ScaleOutModal to disable bot's automatic TP/SL for specific positions
- ProtectiveOrderService tracks disabled positions in disabledDefaultTPSL Set
- Position Manager checks isDefaultTPSLDisabled() before placing/adjusting TP/SL
- Cancels existing default TP/SL orders when option is enabled
- Automatically resumes default TP/SL when scale out is deactivated
- Preserves robustness: only skips disabled positions, monitors all others normally

Smart Warning System:
- No warning when breakeven 100% or any trim level is 100% (full position exit)
- 'No exit protection' warning when no methods enabled
- 'No stop loss protection' warning when only trailing TP (no downside protection)
- 'Partial exit only' warning when no 100% trim levels configured
- Confirmation prompts on submit for risky configurations
- Prevents activating with disabled TP/SL and no exit methods

UI/UX Improvements:
- Added DCA toggle: 'DCA on Drop Below Entry' (continues liq hunting when enabled)
- WebSocket error banner now waits 5 seconds before showing (prevents flash on page load)
- Context-aware warnings based on configured exit methods
- Validation ensures at least one exit method when default TP/SL disabled

Technical Details:
- ScaleOutSettings interface: added disableDefaultTPSL flag
- ProtectiveOrder triggerType: 'trailing_stop' → 'trailing_tp'
- positionManager.adjustProtectiveOrders(): checks isDefaultTPSLDisabled() before managing TP/SL
- positionManager.placeProtectiveOrders(): checks isDefaultTPSLDisabled() before placing orders
- cancelDefaultTPSL() method filters TAKE_PROFIT_MARKET, STOP_MARKET orders (excludes po_ prefix)
- Cleanup on deactivation: removes from disabledDefaultTPSL Set to resume normal TP/SL management

Files Modified:
- src/lib/services/protectiveOrderService.ts (trailing TP transformation, disable TP/SL tracking)
- src/components/ScaleOutModal.tsx (UI updates, smart warnings, validation)
- src/lib/bot/positionManager.ts (skip disabled positions in TP/SL management)
- src/components/PersistentErrorBanner.tsx (5s delay for WebSocket errors)
- src/bot/index.ts (event handlers for scale out)
- src/app/api/positions/scale-out/*.ts (API routes)
… improvements

- Always run trade quality service (passive mode records without filtering)
- Persist trade signals to SQLite database (data/trade_quality.db)
- Add /api/trade-quality endpoint for fetching persisted signals
- TradeQualityPanel loads historical data on mount
- Show 'Passive' badge when scoring is disabled but still recording
- Update config UI to explain active vs passive mode
- Fix protectiveOrderService import (getPositions from orders.ts)
… stash

- Add Long vs Short Sentiment panel with bullish/bearish/neutral indicator
- Add whale% column showing volume from 0K+ liquidations
- Add hourly opportunity ($/hr) calculation
- Add time window options: 60d, 90d, all time
- Add suggestion filters for recommended/low-activity symbols
- Add BTC volume correlation display
…blocks

- Pass qualityScore along with VWAP blocked events in hunter
- TradeQualityPanel handles both QUALITY_FILTER and VWAP_FILTER block types
- Show prominent block reason banner (orange for VWAP, red for quality)
- Display 'VWAP BLOCK' label instead of 'SKIP' for VWAP filtered trades
- Track VWAP blocks separately in stats
- Load blockType from database for persisted signals
- Call detectSpike() on every VWAP price update (every ~1 second)
- Previously spike detection only ran when liquidations came in
- Now price history is populated from real-time streaming data
- This ensures spike detection has enough data even for infrequent liquidations

The service now uses data from two sources:
1. VWAP Streamer: Real-time price data for spike detection and VWAP crosses
2. Liquidations: Volume trend analysis (appropriate - should reflect actual activity)
Changes:
- Track ALL liquidations for volume/spike analysis (not just threshold-meeting ones)
- Load last 10 minutes of historical liquidations on service start
- Increase volume history lookback from 5 to 10 minutes
- Add sample count to volume trend messages for debugging
- Remove duplicate recordLiquidation call in analyzeAndTrade
- Add tooltips to all score gauges (Spike, Volume, Regime, Total)
- Add tooltips to detailed metrics (Price Move, Spike Time, Vol Ratio, VWAP Dist)
- Add tooltip to VWAP Crosses indicator
- Add tooltips to summary stats (Signals, Strong, Skipped, Avg Q)
- Add 'Recent Signals' section showing last 5 signals below main signal
- Improve Overview tab with better context and descriptions
- Add dedicated aggTrade WebSocket for tick-by-tick price data (5-min klines were too slow)
- Record ALL liquidations from configured symbols for accurate volume tracking
- Fix spike velocity threshold from 0.5%/sec to 0.02%/sec (realistic for 2-min window)
- Add rate limiting: 100ms price throttle, 5s log cooldown, threshold-only logging
- Remove debug logs to reduce noise

Spike and volume scores now properly evaluate (was always 0 before)
- Add signalPrice field to trade signals (shows price at time of signal)
- Display signal price next to symbol in TradeQualityPanel
- Add MAE/MFE tracking service to record price excursions during trades
- Add mae-mfe API endpoint for retrieving trade statistics
- Database migration adds signal_price column to existing tables

Price helps correlate signals with actual trade entries for analysis
- Replace NextAuth with simple JWT-based authentication system
- Add /api/auth/login, /api/auth/verify, /api/auth/simple-logout endpoints
- Update AuthProvider to use custom auth context with useAuth() hook
- Fix WebSocket host detection to prioritize window.location.hostname
- Add websocketPath config option for reverse proxy setups
- Update all components to use new auth system
- Add order cancel/modify and position add API routes
- Add AddToPositionModal, EditOrderModal, searchable-select components
- Remove src/lib/auth.ts (NextAuth config)
- Remove src/app/api/auth/[...nextauth]/route.ts
- Remove src/types/next-auth.d.ts
- Fix api-auth.ts to use jwtVerify instead of NextAuth getToken
- Remove unused signOut import from page.tsx
- Clean up middleware (remove NextAuth cookie backwards compat)
…lback

- Quality-based position size multiplier now only applies when useTradeQualityScoring is enabled
- In passive mode, multiplier is always 1.0 (no size adjustment)
- Removed automatic fallback to exchange minimum - trades now fail with warning if size too small
- Re-apply minPositionSize check after quality multiplier
- New /api/depth/[symbol] endpoint fetches 1000-level order book
- Discovery page now has expandable rows showing depth analysis
- Shows spread, imbalance, and liquidity at multiple % levels
- Add ws to serverExternalPackages to fix production masking error
Was setting secure=true in production mode even over HTTP, causing cookie to be rejected
Log warnings when:
- getBookTicker returns invalid bid/ask (0, NaN, or infinite)
- calculateOptimalPrice detects bad exchange data and returns null
- liquidation events have invalid price data

This helps identify where 0-priced orders originate.
- dataStore: Refresh both balance AND positions when tab becomes visible
- SessionPerformanceCard: Add visibility listener to refresh session data
- PerformanceCardInline: Add visibility listener to refresh 24h PnL data
- SymbolConfigForm: Better error logging with status codes
- symbol-details API: Add specific error messages for rate limits and network issues
Critical RCE vulnerability in React Server Components.
CVSS 10.0 - allows remote code execution without auth.
- Remove dead files: TestToasts.tsx, backup files, duplicate logout route
- Discovery tab: clarify recommendations based on liq volume only
- Add WIP warnings for Paper Mode and Risk Percentage in config
- Trade Quality Scoring off by default
- config.default.json: remove fake ASTERUSDT, sane defaults
- Default trade size:  (was 00) - very conservative
- Fix liquidation database settings not persisting
- Default paperMode: false, riskPercent: 5, maxOpenPositions: 10
- Bot now starts and waits for config instead of crashing
- configLoader: warn instead of throw when no API keys
- Bot gracefully waits for user to configure via web UI
- Web dashboard remains accessible during initial setup
- Trade size is in USDT (margin), not coin units
- Calculate safe minimums based on leverage:
  - BTC at 3x: 0, 5x: 0, 10x: 5
  - ETH/others at 3x: .5, 5x: .5, 10x:
- Add 50% buffer over exchange minimums for safety
- Remove hardcoded BTC/ETH from defaults.ts
- Fix DEFAULT_SYMBOL_CONFIG to use  USDT
- Per-symbol threshold toggle now always visible (disabled if global off)
- Shows warning when global threshold not enabled
- Reduced verbose error logging when waiting for API keys
- Single clean log line instead of multiple error broadcasts
- Add 5-minute throttling between repeated FTA signals for same position/type
- Add useFTAExitAnalysis config option (default: false)
- FTA service now only starts when explicitly enabled
- Add UI toggle in Settings > Trade Quality section
- Clean up throttle tracking when positions are removed
Copilot AI review requested due to automatic review settings December 10, 2025 03:29
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This is a substantial codebase update representing several months of development work with 90 commits and significant changes across 154 files. The PR introduces major architectural changes including replacing NextAuth with custom JWT authentication, adding TradingView-style charting, liquidation discovery features, trade quality scoring system, and paper trading mode.

Key Changes:

  • Custom JWT authentication system replacing NextAuth
  • TradingView-style interactive charts with real-time updates
  • Liquidation discovery and analysis features
  • Trade quality scoring system with VWAP regime detection
  • Paper trading mode with simulated execution

Reviewed changes

Copilot reviewed 114 out of 145 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
src/lib/db/tradeQualityDb.ts New database module for trade quality signal persistence
src/lib/db/paperTradingDb.ts New database for paper trading positions and balance tracking
src/lib/db/database.ts Database optimization improvements and tranche table initialization
src/lib/config/types.ts Schema additions for dynamic position sizing and paper trading
src/lib/bot/hunter.ts Major refactor with quality scoring, WebSocket improvements, dynamic sizing
src/lib/auth/api-auth.ts Authentication switched from NextAuth to jose JWT
src/components/TradingViewChart.tsx New comprehensive charting component with liquidations overlay
src/components/TradeQualityPanel.tsx New UI for trade quality monitoring and analysis
Comments suppressed due to low confidence (1)

src/components/SymbolConfigForm.tsx:1

  • [nitpick] The warning uses "deplete" which is correct, but "drain" might be more commonly understood in financial contexts. However, this is subjective and the current wording is acceptable.
'use client';

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

entry_time INTEGER NOT NULL,
order_id TEXT NOT NULL UNIQUE,
current_price REAL,
updated_at INTEGER DEFAULT (strftime('%s', 'now')),
Copy link

Copilot AI Dec 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SQLite's strftime('%s', 'now') returns the current Unix timestamp as a string, not an integer. The INTEGER DEFAULT with strftime will work due to SQLite's type affinity, but it's semantically incorrect. Consider using DEFAULT (CAST(strftime('%s', 'now') AS INTEGER)) for clarity and correctness.

Copilot uses AI. Check for mistakes.
longVolumeThresholdUSDT: 5000,
shortVolumeThresholdUSDT: 5000,
tradeSize: 0.001,
tradeSize: 5, // $5 USDT margin - safe minimum for most symbols at 10x leverage
Copy link

Copilot AI Dec 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment states "$5 USDT margin" but the value could be misinterpreted. Consider clarifying that this is the margin amount (not the notional position size) and that at 10x leverage this represents a $50 notional position. The relationship between tradeSize, leverage, and actual position value should be clearer.

Suggested change
tradeSize: 5, // $5 USDT margin - safe minimum for most symbols at 10x leverage
tradeSize: 5, // $5 USDT margin (not notional position size). At 10x leverage, this represents a $50 notional position. tradeSize * leverage = notional position size.

Copilot uses AI. Check for mistakes.
private async handleLiquidationEvent(event: any): Promise<void> {
if (event.e !== 'forceOrder') return; // Not a liquidation event

console.log(`[Hunter] handleLiquidationEvent START: ${event.o.s} @ ${Date.now()}`);
Copy link

Copilot AI Dec 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Debug console.log statements are left in production code (lines 565, 595, 600). These should either be removed or gated behind a debug flag check like if (config.global.debugMode) to avoid cluttering production logs.

Suggested change
console.log(`[Hunter] handleLiquidationEvent START: ${event.o.s} @ ${Date.now()}`);
if (this.config.global.debugMode) {
console.log(`[Hunter] handleLiquidationEvent START: ${event.o.s} @ ${Date.now()}`);
}

Copilot uses AI. Check for mistakes.
try {
// Log the liquidation price for debugging
if (liquidation.price <= 0 || !isFinite(liquidation.price)) {
logWarnWithTimestamp(`Hunter: Received invalid liquidation price for ${liquidation.symbol}: ${liquidation.price} (side: ${liquidation.side})`);
Copy link

Copilot AI Dec 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Invalid liquidation prices are logged as warnings but the function continues execution. This could lead to trades being placed with invalid price data. After logging the warning, the function should return early to prevent potentially erroneous trades.

Suggested change
logWarnWithTimestamp(`Hunter: Received invalid liquidation price for ${liquidation.symbol}: ${liquidation.price} (side: ${liquidation.side})`);
logWarnWithTimestamp(`Hunter: Received invalid liquidation price for ${liquidation.symbol}: ${liquidation.price} (side: ${liquidation.side})`);
return;

Copilot uses AI. Check for mistakes.
logErrorWithTimestamp(` Current trade size (margin): ${tradeSizeUSDT.toFixed(2)} USDT`);
logErrorWithTimestamp(` Notional value: ${notionalUSDT.toFixed(2)} USDT (at ${symbolConfig.leverage}x leverage)`);
logErrorWithTimestamp(` Exchange minimum notional: ${minNotional} USDT`);
logErrorWithTimestamp(` RECOMMENDED: Set minPositionSize to at least ${(minMarginRequired * 1.1).toFixed(2)} USDT`);
Copy link

Copilot AI Dec 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The error message recommends setting minPositionSize but doesn't indicate where this setting is located in the configuration. Adding a hint like "in the Symbol Configuration" would improve user experience.

Suggested change
logErrorWithTimestamp(` RECOMMENDED: Set minPositionSize to at least ${(minMarginRequired * 1.1).toFixed(2)} USDT`);
logErrorWithTimestamp(` RECOMMENDED: Set minPositionSize to at least ${(minMarginRequired * 1.1).toFixed(2)} USDT (in the Symbol Configuration)`);

Copilot uses AI. Check for mistakes.
Comment on lines +33 to +38
const formatPrice = useCallback((symbol: string, price: number | string): string => {
const numPrice = typeof price === 'string' ? parseFloat(price) : price;

if (isNaN(numPrice)) {
return '0.00';
}
Copy link

Copilot AI Dec 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When price is NaN, the function returns '0.00' which could be misleading as it looks like a valid price of zero. Consider returning an empty string, 'N/A', or throwing an error to make invalid data more obvious.

Copilot uses AI. Check for mistakes.
Comment on lines +158 to +159
// Round up to nearest dollar for BTC, nearest 0.5 for others
return isBTC ? Math.ceil(safeMargin) : Math.ceil(safeMargin * 2) / 2;
Copy link

Copilot AI Dec 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The rounding logic for non-BTC symbols (Math.ceil(safeMargin * 2) / 2) could be clearer. Consider extracting this to a named constant or adding a comment explaining that this rounds up to the nearest 0.5 USDT.

Suggested change
// Round up to nearest dollar for BTC, nearest 0.5 for others
return isBTC ? Math.ceil(safeMargin) : Math.ceil(safeMargin * 2) / 2;
// For non-BTC symbols, round up to the nearest 0.5 USDT (e.g., 5.1 -> 5.5, 5.6 -> 6.0)
const roundedNonBTC = Math.ceil(safeMargin * 2) / 2;
// Round up to nearest dollar for BTC, nearest 0.5 for others
return isBTC ? Math.ceil(safeMargin) : roundedNonBTC;

Copilot uses AI. Check for mistakes.
const firstVisibleBar = Math.floor(newRange.from);
if (firstVisibleBar < 20 && !loading && loadHistoricalDataRef.current) {
// User is getting close to the oldest loaded data
loadHistoricalDataRef.current();
Copy link

Copilot AI Dec 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

loadHistoricalDataRef.current is called without checking if it exists first. If the ref hasn't been assigned yet, this will throw an error. Add a null check: loadHistoricalDataRef.current?.() or if (loadHistoricalDataRef.current) { loadHistoricalDataRef.current(); }.

Suggested change
loadHistoricalDataRef.current();
if (typeof loadHistoricalDataRef.current === 'function') {
loadHistoricalDataRef.current();
}

Copilot uses AI. Check for mistakes.
{
success: false,
error: 'Failed to fetch liquidations',
details: error instanceof Error ? error.message : String(error),
Copy link

Copilot AI Dec 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error details from the server are being exposed to the client in the API response. While helpful for debugging, this could leak sensitive information about the server's internal state or file paths. Consider sanitizing error messages or only including details in development mode.

Suggested change
details: error instanceof Error ? error.message : String(error),
// details field removed to avoid leaking sensitive information

Copilot uses AI. Check for mistakes.
File was already in .gitignore but was being tracked.
Users should create their own ecosystem.config.js locally.
- Adding to an existing position in same direction should not count
  against maxOpenPositions limit (e.g., adding to ETH long when at 5/5)
- Added hasPositionInDirection() to PositionTracker interface
- Hunter now checks if trade would add to existing position before
  blocking due to max positions limit
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants