public Rent(Identifier property, DateTime signing, int forMonths, Pecuniam monthlyRent, Pecuniam deposit) : base(signing) { //calc number of days till the first day of the next month if (signing.Day != 1) { _dtOfFirstFullRentDue = signing.Month == 12 ? new DateTime(signing.Year + 1, 1, _dayOfMonthRentDue) : new DateTime(signing.Year, signing.Month + 1, _dayOfMonthRentDue); var tsTillNextMonth = _dtOfFirstFullRentDue - signing; _proRatedAmt = new Pecuniam(Math.Round(monthlyRent.Amount/30 * (tsTillNextMonth.Days - 1), 2)); } else { _proRatedAmt = Pecuniam.Zero; _dtOfFirstFullRentDue = signing; } LeaseExpiry = _dtOfFirstFullRentDue.AddMonths(forMonths); var fullTermAmt = _proRatedAmt + new Pecuniam(monthlyRent.Amount*forMonths); base.TradeLine.Balance.AddTransaction(signing, fullTermAmt); base.TradeLine.FormOfCredit = FormOfCredit.None; LeaseTermInMonths = forMonths; Deposit = deposit; MonthlyPmt = monthlyRent; Id = property; }
/// <summary> /// Creates purchase transactions on <see cref="t"/> at random for the given <see cref="dt"/>. /// </summary> /// <param name="spender"></param> /// <param name="t"></param> /// <param name="dt"></param> /// <param name="daysMax"></param> /// <param name="randMaxFactor"> /// The multiplier used for the rand dollar's max, raising this value /// will raise every transactions possiable max by a factor of this. /// </param> public static void CreateSingleDaysPurchases(Personality spender, ITransactionable t, DateTime? dt, double daysMax, int randMaxFactor = 10) { if (t == null) throw new ArgumentNullException(nameof(t)); if (daysMax <= 0) return; var ccDate = dt ?? DateTime.Today; //build charges history var keepSpending = true; var spentSum = new Pecuniam(0); while (keepSpending) //want possiable multiple transactions per day { //if we reached target then exit if (spentSum >= new Pecuniam((decimal)daysMax)) return; var isXmasSeason = ccDate.Month >= 11 && ccDate.Day >= 20; var isWeekend = ccDate.DayOfWeek == DayOfWeek.Friday || ccDate.DayOfWeek == DayOfWeek.Saturday || ccDate.DayOfWeek == DayOfWeek.Sunday; var actingIrresp = spender?.GetRandomActsIrresponsible() ?? false; var isbigTicketItem = Etx.TryAboveOrAt(96, Etx.Dice.OneHundred); var isSomeEvenAmt = Etx.TryBelowOrAt(3, Etx.Dice.Ten); //keep times during normal waking hours var randCcDate = ccDate.Date.AddHours(Etx.IntNumber(6, isWeekend ? 23 : 19)) .AddMinutes(Etx.IntNumber(0, 59)) .AddSeconds(Etx.IntNumber(0, 59)) .AddMilliseconds(Etx.IntNumber(0, 999)); //make purchase based various factors var v = 2; v = isXmasSeason ? v + 1 : v; v = isWeekend ? v + 2 : v; v = actingIrresp ? v + 3 : v; randMaxFactor = isbigTicketItem ? randMaxFactor * 10 : randMaxFactor; if (Etx.TryBelowOrAt(v, Etx.Dice.Ten)) { //create some random purchase amount var chargeAmt = Pecuniam.GetRandPecuniam(5, v * randMaxFactor, isSomeEvenAmt ? 10 : 0); //check if account is maxed-out\empty if (!t.Pop(randCcDate, chargeAmt)) return; spentSum += chargeAmt; } //determine if more transactions for this day keepSpending = Etx.CoinToss; } }
/// <summary> /// Creates random transaction history. /// </summary> /// <param name="american"></param> /// <param name="isRenting">Optional, force the generated instance as renting (instead of mortgage)</param> public NorthAmericanWealth(NorthAmerican american, bool isRenting = false) { if(american == null) throw new ArgumentNullException(nameof(american)); _amer = american; var usCityArea = _amer.Address.HomeCityArea as UsCityStateZip; if (usCityArea == null) return; CreditScore = new PersonalCreditScore(american); //determine if renting or own _isRenting = isRenting || GetIsLeaseResidence(usCityArea); var edu = _amer.Education?.EduLevel ?? (OccidentalEdu.HighSchool | OccidentalEdu.Grad); var race = _amer.Race; var region = usCityArea.State?.GetStateData()?.Region ?? AmericanRegion.Midwest; _homeDebtFactor = GetFactor(FactorTables.HomeDebt, edu, race, region, _amer.Age, _amer.MyGender, _amer.MaritialStatus); _vehicleDebtFactor = GetFactor(FactorTables.VehicleDebt, edu, race, region, _amer.Age, _amer.MyGender, _amer.MaritialStatus); _ccDebtFactor = GetFactor(FactorTables.CreditCardDebt, edu, race, region, _amer.Age, _amer.MyGender, _amer.MaritialStatus); _savingAcctFactor = GetFactor(FactorTables.SavingsAccount, edu, race, region, _amer.Age, _amer.MyGender, _amer.MaritialStatus); _checkingAcctFactor = GetFactor(FactorTables.CheckingAccount, edu, race, region, _amer.Age, _amer.MyGender, _amer.MaritialStatus); _netWorthFactor = GetFactor(FactorTables.NetWorth, edu, race, region, _amer.Age, _amer.MyGender, _amer.MaritialStatus); _homeEquityFactor = GetFactor(FactorTables.HomeEquity, edu, race, region, _amer.Age, _amer.MyGender, _amer.MaritialStatus); _vehicleEquityFactor = GetFactor(FactorTables.VehicleEquity, edu, race, region, _amer.Age, _amer.MyGender, _amer.MaritialStatus); var payBase = new Pecuniam(2000); Func<Pecuniam, double> calcMonthlyPay = pecuniam => Math.Round((double)GetYearlyIncome(pecuniam, _netWorthFactor).Amount / 12, 2); Paycheck = Math.Round(calcMonthlyPay(payBase) / 2, 2).ToPecuniam(); }
/// <summary> /// Creates a random <see cref="FixedRateLoan"/> instance with a history and adds it to the /// <see cref="Opes.VehicleDebt"/> collection. /// </summary> /// <param name="stdDevAsPercent"></param> /// <returns></returns> /// <remarks> /// Returns zero 9% of the time. /// [https://people.hofstra.edu/geotrans/eng/ch6en/conc6en/USAownershipcars.html] /// </remarks> protected internal Pecuniam AddVehicleLoan(double stdDevAsPercent = DF_STD_DEV_PERCENT) { //roll for no-car if (Etx.TryBelowOrAt(9, Etx.Dice.OneHundred)) return Pecuniam.Zero; //calc a rand amount of what is still owed var randCarDebt = GetRandomFactorValue(FactorTables.VehicleDebt, _vehicleDebtFactor, stdDevAsPercent); //allow for car to be paid off if (Etx.TryBelowOrAt(23, Etx.Dice.OneHundred)) randCarDebt = 0.0D; var vin = Gov.Nhtsa.Vin.GetRandomVin(randCarDebt <= 2000.0D); //this would never happen while (_amer.MyGender == Gender.Male && vin.Description == "Toyota Yaris") vin = Gov.Nhtsa.Vin.GetRandomVin(randCarDebt <= 2000.0D); //calc rand amount of equity var randCarEquity = GetRandomFactorValue(FactorTables.VehicleEquity, _vehicleEquityFactor, stdDevAsPercent); _vehicleEquity += randCarEquity.ToPecuniam(); //get rand interest rate weighted by score var randRate = CreditScore.GetRandomInterestRate(null, Gov.Fed.RiskFreeInterestRate.DF_VALUE + 3.2) * 0.01; var spCost = new Pecuniam((decimal)randCarDebt); var totalCost = new Pecuniam((decimal)(randCarDebt + randCarEquity)); Pecuniam minPmt; var loan = SecuredFixedRateLoan.GetRandomLoanWithHistory(_amer, vin, spCost, totalCost, (float)randRate, 5, out minPmt); loan.Description = string.Join(" ", vin.Value, vin.Description, vin.GetModelYearYyyy()); loan.TradeLine.FormOfCredit = FormOfCredit.Installment; VehicleDebt.Add(loan); return minPmt; }
/// <summary> /// Creates random <see cref="CreditCardAccount"/> instances with a history and adds /// it to the <see cref="Opes.CreditCardDebt"/> collection. /// </summary> /// <param name="stdDevAsPercent"></param> /// <param name="maxCcDebt"></param> protected internal void AddSingleCcDebt(double stdDevAsPercent = DF_STD_DEV_PERCENT) { //create random cc var ccAcct = CreditCardAccount.GetRandomCcAcct(_amer, CreditScore); var pmtNote = GetPaymentNote(ccAcct.Id); //determine timespan for generated history var historyTs = DateTime.Now - ccAcct.Cc.CardHolderSince; //create history for (var i = 1; i < historyTs.Days; i++) { var loopDt = ccAcct.Cc.CardHolderSince.AddDays(i); if (ccAcct.GetStatus(loopDt) == SpStatus.Closed) break; CreateSingleDaysPurchases(_amer.Personality, ccAcct, loopDt, (double)Paycheck.Amount * DF_DAILY_SPEND_PERCENT); if (i%30 != 0 || ccAcct.GetValueAt(loopDt).Amount < 0.0M) continue; var minDue = ccAcct.GetMinPayment(loopDt); if(minDue < new Pecuniam(10.0M)) minDue = new Pecuniam(10.0M); if (_amer.Personality.GetRandomActsIrresponsible()) { var fowardDays = Etx.IntNumber(1, 45); var paidDate = loopDt.AddDays(fowardDays); ccAcct.Push(paidDate, minDue, Pecuniam.Zero, pmtNote); i += fowardDays; } else { var additionalPaid = Pecuniam.GetRandPecuniam(20, 200, 10); ccAcct.Push(loopDt, minDue + additionalPaid, Pecuniam.Zero, pmtNote); } } CreditCardDebt.Add(ccAcct); }
/// <summary> /// Creates random <see cref="Rent"/> instance with a history and adds /// it to the <see cref="Opes.HomeDebt"/> collection. /// </summary> /// <param name="stdDevAsPercent"></param> /// <remarks> /// src [http://www.nmhc.org/Content.aspx?id=4708] /// </remarks> protected internal Pecuniam AddRent(double stdDevAsPercent = DF_STD_DEV_PERCENT) { if (!_isRenting) return Pecuniam.Zero; //create a rent object var avgRent = (double)Rent.GetAvgAmericanRentByYear(null).Amount; var randRent = new Pecuniam( (decimal) GetRandomFactorValue(FactorTables.HomeDebt, _homeDebtFactor, stdDevAsPercent, avgRent)); var term = 12; var randDate = Etx.Date(0, DateTime.Today.AddDays(-2)); var rent = new Rent(_amer.Address, randDate, term, randRent, Etx.CoinToss ? new Pecuniam(250) : new Pecuniam(500)) { Description = $"{term}-Month Lease" }; _amer.Address.IsLeased = true; //create payment history until current var firstPmt = rent.GetMinPayment(randDate); rent.PayRent(randDate.AddDays(1), firstPmt); var rentDueDate = randDate.Month == 12 ? new DateTime(randDate.Year + 1, 1, 1) : new DateTime(randDate.Year, randDate.Month + 1, 1); while (rentDueDate < DateTime.Today) { var paidRentOn = rentDueDate; //move the date rent was paid to some late-date when person acts irresponsible if (_amer.Personality.GetRandomActsIrresponsible()) paidRentOn = paidRentOn.AddDays(Etx.IntNumber(5, 15)); rent.PayRent(paidRentOn, randRent, GetPaymentNote(rent.Id)); rentDueDate = rentDueDate.AddMonths(1); } HomeDebt.Add(rent); return randRent; }
/// <summary> /// Creates random <see cref="FixedRateLoan"/> instance with a history and adds /// it to the <see cref="Opes.HomeDebt"/> collection. /// </summary> /// <param name="stdDevAsPercent"></param> protected internal Pecuniam AddMortgage(double stdDevAsPercent = DF_STD_DEV_PERCENT) { //calc a rand amount of what is still owed var randHouseDebt = GetRandomFactorValue(FactorTables.HomeDebt, _homeDebtFactor, stdDevAsPercent); //calc rand amount of equity accrued var randHouseEquity = GetRandomFactorValue(FactorTables.HomeEquity, _homeEquityFactor, stdDevAsPercent); _homeEquity += randHouseEquity.ToPecuniam(); //get rand interest rate weighted by score var randRate = CreditScore.GetRandomInterestRate(null, Gov.Fed.RiskFreeInterestRate.DF_VALUE) * 0.01; var spCost = new Pecuniam((decimal)randHouseDebt); var totalCost = new Pecuniam((decimal)(randHouseDebt + randHouseEquity)); //create a loan on current residence Pecuniam minPmt; var loan = SecuredFixedRateLoan.GetRandomLoanWithHistory(_amer, _amer.Address, spCost, totalCost, (float) randRate, 30, out minPmt); loan.Description = "30-Year Mortgage"; loan.TradeLine.FormOfCredit = FormOfCredit.Mortgage; HomeDebt.Add(loan); return minPmt; }
/// <summary> /// Creates a full Opes state and history at random. /// </summary> /// <param name="stdDevAsPercent"></param> public void CreateRandomAmericanOpes(double stdDevAsPercent = DF_STD_DEV_PERCENT) { //determine residence pmt _residencePmt += _isRenting ? AddRent(stdDevAsPercent) : AddMortgage(stdDevAsPercent) ?? Pecuniam.Zero; //determin car payment _carPmt += AddVehicleLoan(stdDevAsPercent) ?? Pecuniam.Zero; //add CC's AddTotalCcDebt(stdDevAsPercent); //add bank accounts AddBankingAccounts(stdDevAsPercent); }
public void PayRent(DateTime dt, Pecuniam amt, string note = "") { TradeLine.Balance.AddTransaction(dt, amt.Neg, Pecuniam.Zero, note); }
public void TestOps() { var test00 = Pecuniam.Zero; var test01 = new Pecuniam(1.0M); var testResult = test00 + test01; Assert.AreEqual(1.0M, testResult.Amount); Assert.AreEqual(new Pecuniam(2.0M), new Pecuniam(1.0M) + new Pecuniam(1.0M)); Assert.AreEqual(new Pecuniam(2.0M), new Pecuniam(4.0M) - new Pecuniam(2.0M)); Assert.AreEqual(new Pecuniam(4.0M), new Pecuniam(4.0M) * new Pecuniam(1.0M)); Assert.AreEqual(new Pecuniam(4.0M), new Pecuniam(4.0M) / new Pecuniam(1.0M)); Assert.IsTrue(new Pecuniam(4.0M) > new Pecuniam(3.0M)); Assert.IsTrue(new Pecuniam(1.0M) < new Pecuniam(3.0M)); Assert.IsTrue(new Pecuniam(1.0M) == new Pecuniam(1.0M)); Assert.IsTrue(new Pecuniam(2.0M) != new Pecuniam(1.0M)); }
public Pecuniam GetCurrent(DateTime dt, Dictionary<DateTime, float> variableRate) { if (variableRate == null || variableRate.Keys.Count <= 0) throw new ArgumentNullException(nameof(variableRate)); //get very first recorded transaction var oldestTransaction = Transactions.FirstOrDefault(); if (oldestTransaction == null) return Pecuniam.Zero; var bal = Pecuniam.Zero; //set first transaction as the lower bounds of the current time-frame var prevVdt = oldestTransaction.AtTime; foreach (var vdt in variableRate.Keys) { //the dictionary is the date the rate ended, not began if (DateTime.Compare(prevVdt, dt) > 0) continue; var currVdt = vdt; //this rate was only applicable to this many days var daysAtRate = (currVdt - prevVdt).TotalDays; //this iteration's rate-ending-date is actually beyond our query date if (DateTime.Compare(currVdt, dt) > 0) { daysAtRate = (dt - prevVdt).TotalDays; currVdt = dt; } //get those transactions which occured between var betwixtTs = GetTransactionsBetween(prevVdt, currVdt); betwixtTs.Sort(Comparer); //add in this date-ranges transactions to the running balance bal = betwixtTs.Aggregate(bal, (current, bts) => current + bts.Cash); //get the balance plus iterest for the number of days this rate was in effect bal = new Pecuniam(bal.Amount.PerDiemInterest(variableRate[vdt], daysAtRate)); //save where we ended this time for next iteration prevVdt = currVdt; } return bal; }
protected internal Pecuniam GetTotalCurrentCcDebt(DateTime? dt = null) { var dk = new Pecuniam(0.0M); foreach (var cc in CreditCardDebt.Cast<CreditCardAccount>()) { dk += cc.GetValueAt(dt.GetValueOrDefault(DateTime.Now)).Neg; } return dk; }
/// <summary> /// Calc a yearly income salary or pay at random. /// </summary> /// <param name="min"></param> /// <param name="netWorthFactor">A multiplier to linear eq's result</param> /// <param name="factorCalc"> /// Optional, allows caller to specify how to factor the raw results of /// <see cref="GetAvgEarningPerYear"/> for the <see cref="dt"/>. /// </param> /// <param name="stdDevInUsd"></param> /// <param name="dt"> /// Optional, date used for solving the <see cref="GetAvgEarningPerYear"/> eq. /// </param> /// <returns></returns> public Pecuniam GetYearlyIncome(Pecuniam min, double netWorthFactor, Func<double, double> factorCalc = null, double stdDevInUsd = 2000, DateTime? dt = null) { if (min == null) min = Pecuniam.Zero; //get linear eq for earning var eq = GetAvgEarningPerYear(); if (eq == null) return Pecuniam.Zero; var baseValue = Math.Round(eq.SolveForY(dt.GetValueOrDefault(DateTime.Today).ToDouble()), 2); if (baseValue <= 0) return Pecuniam.Zero; Func<double, double> dfFunc = (d) => { var factorVal = (d / 5) * netWorthFactor; while (Math.Abs(factorVal) > d) factorVal = factorVal / 2; return factorVal; }; factorCalc = factorCalc ?? dfFunc; var factorValue = factorCalc(baseValue); baseValue = Math.Round(baseValue + factorValue, 2); var randValue = Math.Round( Etx.RandomValueInNormalDist(Math.Round(baseValue, 0), stdDevInUsd), 2); return new Pecuniam((decimal)randValue) + min; }