AssetManager.API/AssetManager.Models/DTOs/PortfolioDTO.cs
OpenClaw Agent 05ca501f40 feat: 新增组合净值历史功能
后端实现:
- 新增PortfolioNavHistory实体,记录每日净值、成本、收益率
- 实现IPortfolioNavService接口,支持净值计算和历史回填
- 支持基于交易记录完整计算历史净值(买入卖出都会更新)
- 计算统计指标:最大回撤、夏普比率、波动率

新增API:
- GET /api/v1/portfolio/{id}/nav-history - 获取净值曲线
- POST /api/v1/portfolio/{id}/nav-history/backfill - 回填历史净值
- POST /api/v1/portfolio/{id}/nav-history/calculate - 计算当日净值

数据库:
- 新增portfolio_nav_history表迁移脚本
- 支持组合级别的净值历史记录
2026-03-13 16:08:59 +00:00

211 lines
6.3 KiB
C#
Executable File

namespace AssetManager.Models.DTOs;
public class CreatePortfolioRequest
{
public string? name { get; set; }
public string? strategyId { get; set; }
public string? currency { get; set; }
public List<StockItem>? stocks { get; set; }
}
public class StockItem
{
public string? name { get; set; }
public string? code { get; set; }
public double price { get; set; }
public int amount { get; set; }
public string? date { get; set; }
public string? currency { get; set; }
public string assetType { get; set; } = "Stock"; // Stock / Crypto
}
public class CreatePortfolioResponse
{
public string? id { get; set; }
public double totalValue { get; set; }
public double returnRate { get; set; }
public string? currency { get; set; }
public string? createdAt { get; set; }
}
public class PortfolioDetailResponse
{
public string? id { get; set; }
public string? name { get; set; }
public string? currency { get; set; }
public string? status { get; set; }
public StrategyInfo? strategy { get; set; }
public double portfolioValue { get; set; }
public double totalReturn { get; set; }
public double todayProfit { get; set; }
public double historicalChange { get; set; }
public double dailyVolatility { get; set; }
public string? todayProfitCurrency { get; set; }
public string? logicModel { get; set; }
public string? logicModelStatus { get; set; }
public string? logicModelDescription { get; set; }
public int totalItems { get; set; }
public double totalRatio { get; set; }
public List<PositionItem>? positions { get; set; }
}
public class StrategyInfo
{
public string? id { get; set; }
public string? name { get; set; }
public string? description { get; set; }
}
public class PositionItem
{
public string? id { get; set; }
public string? stockCode { get; set; }
public string? stockName { get; set; }
public string? symbol { get; set; }
public int amount { get; set; }
public double averagePrice { get; set; }
public double currentPrice { get; set; }
public double totalValue { get; set; }
public double profit { get; set; }
public double profitRate { get; set; }
public double changeAmount { get; set; }
public double ratio { get; set; }
public double deviationRatio { get; set; }
public string? currency { get; set; }
}
public class TransactionItem
{
public string? id { get; set; }
public string? portfolioId { get; set; }
public string? date { get; set; }
public string? time { get; set; }
public string? type { get; set; }
public string? title { get; set; }
public string? stockCode { get; set; }
public double amount { get; set; }
public string? currency { get; set; }
public string? status { get; set; }
public string? remark { get; set; }
}
public class GetTransactionsRequest
{
public string? portfolioId { get; set; }
public int limit { get; set; }
public int offset { get; set; }
}
public class GetTransactionsResponse
{
public List<TransactionItem>? items { get; set; }
public int total { get; set; }
public int page { get; set; }
public int pageSize { get; set; }
}
public class CreateTransactionRequest
{
public string? portfolioId { get; set; }
public string? type { get; set; }
public string? stockCode { get; set; }
public int amount { get; set; }
public double price { get; set; }
public string? currency { get; set; }
public string? remark { get; set; }
public string assetType { get; set; } = "Stock"; // Stock / Crypto
public string? transactionTime { get; set; } // 实际交易时间,可选
public string? transactionDate { get; set; } // 交易日期,前端传入 YYYY-MM-DD 格式
}
public class CreateTransactionResponse
{
public string? id { get; set; }
public double totalAmount { get; set; }
public string? status { get; set; }
public string? createdAt { get; set; }
}
public class PortfolioListItem
{
public string? id { get; set; }
public string? name { get; set; }
public string? tags { get; set; }
public string? status { get; set; }
public string? statusType { get; set; }
public string? iconChar { get; set; }
public string? iconBgClass { get; set; }
public string? iconTextClass { get; set; }
public double value { get; set; }
public string? currency { get; set; }
public double returnRate { get; set; }
public string? returnType { get; set; }
}
public class GetPortfoliosResponse
{
public List<PortfolioListItem>? items { get; set; }
}
public class TotalAssetsResponse
{
public double totalValue { get; set; }
public string? currency { get; set; }
public double todayProfit { get; set; }
public string? todayProfitCurrency { get; set; }
public double totalReturnRate { get; set; }
}
// ===== 净值历史相关 DTO =====
public class NavHistoryRequest
{
public DateTime? startDate { get; set; }
public DateTime? endDate { get; set; }
public string? interval { get; set; } = "daily"; // daily, weekly, monthly
}
public class NavHistoryResponse
{
public string? portfolioId { get; set; }
public string? currency { get; set; }
public List<NavItem>? navHistory { get; set; }
public NavStatistics? statistics { get; set; }
}
public class NavItem
{
public string? date { get; set; }
public double nav { get; set; }
public double totalValue { get; set; }
public double totalCost { get; set; }
public double dailyReturn { get; set; }
public double cumulativeReturn { get; set; }
}
public class NavStatistics
{
public double maxReturn { get; set; }
public double minReturn { get; set; }
public double maxDrawdown { get; set; }
public double sharpeRatio { get; set; }
public double volatility { get; set; }
public double totalReturn { get; set; }
public int tradingDays { get; set; }
}
public class BackfillNavRequest
{
public string? portfolioId { get; set; }
public bool force { get; set; } = false; // 是否强制重新计算
}
public class BackfillNavResponse
{
public string? portfolioId { get; set; }
public int recordsCreated { get; set; }
public DateTime? startDate { get; set; }
public DateTime? endDate { get; set; }
public string? message { get; set; }
}