/// <summary> /// 总利息 /// </summary> /// <param name="principal">本金</param> /// <param name="rateType">利率计算方式</param> /// <param name="rate">利率</param> /// <param name="deadline">期限</param> /// <param name="periods">期数</param> /// <returns></returns> public decimal GetTotalInterest(decimal principal, RepaymentRateType rateType, decimal rate, decimal deadline, int periods = 1) { var list = this.GetRepayments(principal, rateType, rate, deadline, periods); if (list == null) { return(0); } return(list.Sum(r => r.Interest)); }
/// <summary> /// 单元金额 /// </summary> /// <param name="rateType">利率计算方式</param> /// <returns></returns> public decimal GetUnitAmount(RepaymentRateType rateType = RepaymentRateType.年利率) { switch (rateType) { case RepaymentRateType.天利率: return(1m); case RepaymentRateType.月利率: return(1m / 30); case RepaymentRateType.季利率: return(1m / 90); default: case RepaymentRateType.年利率: return(1m / 360); } }
/// <summary> /// 获取N倍的单元金额 /// </summary> /// <param name="amount">总金额</param> /// <param name="rateType">利率计算方式</param> /// <returns></returns> public decimal GetNUnitAmount(decimal amount, RepaymentRateType rateType = RepaymentRateType.年利率) { switch (rateType) { case RepaymentRateType.天利率: return(amount * 1m * 30); case RepaymentRateType.月利率: return(amount * 1m); case RepaymentRateType.季利率: return(amount * 1m / 3); default: case RepaymentRateType.年利率: return(amount * 1m / 12); } }
/// <summary> /// 还款列表 /// </summary> /// <param name="principal">本金</param> /// <param name="rateType">利率计算方式</param> /// <param name="rate">利率</param> /// <param name="deadline">期限</param> /// <param name="periods">期数</param> /// <param name="autoFixPrincipalToInteger">是否为自动修正本金整数</param> /// <returns></returns> public override IEnumerable <RepaymentModel> GetRepayments(decimal principal, RepaymentRateType rateType, decimal rate, decimal deadline, int periods = 1, bool autoFixPrincipalToInteger = true) { if (periods <= 0) { throw new DomainException("还款期数不能小于0"); } /*总利息*/ var totalInterest = this.Strategy.GetNUnitAmount(principal * rate * deadline, rateType); var list = new List <RepaymentModel>(periods); /*不用修正本金或进要修正本金但能整除*/ if (!autoFixPrincipalToInteger || (autoFixPrincipalToInteger && principal % periods == 0)) { for (var i = 1; i <= periods; i++) { var model = new RepaymentModel() { Principal = principal / periods, Interest = totalInterest / periods, Period = i, PayDate = this.Strategy.GetPayTime(this.StartDate, deadline * i / periods) }; list.Add(model); } } else { var fixPrincipal = principal - principal % periods; var firstPrinciapl = principal - (periods - 1) * fixPrincipal / periods; var firstModel = new RepaymentModel() { Principal = firstPrinciapl, Interest = totalInterest / periods, Period = 1, PayDate = this.Strategy.GetPayTime(this.StartDate, deadline * 1 / periods) }; list.Add(firstModel); /*只有大于1期后才可能重新计算本金与利息*/ if (periods > 1) { var changeAvg = (principal - firstPrinciapl) / (periods - 1); for (var i = 2; i <= periods; i++) { var model = new RepaymentModel() { Principal = changeAvg, Interest = totalInterest / periods, Period = i, PayDate = this.Strategy.GetPayTime(this.StartDate, deadline * i / periods) }; list.Add(model); } } } return(list); }
/// <summary> /// 还款列表 /// </summary> /// <param name="principal">本金</param> /// <param name="rateType">利率计算方式</param> /// <param name="rate">利率</param> /// <param name="deadline">期限</param> /// <param name="periods">期数</param> /// <param name="autoFixPrincipalToInteger">是否为自动修正本金整数</param> /// <returns></returns> public override IEnumerable <RepaymentModel> GetRepayments(decimal principal, RepaymentRateType rateType, decimal rate, decimal deadline, int periods = 1, bool autoFixPrincipalToInteger = true) { if (periods <= 0) { throw new ArgumentException("还款期数不能小于0"); } return(new[] { new RepaymentModel() { Principal = principal, Interest = this.Strategy.GetNUnitAmount(principal * rate * deadline, rateType), Period = 1, PayDate = this.Strategy.GetPayTime(this.StartDate, deadline) } }); }
/// <summary> /// 还款列表 /// </summary> /// <param name="principal">本金</param> /// <param name="rateType">利率计算方式</param> /// <param name="rate">利率</param> /// <param name="deadline">期限</param> /// <param name="periods">期数</param> /// <param name="autoFixPrincipalToInteger">是否为自动修正本金整数</param> /// <returns></returns> public override IEnumerable <RepaymentModel> GetRepayments(decimal principal, RepaymentRateType rateType, decimal rate, decimal deadline, int periods = 1, bool autoFixPrincipalToInteger = true) { if (periods <= 0) { throw new ArgumentException("还款期数不能小于0"); } var list = new List <RepaymentModel>(periods); for (var i = 1; i < periods; i++) { list.Add(new RepaymentModel() { Principal = 0, Interest = this.Strategy.GetNUnitAmount(principal * rate * deadline, rateType) / periods, Period = i, PayDate = this.Strategy.GetPayTime(this.StartDate, i * deadline / periods) }); } list.Add(new RepaymentModel() { Principal = principal, Interest = this.Strategy.GetNUnitAmount(principal * rate * deadline, rateType) / periods, Period = periods, PayDate = this.Strategy.GetPayTime(this.StartDate, deadline) }); return(list); }
/// <summary> /// 还款列表 /// </summary> /// <param name="principal">本金</param> /// <param name="rateType">利率计算方式</param> /// <param name="rate">利率</param> /// <param name="deadline">期限</param> /// <param name="periods">期数</param> /// <param name="autoFixPrincipalToInteger">是否为自动修正本金整数</param> /// <returns></returns> public abstract IEnumerable <RepaymentModel> GetRepayments(decimal principal, RepaymentRateType rateType, decimal rate, decimal deadline, int periods = 1, bool autoFixPrincipalToInteger = true);
/// <summary> /// 还款列表 /// </summary> /// <param name="principal">本金</param> /// <param name="rateType">利率计算方式</param> /// <param name="rate">利率</param> /// <param name="deadline">期限</param> /// <param name="periods">期数</param> /// <param name="autoFixPrincipalToInteger">是否为自动修正本金整数</param> /// <returns></returns> public override IEnumerable <RepaymentModel> GetRepayments(decimal principal, RepaymentRateType rateType, decimal rate, decimal deadline, int periods = 1, bool autoFixPrincipalToInteger = true) { if (periods <= 0) { throw new DomainException("还款期数不能小于0"); } switch (this.DateType) { case RepaymentTimeUnitType.天: { if (deadline / 30 != periods) { throw new ArgumentException(string.Format("当前以天计算,共{0}天,期数应为{1},但参数的期数却为{2}", deadline, deadline / 30, periods)); } } break; case RepaymentTimeUnitType.季: { if (deadline * 4 != periods) { throw new ArgumentException(string.Format("当前以季计算,共{0}季,期数应为{1},但参数的期数却为{2}", deadline, deadline * 4, periods)); } } break; case RepaymentTimeUnitType.年: { if (deadline * 12 != periods) { throw new ArgumentException(string.Format("当前以年计算,共{0}年,期数应为{1},但参数的期数却为{2}", deadline, deadline * 12, periods)); } } break; case RepaymentTimeUnitType.月: { if (deadline != periods) { throw new ArgumentException(string.Format("当前以月计算,共{0}月,期数应为{1},但参数的期数却为{2}", deadline, deadline, periods)); } } break; } switch (rateType) { case RepaymentRateType.天利率: { rate = rate * 30; } break; case RepaymentRateType.季利率: { rate = rate / 4; } break; case RepaymentRateType.年利率: { rate = rate / 12; } break; case RepaymentRateType.月利率: break; } var list = new List <RepaymentModel>(periods); /*算法中row第二个参数是指期数*/ var factor = (decimal)Math.Pow((double)(1m + rate), periods); var avg = principal * rate * factor / (factor - 1); //if (periods == 1) // return new RepaymentModel[] { new RepaymentModel((avg - principal * rate * this.Strategy.GetUnitAmount()) * deadline, principal * rate * this.Strategy.GetUnitAmount() * deadline, 1, this.Strategy.GetPayTime(this.StartDate, deadline)) }; var avgd = deadline / periods; if (!autoFixPrincipalToInteger || (autoFixPrincipalToInteger && principal % periods == 0)) { for (var i = 1; i <= periods; i++) { var interest = this.Strategy.GetNUnitAmount((principal - list.Sum(o => o.Principal)) * rate * deadline, RepaymentRateType.月利率) / periods; var model = new RepaymentModel() { Principal = (avg - interest), Interest = interest, Period = i, PayDate = this.Strategy.GetPayTime(this.StartDate, deadline * i / periods) }; list.Add(model); } } else { for (var i = 1; i <= periods; i++) { var interest = this.Strategy.GetNUnitAmount((principal - list.Sum(o => o.Principal)) * rate * deadline, RepaymentRateType.月利率) / periods; var fixPrincipal = (avg - interest).FormatC(0); var model = new RepaymentModel() { Principal = fixPrincipal, Interest = interest + (avg - interest - fixPrincipal), Period = i, PayDate = this.Strategy.GetPayTime(this.StartDate, deadline * i / periods) }; list.Add(model); } } //list.Add(new RepaymentModel((avg - principal * rate) * avgd, principal * rate * avgd, 1, this.Strategy.GetPayTime(this.StartDate, avgd * 1))); //for (var i = 2; i <= periods; i++) //{ // var interest = (principal - list.Sum(o => o.Principal)) * rate * avgd; // var model = new RepaymentModel((avg - interest) * avgd, interest * avgd, i, this.Strategy.GetPayTime(this.StartDate, avgd * i)); // list.Add(model); //} return(list); }
/// <summary> /// 还款列表 /// </summary> /// <param name="principal">本金</param> /// <param name="rateType">利率计算方式</param> /// <param name="rate">利率</param> /// <param name="deadline">期限</param> /// <param name="periods">期数</param> /// <param name="autoFixPrincipalToInteger">是否为自动修正本金整数</param> /// <returns></returns> public override IEnumerable <RepaymentModel> GetRepayments(decimal principal, RepaymentRateType rateType, decimal rate, decimal deadline, int periods = 1, bool autoFixPrincipalToInteger = true) { if (periods <= 0) { throw new ArgumentException("还款期数不能小于0"); } var avgPrincipalPeriod = this.principalPeriods.Count(o => o.PayPrincipal); if (periods != this.principalPeriods.Count()) { throw new ArgumentException("还款总期数不等于剩余还款本金期数"); } /*先平均分出本金,在还了本金后要重新减去已经还的本金*/ var prinList = new List <decimal>(avgPrincipalPeriod); var list = new List <RepaymentModel>(periods); var hadPayPrincipal = 0m; /*不用修正本金*/ if (!autoFixPrincipalToInteger) { for (var i = 0; i < avgPrincipalPeriod; i++) { prinList.Add(principal / avgPrincipalPeriod); } int j = 0; for (var i = 1; i <= periods; i++) { if (this.principalPeriods.ElementAt(i - 1).PayPrincipal) { list.Add(new RepaymentModel() { Principal = prinList[j], Interest = this.Strategy.GetNUnitAmount((principal - hadPayPrincipal) * rate * deadline, rateType) / periods, Period = i, PayDate = this.Strategy.GetPayTime(this.StartDate, i * deadline / periods) }); hadPayPrincipal += prinList[j]; j++; } else { list.Add(new RepaymentModel() { Principal = 0, Interest = this.Strategy.GetNUnitAmount((principal - hadPayPrincipal) * rate * deadline, rateType) / periods, Period = i, PayDate = this.Strategy.GetPayTime(this.StartDate, i * deadline / periods) }); } } return(list); } if (principal % avgPrincipalPeriod == 0) { for (var i = 0; i < avgPrincipalPeriod; i++) { prinList.Add(principal / avgPrincipalPeriod); } } else { var fixPrincipal = principal - principal % avgPrincipalPeriod; var firstPrinciapl = principal - (avgPrincipalPeriod - 1) * fixPrincipal / avgPrincipalPeriod; prinList.Add(firstPrinciapl); if (avgPrincipalPeriod > 1) { for (var i = 1; i < avgPrincipalPeriod; i++) { prinList.Add((principal - firstPrinciapl) / (avgPrincipalPeriod - 1)); } } } int k = 0; for (var i = 1; i <= periods; i++) { if (this.principalPeriods.ElementAt(i - 1).PayPrincipal) { list.Add(new RepaymentModel() { Principal = prinList[k], Interest = this.Strategy.GetNUnitAmount((principal - hadPayPrincipal) * rate * deadline, rateType) / periods, Period = i, PayDate = this.Strategy.GetPayTime(this.StartDate, i * deadline / periods) }); hadPayPrincipal += prinList[k]; k++; } else { list.Add(new RepaymentModel() { Principal = 0, Interest = this.Strategy.GetNUnitAmount((principal - hadPayPrincipal) * rate * deadline, rateType) / periods, Period = i, PayDate = this.Strategy.GetPayTime(this.StartDate, i * deadline / periods) }); } } return(list); }
/// <summary> /// 还款列表 /// </summary> /// <param name="principal">本金</param> /// <param name="rateType">利率计算方式</param> /// <param name="rate">利率</param> /// <param name="deadline">期限</param> /// <param name="periods">期数</param> /// <param name="autoFixPrincipalToInteger">是否为自动修正本金整数</param> /// <returns></returns> public override IEnumerable <RepaymentModel> GetRepayments(decimal principal, RepaymentRateType rateType, decimal rate, decimal deadline, int periods = 1, bool autoFixPrincipalToInteger = true) { if (periods <= 0) { throw new ArgumentException("还款期数不能小于0"); } if (periods != this.principalPeriods.Count() || periods != this.principalPeriods.Max(p => p.Period)) { throw new ArgumentException("还款总期数不等于剩余还款本金期数"); } var list = new List <RepaymentModel>(periods); var hadPayPrincipal = 0m; /*不用修正本金*/ if (!autoFixPrincipalToInteger) { for (var i = 1; i <= periods; i++) { var percent = this.principalPeriods.ElementAt(i - 1); list.Add(new RepaymentModel() { Principal = principal * percent.Percent / 100, Interest = this.Strategy.GetNUnitAmount((principal - hadPayPrincipal) * rate * deadline, rateType) / periods, Period = i, PayDate = this.Strategy.GetPayTime(this.StartDate, i * deadline / periods) }); hadPayPrincipal += principal * percent.Percent / 100; } return(list); } for (var i = 1; i <= periods; i++) { var percent = this.principalPeriods.ElementAt(i - 1); if (i != periods) { list.Add(new RepaymentModel() { Principal = principal * percent.Percent / 100, Interest = this.Strategy.GetNUnitAmount((principal - hadPayPrincipal) * rate * deadline, rateType) / periods, Period = i, PayDate = this.Strategy.GetPayTime(this.StartDate, i * deadline / periods) }); } else { list.Add(new RepaymentModel() { Principal = principal - hadPayPrincipal, Interest = this.Strategy.GetNUnitAmount((principal - hadPayPrincipal) * rate * deadline, rateType) / periods, Period = i, PayDate = this.Strategy.GetPayTime(this.StartDate, i * deadline / periods) }); } hadPayPrincipal += principal * percent.Percent / 100; } return(list); }