99 lines
2.6 KiB
Go
99 lines
2.6 KiB
Go
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
var (
|
|
Global *GlobalConfig
|
|
Account *AccountConfig
|
|
HttpTimeOut time.Duration = 5 * time.Second
|
|
)
|
|
|
|
type GlobalConfig struct {
|
|
QMTBaseURL string `yaml:"qmt_base_url"`
|
|
QMTToken string `yaml:"qmt_token"`
|
|
APIHost string `yaml:"api_host"`
|
|
QMTDataDir string `yaml:"qmt_data_dir"`
|
|
Hosts map[string]string `yaml:"hosts"`
|
|
}
|
|
|
|
type AccountConfig struct {
|
|
AccountID string `yaml:"account_id"`
|
|
HostKey string `yaml:"host_key"`
|
|
OrderTimeoutSec int `yaml:"order_timeout_seconds"`
|
|
BuyValue float64 `yaml:"buy_value"`
|
|
MinCashRatio float64 `yaml:"min_cash_ratio"`
|
|
LossTriggerPct float64 `yaml:"loss_trigger_pct"`
|
|
GridStepPct float64 `yaml:"grid_step_pct"`
|
|
MinProfitPct float64 `yaml:"min_profit_pct"`
|
|
WatchTimeoutSec int `yaml:"watch_timeout_seconds"`
|
|
ReboundThreshold float64 `yaml:"rebound_threshold"`
|
|
}
|
|
|
|
// Load 根据 global.yaml 中的 hosts 映射加载当前计算机的账户配置。
|
|
func Load(etcDir string) error {
|
|
var global GlobalConfig
|
|
if err := readYAML(filepath.Join(etcDir, "global.yaml"), &global); err != nil {
|
|
return err
|
|
}
|
|
hostname, err := os.Hostname()
|
|
if err != nil {
|
|
return fmt.Errorf("读取计算机名失败: %w", err)
|
|
}
|
|
if global.QMTBaseURL == "" || global.APIHost == "" || global.QMTDataDir == "." {
|
|
return fmt.Errorf("Global 配置缺少必要参数")
|
|
}
|
|
if err := os.MkdirAll(global.QMTDataDir, 0o755); err != nil {
|
|
return fmt.Errorf("创建目录 %s 失败: %w", global.QMTDataDir, err)
|
|
}
|
|
|
|
accountFile := hostAccountFile(global.Hosts, hostname)
|
|
if accountFile == "" {
|
|
return fmt.Errorf("global.yaml 未配置计算机 %q", hostname)
|
|
}
|
|
if filepath.Ext(accountFile) == "" {
|
|
accountFile += ".yaml"
|
|
}
|
|
|
|
var account AccountConfig
|
|
if err := readYAML(filepath.Join(etcDir, accountFile), &account); err != nil {
|
|
return err
|
|
}
|
|
|
|
if account.BuyValue <= 0 || account.GridStepPct <= 0 {
|
|
return fmt.Errorf("buy_value、grid_step_pct 和超时时间必须大于 0")
|
|
}
|
|
|
|
Global = &global
|
|
Account = &account
|
|
|
|
return nil
|
|
}
|
|
|
|
func readYAML(path string, dest any) error {
|
|
raw, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return fmt.Errorf("读取配置 %s 失败: %w", path, err)
|
|
}
|
|
if err := yaml.Unmarshal(raw, dest); err != nil {
|
|
return fmt.Errorf("解析配置 %s 失败: %w", path, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func hostAccountFile(hosts map[string]string, hostname string) string {
|
|
for host, file := range hosts {
|
|
if strings.EqualFold(strings.TrimSpace(host), strings.TrimSpace(hostname)) {
|
|
return strings.TrimSpace(file)
|
|
}
|
|
}
|
|
return ""
|
|
}
|