using System; using System.Collections.Generic; using System.Globalization; using System.IO; namespace Myc.HmaSma { /// /// DTO representing a single row in the HMA/SMA configuration file. /// public class HmaSmaParameters { // Initialized to string.Empty to satisfy CS8618 public string Symbol { get; set; } = string.Empty; public string Timeframe { get; set; } = string.Empty; public double EntrySig { get; set; } public double SlSig { get; set; } public int SmaBias { get; set; } public int HmaBias { get; set; } public int HmaCluster { get; set; } public bool BiasFilter { get; set; } public int BiasAvg { get; set; } public bool DynMgmt { get; set; } public bool TelegramOnly { get; set; } public override string ToString() { return $"{Symbol} {Timeframe}: SMA={SmaBias}, HMA={HmaBias}, Cluster={HmaCluster}"; } } /// /// Handles parsing and caching of HMA/SMA configuration files. /// public class HmaSmaLoader { // Key: "SYMBOL_TIMEFRAME" (Normalized to UpperCase) private readonly Dictionary _cache = new Dictionary(); private readonly string _filePath; public HmaSmaLoader(string filePath) { _filePath = filePath; } /// /// Reads the file and populates the internal cache. /// Throws FileNotFoundException if file is missing. /// Returns number of successfully loaded entries. /// public int Load() { _cache.Clear(); if (!File.Exists(_filePath)) throw new FileNotFoundException($"Config file not found: {_filePath}"); var lines = File.ReadAllLines(_filePath); int loadedCount = 0; foreach (var line in lines) { var trimmed = line.Trim(); if (string.IsNullOrWhiteSpace(trimmed) || trimmed.StartsWith("#")) continue; // Split by whitespace (tabs or spaces) var cols = trimmed.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); // Ensure we have at least 11 columns based on specification if (cols.Length < 11) continue; try { var param = new HmaSmaParameters { Symbol = cols[0], Timeframe = cols[1], EntrySig = double.Parse(cols[2], CultureInfo.InvariantCulture), SlSig = double.Parse(cols[3], CultureInfo.InvariantCulture), SmaBias = int.Parse(cols[4], CultureInfo.InvariantCulture), HmaBias = int.Parse(cols[5], CultureInfo.InvariantCulture), HmaCluster = int.Parse(cols[6], CultureInfo.InvariantCulture), BiasFilter = bool.Parse(cols[7]), BiasAvg = int.Parse(cols[8], CultureInfo.InvariantCulture), DynMgmt = bool.Parse(cols[9]), TelegramOnly = bool.Parse(cols[10]) }; string key = BuildKey(param.Symbol, param.Timeframe); // Overwrite duplicates if they exist lower in the file _cache[key] = param; loadedCount++; } catch (Exception) { // Fail silently for single bad lines, or log if logger provided. // For library code, we skip invalid lines to ensure robustness. continue; } } return loadedCount; } /// /// Retrieves configuration for a specific symbol and timeframe. /// Returns null if not found. /// public HmaSmaParameters? GetParameters(string symbol, string timeframe) { string key = BuildKey(symbol, timeframe); return _cache.TryGetValue(key, out var parameters) ? parameters : null; } private static string BuildKey(string symbol, string timeframe) { return $"{symbol.ToUpperInvariant()}_{timeframe.ToUpperInvariant()}"; } } }