Implemented a new method, `resolveTraderDataWalletKey`, to retrieve the claw402 wallet key based on the selected AI model and user ID. This enhancement allows for better integration of the claw402 model within the trader configuration, ensuring that the correct wallet key is used for trading operations. The `AutoTraderConfig` struct has been updated to include the new `Claw402WalletKey` field, improving the overall handling of wallet keys in the trading process.
When a trader uses claw402 as AI provider, the same wallet private key
is now automatically used to route nofxos data API calls (AI500, OI,
NetFlow, etc.) through claw402 payment as well.
Users don't need to configure anything extra — if they already set up
claw402 for AI, data APIs automatically go through claw402 too.
- Track consecutive AI failures
- After 3 failures: activate safe mode (no new positions, close/hold only)
- Auto-deactivate when AI recovers
- Keep loop running in safe mode (retry each cycle)
- Log clearly: 🛡️ SAFE MODE ACTIVATED/DEACTIVATED
Remove the entire AI Debate Arena module (~5,300 lines) to simplify
the codebase. This removes the multi-AI debate trading decision system
including backend engine, API handlers, database store, frontend page,
navigation, translations, and documentation references.
* feat(telegram): add AI agent bot with streaming and account context
- Add Telegram bot with long-polling and AI agent loop (api_call tool)
- SSE streaming with real-time message editing and ⏳ placeholder
- Account state injection at conversation start (models, exchanges,
strategies, traders, per-trader PnL and statistics)
- Lane semaphore per chat serializes concurrent messages (60s timeout)
- Idle timeout watchdog (60s) prevents hung streaming connections
- Look-ahead buffer prevents partial <api_call> tag leaking to user
- Fix PUT /strategies/:id to merge config (read-then-merge pattern)
- Add route registry with full API schema for LLM documentation
- Add TelegramConfig store and Web UI config modal
- Add GetAnyEnabled to AIModel store for bot LLM client selection
* fix(telegram): eliminate narration, add full-setup workflow and tests
- Rewrite NO NARRATION rule: response is EITHER api_call tag alone OR
final text reply — no text before api_call under any circumstances
- Ban all narration patterns: 现在我将/好的/正在/I will/Let me etc.
- Add 'create strategy + create trader + start' full setup workflow
- Add 12 automated tests covering:
- No narration leaking to user (5 narration variants tested)
- api_call tag never leaks to user
- Full setup workflow: POST strategy → verify → POST trader → start
- Start existing trader workflow
- Max iterations safety, tag stripping, parser edge cases
* refactor(agent): replace XML api_call with native function calling
Migrate the Telegram bot agent from an XML tag hack (<api_call>) to
OpenAI-native function calling via CallWithRequestFull.
Key changes:
- mcp/interface.go: add parseMCPResponseFull to clientHooks interface
- mcp/client.go: route callWithRequestFull through hooks for overridability
- mcp/claude_client.go: override parseMCPResponseFull for Claude response
format (tool_use blocks instead of choices[].message.tool_calls)
- telegram/agent/agent.go: rewrite Run() to use CallWithRequestFull;
define api_request tool with JSON Schema; implement tool-call loop
with role="tool" result messages; remove XML parsing entirely
- telegram/agent/apicall.go: remove parseAPICall (dead code)
- telegram/agent/prompt.go: simplify — remove XML format instructions,
replace with concise api_request tool usage instructions
- telegram/agent/agent_test.go: rebuild all tests using LLMResponse
objects; add TestNarrationStructurallyImpossible, TestOnChunkCalledWithFinalReply,
TestToolCallIDPropagated; remove XML-specific tests
Architecture advantage: with native function calling, the LLM returns
EITHER ToolCalls OR Content — never both. Narration is now structurally
impossible at the protocol level, not just enforced by prompt rules.
All 11 agent tests pass. mcp package tests pass.
* refactor(mcp): route buildRequestBodyFromRequest through hooks + full Anthropic format
Problem: callWithRequest/Full/Stream all called client.buildRequestBodyFromRequest
directly (not via hooks), so ClaudeClient could never override it. This meant
tool calling sent OpenAI format to Anthropic (wrong field names, wrong roles).
Changes:
mcp/interface.go
- Add buildRequestBodyFromRequest(*Request) map[string]any to clientHooks
- Improve comments: document what each hook group does and why
mcp/client.go
- All three paths (callWithRequest, callWithRequestFull, CallWithRequestStream)
now call client.hooks.buildRequestBodyFromRequest — ClaudeClient picks up
mcp/claude_client.go
- Full rewrite with format comparison table in package doc
- buildRequestBodyFromRequest: produces correct Anthropic wire format
* system prompt → top-level "system" field
* tools: parameters → input_schema, no "type:function" wrapper
* tool_choice "auto" → {"type":"auto"} object
* assistant tool calls → content[{type:tool_use, id, name, input}]
* role=tool results → role=user content[{type:tool_result,...}]
* consecutive tool results merged into single user turn
- convertMessagesToAnthropic: handles all three message types
- parseMCPResponseFull: extracts text + tool_use blocks
- parseMCPResponse: delegates to parseMCPResponseFull
All mcp and agent tests pass.
* fix(telegram): fix claude client dispatch + strategy creation workflow
- telegram/bot.go: clientForProvider now returns NewClaudeClient() for
'claude' provider (was incorrectly falling back to DeepSeekClient which
uses OpenAI wire format, breaking Anthropic API calls)
- api/server.go: fix scan_interval_minutes schema default (3, not 60);
POST /api/strategies now clearly states config is OPTIONAL with complete
working defaults; POST /api/traders removes redundant GET workflow note
- telegram/agent/prompt.go: simplify strategy creation — just POST {name}
without config (backend applies full working defaults automatically);
only include config when user requests custom settings
* test(mcp): add ClaudeClient wire format tests
Tests cover all Anthropic-specific format conversions:
- system prompt lifted to top-level field
- tools use input_schema (not parameters)
- tool_choice is object {type:auto} not string
- assistant tool calls → content[{type:tool_use}]
- consecutive tool results merged into single user turn
- parseMCPResponseFull: text, tool_use, and error cases
- x-api-key header (not Authorization: Bearer)
- /messages endpoint URL
* fix(telegram): clientForProvider returns correct client for all 7 providers
Previously qwen/kimi/grok/gemini all fell back to DeepSeekClient.
Each provider now gets its own dedicated client with correct default
base URL and model. All 7 providers now fully supported:
openai, deepseek, claude, qwen, kimi, grok, gemini
* fix(telegram): newLLMClient uses bound user's model, not any user's model
GetAnyEnabled() searched across all users in DB — if user B has an
enabled model, bot could use their API key while acting as user A.
Now uses GetDefault(botUserID) which only looks up the bound user's
enabled model, matching the same user scope as all API calls.
* fix(auth): single-user deployment by default, no open registration
Registration logic redesigned:
- Empty DB (first-time setup): registration always open, no config needed
- After first user exists: registration closed by default
- Multi-user opt-in: set REGISTRATION_ENABLED=true + MAX_USERS=N in .env
Config defaults changed:
- RegistrationEnabled: true → false (closed after first user)
- MaxUsers: 10 → 1 (single-user deployment default)
This eliminates the confusion of multiple users appearing in a personal
deployment where Telegram is bound to a single admin account.
* feat(solo): beginner-friendly onboarding — smart setup guide + direct config commands
start.sh:
- Interactive Telegram Bot Token prompt on first run
- Token format validation (must match 12345:ABC... pattern)
- Friendly step-by-step startup instructions after launch
telegram/bot.go:
- /start now shows context-aware setup guide based on actual config state:
- No AI model → explains how to configure, lists all providers
- AI model OK but no exchange → guides to configure exchange via chat
- All configured → full capabilities welcome message
- New: direct setup commands ('配置 deepseek sk-xxx') bypass LLM entirely
so AI model can be configured even before any model exists (bootstrap fix)
- All messages now in Chinese (匹配用户语言)
telegram/agent/prompt.go:
- Added first-time setup detection section
- Agent told to never ask user to visit web UI — everything via chat
* feat(i18n): bilingual EN/ZH setup guide with language selection
store/telegram_config.go:
- Add Language field to TelegramConfig (persisted in DB)
- Add SetLanguage(lang) and GetLanguage() methods
- Default language: English (en)
telegram/bot.go:
- First /start triggers language selection (1=English, 2=中文)
- /lang command to change language at any time
- awaitingLang state machine handles language choice before any other input
- buildSetupGuide() now fully bilingual (EN/ZH), context-aware:
Step 1: configure AI model (no model yet)
Step 2: configure exchange (model OK, no exchange)
Ready: show full capabilities
- tryHandleSetupCommand() bilingual: 'configure/配置 <provider> <key>'
- helpMessage(lang) fully bilingual
- All error/status messages bilingual
Default: English. isLangDefault() detects whether user has explicitly
chosen a language vs falling back to the 'en' default.
* fix(telegram): use Markdown rendering + simplify language selection condition
- sendMarkdownMsg() helper: sends with ParseMode=Markdown, falls back to plain text
- All formatted messages (langSelectionMsg, buildSetupGuide, helpMessage) now render
bold text and code blocks correctly in Telegram
- Simplify /start language check: isLangDefault(st) alone is sufficient
(lang == 'en' && isLangDefault was redundant — GetLanguage returns 'en' when empty)
* fix(start.sh): translate all user-facing text to English
Entire script was in Chinese. Now English-first throughout:
- startup banner, prompts, success/error messages
- setup_telegram(): English instructions and validation messages
- start(): English next-steps after launch
- stop/restart/clean/update/regenerate-keys/show_help: all English
* fix(telegram): remove 'default' user fallback — resolve user dynamically
- botUserID no longer captured once at startup (was 'default' if no user yet)
- resolveBotUser() reads first registered user from DB on demand:
* called on every /start (handles: registered after bot launch)
* called before every AI message (handles mid-session registration)
- If no user registered: clear English error 'No account found. Please register on the web UI first'
- start.sh: fix set_env_var appending without newline (token was concatenated to prev line)
* refactor(telegram): clean onboarding — web UI for setup, Telegram for operations
- /start shows clean status: 'setup required → open web UI' or 'ready → examples'
- Removed tryHandleSetupCommand (no more CLI-style 'configure deepseek sk-xxx')
- Removed automatic language selection on /start (use /lang anytime instead)
- newLLMClient returns nil when no model → clear guard, not fallback
- statusMsg() replaces buildSetupGuide(): two states only (missing config / ready)
- Bot is now purely an operations interface; config lives in the web UI
* refactor: single-user web-based setup — replace env config with Settings UI
Move from multi-user env-var config to single-user web-first architecture:
- Add SetupPage for first-time initialization (replaces /register)
- Add SettingsPage for AI models, exchanges, Telegram, and password management
- Enrich all API route schemas with exact ID usage documentation
- Add PUT /user/password endpoint for in-app password changes
- Remove REGISTRATION_ENABLED, MAX_USERS, TELEGRAM_BOT_TOKEN from env config
- Simplify LoginPage design, remove admin mode and registration links
- Telegram bot now resolves user email for identity display
- start.sh no longer runs interactive Telegram setup
* feat: add blockRun (x402 USDC) support to all AI model consumers
- telegram/bot.go: add blockrun-base, blockrun-sol, minimax to
clientForProvider; fix newLLMClient to prefer TelegramConfig.ModelID
over GetDefault; log USDC payment provider usage
- debate/engine.go: add blockrun-base, blockrun-sol to InitializeClients
- api/strategy.go: add blockrun-base, blockrun-sol to runRealAITest
- backtest/ai_client.go: add blockrun-base, blockrun-sol to configureMCPClient
* feat: add Claw402 (claw402.ai) x402 USDC payment provider
Add Claw402Client for claw402.ai's x402 micropayment gateway (Base USDC).
Supports 15+ AI models (GPT-5.4, Claude Opus, DeepSeek, Qwen, Grok, etc.)
with per-model endpoint routing.
- mcp/claw402.go: new client with model→endpoint mapping, x402 v2 payment flow
- mcp/blockrun_base.go: extract shared signX402Payment() for reuse
- Register "claw402" provider in all 6 consumer switch statements:
api/server.go, api/strategy.go, trader/auto_trader.go,
telegram/bot.go, debate/engine.go, backtest/ai_client.go
* feat: redesign Claw402 model config UI — friendly wallet setup, USDC guide, official logo, nginx no-cache for index.html
* refactor: centralize x402 payment flow into shared mcp/x402.go
Extract duplicated doRequestWithPayment/call/CallWithRequestFull/buildRequest/
setAuthHeader (~165 lines x3) into shared helpers in mcp/x402.go. Consolidate
shared types (x402v2PaymentRequired, x402AcceptOption, x402Resource) and remove
duplicate Solana types. Fix validAfter to 0 (official SDK standard), drain 402
body before retry, log Payment-Response tx hash, check Payment-Required before
X-Payment-Required.
* fix: stop PR template bot from overwriting user-written descriptions
The pr-template-suggester workflow was triggered on opened/edited/synchronize
events and forcefully replaced the PR body with a template when body < 100 chars.
This caused user-written descriptions to be overwritten.
Replace with a lightweight labeler (OpenClaw-style) that:
- Only adds labels (backend/frontend/docs, size: XS/S/M/L/XL)
- Never modifies the PR body
- Simplified unified PR template at .github/pull_request_template.md
* chore: simplify PR template (OpenClaw-style)
Integrates BlockRun (blockrun.ai) as a new AI provider option via x402
micropayment protocol, allowing users to access top AI models with USDC
without requiring individual API keys.
- Add BlockRun Base (EVM) and Solana wallet providers to model selector
- Implement x402 v2 EIP-712 payment signing for Base (mcp/blockrun_base.go)
- Implement x402 v2 SPL TransferChecked signing for Solana (mcp/blockrun_sol.go)
- Wire blockrun-base and blockrun-sol into trader factory (auto_trader.go)
- Register both providers in supported models API (server.go)
- Add BlockRun card UI with wallet key input in Step 0/1 of model config modal
- Add BlockRun SVG icon and ModelIcons support
- Add setup guides for Base and Solana wallet configuration (docs/)
- Available flagship models: GPT-5.4, Claude Opus 4.6, Gemini 3.1 Pro,
Grok 3, DeepSeek Chat, MiniMax M2.5
Add MiniMax as a new AI model provider with OpenAI-compatible API.
Supported models:
- MiniMax-M2.5 (default) - Peak Performance, Ultimate Value
- MiniMax-M2.5-highspeed - Same performance, faster and more agile
Changes:
- Add MiniMax client (mcp/minimax_client.go) with OpenAI-compatible API
- Add comprehensive unit tests (mcp/minimax_client_test.go)
- Add WithMiniMaxConfig option (mcp/options.go)
- Register MiniMax provider in trader, debate engine, backtest, and API
- Add MiniMax to frontend provider config and model icons
- Add MiniMax SVG icon
API Base URL: https://api.minimax.io/v1
This PR adds support for Hyperliquid's Unified Account mode where Spot USDC
balance can be used as collateral for Perpetual trading.
Changes:
- Add HyperliquidUnifiedAcct field to Exchange config (default: true)
- Update HyperliquidTrader to support unified account mode
- When enabled, Spot USDC balance is added to available trading balance
- Update API request/response structs for unified account toggle
- Update trader config propagation from exchange config
This aligns with Hyperliquid's roadmap to make Unified Account the default.
- Add adaptivePriceRound() in store/position.go for database storage
- Update position_builder.go to use adaptive precision for entry/exit prices
- Add Gate to OrderSync skip list in auto_trader.go
- Add debug logging in gate/order_sync.go for price parsing issues
- Create web/src/utils/format.ts with formatPrice() for frontend display
- Update TraderDashboardPage.tsx and PositionHistory.tsx to use adaptive formatting
Fixes issue where meme coin prices (e.g. 0.000000166) displayed as 0.0000
- Add server time synchronization for KuCoin API to fix timestamp error (400002)
- Return empty list instead of error when no available coins (ai500.go)
- Save cycle record even when no candidate coins (show in frontend without red error)
- Update Claude icon to Anthropic dark brand color (#141413)
- Add exchange and AI model icons to README.md and README.ja.md
Gate.io Integration:
- Add Gate trader with full Trader interface implementation
- Add order_sync.go for background trade synchronization
- Fix quantity display (convert contracts to actual tokens via quanto_multiplier)
- Fix fill price return in OpenLong/OpenShort/CloseLong/CloseShort
- Add Gate-specific CoinAnk K-line data source support
- Add Gate to supported exchanges in frontend and backend
- Add Gate/KuCoin logo SVG icons
Trader Package Refactoring:
- Move exchange-specific code into subdirectories (binance/, bybit/, okx/, bitget/, hyperliquid/, aster/, lighter/, gate/)
- Create types/ package for shared types to avoid circular dependencies
- Move TraderTestSuite to trader/testutil package to avoid import cycles
- Update market.GetWithExchange to support exchange-specific data
* feat: add AI grid trading and market regime classification
- Add GridTrader interface with PlaceLimitOrder, CancelOrder, GetOrderBook
- Implement GridTrader for all exchanges (Binance, Bybit, OKX, Bitget, Hyperliquid, Aster, Lighter)
- Add grid engine with ATR-based boundary calculation and fund distribution
- Add market regime classification documents (Chinese/English)
- Add GridConfigEditor component for frontend configuration
* fix: implement GetOpenOrders for Lighter exchange
* debug: add logging for Lighter GetActiveOrders API call
* fix: correct Lighter API response parsing for GetOpenOrders
- 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
* feat: implement GetOpenOrders for Aster, OKX, Bitget exchanges
- Aster: uses /fapi/v3/openOrders endpoint
- OKX: uses /api/v5/trade/orders-pending and orders-algo-pending
- Bitget: uses /api/v2/mix/order/orders-pending and orders-plan-pending
* fix: address code review issues for GetOpenOrders
- 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
* fix: provide FromAccountIndex and ApiKeyIndex for Lighter nonce auto-fetch
Root cause: SDK requires these fields to fetch nonce from API, otherwise nonce gets cached/stuck
* fix: use auth query parameter instead of Authorization header for Lighter API
* test: add Lighter API authentication tests and diagnostic tools
* fix(grid): add leverage setting before order placement
CRITICAL BUG FIX:
- Call SetLeverage() in GridTraderAdapter.PlaceLimitOrder()
- Set leverage during grid initialization
- Log leverage setting results
* fix(grid): prevent CancelOrder from canceling all orders
CRITICAL BUG FIX:
- CancelOrder no longer calls CancelAllOrders
- Try exchange-specific CancelOrder if available
- Return error if individual cancellation not supported
* fix(grid): add total position value limit check
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
* feat(grid): implement stop loss execution
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
* feat(grid): add breakout detection and auto-pause
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
* feat(grid): enforce max drawdown limit with emergency exit
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
* feat(grid): enforce daily loss limit
- 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
* fix(grid): update daily PnL when stop loss is executed
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.
* feat(grid): add automatic grid adjustment
- 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
* fix(grid): recalculate bounds in autoAdjustGrid before reinitializing levels
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.
* fix(grid): improve order state sync logic
- 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
* fix(grid): use actual PositionSize sum instead of count in syncGridState heuristic
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.
* docs: add grid market regime detection design
Design for enhanced market state recognition with:
- Multi-dimensional indicators (ATR, Bollinger, EMA, MACD, RSI)
- Multi-period box indicators (72/240/500 1h candles)
- 4-level ranging classification
- Breakout detection and handling
- Frontend risk control panel
* docs: add grid market regime implementation plan
20 tasks covering:
- Donchian channel calculation
- Box data types and API
- Regime classification (4 levels)
- Breakout detection and handling
- False breakout recovery
- Frontend risk panel
- AI prompt updates
* feat(market): add Donchian channel calculation
Add calculateDonchian function to compute highest high and lowest low
over a specified period. This is the foundation for box (range) detection
in the multi-period box indicator system for grid trading.
* fix(market): handle invalid period in calculateDonchian
* feat(market): add BoxData and RegimeLevel types
* feat(market): add GetBoxData for multi-period box calculation
Adds calculateBoxData internal function and GetBoxData public API that
fetches 1h klines and computes three Donchian box levels (short/mid/long).
This will be used by the grid trading system to detect market regime.
* feat(store): add box and regime fields to grid models
* feat(trader): add regime classification and breakout detection
Implements Tasks 6-9 for grid market regime awareness:
- Task 6: classifyRegimeLevel with Bollinger/ATR thresholds
- Task 7: detectBoxBreakout for multi-period box breakouts
- Task 8: confirmBreakout with 3-candle confirmation logic
- Task 9: getBreakoutAction mapping breakout levels to actions
* feat(trader): integrate box breakout detection into grid cycle
- Task 10: Add checkBoxBreakout with 3-candle confirmation
- Task 11: Add checkFalseBreakoutRecovery for 50% position recovery
- Task 12: Add box/breakout/regime fields to GridState
* feat: add grid risk panel with API endpoint
- Task 13: Add GridRiskInfo type to frontend
- Task 14: Add /traders/:id/grid-risk API endpoint
- Task 15: Add GetGridRiskInfo method to AutoTrader
- Task 16: Create GridRiskPanel component with i18n
* feat(kernel): add box indicators to AI prompt
- Add BoxData field to GridContext
- Add box indicator table to both zh/en prompts
- Show breakout/warning alerts based on price position
* feat(web): integrate GridRiskPanel into TraderDashboardPage
* feat(lighter): improve API key validation and market caching
- Add API key validation status tracking
- Add market list caching to reduce API calls
- Improve logging (debug vs info levels)
- Add comprehensive integration tests
- Update trader manager and store for lighter support
* fix: remove hardcoded test wallet address
* fix(grid): improve GridRiskPanel layout and fix liquidation data
- Make panel collapsible with summary badges when collapsed
- Use compact 2-column grid layout for detailed info
- Fix auth token key (token -> auth_token)
- Only calculate liquidation distance when position exists
* fix(grid): add isRunning checks to prevent trades after Stop() is called
- 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
- 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
- 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
- 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
- Add maxMktSz check for OKX market orders to prevent exceeding limits
- Increase margin safety buffer (0.1% fee + 1% buffer) for all exchanges
- Fix Binance position closure detection with direct trade queries
- Move Recent Completed Trades before Current Positions in AI prompt
- Update README screenshots with table layout for better alignment
- Fix initial balance using available_balance instead of total_equity
- Fix WSMonitor nil pointer by starting market monitor before loading traders
- Add strategy name display on traders list and dashboard pages
- Various position sync and trading improvements
- Remove trader_orders table and OrderSyncManager (never worked correctly)
- Poll GetOrderStatus to get actual avgPrice, executedQty, and commission
- Get entry price from exchange GetPositions API when closing positions
- Pass fee to trader_positions table on close
- Move TraderStats type to position.go
- Add RawResponse field to FullDecision and DecisionRecord
- Save raw AI response to database for debugging parse failures
- Add IMPORTANT note in prompt: all numeric values must be calculated numbers, not formulas
- Remove system_config, beta_codes, signal_source tables and related code
- Simplify config.go to only read from .env (APIServerPort, JWTSecret, RegistrationEnabled)
- Remove GetCustomCoins, use all USDT perpetual contracts for WSMonitor
- Add trader_equity_snapshots table for equity tracking
- Remove signal source modal from frontend AITradersPage
- Fix WSMonitor nil panic by restoring initialization in main.go
* feat: add OKX exchange trading support
- Add OKX trader client with full trading API integration
- Support API Key, Secret Key, and Passphrase authentication
- Add OKX icon and frontend configuration modal
- Update exchange store and types for OKX fields
* fix: add passphrase column migration and fix exchange type mapping
* fix: show OKX input fields in exchange config modal
* fix: ensure all supported exchanges exist for user when listing
* fix: simplify exchange type check condition for OKX
* debug: add visible debug info for exchange id
* fix: remove debug info from exchange config modal
* fix: add OKX to exchange type condition in AITradersPage
* feat: complete OKX trading support and fix exchange config issues
- Add LIGHTER exchange UI support in AITradersPage
- Add passphrase field to UpdateExchangeConfigRequest type
- Fix OKX HTTP client to bypass proxy (disable system proxy)
- Auto-fetch initial balance from exchange when not set
- Support multiple balance field names for different exchanges
- Add detailed error messages when trader fails to load
- Add lighter_api_key_private_key field to exchange store
* feat: add Strategy Studio with multi-timeframe support
- Add Strategy Studio page with three-column layout for strategy management
- Support multi-timeframe K-line data selection (5m, 15m, 1h, 4h, etc.)
- Add GetWithTimeframes() function in market package for fetching multiple timeframes
- Add TimeframeSeriesData struct for storing per-timeframe technical indicators
- Update formatMarketData() to display all selected timeframes in AI prompt
- Add strategy API endpoints for CRUD operations and test run
- Integrate real AI test runs with configured AI models
- Support custom AI500 and OI Top API URLs from strategy config
* docs: add Strategy Studio screenshot to README files
* feat: add quant data integration and fix position click navigation
- Integrate quant data API (netflow, OI, price changes) into Strategy Studio
- Add enable_quant_data toggle in indicator editor
- Fix position symbol click to navigate to chart (sync defaultSymbol prop)
- Fix TradingView chart fullscreen flickering
* feat: add Strategy Studio with multi-timeframe support
- Add Strategy Studio page with three-column layout for strategy management
- Support multi-timeframe K-line data selection (5m, 15m, 1h, 4h, etc.)
- Add GetWithTimeframes() function in market package for fetching multiple timeframes
- Add TimeframeSeriesData struct for storing per-timeframe technical indicators
- Update formatMarketData() to display all selected timeframes in AI prompt
- Add strategy API endpoints for CRUD operations and test run
- Integrate real AI test runs with configured AI models
- Support custom AI500 and OI Top API URLs from strategy config
* docs: add Strategy Studio screenshot to README files
* fix: correct strategy-studio.png filename case in README
* refactor: remove legacy signal source config and simplify trader creation
- Remove signal source configuration from traders page (now handled by strategy)
- Remove advanced options (legacy config) from TraderConfigModal
- Rename default strategy to "默认山寨策略" with AI500 coin pool URL
- Delete SignalSourceModal and SignalSourceWarning components
- Clean up related stores, hooks, and page components
- Add exchange_id column to track which exchange the position is from
- Update all SELECT/INSERT queries to include exchange_id
- Set exchange_id when creating position record in AutoTrader
- Add migration to add column to existing tables
* refactor: 简化交易动作,移除 update_stop_loss/update_take_profit/partial_close
- 移除 Decision 结构体中的 NewStopLoss, NewTakeProfit, ClosePercentage 字段
- 删除 executeUpdateStopLossWithRecord, executeUpdateTakeProfitWithRecord, executePartialCloseWithRecord 函数
- 简化 logger 中的 partial_close 聚合逻辑
- 更新 AI prompt 和验证逻辑,只保留 6 个核心动作
- 清理相关测试代码
保留的交易动作: open_long, open_short, close_long, close_short, hold, wait
* refactor: 移除 AI学习与反思 模块
- 删除前端 AILearning.tsx 组件和相关引用
- 删除后端 /performance API 接口
- 删除 logger 中 AnalyzePerformance、calculateSharpeRatio 等函数
- 删除 PerformanceAnalysis、TradeOutcome、SymbolPerformance 等结构体
- 删除 Context 中的 Performance 字段
- 移除 AI prompt 中夏普比率自我进化相关内容
- 清理 i18n 翻译文件中的相关条目
该模块基于磁盘存储计算,经常出错,做减法移除
* refactor: 将数据库操作统一迁移到 store 包
- 新增 store/ 包,统一管理所有数据库操作
- store.go: 主 Store 结构,懒加载各子模块
- user.go, ai_model.go, exchange.go, trader.go 等子模块
- 支持加密/解密函数注入 (SetCryptoFuncs)
- 更新 main.go 使用 store.New() 替代 config.NewDatabase()
- 更新 api/server.go 使用 *store.Store 替代 *config.Database
- 更新 manager/trader_manager.go:
- 新增 LoadTradersFromStore, LoadUserTradersFromStore 方法
- 删除旧版 LoadUserTraders, LoadTraderByID, loadSingleTrader 等方法
- 移除 nofx/config 依赖
- 删除 config/database.go 和 config/database_test.go
- 更新 api/server_test.go 使用 store.Trader 类型
- 清理 logger/ 包中未使用的 telegram 相关代码
* refactor: unify encryption key management via .env
- Remove redundant EncryptionManager and SecureStorage
- Simplify CryptoService to load keys from environment variables only
- RSA_PRIVATE_KEY: RSA private key for client-server encryption
- DATA_ENCRYPTION_KEY: AES-256 key for database encryption
- JWT_SECRET: JWT signing key for authentication
- Update start.sh to auto-generate missing keys on first run
- Remove secrets/ directory and file-based key storage
- Delete obsolete encryption setup scripts
- Update .env.example with all required keys
* refactor: unify logger usage across mcp package
- Add MCPLogger adapter in logger package to implement mcp.Logger interface
- Update mcp/config.go to use global logger by default
- Remove redundant defaultLogger from mcp/logger.go
- Keep noopLogger for testing purposes
* chore: remove leftover test RSA key file
* chore: remove unused bootstrap package
* refactor: unify logging to use logger package instead of fmt/log
- Replace all fmt.Print/log.Print calls with logger package
- Add auto-initialization in logger package init() for test compatibility
- Update main.go to initialize logger at startup
- Migrate all packages: api, backtest, config, decision, manager, market, store, trader
* refactor: rename database file from config.db to data.db
- Update main.go, start.sh, docker-compose.yml
- Update migration script and documentation
- Update .gitignore and translations
* fix: add RSA_PRIVATE_KEY to docker-compose environment
* fix: add registration_enabled to /api/config response
* fix: Fix navigation between login and register pages
Use window.location.href instead of react-router's navigate() to fix
the issue where URL changes but the page doesn't reload due to App.tsx
using custom route state management.
* fix: Switch SQLite from WAL to DELETE mode for Docker compatibility
WAL mode causes data sync issues with Docker bind mounts on macOS due
to incompatible file locking mechanisms between the container and host.
DELETE mode (traditional journaling) ensures data is written directly
to the main database file.
* refactor: Remove default user from database initialization
The default user was a legacy placeholder that is no longer needed now
that proper user registration is in place.
* feat: Add order tracking system with centralized status sync
- Add trader_orders table for tracking all order lifecycle
- Implement GetOrderStatus interface for all exchanges (Binance, Bybit, Hyperliquid, Aster, Lighter)
- Create OrderSyncManager for centralized order status polling
- Add trading statistics (Sharpe ratio, win rate, profit factor) to AI context
- Include recent completed orders in AI decision input
- Remove per-order goroutine polling in favor of global sync manager
* feat: Add TradingView K-line chart to dashboard
- Create TradingViewChart component with exchange/symbol selectors
- Support Binance, Bybit, OKX, Coinbase, Kraken, KuCoin exchanges
- Add popular symbols quick selection
- Support multiple timeframes (1m to 1W)
- Add fullscreen mode
- Integrate with Dashboard page below equity chart
- Add i18n translations for zh/en
* refactor: Replace separate charts with tabbed ChartTabs component
- Create ChartTabs component with tab switching between equity curve and K-line
- Add embedded mode support for EquityChart and TradingViewChart
- User can now switch between account equity and market chart in same area
* fix: Use ChartTabs in App.tsx and fix embedded mode in EquityChart
- Replace EquityChart with ChartTabs in App.tsx (the actual dashboard renderer)
- Fix EquityChart embedded mode for error and empty data states
- Rename interval state to timeInterval to avoid shadowing window.setInterval
- Add debug logging to ChartTabs component
* feat: Add position tracking system for accurate trade history
- Add trader_positions table to track complete open/close trades
- Add PositionSyncManager to detect manual closes via polling
- Record position on open, update on close with PnL calculation
- Use positions table for trading stats and recent trades (replacing orders table)
- Fix TradingView chart symbol format (add .P suffix for futures)
- Fix DecisionCard wait/hold action color (gray instead of red)
- Auto-append USDT suffix for custom symbol input
* update
---------