Files
monisuo/flutter_monisuo/lib/models/candle.dart

100 lines
2.5 KiB
Dart
Raw Normal View History

import 'package:decimal/decimal.dart';
/// K 线数据模型
class Candle {
final int timestamp; // 毫秒时间戳
final Decimal open;
final Decimal high;
final Decimal low;
final Decimal close;
final Decimal volume;
const Candle({
required this.timestamp,
required this.open,
required this.high,
required this.low,
required this.close,
required this.volume,
});
/// 从 JSON 解析,使用 Decimal 避免精度丢失
factory Candle.fromJson(Map<String, dynamic> json) {
return Candle(
timestamp: json['timestamp'] as int? ?? json['time'] as int? ?? 0,
open: _parseDecimal(json['open']),
high: _parseDecimal(json['high']),
low: _parseDecimal(json['low']),
close: _parseDecimal(json['close']),
volume: _parseDecimal(json['volume']),
);
}
/// 安全解析 Decimal
static Decimal _parseDecimal(dynamic value) {
if (value == null) return Decimal.zero;
if (value is Decimal) return value;
if (value is num) return Decimal.fromJson(value.toString());
if (value is String) {
try {
return Decimal.parse(value);
} catch (_) {
return Decimal.zero;
}
}
return Decimal.zero;
}
Map<String, dynamic> toJson() => {
'timestamp': timestamp,
'open': open.toDouble(),
'high': high.toDouble(),
'low': low.toDouble(),
'close': close.toDouble(),
'volume': volume.toDouble(),
};
/// 转换为 double供图表库使用
double get openDouble => open.toDouble();
double get highDouble => high.toDouble();
double get lowDouble => low.toDouble();
double get closeDouble => close.toDouble();
double get volumeDouble => volume.toDouble();
/// 安全加法(防止溢出)
Decimal safeAdd(Decimal other) {
try {
return open + other;
} catch (_) {
return Decimal.zero;
}
}
/// 安全乘法(防止溢出)
Decimal safeMultiply(Decimal other) {
try {
return open * other;
} catch (_) {
return Decimal.zero;
}
}
/// 格式化价格显示
String formatPrice({int decimalPlaces = 2}) {
return close.toStringAsFixed(decimalPlaces);
}
/// 格式化成交量显示
String formatVolume() {
final vol = volume.toDouble();
if (vol >= 1000000000) {
return '${(vol / 1000000000).toStringAsFixed(2)}B';
} else if (vol >= 1000000) {
return '${(vol / 1000000).toStringAsFixed(2)}M';
} else if (vol >= 1000) {
return '${(vol / 1000).toStringAsFixed(2)}K';
}
return vol.toStringAsFixed(2);
}
}