mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-12 07:16:56 +08:00
Merge pull request #421 from Im-Sue/fix/trader-manager-hyperliquid-testnet-clean
fix(trader): add missing HyperliquidTestnet configuration in loadSing…
This commit is contained in:
@@ -23,9 +23,9 @@ type CompetitionCache struct {
|
|||||||
|
|
||||||
// TraderManager 管理多个trader实例
|
// TraderManager 管理多个trader实例
|
||||||
type TraderManager struct {
|
type TraderManager struct {
|
||||||
traders map[string]*trader.AutoTrader // key: trader ID
|
traders map[string]*trader.AutoTrader // key: trader ID
|
||||||
competitionCache *CompetitionCache
|
competitionCache *CompetitionCache
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTraderManager 创建trader管理器
|
// NewTraderManager 创建trader管理器
|
||||||
@@ -506,19 +506,19 @@ func (tm *TraderManager) GetCompetitionData() (map[string]interface{}, error) {
|
|||||||
tm.competitionCache.mu.RUnlock()
|
tm.competitionCache.mu.RUnlock()
|
||||||
|
|
||||||
tm.mu.RLock()
|
tm.mu.RLock()
|
||||||
|
|
||||||
// 获取所有交易员列表
|
// 获取所有交易员列表
|
||||||
allTraders := make([]*trader.AutoTrader, 0, len(tm.traders))
|
allTraders := make([]*trader.AutoTrader, 0, len(tm.traders))
|
||||||
for _, t := range tm.traders {
|
for _, t := range tm.traders {
|
||||||
allTraders = append(allTraders, t)
|
allTraders = append(allTraders, t)
|
||||||
}
|
}
|
||||||
tm.mu.RUnlock()
|
tm.mu.RUnlock()
|
||||||
|
|
||||||
log.Printf("🔄 重新获取竞赛数据,交易员数量: %d", len(allTraders))
|
log.Printf("🔄 重新获取竞赛数据,交易员数量: %d", len(allTraders))
|
||||||
|
|
||||||
// 并发获取交易员数据
|
// 并发获取交易员数据
|
||||||
traders := tm.getConcurrentTraderData(allTraders)
|
traders := tm.getConcurrentTraderData(allTraders)
|
||||||
|
|
||||||
// 按收益率排序(降序)
|
// 按收益率排序(降序)
|
||||||
sort.Slice(traders, func(i, j int) bool {
|
sort.Slice(traders, func(i, j int) bool {
|
||||||
pnlPctI, okI := traders[i]["total_pnl_pct"].(float64)
|
pnlPctI, okI := traders[i]["total_pnl_pct"].(float64)
|
||||||
@@ -531,14 +531,14 @@ func (tm *TraderManager) GetCompetitionData() (map[string]interface{}, error) {
|
|||||||
}
|
}
|
||||||
return pnlPctI > pnlPctJ
|
return pnlPctI > pnlPctJ
|
||||||
})
|
})
|
||||||
|
|
||||||
// 限制返回前50名
|
// 限制返回前50名
|
||||||
totalCount := len(traders)
|
totalCount := len(traders)
|
||||||
limit := 50
|
limit := 50
|
||||||
if len(traders) > limit {
|
if len(traders) > limit {
|
||||||
traders = traders[:limit]
|
traders = traders[:limit]
|
||||||
}
|
}
|
||||||
|
|
||||||
comparison := make(map[string]interface{})
|
comparison := make(map[string]interface{})
|
||||||
comparison["traders"] = traders
|
comparison["traders"] = traders
|
||||||
comparison["count"] = len(traders)
|
comparison["count"] = len(traders)
|
||||||
@@ -559,21 +559,21 @@ func (tm *TraderManager) getConcurrentTraderData(traders []*trader.AutoTrader) [
|
|||||||
index int
|
index int
|
||||||
data map[string]interface{}
|
data map[string]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建结果通道
|
// 创建结果通道
|
||||||
resultChan := make(chan traderResult, len(traders))
|
resultChan := make(chan traderResult, len(traders))
|
||||||
|
|
||||||
// 并发获取每个交易员的数据
|
// 并发获取每个交易员的数据
|
||||||
for i, t := range traders {
|
for i, t := range traders {
|
||||||
go func(index int, trader *trader.AutoTrader) {
|
go func(index int, trader *trader.AutoTrader) {
|
||||||
// 设置单个交易员的超时时间为3秒
|
// 设置单个交易员的超时时间为3秒
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// 使用通道来实现超时控制
|
// 使用通道来实现超时控制
|
||||||
accountChan := make(chan map[string]interface{}, 1)
|
accountChan := make(chan map[string]interface{}, 1)
|
||||||
errorChan := make(chan error, 1)
|
errorChan := make(chan error, 1)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
account, err := trader.GetAccountInfo()
|
account, err := trader.GetAccountInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -582,10 +582,10 @@ func (tm *TraderManager) getConcurrentTraderData(traders []*trader.AutoTrader) [
|
|||||||
accountChan <- account
|
accountChan <- account
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
status := trader.GetStatus()
|
status := trader.GetStatus()
|
||||||
var traderData map[string]interface{}
|
var traderData map[string]interface{}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case account := <-accountChan:
|
case account := <-accountChan:
|
||||||
// 成功获取账户信息
|
// 成功获取账户信息
|
||||||
@@ -634,18 +634,18 @@ func (tm *TraderManager) getConcurrentTraderData(traders []*trader.AutoTrader) [
|
|||||||
"error": "获取超时",
|
"error": "获取超时",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resultChan <- traderResult{index: index, data: traderData}
|
resultChan <- traderResult{index: index, data: traderData}
|
||||||
}(i, t)
|
}(i, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 收集所有结果
|
// 收集所有结果
|
||||||
results := make([]map[string]interface{}, len(traders))
|
results := make([]map[string]interface{}, len(traders))
|
||||||
for i := 0; i < len(traders); i++ {
|
for i := 0; i < len(traders); i++ {
|
||||||
result := <-resultChan
|
result := <-resultChan
|
||||||
results[result.index] = result.data
|
results[result.index] = result.data
|
||||||
}
|
}
|
||||||
|
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -656,20 +656,20 @@ func (tm *TraderManager) GetTopTradersData() (map[string]interface{}, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从竞赛数据中提取前5名
|
// 从竞赛数据中提取前5名
|
||||||
allTraders, ok := competitionData["traders"].([]map[string]interface{})
|
allTraders, ok := competitionData["traders"].([]map[string]interface{})
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("竞赛数据格式错误")
|
return nil, fmt.Errorf("竞赛数据格式错误")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 限制返回前5名
|
// 限制返回前5名
|
||||||
limit := 5
|
limit := 5
|
||||||
topTraders := allTraders
|
topTraders := allTraders
|
||||||
if len(allTraders) > limit {
|
if len(allTraders) > limit {
|
||||||
topTraders = allTraders[:limit]
|
topTraders = allTraders[:limit]
|
||||||
}
|
}
|
||||||
|
|
||||||
result := map[string]interface{}{
|
result := map[string]interface{}{
|
||||||
"traders": topTraders,
|
"traders": topTraders,
|
||||||
"count": len(topTraders),
|
"count": len(topTraders),
|
||||||
@@ -889,6 +889,7 @@ func (tm *TraderManager) loadSingleTrader(traderCfg *config.TraderRecord, aiMode
|
|||||||
DefaultCoins: defaultCoins,
|
DefaultCoins: defaultCoins,
|
||||||
TradingCoins: tradingCoins,
|
TradingCoins: tradingCoins,
|
||||||
SystemPromptTemplate: traderCfg.SystemPromptTemplate, // 系统提示词模板
|
SystemPromptTemplate: traderCfg.SystemPromptTemplate, // 系统提示词模板
|
||||||
|
HyperliquidTestnet: exchangeCfg.Testnet, // Hyperliquid测试网
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据交易所类型设置API密钥
|
// 根据交易所类型设置API密钥
|
||||||
|
|||||||
Reference in New Issue
Block a user