feat(app): add evaluation history, bot control panel, simulation visualizer, and vendored signalr_core
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
/// Typed counterpart of the backend `EquityPointDto`
|
||||
/// (see `FinlyticCore/Dtos/Simulation/SimulationDtos.cs`).
|
||||
class EquityPointModel extends Equatable {
|
||||
final DateTime timestampUtc;
|
||||
final double portfolioValue;
|
||||
final double drawdownPercent;
|
||||
|
||||
const EquityPointModel({
|
||||
required this.timestampUtc,
|
||||
required this.portfolioValue,
|
||||
required this.drawdownPercent,
|
||||
});
|
||||
|
||||
factory EquityPointModel.fromJson(Map<String, dynamic> json) {
|
||||
double parseDbl(dynamic val) {
|
||||
if (val == null) return 0.0;
|
||||
if (val is num) return val.toDouble();
|
||||
return double.tryParse(val.toString()) ?? 0.0;
|
||||
}
|
||||
|
||||
return EquityPointModel(
|
||||
timestampUtc: DateTime.tryParse(json['timestampUtc']?.toString() ?? '') ?? DateTime.now(),
|
||||
portfolioValue: parseDbl(json['portfolioValue']),
|
||||
drawdownPercent: parseDbl(json['drawdownPercent']),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [timestampUtc, portfolioValue, drawdownPercent];
|
||||
}
|
||||
|
||||
/// Typed counterpart of the backend `BacktestReportDto`
|
||||
/// (see `FinlyticCore/Dtos/Simulation/SimulationDtos.cs`).
|
||||
///
|
||||
/// `equityCurve` is intentionally a plain (possibly empty) list rather than
|
||||
/// a fallback with a synthetic starting point: an empty list means "no
|
||||
/// equity curve data returned" and MUST be rendered as an explicit empty
|
||||
/// state, never as an invented chart (Rules.md §4).
|
||||
class BacktestReportModel extends Equatable {
|
||||
final String runId;
|
||||
final String isin;
|
||||
final String symbol;
|
||||
final String strategyKey;
|
||||
final String timeframe;
|
||||
final int totalTrades;
|
||||
final int winningTrades;
|
||||
final int losingTrades;
|
||||
final double winRatePercent;
|
||||
final double profitFactor;
|
||||
final double maxDrawdownPercent;
|
||||
final double totalReturnPercent;
|
||||
final double expectancyEur;
|
||||
final double sharpeRatio;
|
||||
final List<EquityPointModel> equityCurve;
|
||||
|
||||
const BacktestReportModel({
|
||||
this.runId = '',
|
||||
this.isin = '',
|
||||
this.symbol = '',
|
||||
this.strategyKey = '',
|
||||
this.timeframe = '',
|
||||
this.totalTrades = 0,
|
||||
this.winningTrades = 0,
|
||||
this.losingTrades = 0,
|
||||
this.winRatePercent = 0.0,
|
||||
this.profitFactor = 0.0,
|
||||
this.maxDrawdownPercent = 0.0,
|
||||
this.totalReturnPercent = 0.0,
|
||||
this.expectancyEur = 0.0,
|
||||
this.sharpeRatio = 0.0,
|
||||
this.equityCurve = const [],
|
||||
});
|
||||
|
||||
factory BacktestReportModel.fromJson(Map<String, dynamic> json) {
|
||||
double parseDbl(dynamic val) {
|
||||
if (val == null) return 0.0;
|
||||
if (val is num) return val.toDouble();
|
||||
return double.tryParse(val.toString()) ?? 0.0;
|
||||
}
|
||||
|
||||
final rawCurve = json['equityCurve'];
|
||||
final curve = rawCurve is List
|
||||
? rawCurve
|
||||
.whereType<Map>()
|
||||
.map((e) => EquityPointModel.fromJson(Map<String, dynamic>.from(e)))
|
||||
.toList()
|
||||
: const <EquityPointModel>[];
|
||||
|
||||
return BacktestReportModel(
|
||||
runId: json['runId']?.toString() ?? '',
|
||||
isin: json['isin']?.toString() ?? '',
|
||||
symbol: json['symbol']?.toString() ?? '',
|
||||
strategyKey: json['strategyKey']?.toString() ?? '',
|
||||
timeframe: json['timeframe']?.toString() ?? '',
|
||||
totalTrades: (json['totalTrades'] as num?)?.toInt() ?? 0,
|
||||
winningTrades: (json['winningTrades'] as num?)?.toInt() ?? 0,
|
||||
losingTrades: (json['losingTrades'] as num?)?.toInt() ?? 0,
|
||||
winRatePercent: parseDbl(json['winRatePercent']),
|
||||
profitFactor: parseDbl(json['profitFactor']),
|
||||
maxDrawdownPercent: parseDbl(json['maxDrawdownPercent']),
|
||||
totalReturnPercent: parseDbl(json['totalReturnPercent']),
|
||||
expectancyEur: parseDbl(json['expectancyEur']),
|
||||
sharpeRatio: parseDbl(json['sharpeRatio']),
|
||||
equityCurve: curve,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
runId,
|
||||
isin,
|
||||
symbol,
|
||||
strategyKey,
|
||||
timeframe,
|
||||
totalTrades,
|
||||
winningTrades,
|
||||
losingTrades,
|
||||
winRatePercent,
|
||||
profitFactor,
|
||||
maxDrawdownPercent,
|
||||
totalReturnPercent,
|
||||
expectancyEur,
|
||||
sharpeRatio,
|
||||
equityCurve,
|
||||
];
|
||||
}
|
||||
Reference in New Issue
Block a user