diff --git a/Binance.TradeRobot.API/.config/dotnet-tools.json b/Binance.TradeRobot.API/.config/dotnet-tools.json new file mode 100644 index 0000000..82e7e22 --- /dev/null +++ b/Binance.TradeRobot.API/.config/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "dotnet-ef": { + "version": "6.0.2", + "commands": [ + "dotnet-ef" + ] + } + } +} \ No newline at end of file diff --git a/Binance.TradeRobot.API/Binance.TradeRobot.API.xml b/Binance.TradeRobot.API/Binance.TradeRobot.API.xml index cc60b1f..3f95d9c 100644 --- a/Binance.TradeRobot.API/Binance.TradeRobot.API.xml +++ b/Binance.TradeRobot.API/Binance.TradeRobot.API.xml @@ -8,7 +8,7 @@ 用户登录 - + 密码需小写md5加密 @@ -16,27 +16,27 @@ 获取用户列表 - + 获取用户资金变更记录 - 获取用户盈亏记录 + 获取用户盈亏记录,暂未开放 - + 追投 - + 提现 - + 转移资金 diff --git a/Binance.TradeRobot.API/Controllers/BaseApiController.cs b/Binance.TradeRobot.API/Controllers/BaseApiController.cs index 7cb4b3d..57ed128 100644 --- a/Binance.TradeRobot.API/Controllers/BaseApiController.cs +++ b/Binance.TradeRobot.API/Controllers/BaseApiController.cs @@ -1,4 +1,6 @@ -using Microsoft.AspNetCore.Mvc; +using Binance.TradeRobot.Model.Dto; +using Microsoft.AspNetCore.Mvc; +using System.Linq; namespace Binance.TradeRobot.API.Controllers { @@ -7,5 +9,16 @@ namespace Binance.TradeRobot.API.Controllers [ApiController] public class BaseApiController : ControllerBase { + public LoginResponse LoginUser + { + get + { + return new LoginResponse() + { + Id = long.Parse(HttpContext.User.Claims.FirstOrDefault(c => c.Type == "Id").Value), + UserName = HttpContext.User.Claims.FirstOrDefault(c => c.Type == "UserName").Value + }; + } + } } } diff --git a/Binance.TradeRobot.API/Controllers/UserController.cs b/Binance.TradeRobot.API/Controllers/UserController.cs index 9157db0..64ae43a 100644 --- a/Binance.TradeRobot.API/Controllers/UserController.cs +++ b/Binance.TradeRobot.API/Controllers/UserController.cs @@ -1,9 +1,13 @@ using Binance.TradeRobot.Business; using Binance.TradeRobot.Model.Dto; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; namespace Binance.TradeRobot.API.Controllers { + [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] public class UserController : BaseApiController { private UserBusiness userBusiness; @@ -15,9 +19,10 @@ namespace Binance.TradeRobot.API.Controllers /// /// 用户登录 /// - /// + /// 密码需小写md5加密 /// [HttpPost] + [AllowAnonymous] public LoginResponse Login([FromBody] LoginRequest loginRequest) { return userBusiness.Login(loginRequest); @@ -27,53 +32,54 @@ namespace Binance.TradeRobot.API.Controllers /// 获取用户列表 /// [HttpGet] - public void GetUserList() + public IList GetUserList() { - + return userBusiness.GetUserList(); } /// /// 获取用户资金变更记录 /// [HttpGet] - public void GetUserAccountFundChangeRecordList() + public UserAccountChangeRecordListResponse GetUserAccountFundChangeRecordList([FromBody] QueryUserAccountRequest queryUserAccountRequest) { - + return userBusiness.GetUserAccountFundChangeRecordList(queryUserAccountRequest); } /// - /// 获取用户盈亏记录 + /// 获取用户盈亏记录,暂未开放 /// [HttpGet] public void GetUserAccountProfitLossRecordList() { + } /// /// 追投 /// [HttpPost] - public void AddFunds() + public void AddFunds([FromBody] FundsChangeRequest fundsChangeRequest) { - + userBusiness.AddFunds(LoginUser.Id, fundsChangeRequest); } /// /// 提现 /// [HttpPost] - public void ReduceFunds() + public void ReduceFunds([FromBody] FundsChangeRequest fundsChangeRequest) { - + userBusiness.ReduceFunds(LoginUser.Id, fundsChangeRequest); } /// /// 转移资金 /// [HttpPost] - public void TransferFunds() + public void TransferFunds([FromBody] FundsTransferRequest fundsTransferRequest) { - + userBusiness.TransferFunds(LoginUser.Id, fundsTransferRequest); } } } diff --git a/Binance.TradeRobot.Business/BaseBusiness.cs b/Binance.TradeRobot.Business/BaseBusiness.cs index c9dcd0d..9ae97c7 100644 --- a/Binance.TradeRobot.Business/BaseBusiness.cs +++ b/Binance.TradeRobot.Business/BaseBusiness.cs @@ -1,13 +1,17 @@ -namespace Binance.TradeRobot.Business +using Yitter.IdGenerator; + +namespace Binance.TradeRobot.Business { public class BaseBusiness { protected IFreeSql fsql; protected NLogManager logManager; - public BaseBusiness(IFreeSql fsql, NLogManager logManager) + protected IIdGenerator idGenerator; + public BaseBusiness(IFreeSql fsql, NLogManager logManager, IIdGenerator idGenerator) { this.fsql = fsql; this.logManager = logManager; + this.idGenerator = idGenerator; } } } diff --git a/Binance.TradeRobot.Business/Binance.TradeRobot.Business.xml b/Binance.TradeRobot.Business/Binance.TradeRobot.Business.xml index 4de0ee0..a3d173f 100644 --- a/Binance.TradeRobot.Business/Binance.TradeRobot.Business.xml +++ b/Binance.TradeRobot.Business/Binance.TradeRobot.Business.xml @@ -4,5 +4,23 @@ Binance.TradeRobot.Business + + + 计算成员分红/本金比例 + + + 比例乘100 + + + + 单向资产变更 + + + + + + + + diff --git a/Binance.TradeRobot.Business/Extensions/FreeSqlExtension.cs b/Binance.TradeRobot.Business/Extensions/FreeSqlExtension.cs new file mode 100644 index 0000000..8b1e8fc --- /dev/null +++ b/Binance.TradeRobot.Business/Extensions/FreeSqlExtension.cs @@ -0,0 +1,17 @@ +using FreeSql; +using System; +using System.Collections.Generic; + +namespace Binance.TradeRobot.Business.Extensions +{ + public static class FreeSqlExtension + { + public static ISelect WithLock(this ISelect that, SqlServerLock lockType = SqlServerLock.NoLock, Dictionary rule = null) where T2 : class where T3 : class + { + return rule == null ? + that.AsAlias((type, old) => $"{old} With({lockType})") : + that.AsAlias((type, old) => rule.TryGetValue(type, out var trybool) && trybool ? $"{old} With({lockType.ToString()})" : old); + } + + } +} diff --git a/Binance.TradeRobot.Business/Extensions/UserExtension.cs b/Binance.TradeRobot.Business/Extensions/UserExtension.cs new file mode 100644 index 0000000..a81a663 --- /dev/null +++ b/Binance.TradeRobot.Business/Extensions/UserExtension.cs @@ -0,0 +1,25 @@ +using Binance.TradeRobot.Model.Dto; +using System.Collections.Generic; +using System.Linq; + +namespace Binance.TradeRobot.Business.Extensions +{ + public static class UserExtension + { + /// + /// 计算成员分红/本金比例 + /// + /// + /// 比例乘100 + public static void CalculateRatio(this IList userList, bool multiplyBy100 = true) + { + var totalAssets = userList.Sum(u => u.TotalAssets); //总资产 + var totalCostAmount = userList.Sum(u => u.CostAmount); //总本金 + foreach (var u in userList) + { + u.CostRatio = totalCostAmount == 0 ? 0 : u.CostAmount / totalCostAmount * (multiplyBy100 ? 100 : 1); + u.DividendRatio = totalAssets == 0 ? 0 : u.TotalAssets / totalAssets * (multiplyBy100 ? 100 : 1); + } + } + } +} diff --git a/Binance.TradeRobot.Business/UserBusiness.cs b/Binance.TradeRobot.Business/UserBusiness.cs index 1395819..95c8607 100644 --- a/Binance.TradeRobot.Business/UserBusiness.cs +++ b/Binance.TradeRobot.Business/UserBusiness.cs @@ -1,4 +1,5 @@ -using Binance.TradeRobot.Common.DI; +using Binance.TradeRobot.Business.Extensions; +using Binance.TradeRobot.Common.DI; using Binance.TradeRobot.Common.Extensions; using Binance.TradeRobot.Model.Base; using Binance.TradeRobot.Model.Db; @@ -9,8 +10,10 @@ using Microsoft.IdentityModel.Tokens; using System; using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; +using System.Linq; using System.Security.Claims; using System.Text; +using Yitter.IdGenerator; namespace Binance.TradeRobot.Business { @@ -19,7 +22,7 @@ namespace Binance.TradeRobot.Business { private IConfiguration configuration; - public UserBusiness(IFreeSql fsql, NLogManager logManager, IConfiguration configuration) : base(fsql, logManager) + public UserBusiness(IFreeSql fsql, NLogManager logManager, IIdGenerator idGenerator, IConfiguration configuration) : base(fsql, logManager, idGenerator) { this.configuration = configuration; } @@ -53,5 +56,231 @@ namespace Binance.TradeRobot.Business Token = token }; } + + public IList GetUserList() + { + var userList = fsql.Select().ToList().Map>(); + userList.CalculateRatio(); + return userList; + } + + #region 用户资产 + + /// + /// 单向资产变更 + /// + /// + /// + /// + /// + /// + /// + private void OneWayAssetChange(long operationUserId, decimal changeAmount, long changeUserId, Enums.CapitalChangeType capitalChangeType, string remark) + { + var changeUser = fsql.Select(changeUserId).ToOne().Map(); + if (changeUser == null) + throw new BusinessException("资金变更用户不存在"); + + if (capitalChangeType == Enums.CapitalChangeType.Reduce) + { + if (changeUser.TotalAssets < changeAmount) + throw new BusinessException("用户资产小于减持资金,不能提现"); + + //获取交易所账户总额(usdt) + //var apiKeyList = stockExchangeAccountBusiness.GetAPIKeyList(null); + //var totalBalance = apiKeyList.Sum(k => k.Balance); + //if (totalBalance < changeAmount) + // throw new BusinessException("交易所总余额小于减持资金,不能提现"); + } + + if (capitalChangeType == Enums.CapitalChangeType.Add) + { + changeUser.CostAmount += changeAmount; + } + else if (capitalChangeType == Enums.CapitalChangeType.Reduce) + { + if (changeUser.Profit > 0) + { + if (changeUser.Profit >= changeAmount) + changeUser.Profit -= changeAmount; //收益足够提现,只扣收益 + else + { + var lessChangeAmount = changeAmount; //收益不足提现,先扣收益,不足部分再扣本金 + lessChangeAmount -= changeUser.Profit; + changeUser.Profit = 0; + changeUser.CostAmount -= lessChangeAmount; + } + } + else + { + changeUser.CostAmount -= changeAmount; + } + } + + fsql.Transaction(() => + { + fsql.Update(changeUser.Id).Set(u => u.CostAmount, changeUser.CostAmount) + .Set(u => u.Profit, changeUser.Profit) + .SetIf(capitalChangeType == Enums.CapitalChangeType.Reduce, u => u.WithdrawAmount + changeAmount) + .ExecuteAffrows(); + + fsql.Insert(new UserAccountFundChangeRecord() + { + Id = idGenerator.NewLong(), + ChangeAmount = changeAmount, + UserId = changeUserId, + OperationType = capitalChangeType, + OperationUserId = operationUserId, + Remark = remark, + Direction = capitalChangeType == Enums.CapitalChangeType.Add ? Enums.FundDirection.In : Enums.FundDirection.Out + }).ExecuteAffrows(); + }); + } + + public void AddFunds(long operationUserId, FundsChangeRequest fundsChangeRequest) + { + if (fundsChangeRequest.ChangeAmount <= 0) + throw new BusinessException("无效金额"); + OneWayAssetChange(operationUserId, fundsChangeRequest.ChangeAmount, fundsChangeRequest.UserId, Enums.CapitalChangeType.Add, fundsChangeRequest.Remark); + } + + public void ReduceFunds(long operationUserId, FundsChangeRequest fundsChangeRequest) + { + if (fundsChangeRequest.ChangeAmount <= 0) + throw new BusinessException("无效金额"); + OneWayAssetChange(operationUserId, fundsChangeRequest.ChangeAmount, fundsChangeRequest.UserId, Enums.CapitalChangeType.Reduce, fundsChangeRequest.Remark); + } + + public void TransferFunds(long operationUserId, FundsTransferRequest fundsTransferRequest) + { + if (fundsTransferRequest.ChangeAmount <= 0) + throw new BusinessException("无效金额"); + + var userList = fsql.Select().ToList().Map>(); + var fromUser = userList.FirstOrDefault(u => u.Id == fundsTransferRequest.FromUserId); + if (fromUser == null) + throw new BusinessException("资金变更用户不存在"); + var toUser = userList.FirstOrDefault(u => u.Id == fundsTransferRequest.ToUserId); + if (toUser == null) + throw new BusinessException("资金变更用户不存在"); + + if (fromUser.TotalAssets < fundsTransferRequest.ChangeAmount) + throw new BusinessException("用户资产小于转移资金,不能转移"); + + if (fromUser.Profit > 0) + { + if (fromUser.Profit >= fundsTransferRequest.ChangeAmount) + fromUser.Profit -= fundsTransferRequest.ChangeAmount; //收益足够提现,只扣收益 + else + { + var lessChangeAmount = fundsTransferRequest.ChangeAmount; //收益不足提现,先扣收益,不足部分再扣本金 + lessChangeAmount -= fromUser.Profit; + fromUser.Profit = 0; + fromUser.CostAmount -= lessChangeAmount; + } + } + else + { + fromUser.CostAmount -= fundsTransferRequest.ChangeAmount; + } + + fsql.Transaction(() => + { + fsql.Update(fromUser.Id).Set(u => u.CostAmount, fromUser.CostAmount) + .Set(u => u.Profit, fromUser.Profit) + .Set(u => u.WithdrawAmount + fundsTransferRequest.ChangeAmount) + .ExecuteAffrows(); + + fsql.Update(toUser.Id).Set(u => u.CostAmount + fundsTransferRequest.ChangeAmount) + .ExecuteAffrows(); + + fsql.Insert(new UserAccountFundChangeRecord() + { + Id = idGenerator.NewLong(), + ChangeAmount = fundsTransferRequest.ChangeAmount, + UserId = fundsTransferRequest.FromUserId, + OperationType = Enums.CapitalChangeType.Transfer, + OperationUserId = operationUserId, + Remark = fundsTransferRequest.Remark, + Direction = Enums.FundDirection.Out, + ToUserId = fundsTransferRequest.ToUserId + }).ExecuteAffrows(); + + fsql.Insert(new UserAccountFundChangeRecord() + { + Id = idGenerator.NewLong(), + ChangeAmount = fundsTransferRequest.ChangeAmount, + UserId = fundsTransferRequest.ToUserId, + OperationType = Enums.CapitalChangeType.Transfer, + OperationUserId = operationUserId, + Remark = fundsTransferRequest.Remark, + Direction = Enums.FundDirection.In, + ToUserId = fundsTransferRequest.FromUserId + }).ExecuteAffrows(); + }); + } + + public UserAccountChangeRecordListResponse GetUserAccountFundChangeRecordList(QueryUserAccountRequest queryUserAccountRequest) + { + var list = fsql.Select() + .InnerJoin((ucr, u, ou, tu) => ucr.UserId == u.Id) + .InnerJoin((ucr, u, ou, tu) => ucr.OperationUserId == ou.Id) + .LeftJoin((ucr, u, ou, tu) => ucr.ToUserId == tu.Id) + .Where((ucr, u, ou, tu) => ucr.UserId == queryUserAccountRequest.UserId) + .Count(out var recordCount) + .Page(queryUserAccountRequest.PageIndex, queryUserAccountRequest.PageSize) + .ToList((ucr, u, ou, tu) => new UserAccountFundChangeRecordResponse() + { + Id = ucr.Id, + ChangeAmount = ucr.ChangeAmount, + CreateTime = ucr.CreateTime, + OperationType = ucr.OperationType, + OperationUserId = ucr.OperationUserId, + OperationUserName = ou.UserName, + UserId = ucr.UserId, + UserName = u.UserName, + Remark = ucr.Remark, + Direction = ucr.Direction, + ToUserId = tu.Id, + ToUserName = tu.UserName + }); + return new UserAccountChangeRecordListResponse() + { + List = list, + RecordCount = recordCount + }; + } + + //public UserAccountProfitLossRecordListResponse GetUserAccountProfitLossRecordList(QueryUserAccountRequest queryUserAccountRequest) + //{ + // var list = fsql.Select() + // .WithLock(SqlServerLock.NoLock) + // .InnerJoin((p, u, r) => p.UserId == u.Id) + // .InnerJoin((p, u, r) => p.RobotId == r.Id) + // .Where((p, u, r) => p.UserId == queryUserAccountRequest.UserId) + // .Count(out var recordCount) + // .Page(queryUserAccountRequest.PageIndex, queryUserAccountRequest.PageSize) + // .ToList((p, u, r) => new UserAccountProfitLossRecordResponse() + // { + // Id = p.Id, + // ChangeAmount = p.ChangeAmount, + // CreateTime = p.CreateTime, + // DividendRatio = p.DividendRatio, + // OrderProfit = p.OrderProfit, + // RobotId = p.RobotId, + // SpotOrderId = p.SpotOrderId, + // Symbol = r.Symbol, + // UserId = p.UserId, + // UserName = u.UserName, + // UserProfit = p.UserProfit + // }); + // return new UserAccountProfitLossRecordListResponse() + // { + // List = list, + // RecordCount = recordCount + // }; + //} + + #endregion } } diff --git a/Binance.TradeRobot.Model/Base/MappingProfiles.cs b/Binance.TradeRobot.Model/Base/MappingProfiles.cs index b63616d..ebf17f8 100644 --- a/Binance.TradeRobot.Model/Base/MappingProfiles.cs +++ b/Binance.TradeRobot.Model/Base/MappingProfiles.cs @@ -4,5 +4,9 @@ namespace Binance.TradeRobot.Model.Base { public class MappingProfiles : Profile { + public MappingProfiles() + { + + } } } diff --git a/Binance.TradeRobot.Model/Binance.TradeRobot.Model.xml b/Binance.TradeRobot.Model/Binance.TradeRobot.Model.xml index 079612d..65c6842 100644 --- a/Binance.TradeRobot.Model/Binance.TradeRobot.Model.xml +++ b/Binance.TradeRobot.Model/Binance.TradeRobot.Model.xml @@ -119,5 +119,45 @@ 密码需要Md5小写加密 + + + 页数,从1开始 + + + + + 每页记录数 + + + + + 资金变更用户名 + + + + + 操作用户名 + + + + + 对端用户名 + + + + + 总资产(本金+收益) + + + + + 本金比例 + + + + + 分红比例 + + diff --git a/Binance.TradeRobot.Model/Db/UserAccountFundChangeRecord.cs b/Binance.TradeRobot.Model/Db/UserAccountFundChangeRecord.cs index 0475840..d084bb9 100644 --- a/Binance.TradeRobot.Model/Db/UserAccountFundChangeRecord.cs +++ b/Binance.TradeRobot.Model/Db/UserAccountFundChangeRecord.cs @@ -41,6 +41,9 @@ namespace Binance.TradeRobot.Model.Db /// 对端用户Id /// public long? ToUserId { get; set; } + + [Column(StringLength = 100)] + public string Remark { get; set; } } } diff --git a/Binance.TradeRobot.Model/Db/UserAccountProfitLossRecord.cs b/Binance.TradeRobot.Model/Db/UserAccountProfitLossRecord.cs index 3d74bf3..46b3e86 100644 --- a/Binance.TradeRobot.Model/Db/UserAccountProfitLossRecord.cs +++ b/Binance.TradeRobot.Model/Db/UserAccountProfitLossRecord.cs @@ -30,8 +30,8 @@ namespace Binance.TradeRobot.Model.Db [Column(DbType = "decimal(18,2)")] public decimal DividendRatio { get; set; } = 0.0M; - - public long? Id { get; set; } + [Column(IsPrimary = true)] + public long Id { get; set; } public long OrderId { get; set; } diff --git a/Binance.TradeRobot.Model/Dto/Request/User/FundsChangeRequest.cs b/Binance.TradeRobot.Model/Dto/Request/User/FundsChangeRequest.cs new file mode 100644 index 0000000..451c5b9 --- /dev/null +++ b/Binance.TradeRobot.Model/Dto/Request/User/FundsChangeRequest.cs @@ -0,0 +1,11 @@ +namespace Binance.TradeRobot.Model.Dto +{ + public class FundsChangeRequest + { + public long UserId { get; set; } + + public decimal ChangeAmount { get; set; } + + public string Remark { get; set; } + } +} diff --git a/Binance.TradeRobot.Model/Dto/Request/User/FundsTransferRequest.cs b/Binance.TradeRobot.Model/Dto/Request/User/FundsTransferRequest.cs new file mode 100644 index 0000000..d8ae489 --- /dev/null +++ b/Binance.TradeRobot.Model/Dto/Request/User/FundsTransferRequest.cs @@ -0,0 +1,13 @@ +namespace Binance.TradeRobot.Model.Dto +{ + public class FundsTransferRequest + { + public long FromUserId { get; set; } + + public long ToUserId { get; set; } + + public decimal ChangeAmount { get; set; } + + public string Remark { get; set; } + } +} diff --git a/Binance.TradeRobot.Model/Dto/Request/User/LoginRequest.cs b/Binance.TradeRobot.Model/Dto/Request/User/LoginRequest.cs index fe1fc30..b84cb2b 100644 --- a/Binance.TradeRobot.Model/Dto/Request/User/LoginRequest.cs +++ b/Binance.TradeRobot.Model/Dto/Request/User/LoginRequest.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Binance.TradeRobot.Model.Dto +namespace Binance.TradeRobot.Model.Dto { public class LoginRequest { diff --git a/Binance.TradeRobot.Model/Dto/Request/User/QueryUserAccountRequest.cs b/Binance.TradeRobot.Model/Dto/Request/User/QueryUserAccountRequest.cs new file mode 100644 index 0000000..29ace3a --- /dev/null +++ b/Binance.TradeRobot.Model/Dto/Request/User/QueryUserAccountRequest.cs @@ -0,0 +1,17 @@ +namespace Binance.TradeRobot.Model.Dto +{ + public class QueryUserAccountRequest + { + public long UserId { get; set; } + + /// + /// 页数,从1开始 + /// + public int PageIndex { get; set; } + + /// + /// 每页记录数 + /// + public int PageSize { get; set; } + } +} diff --git a/Binance.TradeRobot.Model/Dto/Response/User/UserAccountFundChangeRecordResponse.cs b/Binance.TradeRobot.Model/Dto/Response/User/UserAccountFundChangeRecordResponse.cs new file mode 100644 index 0000000..a616c40 --- /dev/null +++ b/Binance.TradeRobot.Model/Dto/Response/User/UserAccountFundChangeRecordResponse.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; + +namespace Binance.TradeRobot.Model.Dto +{ + public class UserAccountFundChangeRecordResponse : Db.UserAccountFundChangeRecord + { + /// + /// 资金变更用户名 + /// + public string UserName { get; set; } + + /// + /// 操作用户名 + /// + public string OperationUserName { get; set; } + + /// + /// 对端用户名 + /// + public string ToUserName { get; set; } + } + + public class UserAccountChangeRecordListResponse + { + public long RecordCount { get; set; } + + public IList List { get; set; } + } +} diff --git a/Binance.TradeRobot.Model/Dto/Response/User/UserResponse.cs b/Binance.TradeRobot.Model/Dto/Response/User/UserResponse.cs index 6057e9f..ad3ff46 100644 --- a/Binance.TradeRobot.Model/Dto/Response/User/UserResponse.cs +++ b/Binance.TradeRobot.Model/Dto/Response/User/UserResponse.cs @@ -1,6 +1,20 @@ namespace Binance.TradeRobot.Model.Dto { - public class UserResponse + public class UserResponse : Db.User { + /// + /// 总资产(本金+收益) + /// + public decimal TotalAssets { get { return CostAmount + Profit; } } + + /// + /// 本金比例 + /// + public decimal CostRatio { get; set; } + + /// + /// 分红比例 + /// + public decimal DividendRatio { get; set; } } }