Files
nofx/main.go
tinkle-community 2334d78e4a refactor: simplify config and remove unused database tables
- 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
2025-12-07 20:17:03 +08:00

158 lines
4.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"nofx/api"
"nofx/auth"
"nofx/backtest"
"nofx/config"
"nofx/crypto"
"nofx/logger"
"nofx/manager"
"nofx/market"
"nofx/mcp"
"nofx/store"
"os"
"os/signal"
"syscall"
"github.com/joho/godotenv"
)
func main() {
// 加载 .env 环境变量
_ = godotenv.Load()
// 初始化日志
logger.Init(nil)
logger.Info("╔════════════════════════════════════════════════════════════╗")
logger.Info("║ 🤖 AI多模型交易系统 - 支持 DeepSeek & Qwen ║")
logger.Info("╚════════════════════════════════════════════════════════════╝")
// 初始化全局配置(从 .env 加载)
config.Init()
cfg := config.Get()
logger.Info("✅ 配置加载完成")
// 初始化数据库
dbPath := "data.db"
if len(os.Args) > 1 {
dbPath = os.Args[1]
}
logger.Infof("📋 初始化数据库: %s", dbPath)
st, err := store.New(dbPath)
if err != nil {
logger.Fatalf("❌ 初始化数据库失败: %v", err)
}
defer st.Close()
backtest.UseDatabase(st.DB())
// 初始化加密服务
logger.Info("🔐 初始化加密服务...")
cryptoService, err := crypto.NewCryptoService()
if err != nil {
logger.Fatalf("❌ 初始化加密服务失败: %v", err)
}
encryptFunc := func(plaintext string) string {
if plaintext == "" {
return plaintext
}
encrypted, err := cryptoService.EncryptForStorage(plaintext)
if err != nil {
logger.Warnf("⚠️ 加密失败: %v", err)
return plaintext
}
return encrypted
}
decryptFunc := func(encrypted string) string {
if encrypted == "" {
return encrypted
}
if !cryptoService.IsEncryptedStorageValue(encrypted) {
return encrypted
}
decrypted, err := cryptoService.DecryptFromStorage(encrypted)
if err != nil {
logger.Warnf("⚠️ 解密失败: %v", err)
return encrypted
}
return decrypted
}
st.SetCryptoFuncs(encryptFunc, decryptFunc)
logger.Info("✅ 加密服务初始化成功")
// 设置 JWT 密钥
auth.SetJWTSecret(cfg.JWTSecret)
logger.Info("🔑 JWT 密钥已设置")
// 创建 TraderManager 与 BacktestManager
traderManager := manager.NewTraderManager()
mcpClient := newSharedMCPClient()
backtestManager := backtest.NewManager(mcpClient)
if err := backtestManager.RestoreRuns(); err != nil {
logger.Warnf("⚠️ 恢复历史回测失败: %v", err)
}
// 从数据库加载所有交易员到内存
if err := traderManager.LoadTradersFromStore(st); err != nil {
logger.Fatalf("❌ 加载交易员失败: %v", err)
}
// 显示加载的交易员信息
traders, err := st.Trader().List("default")
if err != nil {
logger.Fatalf("❌ 获取交易员列表失败: %v", err)
}
logger.Info("🤖 数据库中的AI交易员配置:")
if len(traders) == 0 {
logger.Info(" (无交易员配置请通过Web管理界面创建)")
} else {
for _, t := range traders {
status := "❌ 已停止"
if t.IsRunning {
status = "✅ 运行中"
}
logger.Infof(" • %s [%s] %s - AI模型: %s, 交易所: %s",
t.Name, t.ID[:8], status, t.AIModelID, t.ExchangeID)
}
}
// 启动 WebSocket 行情监控(获取所有 USDT 永续合约的行情数据)
go market.NewWSMonitor(150).Start(nil)
logger.Info("📊 WebSocket 行情监控已启动")
// 启动API服务器
server := api.NewServer(traderManager, st, cryptoService, backtestManager, cfg.APIServerPort)
go func() {
if err := server.Start(); err != nil {
logger.Fatalf("❌ API服务器启动失败: %v", err)
}
}()
// 等待中断信号
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
logger.Info("✅ 系统启动完成,等待交易指令...")
logger.Info("📌 提示: 使用 Ctrl+C 停止系统")
<-quit
logger.Info("📴 收到停止信号,正在关闭系统...")
// 停止所有交易员
traderManager.StopAll()
logger.Info("✅ 系统已安全关闭")
}
// newSharedMCPClient 创建共享的 MCP AI 客户端(用于回测)
func newSharedMCPClient() mcp.AIClient {
apiKey := os.Getenv("DEEPSEEK_API_KEY")
if apiKey == "" {
logger.Warn("⚠️ DEEPSEEK_API_KEY 未设置AI 功能将不可用")
return nil
}
return mcp.NewDeepSeekClient()
}