币安量化交易
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

299 lines
14 KiB

using Binance.TradeRobot.Business.Extensions;
using Binance.TradeRobot.Common.DI;
3 years ago
using Binance.TradeRobot.Common.Extensions;
using Binance.TradeRobot.Model.Base;
using Binance.TradeRobot.Model.Db;
using Binance.TradeRobot.Model.Dto;
using Microsoft.Extensions.Caching.Memory;
3 years ago
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
3 years ago
using System.Security.Claims;
using System.Text;
using Yitter.IdGenerator;
3 years ago
namespace Binance.TradeRobot.Business
{
[BatchRegistration(ServiceLifetime.Singleton, RegistrationType.Self)]
public class UserBusiness : BaseBusiness
{
private IConfiguration configuration;
public UserBusiness(IFreeSql fsql, NLogManager logManager, IIdGenerator idGenerator, IConfiguration configuration, IMemoryCache memoryCache) : base(fsql, logManager, idGenerator, memoryCache)
3 years ago
{
this.configuration = configuration;
}
public LoginResponse Login(LoginRequest loginRequest)
{
var pwd = loginRequest.Pwd.ToMD5();
var user = fsql.Select<User>().Where(u => u.UserName == loginRequest.UserName && u.Pwd == pwd).ToOne();
if (user == null)
throw new BusinessException("用户名或密码错误");
#region 签发token
var claims = new List<Claim>()
{
new Claim("Id",user.Id.ToString()),
new Claim("UserName",user.UserName),
};
var jwtSecret = configuration.GetSection("JwtConfig:Secret").Value;
var jwtIssuer = configuration.GetSection("JwtConfig:Issuer").Value;
var jwtAudience = configuration.GetSection("JwtConfig:Audience").Value;
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSecret));
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var jwtToken = new JwtSecurityToken(jwtIssuer, jwtAudience, claims, expires: DateTime.Now.AddDays(30), signingCredentials: credentials);
var token = new JwtSecurityTokenHandler().WriteToken(jwtToken);
#endregion
return new LoginResponse()
{
Id = user.Id,
UserName = user.UserName,
Token = token
};
}
3 years ago
public IList<UserResponse> GetUserList(bool multiplyBy100 = true)
{
var userList = fsql.Select<User>().ToList(u => new UserResponse()
{
Id = u.Id,
CostAmount = u.CostAmount,
CreateTime = u.CreateTime,
Profit = u.Profit,
UpdateTime = u.UpdateTime,
UserName = u.UserName,
WithdrawAmount = u.WithdrawAmount
});
3 years ago
userList.CalculateRatio(multiplyBy100);
return userList;
}
#region 用户资产
/// <summary>
/// 单向资产变更
/// </summary>
/// <param name="operationUserId"></param>
/// <param name="changeAmount"></param>
/// <param name="changeUserId"></param>
/// <param name="capitalChangeType"></param>
/// <param name="remark"></param>
/// <exception cref="BusinessException"></exception>
private void OneWayAssetChange(long operationUserId, decimal changeAmount, long changeUserId, Enums.CapitalChangeType capitalChangeType, string remark)
{
var changeUser = fsql.Select<User>(changeUserId).ToOne().Map<UserResponse>();
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("交易所总余额小于减持资金,不能提现");
}
3 years ago
changeUser.ChangeAmount(capitalChangeType, changeAmount, true);
//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<User>(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<User>().ToList().Map<IList<UserResponse>>();
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<User>(fromUser.Id).Set(u => u.CostAmount, fromUser.CostAmount)
.Set(u => u.Profit, fromUser.Profit)
.Set(u => u.WithdrawAmount + fundsTransferRequest.ChangeAmount)
.ExecuteAffrows();
fsql.Update<User>(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<UserAccountFundChangeRecord, User, User, User>()
.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)
3 years ago
.OrderByDescending((ucr, u, ou, tu) => ucr.CreateTime)
.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
};
}
3 years ago
public UserAccountProfitLossRecordListResponse GetUserAccountProfitLossRecordList(QueryUserAccountRequest queryUserAccountRequest)
{
var list = fsql.Select<Model.Db.UserAccountProfitLossRecord, Model.Db.User, Model.Db.Robot>()
.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)
3 years ago
.OrderByDescending((p, u, r) => p.CreateTime)
3 years ago
.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,
OrderId = p.OrderId,
Symbol = r.Symbol,
UserId = p.UserId,
UserName = u.UserName,
UserProfit = p.UserProfit
});
return new UserAccountProfitLossRecordListResponse()
{
List = list,
RecordCount = recordCount
};
}
#endregion
3 years ago
}
}