Skip to content

Conversation

@cj4c0b1
Copy link
Owner

@cj4c0b1 cj4c0b1 commented Oct 13, 2025

🐳 Docker Implementation

Fixes CryptoGnome#71

This PR adds complete Docker support for the Aster Lick Hunter Node project, making deployment significantly easier and more reliable.

📦 What's New

Core Docker Files

  • Dockerfile - Multi-stage production build with security best practices
  • docker-compose.yml - Production deployment configuration
  • docker-compose.dev.yml - Development mode with hot reload
  • .dockerignore - Optimized build context
  • docker-entrypoint.sh - Container initialization and setup

Developer Tools

  • Makefile - Convenient commands (make up, make logs, make backup, etc.)
  • docker-start.sh - Interactive setup wizard
  • .env.example - Environment variable template

Documentation

  • docs/DOCKER.md - Comprehensive 400+ line deployment guide
  • DOCKER_SETUP_SUMMARY.md - Implementation overview
  • README.md - Updated with Docker installation instructions

CI/CD

  • .github/workflows/docker-build.yml - Automated Docker builds and tests

API Endpoints

  • /api/health - Health check endpoint for monitoring

✨ Features

Security

  • ✅ Non-root user (nextjs:nodejs, UID/GID 1001)
  • ✅ Multi-stage builds for minimal image size
  • ✅ Read-only mounts where appropriate
  • ✅ Environment variable secrets

Reliability

  • ✅ Health checks every 30s
  • ✅ Auto-restart on failure
  • ✅ Data persistence with volumes
  • ✅ Graceful shutdown handling

Developer Experience

  • ✅ One-command setup: make up
  • ✅ Interactive script: ./docker-start.sh
  • ✅ Development mode with hot reload
  • ✅ Easy backup/restore: make backup

🚀 Quick Start

Using Makefile (Recommended)

make build    # Build Docker image
make up       # Start containers
make logs     # View logs
make health   # Check status

Using Docker Compose

docker-compose up -d

Using Interactive Script

./docker-start.sh

🔧 Configuration

Environment Variables

  • NEXTAUTH_SECRET - Session encryption secret (required)
  • NEXT_PUBLIC_WS_HOST - WebSocket host (default: localhost)
  • DASHBOARD_PORT - Dashboard port (default: 3000)
  • WEBSOCKET_PORT - WebSocket port (default: 8080)

Volume Mounts

  • ./data:/app/data - Database and application data
  • ./.env.local:/app/.env.local - Environment variables

🐛 Bug Fixes

This PR also includes fixes for:

  • ✅ Postinstall script errors during Docker build
  • ✅ TypeScript build errors (undefined leverage, unused variables)
  • ✅ Config file initialization issues
  • ✅ Container restart loops

📊 Testing

Container Status: Healthy and running
Dashboard: http://localhost:3000 (accessible)
Health API: http://localhost:3000/api/health (passing)
WebSocket: ws://localhost:8080 (operational)
Bot: Running in paper mode with simulated liquidations

Performance Metrics:

  • CPU Usage: ~1%
  • Memory: ~313 MiB
  • Image Size: 1.2 GB (optimized with multi-stage build)

📚 Documentation

See docs/DOCKER.md for:

  • Detailed installation instructions
  • Configuration options
  • Production deployment guide
  • Troubleshooting tips
  • Backup and restore procedures

🎯 Benefits

For Users

  • Easier Setup - No Node.js installation required
  • Isolated Environment - No conflicts with system packages
  • Consistent - Same environment everywhere
  • Portable - Run anywhere Docker runs
  • Safe - Easy rollback and recovery

For Developers

  • Reproducible - Same environment for all developers
  • Fast Deployment - One command to deploy
  • Easy Testing - Spin up/down quickly
  • CI/CD Ready - Automated builds and tests
  • Scalable - Easy to add more services

📝 Breaking Changes

None - This is purely additive. Existing installation methods continue to work.

🔗 Related Issues

Closes CryptoGnome#71

CryptoGnome and others added 30 commits October 5, 2025 23:46
…oGnome#39)

