package main import ( "context" "encoding/json" "fmt" "os" "path/filepath" "sort" "strings" "time" "big-qmt/go-client/sdk" ) var ( BaseURL = "http://127.0.0.1:10086" Token = "QMTbyYanweidong" AccountType = "stock" Timeout = 15 * time.Second ) func main() { client := sdk.New(BaseURL, Token, Timeout).SetAccountType(AccountType) ctx, cancel := context.WithTimeout(context.Background(), Timeout) defer cancel() assets, err := client.Assets(ctx) if err != nil { fatal("获取资产失败: %v", err) } _, positions, err := client.Positions(ctx) if err != nil { fatal("获取持仓失败: %v", err) } fmt.Println(strings.Repeat("=", 80)) fmt.Printf("【时间】%s\n", time.Now().Format("2006-01-02 15:04:05")) fmt.Printf("【服务】%s accountType=%s\n", BaseURL, AccountType) fmt.Printf("【资金】总资产:%.2f元,可用资金:%.2f元\n", assets.Total, assets.Available) fmt.Printf("【持仓】%d只\n", len(positions)) fmt.Println(strings.Repeat("=", 80)) sort.Slice(positions, func(i, j int) bool { return positions[i].StockCode < positions[j].StockCode }) for _, p := range positions { if p.Volume <= 0 { continue } fmt.Printf( "【持仓】%s %s 持仓=%d 可用=%d 冻结=%d 在途=%d 昨仓=%d 成本=%.3f 现价=%.3f 市值=%.2f 浮盈=%.2f 盈亏比例=%.2f%%\n", p.StockCode, p.StockName, p.Volume, p.CanUseVolume, p.FrozenVolume, p.OnRoadVolume, p.YesterdayVolume, p.OpenPrice, p.LastPrice, p.MarketValue, p.FloatProfit, p.ProfitRate*100, ) } codes := loadPassCodes() printTicks(client, codes) // if _, err := client.Shutdown(ctx); err != nil { // fatal("关闭服务失败: %v", err) // } // fmt.Println("【服务】已关闭") } func loadPassCodes() []string { dir := strings.TrimSpace(os.Getenv("QMT_DATA_DIR")) if dir == "" { fatal("环境变量 QMT_DATA_DIR 为空") } path := filepath.Join(dir, "pass_codes.json") raw, err := os.ReadFile(path) if err != nil { fatal("读取 %s 失败: %v", path, err) } var codes []string if err := json.Unmarshal(raw, &codes); err != nil { fatal("解析 %s 失败: %v", path, err) } return codes } func printTicks(client *sdk.Client, codes []string) { fmt.Println(strings.Repeat("-", 80)) if len(codes) == 0 { fmt.Println("【行情】pass_codes.json 为空,跳过") return } ctx, cancel := context.WithTimeout(context.Background(), Timeout) defer cancel() ticks, err := client.FullTick(ctx, codes) if err != nil { fatal("获取行情失败: %v", err) } fmt.Printf("【行情】请求 %d 只,返回 %d 只\n", len(codes), len(ticks)) keys := make([]string, 0, len(ticks)) for code := range ticks { keys = append(keys, code) } sort.Strings(keys) for _, code := range keys { t := ticks[code] fmt.Printf("【Tick】%s last=%.3f close=%.3f open=%s high=%s low=%s volume=%s\n", code, t.LastPrice, t.LastClose, rawStr(t.Raw, "open", "lastOpen", "Open"), rawStr(t.Raw, "high", "High"), rawStr(t.Raw, "low", "Low"), rawStr(t.Raw, "volume", "Volume"), ) } } func rawStr(m map[string]any, names ...string) string { for _, name := range names { if v, ok := m[name]; ok && v != nil { return fmt.Sprint(v) } } return "-" } func fatal(format string, args ...any) { fmt.Fprintf(os.Stderr, format+"\n", args...) os.Exit(1) }