fix 字段名称错误
This commit is contained in:
parent
60f3b487ff
commit
49b9adfdab
@ -45,7 +45,7 @@ public class PortfolioController : ControllerBase
|
|||||||
var response = await _portfolioFacade.CreatePortfolioWithValidationAsync(request, userId);
|
var response = await _portfolioFacade.CreatePortfolioWithValidationAsync(request, userId);
|
||||||
return Ok(new ApiResponse<CreatePortfolioResponse>
|
return Ok(new ApiResponse<CreatePortfolioResponse>
|
||||||
{
|
{
|
||||||
code = StatusCodes.Success,
|
code = Models.StatusCodes.Success,
|
||||||
data = response,
|
data = response,
|
||||||
message = "创建成功"
|
message = "创建成功"
|
||||||
});
|
});
|
||||||
@ -54,7 +54,7 @@ public class PortfolioController : ControllerBase
|
|||||||
{
|
{
|
||||||
return BadRequest(new ApiResponse<CreatePortfolioResponse>
|
return BadRequest(new ApiResponse<CreatePortfolioResponse>
|
||||||
{
|
{
|
||||||
code = StatusCodes.BadRequest,
|
code = Models.StatusCodes.BadRequest,
|
||||||
data = null,
|
data = null,
|
||||||
message = ex.Message
|
message = ex.Message
|
||||||
});
|
});
|
||||||
@ -72,7 +72,7 @@ public class PortfolioController : ControllerBase
|
|||||||
|
|
||||||
return Ok(new ApiResponse<List<PortfolioListItem>>
|
return Ok(new ApiResponse<List<PortfolioListItem>>
|
||||||
{
|
{
|
||||||
code = StatusCodes.Success,
|
code = Models.StatusCodes.Success,
|
||||||
data = portfolios,
|
data = portfolios,
|
||||||
message = "success"
|
message = "success"
|
||||||
});
|
});
|
||||||
@ -91,7 +91,7 @@ public class PortfolioController : ControllerBase
|
|||||||
var portfolio = await _portfolioFacade.GetPortfolioDetailAsync(id, userId);
|
var portfolio = await _portfolioFacade.GetPortfolioDetailAsync(id, userId);
|
||||||
return Ok(new ApiResponse<PortfolioDetailResponse>
|
return Ok(new ApiResponse<PortfolioDetailResponse>
|
||||||
{
|
{
|
||||||
code = StatusCodes.Success,
|
code = Models.StatusCodes.Success,
|
||||||
data = portfolio,
|
data = portfolio,
|
||||||
message = "success"
|
message = "success"
|
||||||
});
|
});
|
||||||
@ -100,7 +100,7 @@ public class PortfolioController : ControllerBase
|
|||||||
{
|
{
|
||||||
return NotFound(new ApiResponse<PortfolioDetailResponse>
|
return NotFound(new ApiResponse<PortfolioDetailResponse>
|
||||||
{
|
{
|
||||||
code = StatusCodes.NotFound,
|
code = Models.StatusCodes.NotFound,
|
||||||
data = null,
|
data = null,
|
||||||
message = "组合不存在"
|
message = "组合不存在"
|
||||||
});
|
});
|
||||||
@ -120,7 +120,7 @@ public class PortfolioController : ControllerBase
|
|||||||
{
|
{
|
||||||
return NotFound(new ApiResponse<object>
|
return NotFound(new ApiResponse<object>
|
||||||
{
|
{
|
||||||
code = StatusCodes.NotFound,
|
code = Models.StatusCodes.NotFound,
|
||||||
data = null,
|
data = null,
|
||||||
message = "组合不存在"
|
message = "组合不存在"
|
||||||
});
|
});
|
||||||
@ -128,7 +128,7 @@ public class PortfolioController : ControllerBase
|
|||||||
|
|
||||||
return Ok(new ApiResponse<object>
|
return Ok(new ApiResponse<object>
|
||||||
{
|
{
|
||||||
code = StatusCodes.Success,
|
code = Models.StatusCodes.Success,
|
||||||
data = null,
|
data = null,
|
||||||
message = "删除成功"
|
message = "删除成功"
|
||||||
});
|
});
|
||||||
@ -148,9 +148,9 @@ public class PortfolioController : ControllerBase
|
|||||||
|
|
||||||
var request = new NavHistoryRequest
|
var request = new NavHistoryRequest
|
||||||
{
|
{
|
||||||
startDate = startDate,
|
StartDate = startDate,
|
||||||
endDate = endDate,
|
EndDate = endDate,
|
||||||
interval = interval ?? "daily"
|
Interval = interval ?? "daily"
|
||||||
};
|
};
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -158,7 +158,7 @@ public class PortfolioController : ControllerBase
|
|||||||
var response = await _portfolioFacade.GetNavHistoryAsync(id, request, userId);
|
var response = await _portfolioFacade.GetNavHistoryAsync(id, request, userId);
|
||||||
return Ok(new ApiResponse<NavHistoryResponse>
|
return Ok(new ApiResponse<NavHistoryResponse>
|
||||||
{
|
{
|
||||||
code = StatusCodes.Success,
|
code = Models.StatusCodes.Success,
|
||||||
data = response,
|
data = response,
|
||||||
message = "success"
|
message = "success"
|
||||||
});
|
});
|
||||||
@ -167,7 +167,7 @@ public class PortfolioController : ControllerBase
|
|||||||
{
|
{
|
||||||
return NotFound(new ApiResponse<NavHistoryResponse>
|
return NotFound(new ApiResponse<NavHistoryResponse>
|
||||||
{
|
{
|
||||||
code = StatusCodes.NotFound,
|
code = Models.StatusCodes.NotFound,
|
||||||
data = null,
|
data = null,
|
||||||
message = "组合不存在"
|
message = "组合不存在"
|
||||||
});
|
});
|
||||||
@ -189,7 +189,7 @@ public class PortfolioController : ControllerBase
|
|||||||
var response = await _portfolioFacade.BackfillNavHistoryAsync(id, userId, force);
|
var response = await _portfolioFacade.BackfillNavHistoryAsync(id, userId, force);
|
||||||
return Ok(new ApiResponse<BackfillNavResponse>
|
return Ok(new ApiResponse<BackfillNavResponse>
|
||||||
{
|
{
|
||||||
code = StatusCodes.Success,
|
code = Models.StatusCodes.Success,
|
||||||
data = response,
|
data = response,
|
||||||
message = "success"
|
message = "success"
|
||||||
});
|
});
|
||||||
@ -198,7 +198,7 @@ public class PortfolioController : ControllerBase
|
|||||||
{
|
{
|
||||||
return NotFound(new ApiResponse<BackfillNavResponse>
|
return NotFound(new ApiResponse<BackfillNavResponse>
|
||||||
{
|
{
|
||||||
code = StatusCodes.NotFound,
|
code = Models.StatusCodes.NotFound,
|
||||||
data = null,
|
data = null,
|
||||||
message = "组合不存在"
|
message = "组合不存在"
|
||||||
});
|
});
|
||||||
@ -220,7 +220,7 @@ public class PortfolioController : ControllerBase
|
|||||||
var transaction = await _portfolioFacade.CreateTransactionAsync(id, request, userId);
|
var transaction = await _portfolioFacade.CreateTransactionAsync(id, request, userId);
|
||||||
return Ok(new ApiResponse<TransactionItem>
|
return Ok(new ApiResponse<TransactionItem>
|
||||||
{
|
{
|
||||||
code = StatusCodes.Success,
|
code = Models.StatusCodes.Success,
|
||||||
data = transaction,
|
data = transaction,
|
||||||
message = "交易创建成功"
|
message = "交易创建成功"
|
||||||
});
|
});
|
||||||
@ -229,7 +229,7 @@ public class PortfolioController : ControllerBase
|
|||||||
{
|
{
|
||||||
return NotFound(new ApiResponse<TransactionItem>
|
return NotFound(new ApiResponse<TransactionItem>
|
||||||
{
|
{
|
||||||
code = StatusCodes.NotFound,
|
code = Models.StatusCodes.NotFound,
|
||||||
data = null,
|
data = null,
|
||||||
message = "组合不存在"
|
message = "组合不存在"
|
||||||
});
|
});
|
||||||
@ -249,20 +249,20 @@ public class PortfolioController : ControllerBase
|
|||||||
|
|
||||||
var request = new GetTransactionsRequest
|
var request = new GetTransactionsRequest
|
||||||
{
|
{
|
||||||
portfolioId = id,
|
PortfolioId = id,
|
||||||
limit = limit,
|
Limit = limit,
|
||||||
offset = offset
|
Offset = offset
|
||||||
};
|
};
|
||||||
|
|
||||||
var transactions = await _portfolioFacade.GetTransactionsAsync(id, request, userId);
|
var transactions = await _portfolioFacade.GetTransactionsAsync(id, request, userId);
|
||||||
|
|
||||||
return Ok(new ApiResponse<GetTransactionsResponse>
|
return Ok(new ApiResponse<GetTransactionsResponse>
|
||||||
{
|
{
|
||||||
code = StatusCodes.Success,
|
code = Models.StatusCodes.Success,
|
||||||
data = new GetTransactionsResponse
|
data = new GetTransactionsResponse
|
||||||
{
|
{
|
||||||
items = transactions,
|
Items = transactions,
|
||||||
total = transactions.Count
|
Total = transactions.Count
|
||||||
},
|
},
|
||||||
message = "success"
|
message = "success"
|
||||||
});
|
});
|
||||||
@ -281,7 +281,7 @@ public class PortfolioController : ControllerBase
|
|||||||
var signal = await _portfolioFacade.GetStrategySignalAsync(id, userId);
|
var signal = await _portfolioFacade.GetStrategySignalAsync(id, userId);
|
||||||
return Ok(new ApiResponse<StrategySignalResponse>
|
return Ok(new ApiResponse<StrategySignalResponse>
|
||||||
{
|
{
|
||||||
code = StatusCodes.Success,
|
code = Models.StatusCodes.Success,
|
||||||
data = signal,
|
data = signal,
|
||||||
message = "success"
|
message = "success"
|
||||||
});
|
});
|
||||||
@ -290,7 +290,7 @@ public class PortfolioController : ControllerBase
|
|||||||
{
|
{
|
||||||
return NotFound(new ApiResponse<StrategySignalResponse>
|
return NotFound(new ApiResponse<StrategySignalResponse>
|
||||||
{
|
{
|
||||||
code = StatusCodes.NotFound,
|
code = Models.StatusCodes.NotFound,
|
||||||
data = null,
|
data = null,
|
||||||
message = "组合不存在"
|
message = "组合不存在"
|
||||||
});
|
});
|
||||||
|
|||||||
@ -28,7 +28,7 @@ public class StrategyController : ControllerBase
|
|||||||
return User.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? throw new Exception("User not authenticated");
|
return User.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? throw new Exception("User not authenticated");
|
||||||
}
|
}
|
||||||
|
|
||||||
private StrategyListItemDTO MapToStrategyListItemDTO(Strategy strategy)
|
private StrategyListItemDto MapToStrategyListItemDTO(Strategy strategy)
|
||||||
{
|
{
|
||||||
List<string> tags = new List<string>();
|
List<string> tags = new List<string>();
|
||||||
if (!string.IsNullOrEmpty(strategy.Tags))
|
if (!string.IsNullOrEmpty(strategy.Tags))
|
||||||
@ -41,18 +41,18 @@ public class StrategyController : ControllerBase
|
|||||||
catch { }
|
catch { }
|
||||||
}
|
}
|
||||||
|
|
||||||
return new StrategyListItemDTO
|
return new StrategyListItemDto
|
||||||
{
|
{
|
||||||
id = strategy.Id,
|
Id = strategy.Id,
|
||||||
userId = strategy.UserId,
|
UserId = strategy.UserId,
|
||||||
name = strategy.Alias,
|
Name = strategy.Alias,
|
||||||
type = strategy.Type,
|
Type = strategy.Type,
|
||||||
description = strategy.Description,
|
Description = strategy.Description,
|
||||||
tags = tags,
|
Tags = tags,
|
||||||
riskLevel = strategy.RiskLevel,
|
RiskLevel = strategy.RiskLevel,
|
||||||
config = strategy.Config,
|
Config = strategy.Config,
|
||||||
createdAt = strategy.CreatedAt,
|
CreatedAt = strategy.CreatedAt,
|
||||||
updatedAt = strategy.UpdatedAt
|
UpdatedAt = strategy.UpdatedAt
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +64,7 @@ public class StrategyController : ControllerBase
|
|||||||
/// 此接口用于获取当前登录用户的所有策略列表。
|
/// 此接口用于获取当前登录用户的所有策略列表。
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
[HttpGet("strategies")]
|
[HttpGet("strategies")]
|
||||||
public ActionResult<ApiResponse<List<StrategyListItemDTO>>> GetStrategies()
|
public ActionResult<ApiResponse<List<StrategyListItemDto>>> GetStrategies()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -76,7 +76,7 @@ public class StrategyController : ControllerBase
|
|||||||
|
|
||||||
_logger.LogInformation("Strategies retrieved successfully");
|
_logger.LogInformation("Strategies retrieved successfully");
|
||||||
|
|
||||||
return Ok(new ApiResponse<List<StrategyListItemDTO>>
|
return Ok(new ApiResponse<List<StrategyListItemDto>>
|
||||||
{
|
{
|
||||||
code = AssetManager.Models.StatusCodes.Success,
|
code = AssetManager.Models.StatusCodes.Success,
|
||||||
data = strategyListItems,
|
data = strategyListItems,
|
||||||
@ -87,7 +87,7 @@ public class StrategyController : ControllerBase
|
|||||||
{
|
{
|
||||||
_logger.LogError(ex, "Error retrieving strategies");
|
_logger.LogError(ex, "Error retrieving strategies");
|
||||||
|
|
||||||
return StatusCode(AssetManager.Models.StatusCodes.InternalServerError, new ApiResponse<List<StrategyListItemDTO>>
|
return StatusCode(AssetManager.Models.StatusCodes.InternalServerError, new ApiResponse<List<StrategyListItemDto>>
|
||||||
{
|
{
|
||||||
code = AssetManager.Models.StatusCodes.InternalServerError,
|
code = AssetManager.Models.StatusCodes.InternalServerError,
|
||||||
data = null,
|
data = null,
|
||||||
@ -105,7 +105,7 @@ public class StrategyController : ControllerBase
|
|||||||
/// 此接口用于获取指定策略的详细信息。
|
/// 此接口用于获取指定策略的详细信息。
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
[HttpGet("{id}")]
|
[HttpGet("{id}")]
|
||||||
public ActionResult<ApiResponse<StrategyListItemDTO>> GetStrategyById(string id)
|
public ActionResult<ApiResponse<StrategyListItemDto>> GetStrategyById(string id)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -117,7 +117,7 @@ public class StrategyController : ControllerBase
|
|||||||
|
|
||||||
_logger.LogInformation($"Strategy {id} retrieved successfully");
|
_logger.LogInformation($"Strategy {id} retrieved successfully");
|
||||||
|
|
||||||
return Ok(new ApiResponse<StrategyListItemDTO>
|
return Ok(new ApiResponse<StrategyListItemDto>
|
||||||
{
|
{
|
||||||
code = AssetManager.Models.StatusCodes.Success,
|
code = AssetManager.Models.StatusCodes.Success,
|
||||||
data = strategyItem,
|
data = strategyItem,
|
||||||
@ -128,7 +128,7 @@ public class StrategyController : ControllerBase
|
|||||||
{
|
{
|
||||||
_logger.LogError(ex, $"Error retrieving strategy {id}");
|
_logger.LogError(ex, $"Error retrieving strategy {id}");
|
||||||
|
|
||||||
return StatusCode(AssetManager.Models.StatusCodes.InternalServerError, new ApiResponse<StrategyListItemDTO>
|
return StatusCode(AssetManager.Models.StatusCodes.InternalServerError, new ApiResponse<StrategyListItemDto>
|
||||||
{
|
{
|
||||||
code = AssetManager.Models.StatusCodes.InternalServerError,
|
code = AssetManager.Models.StatusCodes.InternalServerError,
|
||||||
data = null,
|
data = null,
|
||||||
@ -146,11 +146,11 @@ public class StrategyController : ControllerBase
|
|||||||
/// 此接口用于创建新的策略。
|
/// 此接口用于创建新的策略。
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public ActionResult<ApiResponse<StrategyListItemDTO>> CreateStrategy([FromBody] CreateStrategyRequest request)
|
public ActionResult<ApiResponse<StrategyListItemDto>> CreateStrategy([FromBody] CreateStrategyRequest request)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_logger.LogInformation($"Request to create strategy: {request.name}");
|
_logger.LogInformation($"Request to create strategy: {request.Name}");
|
||||||
|
|
||||||
var userId = GetCurrentUserId();
|
var userId = GetCurrentUserId();
|
||||||
var strategy = _strategyService.CreateStrategy(request, userId);
|
var strategy = _strategyService.CreateStrategy(request, userId);
|
||||||
@ -158,7 +158,7 @@ public class StrategyController : ControllerBase
|
|||||||
|
|
||||||
_logger.LogInformation($"Strategy {strategy.Id} created successfully");
|
_logger.LogInformation($"Strategy {strategy.Id} created successfully");
|
||||||
|
|
||||||
return Ok(new ApiResponse<StrategyListItemDTO>
|
return Ok(new ApiResponse<StrategyListItemDto>
|
||||||
{
|
{
|
||||||
code = AssetManager.Models.StatusCodes.Success,
|
code = AssetManager.Models.StatusCodes.Success,
|
||||||
data = strategyItem,
|
data = strategyItem,
|
||||||
@ -169,7 +169,7 @@ public class StrategyController : ControllerBase
|
|||||||
{
|
{
|
||||||
_logger.LogError(ex, "Error creating strategy");
|
_logger.LogError(ex, "Error creating strategy");
|
||||||
|
|
||||||
return StatusCode(AssetManager.Models.StatusCodes.InternalServerError, new ApiResponse<StrategyListItemDTO>
|
return StatusCode(AssetManager.Models.StatusCodes.InternalServerError, new ApiResponse<StrategyListItemDto>
|
||||||
{
|
{
|
||||||
code = AssetManager.Models.StatusCodes.InternalServerError,
|
code = AssetManager.Models.StatusCodes.InternalServerError,
|
||||||
data = null,
|
data = null,
|
||||||
@ -188,7 +188,7 @@ public class StrategyController : ControllerBase
|
|||||||
/// 此接口用于更新指定策略的信息。
|
/// 此接口用于更新指定策略的信息。
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
[HttpPut("{id}")]
|
[HttpPut("{id}")]
|
||||||
public ActionResult<ApiResponse<StrategyListItemDTO>> UpdateStrategy(string id, [FromBody] UpdateStrategyRequest request)
|
public ActionResult<ApiResponse<StrategyListItemDto>> UpdateStrategy(string id, [FromBody] UpdateStrategyRequest request)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -200,7 +200,7 @@ public class StrategyController : ControllerBase
|
|||||||
|
|
||||||
_logger.LogInformation($"Strategy {id} updated successfully");
|
_logger.LogInformation($"Strategy {id} updated successfully");
|
||||||
|
|
||||||
return Ok(new ApiResponse<StrategyListItemDTO>
|
return Ok(new ApiResponse<StrategyListItemDto>
|
||||||
{
|
{
|
||||||
code = AssetManager.Models.StatusCodes.Success,
|
code = AssetManager.Models.StatusCodes.Success,
|
||||||
data = strategyItem,
|
data = strategyItem,
|
||||||
@ -211,7 +211,7 @@ public class StrategyController : ControllerBase
|
|||||||
{
|
{
|
||||||
_logger.LogError(ex, $"Error updating strategy {id}");
|
_logger.LogError(ex, $"Error updating strategy {id}");
|
||||||
|
|
||||||
return StatusCode(AssetManager.Models.StatusCodes.InternalServerError, new ApiResponse<StrategyListItemDTO>
|
return StatusCode(AssetManager.Models.StatusCodes.InternalServerError, new ApiResponse<StrategyListItemDto>
|
||||||
{
|
{
|
||||||
code = AssetManager.Models.StatusCodes.InternalServerError,
|
code = AssetManager.Models.StatusCodes.InternalServerError,
|
||||||
data = null,
|
data = null,
|
||||||
|
|||||||
@ -54,15 +54,15 @@ public class PortfolioService : IPortfolioService
|
|||||||
.Where(s => s.Id == request.StrategyId && s.UserId == userId)
|
.Where(s => s.Id == request.StrategyId && s.UserId == userId)
|
||||||
.First();
|
.First();
|
||||||
|
|
||||||
if (strategy != null && !string.IsNullOrEmpty(strategy.Config))
|
if (Strategy != null && !string.IsNullOrEmpty(Strategy.Config))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 风险平价策略
|
// 风险平价策略
|
||||||
if (strategy.Type?.Equals("risk_parity", StringComparison.OrdinalIgnoreCase) == true)
|
if (Strategy.Type?.Equals("risk_parity", StringComparison.OrdinalIgnoreCase) == true)
|
||||||
{
|
{
|
||||||
// 处理可能的双层转义
|
// 处理可能的双层转义
|
||||||
string configJson = strategy.Config;
|
string configJson = Strategy.Config;
|
||||||
if (configJson.StartsWith("\"") && configJson.EndsWith("\""))
|
if (configJson.StartsWith("\"") && configJson.EndsWith("\""))
|
||||||
{
|
{
|
||||||
// 去掉外层的引号和转义
|
// 去掉外层的引号和转义
|
||||||
@ -219,7 +219,7 @@ public class PortfolioService : IPortfolioService
|
|||||||
.Where(pos => pos.PortfolioId == portfolio.Id)
|
.Where(pos => pos.PortfolioId == portfolio.Id)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
foreach (var pos in positions)
|
foreach (var pos in Positions)
|
||||||
{
|
{
|
||||||
if (pos.StockCode == null || pos.Currency == null)
|
if (pos.StockCode == null || pos.Currency == null)
|
||||||
{
|
{
|
||||||
@ -235,7 +235,7 @@ public class PortfolioService : IPortfolioService
|
|||||||
if (priceResponse.Price > 0)
|
if (priceResponse.Price > 0)
|
||||||
{
|
{
|
||||||
CurrentPrice = priceResponse.Price;
|
CurrentPrice = priceResponse.Price;
|
||||||
previousClose = priceResponse.PreviousClose > 0 ? priceResponse.PreviousClose : currentPrice;
|
previousClose = priceResponse.PreviousClose > 0 ? priceResponse.PreviousClose : CurrentPrice;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -243,14 +243,14 @@ public class PortfolioService : IPortfolioService
|
|||||||
_logger.LogWarning(ex, "获取标的 {StockCode} 实时价格失败,使用成本价作为当前价", pos.StockCode);
|
_logger.LogWarning(ex, "获取标的 {StockCode} 实时价格失败,使用成本价作为当前价", pos.StockCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
decimal currentPositionValue = pos.Shares * currentPrice;
|
decimal currentPositionValue = pos.Shares * CurrentPrice;
|
||||||
decimal costPositionValue = pos.Shares * pos.AvgPrice;
|
decimal costPositionValue = pos.Shares * pos.AvgPrice;
|
||||||
decimal TodayProfit = previousClose > 0 ? pos.Shares * (currentPrice - previousClose) : 0;
|
decimal TodayProfit = previousClose > 0 ? pos.Shares * (CurrentPrice - previousClose) : 0;
|
||||||
|
|
||||||
// 换算到目标本位币
|
// 换算到目标本位币
|
||||||
decimal currentInTarget = await _exchangeRateService.ConvertAmountAsync(currentPositionValue, pos.Currency, targetCurrency);
|
decimal currentInTarget = await _exchangeRateService.ConvertAmountAsync(currentPositionValue, pos.Currency, targetCurrency);
|
||||||
decimal costInTarget = await _exchangeRateService.ConvertAmountAsync(costPositionValue, pos.Currency, targetCurrency);
|
decimal costInTarget = await _exchangeRateService.ConvertAmountAsync(costPositionValue, pos.Currency, targetCurrency);
|
||||||
decimal todayProfitInTarget = await _exchangeRateService.ConvertAmountAsync(todayProfit, pos.Currency, targetCurrency);
|
decimal todayProfitInTarget = await _exchangeRateService.ConvertAmountAsync(TodayProfit, pos.Currency, targetCurrency);
|
||||||
|
|
||||||
_logger.LogInformation("标的 {StockCode} 换算: {Amount} {From} → {Converted} {To},汇率: {Rate}",
|
_logger.LogInformation("标的 {StockCode} 换算: {Amount} {From} → {Converted} {To},汇率: {Rate}",
|
||||||
pos.StockCode, currentPositionValue, pos.Currency, currentInTarget, targetCurrency,
|
pos.StockCode, currentPositionValue, pos.Currency, currentInTarget, targetCurrency,
|
||||||
@ -302,7 +302,7 @@ public class PortfolioService : IPortfolioService
|
|||||||
decimal totalTodayProfit = 0;
|
decimal totalTodayProfit = 0;
|
||||||
var positionItems = new List<PositionItem>();
|
var positionItems = new List<PositionItem>();
|
||||||
|
|
||||||
foreach (var pos in positions)
|
foreach (var pos in Positions)
|
||||||
{
|
{
|
||||||
if (pos.StockCode == null || pos.Currency == null)
|
if (pos.StockCode == null || pos.Currency == null)
|
||||||
{
|
{
|
||||||
@ -318,7 +318,7 @@ public class PortfolioService : IPortfolioService
|
|||||||
if (priceResponse.Price > 0)
|
if (priceResponse.Price > 0)
|
||||||
{
|
{
|
||||||
CurrentPrice = priceResponse.Price;
|
CurrentPrice = priceResponse.Price;
|
||||||
previousClose = priceResponse.PreviousClose > 0 ? priceResponse.PreviousClose : currentPrice;
|
previousClose = priceResponse.PreviousClose > 0 ? priceResponse.PreviousClose : CurrentPrice;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -326,16 +326,16 @@ public class PortfolioService : IPortfolioService
|
|||||||
_logger.LogWarning(ex, "获取标的 {StockCode} 实时价格失败,使用成本价作为当前价", pos.StockCode);
|
_logger.LogWarning(ex, "获取标的 {StockCode} 实时价格失败,使用成本价作为当前价", pos.StockCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
decimal positionValue = pos.Shares * currentPrice;
|
decimal positionValue = pos.Shares * CurrentPrice;
|
||||||
decimal cost = pos.Shares * pos.AvgPrice;
|
decimal cost = pos.Shares * pos.AvgPrice;
|
||||||
decimal Profit = positionValue - cost;
|
decimal Profit = positionValue - cost;
|
||||||
double ProfitRate = cost > 0 ? (double)(profit / cost * 100) : 0;
|
double ProfitRate = cost > 0 ? (double)(Profit / cost * 100) : 0;
|
||||||
decimal TodayProfit = previousClose > 0 ? pos.Shares * (currentPrice - previousClose) : 0;
|
decimal TodayProfit = previousClose > 0 ? pos.Shares * (CurrentPrice - previousClose) : 0;
|
||||||
|
|
||||||
// 转换为组合本位币
|
// 转换为组合本位币
|
||||||
decimal positionValueInTarget = await _exchangeRateService.ConvertAmountAsync(positionValue, pos.Currency, targetCurrency);
|
decimal positionValueInTarget = await _exchangeRateService.ConvertAmountAsync(positionValue, pos.Currency, targetCurrency);
|
||||||
decimal costInTarget = await _exchangeRateService.ConvertAmountAsync(cost, pos.Currency, targetCurrency);
|
decimal costInTarget = await _exchangeRateService.ConvertAmountAsync(cost, pos.Currency, targetCurrency);
|
||||||
decimal todayProfitInTarget = await _exchangeRateService.ConvertAmountAsync(todayProfit, pos.Currency, targetCurrency);
|
decimal todayProfitInTarget = await _exchangeRateService.ConvertAmountAsync(TodayProfit, pos.Currency, targetCurrency);
|
||||||
|
|
||||||
totalPortfolioValue += positionValueInTarget;
|
totalPortfolioValue += positionValueInTarget;
|
||||||
totalCost += costInTarget;
|
totalCost += costInTarget;
|
||||||
@ -349,10 +349,10 @@ public class PortfolioService : IPortfolioService
|
|||||||
Symbol = pos.StockCode,
|
Symbol = pos.StockCode,
|
||||||
Amount = (int)pos.Shares,
|
Amount = (int)pos.Shares,
|
||||||
AveragePrice = (double)pos.AvgPrice,
|
AveragePrice = (double)pos.AvgPrice,
|
||||||
CurrentPrice = (double)currentPrice,
|
CurrentPrice = (double)TodayProfit,
|
||||||
TotalValue = (double)positionValueInTarget,
|
TotalValue = (double)positionValueInTarget,
|
||||||
Profit = (double)(positionValueInTarget - costInTarget),
|
Profit = (double)(positionValueInTarget - costInTarget),
|
||||||
ProfitRate = profitRate,
|
ProfitRate = ProfitRate,
|
||||||
ChangeAmount = (double)todayProfitInTarget,
|
ChangeAmount = (double)todayProfitInTarget,
|
||||||
Ratio = 0, // 后面统一计算比例
|
Ratio = 0, // 后面统一计算比例
|
||||||
DeviationRatio = 0, // 后续实现
|
DeviationRatio = 0, // 后续实现
|
||||||
@ -367,7 +367,7 @@ public class PortfolioService : IPortfolioService
|
|||||||
}
|
}
|
||||||
|
|
||||||
decimal TotalReturn = totalPortfolioValue - totalCost;
|
decimal TotalReturn = totalPortfolioValue - totalCost;
|
||||||
double totalReturnRate = totalCost > 0 ? (double)(totalReturn / totalCost * 100) : 0;
|
double totalReturnRate = totalCost > 0 ? (double)(TotalReturn / totalCost * 100) : 0;
|
||||||
|
|
||||||
return new PortfolioDetailResponse
|
return new PortfolioDetailResponse
|
||||||
{
|
{
|
||||||
@ -382,7 +382,7 @@ public class PortfolioService : IPortfolioService
|
|||||||
Description = "策略描述"
|
Description = "策略描述"
|
||||||
},
|
},
|
||||||
PortfolioValue = (double)totalPortfolioValue,
|
PortfolioValue = (double)totalPortfolioValue,
|
||||||
TotalReturn = (double)totalReturn,
|
TotalReturn = (double)TotalReturn,
|
||||||
TodayProfit = (double)totalTodayProfit,
|
TodayProfit = (double)totalTodayProfit,
|
||||||
HistoricalChange = totalReturnRate,
|
HistoricalChange = totalReturnRate,
|
||||||
DailyVolatility = 0, // 后续实现
|
DailyVolatility = 0, // 后续实现
|
||||||
@ -390,7 +390,7 @@ public class PortfolioService : IPortfolioService
|
|||||||
LogicModel = "HFEA 风险平价逻辑",
|
LogicModel = "HFEA 风险平价逻辑",
|
||||||
LogicModelStatus = "监控中",
|
LogicModelStatus = "监控中",
|
||||||
LogicModelDescription = "目标权重 季度调仓",
|
LogicModelDescription = "目标权重 季度调仓",
|
||||||
TotalItems = positions.Count,
|
TotalItems = Positions.Count,
|
||||||
TotalRatio = 100.0,
|
TotalRatio = 100.0,
|
||||||
Positions = positionItems
|
Positions = positionItems
|
||||||
};
|
};
|
||||||
@ -576,7 +576,7 @@ public class PortfolioService : IPortfolioService
|
|||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
decimal totalPortfolioValue = 0;
|
decimal totalPortfolioValue = 0;
|
||||||
foreach (var pos in positions)
|
foreach (var pos in Positions)
|
||||||
{
|
{
|
||||||
if (pos.StockCode == null)
|
if (pos.StockCode == null)
|
||||||
{
|
{
|
||||||
@ -598,7 +598,7 @@ public class PortfolioService : IPortfolioService
|
|||||||
_logger.LogWarning(ex, "获取标的 {StockCode} 实时价格失败,使用成本价计算组合总价值", pos.StockCode);
|
_logger.LogWarning(ex, "获取标的 {StockCode} 实时价格失败,使用成本价计算组合总价值", pos.StockCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
totalPortfolioValue += pos.Shares * currentPrice;
|
totalPortfolioValue += pos.Shares * CurrentPrice;
|
||||||
}
|
}
|
||||||
|
|
||||||
portfolio.TotalValue = totalPortfolioValue;
|
portfolio.TotalValue = totalPortfolioValue;
|
||||||
@ -648,7 +648,7 @@ public class PortfolioService : IPortfolioService
|
|||||||
|
|
||||||
public Task<List<TransactionItem>> GetTransactionsAsync(string portfolioId, GetTransactionsRequest request, string userId)
|
public Task<List<TransactionItem>> GetTransactionsAsync(string portfolioId, GetTransactionsRequest request, string userId)
|
||||||
{
|
{
|
||||||
var response = GetTransactions(portfolioId, userId, request.limit, request.offset);
|
var response = GetTransactions(portfolioId, userId, request.Limit, request.Offset);
|
||||||
return Task.FromResult(response.Items ?? new List<TransactionItem>());
|
return Task.FromResult(response.Items ?? new List<TransactionItem>());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -659,7 +659,7 @@ public class PortfolioService : IPortfolioService
|
|||||||
|
|
||||||
return new TransactionItem
|
return new TransactionItem
|
||||||
{
|
{
|
||||||
Id = response.id,
|
Id = response.Id,
|
||||||
PortfolioId = portfolioId,
|
PortfolioId = portfolioId,
|
||||||
Date = DateTime.Now.ToString("yyyy-MM-dd"),
|
Date = DateTime.Now.ToString("yyyy-MM-dd"),
|
||||||
Time = DateTime.Now.ToString("HH:mm:ss"),
|
Time = DateTime.Now.ToString("HH:mm:ss"),
|
||||||
@ -667,7 +667,7 @@ public class PortfolioService : IPortfolioService
|
|||||||
StockCode = request.StockCode,
|
StockCode = request.StockCode,
|
||||||
Amount = response.TotalAmount,
|
Amount = response.TotalAmount,
|
||||||
Currency = request.Currency,
|
Currency = request.Currency,
|
||||||
Status = response.status,
|
Status = response.Status,
|
||||||
Remark = request.Remark
|
Remark = request.Remark
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -687,9 +687,9 @@ public class PortfolioService : IPortfolioService
|
|||||||
var Positions = _db.Queryable<Position>()
|
var Positions = _db.Queryable<Position>()
|
||||||
.Where(pos => pos.PortfolioId == portfolioId)
|
.Where(pos => pos.PortfolioId == portfolioId)
|
||||||
.ToList();
|
.ToList();
|
||||||
if (positions.Any())
|
if (Positions.Any())
|
||||||
{
|
{
|
||||||
_db.Deleteable(positions).ExecuteCommand();
|
_db.Deleteable(Positions).ExecuteCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除相关交易
|
// 删除相关交易
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
using AssetManager.Data;
|
using AssetManager.Data;
|
||||||
using AssetManager.Data.Repositories;
|
using AssetManager.Data.Repositories;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using Moq;
|
using Moq;
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|||||||
@ -3,6 +3,7 @@ using AssetManager.Infrastructure.Services;
|
|||||||
using AssetManager.Models.DTOs;
|
using AssetManager.Models.DTOs;
|
||||||
using AssetManager.Services;
|
using AssetManager.Services;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using Moq;
|
using Moq;
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user