## Problem
- Recent orders table was not displaying all trade data correctly
- When multiple orders closed simultaneously (e.g., TP + entry order), only one PnL value was shown
- Income history matching used a 5-second time window that caused Map key collisions
- Only 5 configured symbols had their orders fetched

## Root Cause
1. Time-window based PnL matching overwrote values when multiple orders closed at the same time
2. Map structure stored only the last PnL entry per time window
3. Symbol fetch was limited to first 5 configured symbols

## Solution
- Replace income history matching with direct trade data from `/fapi/v1/userTrades` endpoint
- Use orderId-based mapping instead of time windows for precise PnL matching
- Aggregate PnL for orders with multiple fills
- Remove 5-symbol fetch limit to show all configured symbols

## Changes
- **src/lib/types/order.ts**: Add Trade interface for user trades API
- **src/lib/api/orders.ts**: Add getUserTrades() function for fetching trade history
- **src/app/api/orders/all/route.ts**: Replace income history logic with user trades, remove symbol limit

## Testing
- TypeScript compilation passes with no errors
- All configured symbols will now display order history
- Multiple simultaneous closes will each show correct PnL values
- Historical PnL data persists across page refreshes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
…isplay

fix: resolve order PnL display issues with simultaneous closes (CryptoGnome#39)
- Removed unused state variables (_isOptimizing, _optimizationResult, _showOptimizationModal)
- Removed unused _handleOptimizeClick and _applyOptimizedParams functions
- Removed unused symbol prop from component interface
- Cleans up ~60 lines of dead code that was never called

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
…-size-issue

Approved and merged to dev. All TypeScript and linting checks pass.
- Version checker now detects current git branch dynamically
- Fetches and compares against the correct remote branch (origin/dev, origin/main, etc.)
- Displays branch name prominently in the UI alongside commit hash
- Automatically adapts when switching between branches

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
…e#50)

* feat: add configuration optimizer with UI and critical bug fix

## New Features
- Full-featured optimizer UI in main dashboard
- Real-time progress tracking with WebSocket integration
- Apply optimized settings directly from UI
- Reset button to clear cached optimization results
- Interactive weight sliders for PnL/Sharpe/Drawdown optimization

## Components Added
- OptimizerButton: Main trigger button with inline progress
- OptimizerDialog: Full optimization interface with tabs
- OptimizerProgressBar: Real-time progress with ETA
- OptimizerResults: Before/after comparison view
- OptimizerWeightSliders: Interactive weight configuration

## API Routes
- /api/optimizer/run: Start optimization job
- /api/optimizer/status: Poll job progress
- /api/optimizer/apply: Apply optimized config
- /api/optimizer/cancel: Cancel running job
- /api/optimizer/reset: Clear cached results

## Critical Bug Fix
- Fixed optimizer script not applying symbol-specific settings
- optimizedConfig.symbols now properly updated with optimized values
- Previously only maxOpenPositions was applied, now ALL settings are applied
- Adds optimized thresholds, trade sizes, leverage, TP/SL, time windows, cooldowns

## Backend Services
- optimizerService: Job management with disk persistence
- Survives route reloads and server restarts
- Automatic config reload in UI after applying changes

## Configuration
- Added optimizer dependencies to package.json
- Updated .gitignore for backup files and optimizer cache

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* chore: add .claude settings and agents to gitignore

- Add .claude/settings.local.json to gitignore
- Add .claude/agents/ to gitignore
- Remove .claude/settings.local.json from git tracking

* feat: add dedicated /optimizer page with comprehensive UI

- Add "Optimizer" to sidebar navigation with Target icon
- Create full-page /optimizer route with three sections:
  - Configuration panel with weight sliders and symbol multi-select
  - Real-time progress tracking with OptimizerProgressBar
  - Results display with before/after comparison and per-symbol recommendations

New Components:
- OptimizerConfigPanel: Weight configuration, symbol selection, advanced options collapsible
- BeforeAfterComparison: Side-by-side metric comparison with improvement indicators
- SymbolRecommendationsTable: Sortable, expandable table showing per-symbol optimizations
- BotControlButtons: Start/Pause/Stop controls for bot management

UI Enhancements:
- Add shadcn components: Checkbox, Collapsible, AlertDialog
- Update OptimizerDialog with "Open Full Page View" link
- Add confirmation dialog for applying configuration changes
- Export results functionality with JSON download

Bug Fixes:
- Fix OptimizerProgressBar button size (xs → sm)
- Fix optimizer environment variable type errors in optimizerService
- Remove unused imports and fix ESLint errors

Closes CryptoGnome#27 - Bot control functionality (Pause/Start/Stop)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* fix: resolve order PnL display issues with simultaneous closes (CryptoGnome#39)

## Problem
- Recent orders table was not displaying all trade data correctly
- When multiple orders closed simultaneously (e.g., TP + entry order), only one PnL value was shown
- Income history matching used a 5-second time window that caused Map key collisions
- Only 5 configured symbols had their orders fetched

## Root Cause
1. Time-window based PnL matching overwrote values when multiple orders closed at the same time
2. Map structure stored only the last PnL entry per time window
3. Symbol fetch was limited to first 5 configured symbols

## Solution
- Replace income history matching with direct trade data from `/fapi/v1/userTrades` endpoint
- Use orderId-based mapping instead of time windows for precise PnL matching
- Aggregate PnL for orders with multiple fills
- Remove 5-symbol fetch limit to show all configured symbols

## Changes
- **src/lib/types/order.ts**: Add Trade interface for user trades API
- **src/lib/api/orders.ts**: Add getUserTrades() function for fetching trade history
- **src/app/api/orders/all/route.ts**: Replace income history logic with user trades, remove symbol limit

## Testing
- TypeScript compilation passes with no errors
- All configured symbols will now display order history
- Multiple simultaneous closes will each show correct PnL values
- Historical PnL data persists across page refreshes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* fix: remove shortTradeSize from default config and fix form handling

* feat: make recommended trade size clickable button

* fix: adjust trade size buffer to 30.5% and round up to nearest dollar

* chore: remove unused optimization code from SymbolConfigForm

- Removed unused state variables (_isOptimizing, _optimizationResult, _showOptimizationModal)
- Removed unused _handleOptimizeClick and _applyOptimizedParams functions
- Removed unused symbol prop from component interface
- Cleans up ~60 lines of dead code that was never called

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* feat: make version checker branch-aware for main/dev branches

- Version checker now detects current git branch dynamically
- Fetches and compares against the correct remote branch (origin/dev, origin/main, etc.)
- Displays branch name prominently in the UI alongside commit hash
- Automatically adapts when switching between branches

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* fix: correct separate trade sizes switch logic - use OR instead of AND

---------

Co-authored-by: fciaf420 <[email protected]>
Co-authored-by: Claude <[email protected]>
Co-authored-by: j4c0b1 <[email protected]>
- Replace auto-normalization with proportional distribution
- When one slider changes, automatically adjust the other two proportionally
- Maintains the ratio between unchanged sliders
- Prevents "Weights must sum to 100%" validation errors
- Removes useEffect dependency that caused re-render issues

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
- Fixed race condition where old state values were used in calculations
- Each handler now calculates all three weights at once using current values
- Changed from Math.round to ensuring exact sum by calculating remainder
- PnL slider: distributes remaining to Sharpe/Drawdown proportionally
- Sharpe slider: distributes remaining to PnL/Drawdown proportionally
- Drawdown slider: distributes remaining to PnL/Sharpe proportionally
- Handles edge case when other sliders are at 0 by splitting evenly

This ensures total always equals exactly 100% with no validation errors.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Changed strategy to prevent locked sliders:
- PnL slider: adjusts Drawdown automatically (Sharpe stays fixed)
- Sharpe slider: adjusts Drawdown automatically (PnL stays fixed)
- Drawdown slider: manual control (user adjusts PnL/Sharpe to balance)

This allows users to freely adjust all sliders without getting locked.
Added helpful tip to explain auto-adjustment behavior.

Example: Move PnL from 50→60, Drawdown auto-adjusts from 20→10
User can then manually adjust any slider to fine-tune the distribution.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
…e bug

Root cause: Parent component (OptimizerConfigPanel) created closures that
captured stale state values, causing race conditions when multiple onChange
handlers were called sequentially.

Solution:
- Added internal state (pnl, sharpe, drawdown) to OptimizerWeightSliders
- Syncs with props via useEffect when external values change
- All slider interactions use fresh internal state values
- Auto-adjusts Drawdown when PnL/Sharpe changes to maintain 100% total
- No more stale closures or race conditions

Behavior:
- Move PnL slider → Drawdown auto-adjusts (Sharpe stays fixed)
- Move Sharpe slider → Drawdown auto-adjusts (PnL stays fixed)
- Move Drawdown slider → Manual control (user adjusts PnL/Sharpe to balance)
- Total always equals 100% when adjusting PnL or Sharpe
- All sliders remain interactive and responsive

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
…allback

Fixed "Optimizer exited with code 1" error caused by missing config.user.json.

Changes:
- Added loadConfig() function with fallback logic:
  1. Try config.user.json first
  2. Fall back to config.default.json if user config doesn't exist
  3. Throw error if neither exists
- Added missing configPath variable in maybeApplyOptimizedConfig()
- Always writes optimized config to config.user.json (creating it if needed)

This matches the config loading behavior of the rest of the application
and allows the optimizer to run even when user hasn't created a config yet.

Fixes: "ENOENT: no such file or directory, open 'config.user.json'"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Fixed crash when optimizer runs with no liquidation data in database.

Changes to optimize-config.js:
- Added check for 0 liquidation events before accessing min/max price
- Shows clear error message when no data is available:
  "⚠️  No liquidation data available for analysis"
  "ℹ️  The optimizer requires historical liquidation data to function"
  "ℹ️  Please run the bot to collect data, or import existing data"
- Throws descriptive error instead of crashing on null.toFixed()

Changes to src/app/optimizer/page.tsx:
- Added toast notification on optimization error
- Shows error message to user for 10 seconds
- Resets optimizer state and returns to config screen on error

Before: TypeError: Cannot read properties of null (reading 'toFixed')
After: Clear error message explaining that liquidation data is needed

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Fixed issue where optimizer errors showed generic "Optimizer exited with code 1"
instead of the actual error message from the optimizer script.

Changes to optimizerService.ts:
- Added stdoutBuffer and stderrBuffer to capture all optimizer output
- When optimizer exits with non-zero code, parse output for error messages
- Extract error from "Error: ..." pattern in stdout
- Extract warning from "⚠️ ..." pattern as fallback
- Use last line of stderr if no structured error found
- Pass actual error message to UI instead of generic exit code message

Now users will see helpful messages like:
"Insufficient liquidation data: 0 events found. The optimizer requires historical data to analyze."

Instead of:
"Optimizer exited with code 1"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
- Check navigator.clipboard availability before use
- Add fallback method for older browsers/insecure contexts
- Handle errors with try-catch blocks
- Display appropriate error messages if copying fails
- Resolves SSR and clipboard API availability issues

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
…r-handling

fix: add proper clipboard error handling in errors page
Prevents the Node.js version string (e.g., "Node.js v18.19.1") from being
logged as an error when spawning the optimizer subprocess. This benign
stderr output was causing false error entries in the error logs database.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Detects NODE_MODULE_VERSION errors from better-sqlite3 and provides
clear instructions to run 'npm rebuild better-sqlite3' instead of
showing the raw technical error.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Fixed issue where optimizer results showed 0.00 for Sharpe Ratio, Max Drawdown, and Win Rate in the "After" section. The component was accessing performance metrics at the wrong level in the data structure.

Changes:
- Updated BeforeAfterComparison.tsx to correctly access nested long/short performance data
- Now properly aggregates metrics from rec.performance.current.long and rec.performance.current.short
- Sums Sharpe Ratio from both long and short sides
- Takes max of drawdowns across both sides
- Properly averages win rates from both long and short positions

This fixes the issue where the optimizer would complete successfully but display zeros for all metrics in the results comparison.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
…ics-display

fix: correct optimizer metrics display in BeforeAfterComparison
Fixed issue where Sharpe Ratio was displaying astronomically high values (28 trillion+) in the optimizer results. The component was summing uncapped Sharpe values instead of properly averaging them per symbol.

Changes:
- Added Sharpe Ratio capping between -5 and 5 (matching optimizer script behavior)
- Changed aggregation logic to average per symbol first (long + short / 2), then across symbols
- Separated symbolCount and sideCount for proper averaging of different metrics
- Sharpe ratios now use symbolCount, win rates use sideCount

This matches the calculation method in optimize-config.js lines 487-491 where Sharpe ratios are capped and averaged to prevent infinity from unrealistic backtests.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
…apping

fix: cap Sharpe Ratio display to prevent infinity values
This commit addresses multiple data accuracy issues in the performance chart:

**Trade Count Accuracy**
- Fixed inflated trade count by tracking unique tradeId values
- Previously counted every REALIZED_PNL event, now only unique trades
- Added Set-based deduplication to avoid double-counting

**Complete Income Tracking**
- Added missing INSURANCE_CLEAR income type tracking
- Added missing MARKET_MERCHANT_RETURN_REWARD income type tracking
- Updated DailyPnL and PerformanceMetrics interfaces
- Include all income types in net PnL calculation

**APR Calculation Fix**
- Changed from simple linear extrapolation to compound returns
- Now uses CAGR formula: (1 + return)^(365/days) - 1
- Provides more accurate annualized return projections

**Sharpe Ratio Enhancement**
- Added comprehensive calculation comments
- Updated to track new income types in metrics
- Maintained correct annualization (√365 for 24/7 crypto)

**Data Quality Indicators**
- Added recordCount field to PnLData interface
- Display warning banner when API limit (1000 records) is reached
- Added console logging for data truncation events
- Shows clear message when historical data may be incomplete

**Files Modified:**
- src/lib/api/income.ts: Core aggregation and metrics logic
- src/components/PnLChart.tsx: APR calculation and UI warnings

**Impact:**
- More accurate trade counts matching actual closed positions
- Complete income tracking including insurance and rewards
- Realistic APR projections using compound returns
- Better user transparency with data quality warnings

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
**Problem:**
- API has 1000 record limit per request
- High-volume accounts were missing historical data
- Previous workaround only fetched additional 500 records

**Solution:**
Implemented automatic pagination that fetches ALL available records:
- Loops through batches of 1000 until fewer records returned
- Uses oldest record's timestamp to fetch next batch
- Deduplicates using tranId (transaction ID)
- Includes safety limit of 10 batches max
- Comprehensive console logging for debugging

**How it works:**
1. Fetch first 1000 records (most recent)
2. If we got 1000, fetch next batch using oldest timestamp
3. Repeat until we get < 1000 records (all data retrieved)
4. Remove duplicates and sort by time

**Benefits:**
- Complete historical data for any account size
- No missing records in the middle of ranges
- Proper handling of high-volume trading accounts
- Clear logging shows exactly how many batches fetched

**UI Changes:**
- Changed warning from orange (⚠️) to blue (ℹ️)
- Now shows "Large Dataset" with record count
- Indicates pagination was used successfully

**Example Console Output:**
```
[Income API] Fetching income history for 7d...
[Income API] Batch 1: Fetched 1000 records
[Income API] Batch 2: Fetched 723 records
[Income API] Completed: Got 723 records (less than limit)
[Income API] Total unique records: 1723 (from 2 batches)
```

**Files Modified:**
- src/lib/api/income.ts: Pagination logic
- src/components/PnLChart.tsx: Updated info banner

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
**Problem:**
- Using `new Date(timestamp).toISOString().split('T')[0]` converts to UTC
- This caused timezone shifts for users not in UTC
- Example: A trade at midnight local time might show on previous day

**Root Cause:**
```typescript
// OLD (WRONG):
const date = new Date(record.time).toISOString().split('T')[0];
// For timestamp 1736640000000 (Jan 12, 2025 00:00 EST):
// Returns "2025-01-11" instead of "2025-01-12"
```

**Solution:**
Use UTC date methods directly to maintain consistency:
```typescript
// NEW (CORRECT):
const d = new Date(record.time);
const date = `${d.getUTCFullYear()}-${String(d.getUTCMonth() + 1).padStart(2, '0')}-${String(d.getUTCDate()).padStart(2, '0')}`;
// Always returns correct UTC date regardless of local timezone
```

**Why This Matters:**
- Exchange API timestamps are in UTC
- Chart X-axis parsing expects UTC dates
- Tooltip date display uses UTC dates
- Consistent UTC handling prevents off-by-one day errors

**Impact:**
- Chart dates now display correctly for all timezones
- Daily PnL aggregation matches exchange timezone
- Tooltips show accurate dates

**Files Modified:**
- src/lib/api/income.ts: Line 102-105

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Add explicit tick interval control to Recharts XAxis to ensure more dates
are displayed on the chart. Previously only 3 dates were showing on 30-day
chart due to default auto-tick generation.

Changes:
- Add `interval="preserveStartEnd"` to show start/end dates always
- Add `minTickGap={20}` to control minimum spacing between ticks
- Applied to both daily bar chart and cumulative area chart

This ensures users see appropriate date labels across the entire time range
instead of just a few sparse dates.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Added a new per-symbol configuration option that allows users to force market orders for opening positions, overriding the orderType setting.

Changes:
- Added forceMarketEntry?: boolean to SymbolConfig interface in types.ts
- Updated config.default.json with forceMarketEntry: false default
- Modified Hunter.placeTrade() to check forceMarketEntry before orderType
- Added Order Type Settings UI section in SymbolConfigForm with:
  - Order Type dropdown (LIMIT/MARKET)
  - Force Market Entry toggle switch
  - Alert message when enabled

When forceMarketEntry is true, all opening orders use MARKET type for instant fills regardless of orderType setting. This provides fine-grained per-symbol control for users who want guaranteed fills on volatile symbols.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
cj4c0b1 and others added 29 commits October 9, 2025 21:40
Update gitignore and error page layout
## Issues Fixed

1. **XAxis Domain Issue**
   - Removed problematic `domain={['dataMin', 'dataMax']}` from BarChart
   - Fixes improper date range display with sparse data

2. **Adaptive Tick Intervals**
   - Implemented smart interval calculation based on data density
   - 1-5 points: Show all dates (interval=0)
   - 6-20 points: Show start/end (interval="preserveStartEnd")
   - 21+ points: Show start only (interval="preserveStart")
   - Dynamic minTickGap: 10 for ≤10 points, 20 for >10 points

3. **Timezone-Safe Date Formatting**
   - Fixed date parsing to avoid timezone shifts
   - "2025-09-26" now correctly displays as "9/26" (not "9/25")
   - Applied to both tick formatter and tooltip
   - Uses direct string parsing instead of Date objects

4. **Enhanced Year-Month Display**
   - Long ranges (1y, all) use compact format: "25-09" vs "2025-09"

## Testing

- Created comprehensive test utility: scripts/test-chart-data.ts
- All 6 test scenarios pass
- TypeScript compilation validated

## Files Modified

- src/components/PnLChart.tsx: All chart display fixes
- scripts/test-chart-data.ts: New debugging and testing utility

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
- Add isMounted state tracking to prevent hydration errors in AppSidebar
- Conditionally apply isActive prop only after client-side mount
- Add suppressHydrationWarning to external links to silence React warnings

This prevents server/client content mismatches that occur when pathname
and other dynamic values differ during SSR and client-side rendering.
- Add insuranceClear and marketMerchantReward fields to PnL metrics
- Display insurance and rewards in PerformanceCard when non-zero
- Invalidate income cache after closing positions to reflect realized PnL
- Remove client-side date filtering in PnLChart, rely on API filtering

This ensures accurate income tracking by
…tion

Replace synthetic PnL aggregation with real trade history from exchange API.
This ensures accurate daily and per-symbol PnL metrics by:

- Fetching actual user trades for all symbols in the selected time range
- Auto-discovering traded symbols from income records (not just configured ones)
- Calculating realized PnL from closed positions instead of estimates
- Adding trade statistics (win rate, trade count, win/loss counts)
- Removing artificial zero-value entries for days without trades

The aggregateDailyPnL and aggregateBySymbol functions are replaced with
new *WithTrades variants that query the exchange API for real trade data,
providing accurate performance metrics and eliminating data inconsistencies.
Add tracking for three previously undocumented income types:
- APOLLOX_DEX_REBATE: referral/trading rebates
- USDF_BASE_REWARD: USDF staking rewards
- AUTO_EXCHANGE: automatic asset conversion

Extended all PnL interfaces and aggregation functions to track apolloxRebate
and usdfReward separately. Updated net PnL calculations to include these new
income sources for accurate profit/loss reporting across daily, symbol, and
performance metrics.
Add support for tracking and displaying ApolloX referral rebates and USDF staking rewards across income breakdown chart and per-symbol performance table.

Changes:
- Add apolloxRebate and usdfReward fields to DailyPnL and SymbolPnL interfaces
- Display rebates (yellow) and USDF rewards (cyan) as stacked bars in income chart
- Add tooltip entries for new income sources
- Highlight 'Account Rewards' row in performance table to distinguish account-level rewards from symbol-specific P&L
- Include explanatory tooltip for account rewards

This provides better visibility into all income sources beyond trading P&L, commission, and funding fees.
- Add load more pagination to RecentOrdersTable component with 50-item increments
- Implement dynamic per-symbol limit calculation for better distribution across configured symbols
- Increase max orders per symbol from 200 to 500 for better data coverage
- Extract available symbols from actual orders instead of config for accurate filtering
- Add loading states (loadingMore, hasMore) to support incremental data loading
- Add console logging for order fetching operations
- Clean up redundant variables and improve code clarity

This change improves performance when fetching orders across multiple trading pairs and provides better UX with progressive loading instead of fetching all data upfront.
Add liquidation price tracking to the position table with visual risk indicators. The new column displays:
- Liquidation price for each position
- Warning icons and color coding when price is near liquidation (<20% distance)
- Critical alerts when extremely close to liquidation (<10% distance)
- Distance percentage tooltips for better risk awareness
- Proper calculations for both LONG and SHORT positions

This enhancement helps traders monitor their liquidation risk more effectively and take preventive action before positions are automatically closed.
Add available margin check before placing orders to prevent insufficient balance errors from the exchange. The validation:

- Fetches real-time account info to calculate available vs. used margin
- Compares available balance against required margin for the trade
- Uses direction-specific trade sizes (longTradeSize/shortTradeSize)
- Blocks trade execution if insufficient margin detected
- Broadcasts detailed error information to UI including deficit amount, locked margin, and actionable suggestions
- Gracefully degrades if margin check fails, allowing exchange to reject invalid orders

This prevents failed orders due to margin locked in existing positions and provides users with clear feedback about their account state.
…instant triggers

Add comprehensive logging for threshold system configuration including:
- Startup logging showing global and per-symbol threshold settings
- Configuration change detection with before/after values
- Detailed cooldown checks displaying configured periods and time elapsed

Apply cooldown logic consistently to both threshold-based and instant
trigger systems to prevent duplicate trades within the cooldown window.
Enhanced log messages now include cooldown period in both milliseconds
and seconds for better visibility during operation.

This improves observability and ensures consistent trade spacing across
both trigger modes.
Replace all console.log, console.error, and console.warn calls with
timestamp-based logging utilities (logWithTimestamp, logErrorWithTimestamp,
logWarnWithTimestamp) throughout the bot module.

This change ensures all log messages include consistent timestamps for
better debugging and log analysis.
Add a new "REDUCE" filter option to the orders status dropdown that
displays only reduce-only orders. The implementation:

- Fetches FILLED orders when REDUCE filter is selected
- Applies client-side filtering to identify reduce-only orders based on:
  * Presence of realized PnL
  * reduceOnly flag
  * SL/TP order types (STOP_MARKET, TAKE_PROFIT_MARKET, etc.)
  * closePosition flag
- Adds "Reduce" option to the status filter dropdown

This allows users to quickly view only orders that reduced or closed
positions, separating them from position-opening orders.
Add automatic symbol discovery when no symbols are configured in the
orders API. The system now queries the last 30 days of income history
to extract and use unique symbols as a fallback, preventing empty
results when the symbol configuration is missing.

Changes:
- Query income history API
Changed per-symbol order fetch limit calculation from dynamic
scaling based on number of symbols to a fixed generous amount
(max of 200 or limit * 2). This ensures sufficient orders are
retrieved from each symbol before filtering and sorting across
all symbols.

Also added debug logging to track orders fetched per symbol and
total across all symbols for better observability.

This fixes potential issues where the previous calculation could
fetch too few orders per symbol, resulting in incomplete results
after cross-symbol filtering.
Release: Production-ready features and major improvements
Add critical safety features to prevent and track liquidation events:

- Expand stop-loss candidate range to 0.5-50% for better optimization coverage
- Implement zero-tolerance liquidation filter in parameter optimization to
  automatically reject unsafe configurations
- Add proper liquidation handling with realistic fee calculation (0.5% of
  position value) and 100% margin loss accounting
- Prioritize liquidation checks before TP/SL triggers in position management
  to accurately simulate exchange liquidation mechanics
- Track liquidation events separately in exit reasons for analysis

This ensures the backtesting engine realistically simulates liquidation risk
and automatically excludes dangerous parameter combinations that could result
in total margin loss during live trading.
- Change `let` to `const` for immutable processedData in PnLChart
- Prefix unused function parameters with underscore in RecentOrdersTable and income API
- Remove unused Clock icon import from SessionPerformanceCard
- Remove unused UserTrade type import from income API

These changes improve code quality by eliminating unused imports and making variable intentions clearer without affecting functionality.
Release: Build fixes and liquidation risk management
- Changed PNL percentage calculation to use margin instead of notional value
- Updated both server-side (API) and client-side (PositionTable) calculations
- Now matches aster.dex ROE calculation: (unrealizedPnl / margin) * 100
- Fixes issue CryptoGnome#66
- Add OPTIMIZER_SELECTED_SYMBOLS environment variable support
- Pass selected symbols from optimizer job to optimize-config.js
- Improve logging and progress reporting during optimization
- Add production-ready Dockerfile with multi-stage builds
- Add docker-compose.yml for easy deployment
- Add docker-compose.dev.yml for development mode
- Add .dockerignore for optimized builds
- Add docker-entrypoint.sh for container initialization
- Add health check API endpoint at /api/health
- Add comprehensive Docker documentation (docs/DOCKER.md)
- Add Makefile with convenient Docker commands
- Add docker-start.sh interactive setup script
- Add GitHub Actions workflow for Docker builds
- Add .env.example template
- Update README.md with Docker installation instructions

Features:
- Multi-stage build for optimal image size
- Non-root user for security
- Volume mounts for data persistence
- Health checks for monitoring
- Development and production modes
- Automatic configuration setup
- Easy backup and restore commands
- Remove 'version' attribute from docker-compose.yml
- Remove 'version' attribute from docker-compose.dev.yml
- Add DOCKER_SETUP_SUMMARY.md with comprehensive overview

Docker Compose v2 no longer requires the version attribute and shows warnings when present.
- Fix postinstall script by copying scripts directory before npm install
- Add leverage variable to positionManager TP check
- Fix unused notionalValue variable in positions API
- Replace logWithTrace with logWithTimestamp
- Remove config.user.json volume mount to prevent directory creation
- Update entrypoint to create config.user.json from defaults
- Successfully tested: container runs healthy with dashboard accessible

Docker container now starts successfully and passes health checks.
Dashboard accessible at http://localhost:3000
WebSocket available at ws://localhost:8080
@cj4c0b1 cj4c0b1 added the enhancement New feature or request label Oct 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Request: Docker Container

3 participants