using Knoks.Core.Data.Interfaces; using Knoks.Core.Entities; using Knoks.Core.Entities.Args; using Knoks.Core.Logic.Interfaces; using Microsoft.Extensions.Logging; using System.Linq; using System.Threading.Tasks; namespace Knoks.Core.Logic.Managers { public class KnokPriceManager : IKnokPricelManager { private readonly ILogger _logger; private readonly IUserDao _userDao; private readonly IKnokDao _knokDao; private readonly IKnokPriceDao _knokPriceDao; private readonly IKnokPriceLogic _knokPriceLogic; private readonly IKnokSettings _settings; //TODO - move this to settings private const decimal _objectiveWeight = 0.75m; private const decimal _analysisMultiplier = 0.33m; private const decimal _potenialProfitMultiplier = 10m; private const decimal _profitTimeRatioMultiplier = 100m; private const decimal _profitLossRatioMultiplier = 100m; public KnokPriceManager(ILogger logger, IKnokDao knokDao, IUserDao userDao, IKnokPriceLogic knokPriceLogic, IKnokPriceDao knokPriceDao, IKnokSettings settings) { _logger = logger; _userDao = userDao; _knokDao = knokDao; _knokPriceLogic = knokPriceLogic; _knokPriceDao = knokPriceDao; _settings = settings; } private async Task GetExpectancy(long userId) { var probabilityOfWinning = await _knokPriceDao.GetProbabilityOfWinning(userId); var winPayoff = await _knokPriceDao.GetWinPayoff(userId); var lossPayoff = await _knokPriceDao.GetLossPayoff(userId); return _knokPriceLogic.CalculateExpectancy(probabilityOfWinning, winPayoff, lossPayoff); } private decimal GetPaidPercent(UserRank userRank) { var userRankValue = (UserRankValues)userRank; return ((int)userRankValue) / 100; } private async Task GetObjectivePrice(long userId, UserRank userRank) { var expectancy = await GetExpectancy(userId); var paidPercent = GetPaidPercent(userRank); return _knokPriceLogic.CalculateObjectivePrice(expectancy, paidPercent, _objectiveWeight, _settings.Multiplier); } private decimal GetSubjectivePrice(CreateKnokArgs knok) { var faPrice = knok.Fundamental != null ? _knokPriceLogic.CalcAnalysisPrice(knok.Fundamental.Header, knok.Fundamental.Description, knok.Fundamental.Tags, _analysisMultiplier) : 0m; var taPrice = knok.Technical != null ? _knokPriceLogic.CalcAnalysisPrice(knok.Technical.Header, knok.Technical.Description, knok.Technical.Tags, _analysisMultiplier) : 0m; var potentialProfitPrice = _knokPriceLogic.CalculatePotentialProfitPrice(knok.PotentialProfitValue, _potenialProfitMultiplier);//a var profitTimeRatioPrice = _knokPriceLogic.CalculateProfitTimeRatioPrice(knok.PotentialProfitValue,knok.Duration,_profitTimeRatioMultiplier);//b var profitLossRatioPrice = _knokPriceLogic.CalculateProfitLossRatioPrice(knok.PotentialProfitValue, knok.EntryPriceFrom, knok.EntryPriceTo, knok.StopLoss, _profitLossRatioMultiplier);//c return _knokPriceLogic.CalculateSubjectivePrice(faPrice, taPrice, potentialProfitPrice, profitTimeRatioPrice, profitLossRatioPrice); } private decimal GetNetContribution(CreateKnokArgs knok) { var subjectivePrice = GetSubjectivePrice(knok); return subjectivePrice * (1 - _objectiveWeight); } public async Task TotalPrice(CreateKnokArgs knok, long userId) { var users = await _userDao.GetUsers(userId: userId); var userTypeId = users.First().UserTypeId; var userRank = (UserRank)userTypeId; knok.PotentialProfitValue = _knokPriceLogic.CalculatePotentialProfit(knok.EntryPriceFrom, knok.EntryPriceTo, knok.ExitPriceFrom, knok.ExitPriceTo); var objectivePrice = await GetObjectivePrice(userId, userRank); var netContribution = GetNetContribution(knok); var rankPayoff = _knokPriceLogic.RankPayoff(userRank); var rankWeighted = rankPayoff / 100m * netContribution; return objectivePrice + rankWeighted; } } }