feat: K线数据使用Decimal类型,防止数值精度丢失和溢出

This commit is contained in:
2026-04-07 23:04:27 +08:00
parent ab1486929f
commit 007915b6f2
86 changed files with 64527 additions and 63858 deletions

View File

@@ -1,5 +1,6 @@
import 'package:flutter/foundation.dart';
import 'package:flutter_chen_kchart/k_chart.dart';
import 'package:decimal/decimal.dart';
import '../models/candle.dart';
/// 时间周期
@@ -83,15 +84,15 @@ class ChartProvider extends ChangeNotifier {
List<Candle> _candles = [];
List<Candle> get candles => _candles;
// k_chart 需要的数据格式
// k_chart 需要的数据格式(转换为 double
List<KLineEntity> get klineData {
return _candles.map((c) {
return KLineEntity.fromCustom(
open: c.open,
high: c.high,
low: c.low,
close: c.close,
vol: c.volume,
open: c.openDouble,
high: c.highDouble,
low: c.lowDouble,
close: c.closeDouble,
vol: c.volumeDouble,
time: c.timestamp,
);
}).toList();
@@ -155,7 +156,7 @@ class ChartProvider extends ChangeNotifier {
}
}
/// 生成模拟 K 线数据
/// 生成模拟 K 线数据(使用 Decimal 防止精度丢失)
List<Candle> _generateMockCandles() {
final now = DateTime.now();
final basePrice = _getBasePrice(_symbol);
@@ -176,13 +177,14 @@ class ChartProvider extends ChangeNotifier {
: i * 1440,
));
final random = (i * 17) % 100 / 100;
final change = basePrice * 0.02 * (random - 0.5);
// 使用 Decimal 进行安全计算
final random = Decimal.parse(((i * 17) % 100 / 100).toString());
final change = basePrice * Decimal.parse('0.02') * (random - Decimal.parse('0.5'));
final open = basePrice + change;
final close = open + basePrice * 0.01 * ((i * 13) % 100 / 100 - 0.5);
final high = open > close ? open * 1.005 : close * 1.005;
final low = open < close ? open * 0.995 : close * 0.995;
final volume = 1000 + (i * 37) % 5000;
final close = open + basePrice * Decimal.parse('0.01') * (Decimal.parse(((i * 13) % 100 / 100).toString()) - Decimal.parse('0.5'));
final high = open > close ? open * Decimal.parse('1.005') : close * Decimal.parse('1.005');
final low = open < close ? open * Decimal.parse('0.995') : close * Decimal.parse('0.995');
final volume = Decimal.fromInt(1000 + (i * 37) % 5000);
candles.add(Candle(
timestamp: time.millisecondsSinceEpoch,
@@ -190,29 +192,29 @@ class ChartProvider extends ChangeNotifier {
high: high,
low: low,
close: close,
volume: volume.toDouble(),
volume: volume,
));
}
return candles;
}
double _getBasePrice(String symbol) {
Decimal _getBasePrice(String symbol) {
switch (symbol.toUpperCase()) {
case 'BTC':
return 42000.0;
return Decimal.parse('42000');
case 'ETH':
return 2200.0;
return Decimal.parse('2200');
case 'BNB':
return 300.0;
return Decimal.parse('300');
case 'SOL':
return 100.0;
return Decimal.parse('100');
case 'XRP':
return 0.5;
return Decimal.parse('0.5');
case 'DOGE':
return 0.08;
return Decimal.parse('0.08');
default:
return 100.0;
return Decimal.fromInt(100);
}
}
}