mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-11 23:07:01 +08:00
Merge pull request #416 from zhouyongyou/fix/bug-fixes-collection-v2
fix: 修復 6 個 bug(替代 #271)
This commit is contained in:
@@ -859,19 +859,12 @@ func (s *Server) handleTraderList(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AIModelID 应该已经是 provider(如 "deepseek"),直接使用
|
// 返回完整的 AIModelID(如 "admin_deepseek"),不要截断
|
||||||
// 如果是旧数据格式(如 "admin_deepseek"),提取 provider 部分
|
// 前端需要完整 ID 来验证模型是否存在(与 handleGetTraderConfig 保持一致)
|
||||||
aiModelID := trader.AIModelID
|
|
||||||
// 兼容旧数据:如果包含下划线,提取最后一部分作为 provider
|
|
||||||
if strings.Contains(aiModelID, "_") {
|
|
||||||
parts := strings.Split(aiModelID, "_")
|
|
||||||
aiModelID = parts[len(parts)-1]
|
|
||||||
}
|
|
||||||
|
|
||||||
result = append(result, map[string]interface{}{
|
result = append(result, map[string]interface{}{
|
||||||
"trader_id": trader.ID,
|
"trader_id": trader.ID,
|
||||||
"trader_name": trader.Name,
|
"trader_name": trader.Name,
|
||||||
"ai_model": aiModelID,
|
"ai_model": trader.AIModelID, // 使用完整 ID
|
||||||
"exchange_id": trader.ExchangeID,
|
"exchange_id": trader.ExchangeID,
|
||||||
"is_running": isRunning,
|
"is_running": isRunning,
|
||||||
"initial_balance": trader.InitialBalance,
|
"initial_balance": trader.InitialBalance,
|
||||||
@@ -1801,4 +1794,3 @@ func (s *Server) handleGetPublicTraderConfig(c *gin.Context) {
|
|||||||
|
|
||||||
c.JSON(http.StatusOK, result)
|
c.JSON(http.StatusOK, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -258,17 +258,17 @@ func (d *Database) initDefaultData() error {
|
|||||||
|
|
||||||
// 初始化系统配置 - 创建所有字段,设置默认值,后续由config.json同步更新
|
// 初始化系统配置 - 创建所有字段,设置默认值,后续由config.json同步更新
|
||||||
systemConfigs := map[string]string{
|
systemConfigs := map[string]string{
|
||||||
"admin_mode": "true", // 默认开启管理员模式,便于首次使用
|
"admin_mode": "true", // 默认开启管理员模式,便于首次使用
|
||||||
"beta_mode": "false", // 默认关闭内测模式
|
"beta_mode": "false", // 默认关闭内测模式
|
||||||
"api_server_port": "8080", // 默认API端口
|
"api_server_port": "8080", // 默认API端口
|
||||||
"use_default_coins": "true", // 默认使用内置币种列表
|
"use_default_coins": "true", // 默认使用内置币种列表
|
||||||
"default_coins": `["BTCUSDT","ETHUSDT","SOLUSDT","BNBUSDT","XRPUSDT","DOGEUSDT","ADAUSDT","HYPEUSDT"]`, // 默认币种列表(JSON格式)
|
"default_coins": `["BTCUSDT","ETHUSDT","SOLUSDT","BNBUSDT","XRPUSDT","DOGEUSDT","ADAUSDT","HYPEUSDT"]`, // 默认币种列表(JSON格式)
|
||||||
"max_daily_loss": "10.0", // 最大日损失百分比
|
"max_daily_loss": "10.0", // 最大日损失百分比
|
||||||
"max_drawdown": "20.0", // 最大回撤百分比
|
"max_drawdown": "20.0", // 最大回撤百分比
|
||||||
"stop_trading_minutes": "60", // 停止交易时间(分钟)
|
"stop_trading_minutes": "60", // 停止交易时间(分钟)
|
||||||
"btc_eth_leverage": "5", // BTC/ETH杠杆倍数
|
"btc_eth_leverage": "5", // BTC/ETH杠杆倍数
|
||||||
"altcoin_leverage": "5", // 山寨币杠杆倍数
|
"altcoin_leverage": "5", // 山寨币杠杆倍数
|
||||||
"jwt_secret": "", // JWT密钥,默认为空,由config.json或系统生成
|
"jwt_secret": "", // JWT密钥,默认为空,由config.json或系统生成
|
||||||
}
|
}
|
||||||
|
|
||||||
for key, value := range systemConfigs {
|
for key, value := range systemConfigs {
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -10,7 +10,7 @@ require (
|
|||||||
github.com/golang-jwt/jwt/v5 v5.2.0
|
github.com/golang-jwt/jwt/v5 v5.2.0
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/gorilla/websocket v1.5.3
|
github.com/gorilla/websocket v1.5.3
|
||||||
github.com/mattn/go-sqlite3 v1.14.16
|
github.com/mattn/go-sqlite3 v1.14.22
|
||||||
github.com/pquerna/otp v1.4.0
|
github.com/pquerna/otp v1.4.0
|
||||||
github.com/sirupsen/logrus v1.9.3
|
github.com/sirupsen/logrus v1.9.3
|
||||||
github.com/sonirico/go-hyperliquid v0.17.0
|
github.com/sonirico/go-hyperliquid v0.17.0
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -120,8 +120,8 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
|
|||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
||||||
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||||
github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
|
github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
|
||||||
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
|
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
|
||||||
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
|
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
|
||||||
|
|||||||
@@ -295,6 +295,8 @@ func isRetryableError(err error) bool {
|
|||||||
"connection refused",
|
"connection refused",
|
||||||
"temporary failure",
|
"temporary failure",
|
||||||
"no such host",
|
"no such host",
|
||||||
|
"stream error", // HTTP/2 stream 错误
|
||||||
|
"INTERNAL_ERROR", // 服务端内部错误
|
||||||
}
|
}
|
||||||
for _, retryable := range retryableErrors {
|
for _, retryable := range retryableErrors {
|
||||||
if strings.Contains(errStr, retryable) {
|
if strings.Contains(errStr, retryable) {
|
||||||
|
|||||||
10
start.sh
10
start.sh
@@ -165,6 +165,16 @@ start() {
|
|||||||
# 读取环境变量
|
# 读取环境变量
|
||||||
read_env_vars
|
read_env_vars
|
||||||
|
|
||||||
|
# 确保必要的文件和目录存在(修复 Docker volume 挂载问题)
|
||||||
|
if [ ! -f "config.db" ]; then
|
||||||
|
print_info "创建数据库文件..."
|
||||||
|
touch config.db
|
||||||
|
fi
|
||||||
|
if [ ! -d "decision_logs" ]; then
|
||||||
|
print_info "创建日志目录..."
|
||||||
|
mkdir -p decision_logs
|
||||||
|
fi
|
||||||
|
|
||||||
# Auto-build frontend if missing or forced
|
# Auto-build frontend if missing or forced
|
||||||
# if [ ! -d "web/dist" ] || [ "$1" == "--build" ]; then
|
# if [ ! -d "web/dist" ] || [ "$1" == "--build" ]; then
|
||||||
# build_frontend
|
# build_frontend
|
||||||
|
|||||||
@@ -196,7 +196,8 @@ func NewAutoTrader(config AutoTraderConfig) (*AutoTrader, error) {
|
|||||||
// 设置默认系统提示词模板
|
// 设置默认系统提示词模板
|
||||||
systemPromptTemplate := config.SystemPromptTemplate
|
systemPromptTemplate := config.SystemPromptTemplate
|
||||||
if systemPromptTemplate == "" {
|
if systemPromptTemplate == "" {
|
||||||
systemPromptTemplate = "default" // 默认使用 default 模板
|
// feature/partial-close-dynamic-tpsl 分支默认使用 adaptive(支持动态止盈止损)
|
||||||
|
systemPromptTemplate = "adaptive"
|
||||||
}
|
}
|
||||||
|
|
||||||
return &AutoTrader{
|
return &AutoTrader{
|
||||||
@@ -482,6 +483,12 @@ func (at *AutoTrader) buildTradingContext() (*decision.Context, error) {
|
|||||||
if quantity < 0 {
|
if quantity < 0 {
|
||||||
quantity = -quantity // 空仓数量为负,转为正数
|
quantity = -quantity // 空仓数量为负,转为正数
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 跳过已平仓的持仓(quantity = 0),防止"幽灵持仓"传递给AI
|
||||||
|
if quantity == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
unrealizedPnl := pos["unRealizedProfit"].(float64)
|
unrealizedPnl := pos["unRealizedProfit"].(float64)
|
||||||
liquidationPrice := pos["liquidationPrice"].(float64)
|
liquidationPrice := pos["liquidationPrice"].(float64)
|
||||||
|
|
||||||
|
|||||||
@@ -112,9 +112,10 @@ export function EquityChart({ traderId }: EquityChartProps) {
|
|||||||
? validHistory.slice(-MAX_DISPLAY_POINTS)
|
? validHistory.slice(-MAX_DISPLAY_POINTS)
|
||||||
: validHistory
|
: validHistory
|
||||||
|
|
||||||
// 计算初始余额(使用第一个有效数据点,如果无数据则从account获取,最后才用默认值)
|
// 计算初始余额(优先从 account 获取配置的初始余额,备选从历史数据反推)
|
||||||
const initialBalance =
|
const initialBalance = account?.initial_balance // 从交易员配置读取真实初始余额
|
||||||
validHistory[0]?.total_equity || account?.total_equity || 100 // 默认值改为100,与常见配置一致
|
|| (validHistory[0] ? validHistory[0].total_equity - validHistory[0].pnl : undefined) // 备选:淨值 - 盈亏
|
||||||
|
|| 1000; // 默认值(与创建交易员时的默认配置一致)
|
||||||
|
|
||||||
// 转换数据格式
|
// 转换数据格式
|
||||||
const chartData = displayHistory.map((point) => {
|
const chartData = displayHistory.map((point) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user