/// K线蜡烛数据模型 class KlineCandle { final String coinCode; final String interval; final int openTime; final double openPrice; final double highPrice; final double lowPrice; final double closePrice; final double volume; final int closeTime; final bool isClosed; final int? timestamp; const KlineCandle({ required this.coinCode, required this.interval, required this.openTime, required this.openPrice, required this.highPrice, required this.lowPrice, required this.closePrice, required this.volume, required this.closeTime, this.isClosed = true, this.timestamp, }); factory KlineCandle.fromJson(Map json) { return KlineCandle( coinCode: json['coinCode'] as String? ?? '', interval: json['interval'] as String? ?? '1h', openTime: json['openTime'] as int? ?? 0, openPrice: _toDouble(json['openPrice']), highPrice: _toDouble(json['highPrice']), lowPrice: _toDouble(json['lowPrice']), closePrice: _toDouble(json['closePrice']), volume: _toDouble(json['volume']), closeTime: json['closeTime'] as int? ?? 0, isClosed: json['isClosed'] as bool? ?? true, timestamp: json['timestamp'] as int?, ); } static double _toDouble(dynamic v) { if (v == null) return 0.0; if (v is double) return v; if (v is int) return v.toDouble(); if (v is String) return double.tryParse(v) ?? 0.0; return 0.0; } /// 转换为 k_chart 库的 KLineEntity 格式 Map toKLineEntityMap() { return { 'open': openPrice, 'high': highPrice, 'low': lowPrice, 'close': closePrice, 'vol': volume, 'amount': closePrice * volume, 'time': openTime, 'id': openTime, }; } /// 转换为 k_chart KLineEntity 对象 dynamic toKLineEntity() { // k_chart KLineEntity.fromCustom 构造器 return null; // placeholder, actual conversion in kline_page } /// 从 REST API JSON 转换(历史K线) factory KlineCandle.fromHistoryJson(Map json) { return KlineCandle( coinCode: json['coinCode'] as String? ?? '', interval: json['interval'] as String? ?? '1h', openTime: json['openTime'] as int? ?? 0, openPrice: _toDouble(json['openPrice']), highPrice: _toDouble(json['highPrice']), lowPrice: _toDouble(json['lowPrice']), closePrice: _toDouble(json['closePrice']), volume: _toDouble(json['volume']), closeTime: json['closeTime'] as int? ?? 0, isClosed: true, ); } }