The position-based heuristic was using `float64(previousFilledCount) * level.OrderQuantity`
which incorrectly assumed uniform order quantities. Since the grid uses weighted distribution
(gaussian, pyramid, uniform) where orders have different quantities, this could lead to
incorrect fill detection.
Now sums the actual PositionSize from filled levels for accurate comparison.
Also adds warning log when GetPositions() fails.
- Don't assume missing orders are filled
- Compare position size to determine fill vs cancel
- Properly reset cancelled orders to empty state
- More accurate grid state tracking
Critical fix for grid auto-adjustment:
- Recalculate grid bounds (UpperPrice, LowerPrice, GridSpacing) centered
on current price before reinitializing grid levels
- Preserve filled positions during adjustment by saving and restoring
them to the closest new level after reinitialization
- Hold mutex lock for the entire adjustment operation to ensure atomicity
- Add locked variants of calculateDefaultBounds, calculateATRBounds, and
initializeGridLevels to use during adjustment
Without this fix, autoAdjustGrid was using old boundaries when creating
new grid levels, defeating the purpose of auto-adjustment when price
moved significantly.
- New checkGridSkew() detects imbalanced grid
- autoAdjustGrid() reinitializes around current price
- Prevents grid from becoming ineffective after drift
- Triggers when one side is 3x more filled than other
The updateDailyPnL() function was added but never called, leaving
DailyPnL always at 0 and preventing daily loss limit checks from
triggering.
This fix updates DailyPnL and TotalProfit directly in checkAndExecuteStopLoss()
when a stop loss is executed. We update directly rather than calling
updateDailyPnL() because the mutex is already held in that function.
- Add checkDailyLossLimit() function to check if daily loss exceeds limit
- Track daily PnL with auto-reset at midnight
- Pause grid when DailyLossLimitPct exceeded
- Add updateDailyPnL() helper for realized PnL tracking
- Prevent excessive single-day losses
CRITICAL: Add drawdown protection
- New checkMaxDrawdown() function tracks peak equity
- emergencyExit() closes all positions and cancels orders
- Auto-pause grid when MaxDrawdownPct exceeded
- Protect capital from excessive losses
CRITICAL: Detect price breakout from grid range
- New checkBreakout() function to detect upper/lower breakouts
- Auto-pause grid on significant breakout (>2%)
- Cancel all orders when breakout detected
- Prevent continued losses in trending market
- Minor breakouts (1-2%) logged for AI consideration
CRITICAL: Add code-level stop loss protection
- New checkAndExecuteStopLoss() function
- Checks each filled level against StopLossPct
- Automatically closes positions exceeding stop loss
- Called during every grid state sync
CRITICAL: Prevent excessive position accumulation
- New checkTotalPositionLimit() function
- Checks current + pending + new order value
- Rejects orders that would exceed TotalInvestment x Leverage
- Logs clear error messages when limit exceeded
CRITICAL BUG FIX:
- CancelOrder no longer calls CancelAllOrders
- Try exchange-specific CancelOrder if available
- Return error if individual cancellation not supported
- Add error logging for OKX/Bitget API failures (was silently swallowed)
- Fix Lighter position side logic to handle reduce-only orders
- Change verbose debug logs from Infof to Debugf level
- Changed response field from 'data' to 'orders' to match Lighter API
- Updated OrderResponse struct to match Lighter's actual field names
- Fixed field types: price/quantity as strings, is_ask for side
- Convert all time.Time fields to int64 Unix milliseconds (UTC)
- Add PostgreSQL migration to convert timestamp columns to bigint
- Reduce Binance sync window from 7 days to 24 hours
- Fix dashboard trader name visibility (add nofx-text-main color)
- Add position value column to history table
- Remove hardcoded API keys from test files
- Add NowFunc to GORM config for UTC auto-generated timestamps
- Add .UTC() to all time.UnixMilli() calls in trader files
- Add .UTC() to all time.Now() calls in store and api files
- Fix TypeScript unused imports in frontend
- Add unified NofxOS API key configuration in IndicatorEditor
- Add language field to StrategyConfig for consistent prompt generation
- Auto-update prompt sections when interface language changes
- Remove scattered URL inputs from CoinSourceEditor and IndicatorEditor
- Create nofxos provider package with formatted data output
- Update kernel engine to use config-based language setting
- Migrate all store packages from raw database/sql to GORM ORM
- Add PostgreSQL support alongside SQLite
- Move EncryptedString type to crypto package for cleaner architecture
- Add automatic encryption/decryption for sensitive fields (API keys, secrets)
- Fix PostgreSQL AutoMigrate conflicts by skipping existing tables
- Fix duplicate /klines route registration
- Update tests to use GORM database connections
- Add database configuration support in config package
- Add incremental sync for Binance trades using COMMISSION detection and fromId
- Add stop loss and take profit order support for xyz dex assets
- Add pagination for current positions and position history in UI
- Fix chart market type auto-selection based on exchange
- Fix xyz dex balance calculation (use marginSummary for isolated margin)
- Add Alpaca provider for US stocks market data
- Add TwelveData provider for forex & metals market data
- Add Hyperliquid kline provider
- Centralize API keys in config system
- Add builder fee for order routing
- Improve chart UI with compact design
- Fix position history fee display precision
- Add comprehensive balance calculation tests
- Add historical trading statistics to AI decision context with language detection
- Remove win rate from metrics, focus on profit factor, sharpe ratio, win/loss ratio
- Add option to clear trading data tables during one-click deployment
- Add sqlite to Docker runtime for container-based data clearing
- Remove leverage column from position history table
- Fix max drawdown calculation using virtual starting equity
- Add formula tooltips for all statistics metrics
- Remove leverage parameter from pnlPct calculation
- Parse mgnMode field from OKX positions API response
- Use position's mgnMode (cross/isolated) in close orders instead of hardcoding cross
- This fixes 'no position in this direction' error when closing isolated margin positions
- Add order sync support for Binance, Hyperliquid, Bybit, OKX, Bitget, Aster exchanges
- Fix weighted average exit price calculation for partial closes
- Handle position flip (翻仓) scenarios correctly
- Fix symbol normalization (ETH vs ETHUSDT)
- Skip order recording for exchanges with OrderSync to avoid duplicates
- Add chart timezone localization
- Fix hardcoded 5x position ratio in AI prompt example, now uses configured ratio
- Add position sizing guidance section for AI to calculate proper position size
- Add sub_accounts support for Lighter account API
Lighter SDK validates that StopLossOrder (type=2) and TakeProfitOrder (type=4)
must have TimeInForce=0 (ImmediateOrCancel), not TimeInForce=1 (GoodTillTime).
This was causing stop-loss and take-profit orders to fail validation and not
be submitted to Lighter exchange.
- Upgrade go-binance to v2.8.9 with new Algo Order API
- Migrate SetStopLoss/SetTakeProfit to use AlgoOrderTypeStopMarket/TakeProfitMarket
- Update cancel functions to handle both legacy and Algo orders
- Fix Lighter stop orders using correct order types (type=2/4) with TriggerPrice
- Add CancelAllOrders before opening positions for Bybit and Lighter
- Fix decision limit selector in API handler
- Add stop_loss/take_profit/confidence fields to DecisionAction
- Store decisions array in database with proper serialization
- Redesign DecisionCard with beautiful entry/SL/TP display
- Fix Lighter API field name mismatches (position/size, avg_entry_price/entry_price, sign/side)
- Fix GetBalance return format to match standard fields (totalWalletBalance, totalUnrealizedProfit)
- Fix GetPositions return format to match standard fields (positionAmt, markPrice, unRealizedProfit)
- Add API Key Index field to frontend with explanation
- Update Lighter referral link
- Disable Lighter testnet (mainnet only)
- Add load error tracking for better error messages
- Remove old Lighter V1 implementation files
- Remove test credentials from test files
- Add BitgetTrader with full trading implementation
- Support one-way position mode with proper API parameters
- Add Bitget to all exchange switch statements
- Update exchange icons (Bybit, OKX, Bitget, Lighter)
- Add Bitget to frontend exchange config modal
- Add OI ranking data fetching and formatting for AI prompts
- Fix trader update not saving strategy_id, ai_model_id, initial_balance
- Fix AI API key not set for non-qwen/deepseek providers
- Add strategy_id to trader config API response
- Remove old trader from memory before reloading on update
- Clean up unused useTraderActions.ts
- Add AI debate arena for multi-AI trading decisions
- Fix debate consensus calculation and display
- Fix vote parsing to support both <decision> and <final_vote> tags
- Fix JSON field name compatibility (stop_loss/stop_loss_pct)
- Fix symbol validation to prevent AI hallucinating invalid symbols
- Fix Bybit position side display (was uppercase, now lowercase for consistency)
- Fix NOFX logo navigation to home page
- Add detailed logging for debugging trade execution
- Add new MCP clients for Grok (xAI), OpenAI, Claude, Gemini, Kimi
- Update auto_trader, backtest, and strategy to support all providers
- Add provider icons and fix SVG gradient conflicts
- Add API application links and hints in model config modal
- Show model version in AI model list cards
- Add Chinese/English translations for provider hints
- Remove deprecated traders component files
- Fix OpenLong/OpenShort: use quantity/ctVal instead of quantity*price/ctVal
- Fix GetPositions: convert contract count to base asset (posAmt = contracts * ctVal)
- Fix CloseLong/CloseShort: convert base asset to contracts before sending order
- Fix GetOrderStatus: convert executedQty from contracts to base asset
- Fix SetStopLoss/SetTakeProfit/FormatQuantity: same contract conversion fix