Files
big-qmt/go-client/apps/cmd/main.go
2026-08-25 18:59:18 +08:00

126 lines
3.3 KiB
Go

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)
}