Files
aitrade/pkg/config/yaml.go
T
kaedwen ea141eb012
Build and Push Docker Image / build-and-push (push) Failing after 1m41s
initial
2026-07-02 20:09:44 +02:00

148 lines
3.4 KiB
Go

package config
import (
"fmt"
"os"
"path/filepath"
"time"
"gopkg.in/yaml.v3"
)
// LoadYAMLOrEnv loads configuration from YAML file or falls back to environment variables
func LoadYAMLOrEnv() (*Config, error) {
// Check for config file (in order of preference)
configPaths := []string{
os.Getenv("CONFIG_FILE"), // Highest priority
"./config.yaml",
"./config.yml",
filepath.Join(os.Getenv("HOME"), ".config/aitrade/config.yaml"),
"/etc/aitrade/config.yaml",
}
for _, path := range configPaths {
if path == "" {
continue
}
if _, err := os.Stat(path); err == nil {
cfg, err := loadYAMLFile(path)
if err != nil {
return nil, fmt.Errorf("failed to load %s: %w", path, err)
}
fmt.Printf("Loaded configuration from: %s\n", path)
return cfg, nil
}
}
// Fall back to environment variables
return Load()
}
// loadYAMLFile loads and parses a YAML configuration file
func loadYAMLFile(path string) (*Config, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("failed to read file: %w", err)
}
var cfg Config
if err := yaml.Unmarshal(data, &cfg); err != nil {
return nil, fmt.Errorf("failed to parse YAML: %w", err)
}
// Apply defaults for empty values
applyDefaults(&cfg)
return &cfg, cfg.Validate()
}
// applyDefaults sets default values for empty fields
func applyDefaults(cfg *Config) {
if cfg.IBGateway.Host == "" {
cfg.IBGateway.Host = "127.0.0.1"
}
if cfg.IBGateway.Port == 0 {
cfg.IBGateway.Port = 4001
}
if cfg.IBGateway.ClientID == 0 {
cfg.IBGateway.ClientID = 1
}
if cfg.IBGateway.MarketDataType == 0 {
cfg.IBGateway.MarketDataType = 3 // Default: Delayed (15min, kostenlos)
}
if cfg.Trading.Strategy == "" {
cfg.Trading.Strategy = "normal"
}
if cfg.Trading.StopLossPercent == 0.0 {
cfg.Trading.StopLossPercent = 3.0
}
if cfg.Trading.MaxTradesPerHour == 0 {
cfg.Trading.MaxTradesPerHour = 6
}
if cfg.Trading.MaxParallelTrades == 0 {
cfg.Trading.MaxParallelTrades = 5
}
if cfg.Trading.PendingTime.Duration == 0 {
cfg.Trading.PendingTime.Duration = 300 * time.Second
}
if cfg.Trading.DryRunBalance == 0.0 {
cfg.Trading.DryRunBalance = 100000.0
}
if cfg.Trading.TradingInterval.Duration == 0 {
cfg.Trading.TradingInterval.Duration = 60 * time.Second
}
if len(cfg.Trading.WatchSymbols) == 0 {
cfg.Trading.WatchSymbols = []string{"AAPL", "MSFT", "GOOGL", "TSLA", "AMZN"}
}
if cfg.Trading.TakeProfitPercent == 0.0 {
cfg.Trading.TakeProfitPercent = 5.0
}
if cfg.Trading.HoldTimeMinutes == 0 {
cfg.Trading.HoldTimeMinutes = 30
}
if cfg.Database.Path == "" {
cfg.Database.Path = "./data/aitrade.db"
}
if cfg.Web.Port == "" {
cfg.Web.Port = "8080"
}
if cfg.Web.Host == "" {
cfg.Web.Host = "0.0.0.0"
}
if len(cfg.OIDC.Scopes) == 0 {
cfg.OIDC.Scopes = []string{"openid", "profile", "email"}
}
if cfg.News.PollInterval.Duration == 0 {
cfg.News.PollInterval.Duration = 300 * time.Second
}
if cfg.LLMScorer.Endpoint == "" {
cfg.LLMScorer.Endpoint = "http://localhost:11434"
}
if cfg.LLMScorer.ModelName == "" {
cfg.LLMScorer.ModelName = "mistral"
}
if cfg.LLMScorer.Timeout.Duration == 0 {
cfg.LLMScorer.Timeout.Duration = 30 * time.Second
}
if cfg.LLMScorer.Temperature == 0.0 {
cfg.LLMScorer.Temperature = 0.3
}
if cfg.LLMScorer.MaxRetries == 0 {
cfg.LLMScorer.MaxRetries = 2
}
if cfg.LLMScorer.EnsembleWeight == 0.0 {
cfg.LLMScorer.EnsembleWeight = 0.7
}
if cfg.LogLevel == "" {
cfg.LogLevel = "info"
}
}