wip ledger/register.go

main
Bel LaPointe 2023-10-25 15:47:29 -06:00
parent 8155e57619
commit 31e1a86795
3 changed files with 116 additions and 0 deletions

View File

@ -10,7 +10,9 @@ import (
"os"
"slices"
"sort"
"strconv"
"strings"
"time"
"github.com/go-echarts/go-echarts/v2/charts"
"github.com/go-echarts/go-echarts/v2/opts"
@ -82,6 +84,24 @@ func main() {
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
nameCurrencyDateValue := map[string]map[ledger.Currency]map[string]float64{}

57
ledger/register.go Normal file
View File

@ -0,0 +1,57 @@
package ledger
import (
"fmt"
"io"
"log"
"slices"
"time"
)
func RegisterWithContributionPrediction(reg map[string]Balances, windowAsPercentOfTotalDuration float64) (map[string]Balances, error) {
times, err := registerTimesInUnix(reg)
if err != nil {
return nil, err
}
windowDuration := time.Second * time.Duration(float64(slices.Max(times)-slices.Min(times))*windowAsPercentOfTotalDuration)
log.Println(windowDuration)
lastReal := time.Unix(slices.Max(times), 0)
lastPredicted := lastReal
for lastPredicted.Before(lastReal.Add(windowDuration)) {
lastPredicted = lastPredicted.Add(time.Hour * 24 * time.Duration((45 - lastPredicted.Day())))
log.Println(lastPredicted)
}
result := make(map[string]Balances)
return result, io.EOF
}
func RegisterWithCompoundingInterestPrediction(reg map[string]Balances, windowAsPercentOfTotalDuration float64, name string, rate float64) (map[string]Balances, error) {
result := make(map[string]Balances)
return result, io.EOF
}
func registerTimesInUnix(reg map[string]Balances) ([]int64, error) {
result := make([]int64, 0, len(reg))
for k := range reg {
v, err := registerTime(k)
if err != nil {
return nil, err
}
result = append(result, v.Unix())
}
return result, nil
}
func registerTime(s string) (time.Time, error) {
for _, layout := range []string{
"2006-01-02",
"2006-01",
} {
if t, err := time.ParseInLocation(layout, s, time.Local); err == nil {
return t, err
}
}
return time.Time{}, fmt.Errorf("no layout matching %q", s)
}

39
ledger/register_test.go Normal file
View File

@ -0,0 +1,39 @@
package ledger
import (
"testing"
)
func TestRegisterPredictContribution(t *testing.T) {
// 1n t0 w weight 4
// 2n t1 w weight 2
// 4n t2 w weight 1
input := map[string]Balances{
"2001-01": Balances{"X": Balance{USD: 1}},
"2001-02": Balances{"X": Balance{USD: 2}},
"2001-03": Balances{"X": Balance{USD: 3}},
"2001-04": Balances{"X": Balance{USD: 4}},
"2001-05": Balances{"X": Balance{USD: 5}},
"2001-06": Balances{"X": Balance{USD: 6}},
"2001-07": Balances{"X": Balance{USD: 8}},
"2001-08": Balances{"X": Balance{USD: 10}},
"2001-09": Balances{"X": Balance{USD: 12}},
"2001-10": Balances{"X": Balance{USD: 16}},
}
// 1x4 weight 4 = 16
// 2x2 weight 2 = 8
// 4x1 weight 1 = 4
// (16+8+4) / (4+2+1) = 4
got, err := RegisterWithContributionPrediction(input, .12)
if err != nil {
t.Fatal(err)
}
if len(got) != len(input)+1 {
t.Error(len(got))
}
if balance, ok := got["2001-11"]; !ok {
t.Error(ok)
} else if balance["X"][USD] != 20.0 {
t.Error(balance)
}
}