package main import ( "context" "log" "os" "os/signal" "syscall" "time" "big-qmt/go-client/apps/zt/logic" "big-qmt/go-client/config" "big-qmt/go-client/libs" "big-qmt/go-client/sdk" "github.com/robfig/cron/v3" ) var ( StrategyName = "zt" ) func main() { log.SetFlags(log.LstdFlags | log.Lmicroseconds) ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer stop() // 第一步:只从 YAML 文件加载系统配置和本机账户配置。 err := config.Load("etc") if err != nil { log.Fatalf("[ERROR] 加载配置失败: %v", err) } client := sdk.New(config.Global.QMTBaseURL, config.Global.QMTToken, config.HttpTimeOut) // 第二步:QMT 未就绪时持续重试,退出信号仍可立即终止等待。 assets, positions, ok := waitForQMT(ctx, client) if !ok { return } // 初始化 logic.InitWatch() if err := logic.InitState(StrategyName); err != nil { log.Panicln("ERROR", err.Error()) } if err := logic.SyncPositions(positions); err != nil { log.Panicln("ERROR", err.Error()) } // 第三步:连接成功后接管首次持仓并打印账户概览。 logic.Overview(assets, positions) signals, err := libs.FetchSignal(libs.Dcm_Signal, config.Account.HostKey) if err != nil { log.Printf("[ERROR] [ZT] 获取开仓信号失败: %v", err) signals = &libs.SignalResult{Data: map[string]libs.SignalItem{}} } log.Printf("[INFO] [ZT] 已加载 %d 个开仓信号", len(signals.Data)) // 第四步:工作日每 30 秒触发,交易时段由 RunOnce 统一判断。 books := logic.NewOrderBook() scheduler := cron.New( cron.WithSeconds(), cron.WithChain(cron.SkipIfStillRunning(cron.DefaultLogger)), ) if _, err := scheduler.AddFunc("0,30 * 9-15 * * 1-5", func() { logic.RunOnce(ctx, client, books, signals) }); err != nil { log.Fatalf("[ERROR] 创建计划任务失败: %v", err) } scheduler.Start() log.Printf("[INFO] [ZT] 计划任务已启动") <-ctx.Done() <-scheduler.Stop().Done() log.Printf("[INFO] [ZT] 停止") } func waitForQMT(ctx context.Context, client *sdk.Client) (*sdk.Assets, []sdk.Position, bool) { for { attempt, cancel := context.WithTimeout(ctx, config.HttpTimeOut) assets, assetsErr := client.Assets(attempt) _, positions, positionsErr := client.Positions(attempt) cancel() if assetsErr == nil && positionsErr == nil { log.Printf("[INFO] [ZT] QMT连接成功: %s", config.Global.QMTBaseURL) return assets, positions, true } log.Printf("[WARNING] [ZT] QMT未就绪,5秒后重试: assets=%v positions=%v", assetsErr, positionsErr) select { case <-ctx.Done(): return nil, nil, false case <-time.After(5 * time.Second): } } }