Support hardcoded starting prices.
All checks were successful
Build & Test / Main (push) Successful in 1m0s
All checks were successful
Build & Test / Main (push) Successful in 1m0s
The Coindesk API doesn't have data going all the way back. But since history isn't changing, we can simply put in known prices. Also, extend the CDPR cells to have four digits instead of just two.
This commit is contained in:
parent
4d5dcc46d2
commit
f67323c5f4
@ -28,6 +28,12 @@ defaults:
|
||||
time: 2019-12-31T16:00:00-08:00
|
||||
- name: 2017-
|
||||
time: 2016-12-31T16:00:00-08:00
|
||||
- name: 2013-
|
||||
time: 2012-12-31T16:00:00-08:00
|
||||
startingPrice: 13.30
|
||||
- name: 2011-
|
||||
time: 2010-12-31T16:00:00-08:00
|
||||
startingPrice: 0.30
|
||||
|
||||
assets:
|
||||
ETH:
|
||||
@ -44,6 +50,11 @@ assets:
|
||||
value: 20000
|
||||
- name: $25k
|
||||
value: 25000
|
||||
constantBases:
|
||||
- name: 2020-
|
||||
time: 2019-12-31T16:00:00-08:00
|
||||
- name: 2017-
|
||||
time: 2016-12-31T16:00:00-08:00
|
||||
LTC:
|
||||
goals:
|
||||
- name: $100
|
||||
|
94
moon/moon.go
94
moon/moon.go
@ -2,6 +2,8 @@ package moon
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
@ -74,30 +76,10 @@ func (m *Math) Refresh(ctx context.Context) (err error) {
|
||||
tasks.WithMaxGoroutines(len(m.Columns))
|
||||
//tasks.WithMaxGoroutines(1)
|
||||
now := time.Now()
|
||||
|
||||
for i := range m.Columns {
|
||||
c := &m.Columns[i]
|
||||
tasks.Go(func() error {
|
||||
c.StartingDate = c.Base.From(now)
|
||||
nextDay := c.StartingDate.Add(time.Hour * 24)
|
||||
resp, err := coindesk.GetPriceValues(ctx,
|
||||
m.Asset, c.StartingDate, nextDay)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(resp.Data.Entries) == 0 {
|
||||
c.Projections.Dates = nil
|
||||
return nil
|
||||
}
|
||||
c.StartingPrice = resp.Data.Entries[0].Price
|
||||
c.Gain = float64(m.CurrentPrice) / float64(c.StartingPrice)
|
||||
days := now.Sub(c.StartingDate).Hours() / 24
|
||||
c.CDPR = CDPR(days, c.Gain)
|
||||
c.Projections = ProjectDates(
|
||||
now, float64(m.CurrentPrice),
|
||||
c.CDPR, m.Goals,
|
||||
)
|
||||
return nil
|
||||
return c.project(ctx, m, now)
|
||||
})
|
||||
}
|
||||
err = tasks.Wait()
|
||||
@ -114,27 +96,49 @@ type Column struct {
|
||||
Projections Projection
|
||||
}
|
||||
|
||||
var DefaultGoals = []Goal{
|
||||
{"$100k", 100000},
|
||||
{"$150k", 150000},
|
||||
{"$200k", 200000},
|
||||
{"$250k", 250000},
|
||||
{"$300k", 300000},
|
||||
{"$500k", 500000},
|
||||
{"$1m", 1000000},
|
||||
func (c *Column) project(ctx context.Context, m *Math, now time.Time) (err error) {
|
||||
err = c.fillStartingPrice(ctx, m.Asset, now)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.Gain = float64(m.CurrentPrice) / float64(c.StartingPrice)
|
||||
days := now.Sub(c.StartingDate).Hours() / 24
|
||||
c.CDPR = CDPR(days, c.Gain)
|
||||
c.Projections = ProjectDates(
|
||||
now, float64(m.CurrentPrice),
|
||||
c.CDPR, m.Goals,
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
var DefaultConstantBases = []ConstantBase{
|
||||
{"2020-", time.Unix(1577836800, 0)},
|
||||
{"2017-", time.Unix(1483228800, 0)},
|
||||
func (c *Column) fillStartingPrice(
|
||||
ctx context.Context, asset coindesk.Asset, now time.Time,
|
||||
) error {
|
||||
// if base provides a hardcoded starting price, use it
|
||||
c.StartingDate = c.Base.From(now)
|
||||
c.StartingPrice = coindesk.Price(c.Base.GetStartingPrice())
|
||||
if c.StartingPrice != 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// otherwise, look up the starting price via Coindesk
|
||||
nextDay := c.StartingDate.Add(time.Hour * 24)
|
||||
resp, err := coindesk.GetPriceValues(ctx, asset, c.StartingDate, nextDay)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("getting price for %s on %v: %w",
|
||||
asset, c.StartingDate, err)
|
||||
return err
|
||||
}
|
||||
if len(resp.Data.Entries) == 0 {
|
||||
c.Projections.Dates = nil
|
||||
return errEmptyPriceEntries
|
||||
}
|
||||
c.StartingPrice = resp.Data.Entries[0].Price
|
||||
return nil
|
||||
}
|
||||
|
||||
var DefaultRelativeBases = []RelativeBase{
|
||||
{"Month", time.Duration(-30) * time.Hour * 24},
|
||||
{"Quarter", time.Duration(-90) * time.Hour * 24},
|
||||
{"Half-Year", time.Duration(-182) * time.Hour * 24},
|
||||
{"Year", time.Duration(-365) * time.Hour * 24},
|
||||
}
|
||||
var errEmptyPriceEntries = errors.New("price values response has no entries")
|
||||
|
||||
type Goal struct {
|
||||
Name string `koanf:"name"`
|
||||
@ -145,12 +149,14 @@ type Goal struct {
|
||||
type Base interface {
|
||||
From(now time.Time) time.Time
|
||||
Label() string
|
||||
GetStartingPrice() float64
|
||||
}
|
||||
|
||||
// ConstantBase is a base that is a constant time, e.g. 2020-01-01.
|
||||
type ConstantBase struct {
|
||||
Name string `koanf:"name"`
|
||||
Time time.Time `koanf:"time"`
|
||||
Name string `koanf:"name"`
|
||||
Time time.Time `koanf:"time"`
|
||||
StartingPrice float64 `koanf:"startingPrice"`
|
||||
}
|
||||
|
||||
func (cb ConstantBase) From(_ time.Time) time.Time {
|
||||
@ -161,6 +167,10 @@ func (cb ConstantBase) Label() string {
|
||||
return cb.Name
|
||||
}
|
||||
|
||||
func (cb ConstantBase) GetStartingPrice() float64 {
|
||||
return cb.StartingPrice
|
||||
}
|
||||
|
||||
// RelativeBase is a base that is relative, e.g. "90 days ago."
|
||||
type RelativeBase struct {
|
||||
Name string `koanf:"name"`
|
||||
@ -175,3 +185,7 @@ func (rb RelativeBase) From(now time.Time) time.Time {
|
||||
func (rb RelativeBase) Label() string {
|
||||
return rb.Name
|
||||
}
|
||||
|
||||
func (rb RelativeBase) GetStartingPrice() float64 {
|
||||
return 0
|
||||
}
|
||||
|
@ -11,6 +11,14 @@ func TestCDPR(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestProjection(t *testing.T) {
|
||||
p := moon.ProjectDates(time.Now(), 68900, 1.0055, moon.DefaultGoals)
|
||||
p := moon.ProjectDates(time.Now(), 68900, 1.0055, []moon.Goal{
|
||||
{"$100k", 100000},
|
||||
{"$150k", 150000},
|
||||
{"$200k", 200000},
|
||||
{"$250k", 250000},
|
||||
{"$300k", 300000},
|
||||
{"$500k", 500000},
|
||||
{"$1m", 1000000},
|
||||
})
|
||||
_ = p
|
||||
}
|
||||
|
@ -206,7 +206,7 @@ func refillProjections(m *Model) {
|
||||
|
||||
func renderEntries(c moon.Column) (entries []string) {
|
||||
entries = append(entries, fmt.Sprintf("$%.2f", c.StartingPrice))
|
||||
entries = append(entries, fmt.Sprintf("%.2f%%", (c.CDPR-1)*100))
|
||||
entries = append(entries, fmt.Sprintf("%.4f%%", (c.CDPR-1)*100))
|
||||
never := c.CDPR <= 1
|
||||
for i := range c.Projections.Dates {
|
||||
var cell string
|
||||
|
Loading…
Reference in New Issue
Block a user