no predict contributions if less than 2 balances

This commit is contained in:
Bel LaPointe
2023-10-26 06:10:31 -06:00
parent eda1c564d4
commit 45beb54fbc
2 changed files with 49 additions and 27 deletions

View File

@@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"io" "io"
"log" "log"
"maps"
"net/http" "net/http"
"os" "os"
"slices" "slices"
@@ -77,40 +78,50 @@ func main() {
} }
register := deltas.Like(foolike...).Register() register := deltas.Like(foolike...).Register()
bpis := maps.Clone(bpis)
// MODIFIERS // MODIFIERS
if predictionMonths, err := strconv.ParseInt(r.URL.Query().Get("predictionMonths"), 10, 8); err == nil && predictionMonths > 0 {
predictionDuration := time.Hour * 24 * 365 / 12 * time.Duration(predictionMonths)
if r.URL.Query().Get("predictContributions") != "" {
register, err = ledger.RegisterWithContributionPrediction(register, predictionDuration)
if err != nil {
panic(err)
}
}
for _, nameRate := range r.URL.Query()["predictCompoundingInterest"] {
name := strings.Split(nameRate, "=")[0]
rate, err := strconv.ParseFloat(strings.Split(nameRate, "=")[1], 64)
if err != nil {
panic(err)
}
register, err = ledger.RegisterWithCompoundingInterestPrediction(register, predictionDuration, name, rate)
if err != nil {
panic(err)
}
}
for _, currencyRate := range r.URL.Query()["predictFixedGrowth"] {
currency := strings.Split(currencyRate, "=")[0]
rate, err := strconv.ParseFloat(strings.Split(currencyRate, "=")[1], 64)
if err != nil {
panic(err)
}
bpis, err = ledger.BPIsWithFixedGrowthPrediction(bpis, predictionDuration, currency, rate)
if err != nil {
panic(err)
}
}
}
if r.URL.Query().Get("bpi") != "" { if r.URL.Query().Get("bpi") != "" {
for date := range register { for date := range register {
register[date] = register[date].WithBPIs(bpis) register[date] = register[date].WithBPIs(bpis)
} }
} }
if predictionMonths, err := strconv.ParseInt(r.URL.Query().Get("predictionMonths"), 10, 8); err == nil && predictionMonths > 0 {
predictionDuration := time.Hour * 24 * 365 / 12 * time.Duration(predictionMonths)
if r.URL.Query().Get("predictContributions") != "" {
register = ledger.RegisterWithContributionPrediction(register, predictionDuration)
}
for _, nameRate := range r.URL.Query()["predictCompoundingInterest"] {
splits := strings.Split(nameRate, "=")
if len(splits) != 2 {
panic(splits)
}
name := splits[0]
rate, err := strconv.ParseFloat(splits[1], 64)
if err != nil {
panic(err)
}
register = ledger.RegisterWithCompoundingInterestPrediction(register, predictionDuration, name, rate)
}
}
// /MODIFIERS // /MODIFIERS
nameCurrencyDateValue := map[string]map[ledger.Currency]map[string]float64{} nameCurrencyDateValue := map[string]map[ledger.Currency]map[string]float64{}
dates := []string{}
names := []string{}
for date, balances := range register { for date, balances := range register {
dates = append(dates, date)
for name, balance := range balances { for name, balance := range balances {
names = append(names, name)
for currency, value := range balance { for currency, value := range balance {
if _, ok := nameCurrencyDateValue[name]; !ok { if _, ok := nameCurrencyDateValue[name]; !ok {
nameCurrencyDateValue[name] = make(map[ledger.Currency]map[string]float64) nameCurrencyDateValue[name] = make(map[ledger.Currency]map[string]float64)
@@ -122,13 +133,14 @@ func main() {
} }
} }
} }
slices.Sort(dates)
slices.Sort(names)
chart := NewChart("line") chart := NewChart("line")
if v := r.URL.Query().Get("chart"); v != "" { if v := r.URL.Query().Get("chart"); v != "" {
chart = NewChart(v) chart = NewChart(v)
} }
dates := register.Dates()
names := register.Names()
chart.AddX(dates) chart.AddX(dates)
switch r.URL.Path { switch r.URL.Path {

View File

@@ -55,6 +55,9 @@ func registerWithContributionPredictionForNameForCurrency(reg Register, window t
sort.Slice(contributions, func(i, j int) bool { sort.Slice(contributions, func(i, j int) bool {
return contributions[i].t.Before(contributions[j].t) return contributions[i].t.Before(contributions[j].t)
}) })
if len(contributions) < 2 {
return nil
}
getMedianValueDelta := func(contributions []contribution) float64 { getMedianValueDelta := func(contributions []contribution) float64 {
values := make([]float64, len(contributions)) values := make([]float64, len(contributions))
@@ -72,10 +75,17 @@ func registerWithContributionPredictionForNameForCurrency(reg Register, window t
slices.Sort(lapses) slices.Sort(lapses)
return lapses[len(lapses)/2] return lapses[len(lapses)/2]
} }
contributsSlice := func(percent float64) []contribution {
wouldBe := int(percent * float64(len(contributions)))
if wouldBe == 0 {
wouldBe = 2
}
return contributions[len(contributions)-wouldBe:]
}
eighth := contributions[int(7.0*len(contributions)/8.0):] eighth := contributsSlice(7.0 / 8.0)
quarter := contributions[int(3.0*len(contributions)/4.0):] quarter := contributsSlice(3.0 / 4.0)
half := contributions[int(1.0*len(contributions)/2.0):] half := contributsSlice(1.0 / 2.0)
medianValueDelta := func() float64 { medianValueDelta := func() float64 {
return (4.0*getMedianValueDelta(eighth) + 2.0*getMedianValueDelta(quarter) + 1.0*getMedianValueDelta(half)) / (4.0 + 2.0 + 1.0) return (4.0*getMedianValueDelta(eighth) + 2.0*getMedianValueDelta(quarter) + 1.0*getMedianValueDelta(half)) / (4.0 + 2.0 + 1.0)
}() }()