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

100 lines
2.5 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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);
}
}