Merge pull request #184 from lyricnz/feature/x-labels

Show X axis labels on charts
pull/190/head
Simon Roberts 3 years ago committed by GitHub
commit 562c5fd3f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -172,23 +172,28 @@ func (ct *Cointop) ChartPoints(symbol string, name string) error {
} }
} }
// Resample cachedata var labels []string
timeQuantum := timedata.CalculateTimeQuantum(cacheData)
newStart := time.Unix(start, 0).Add(timeQuantum)
newEnd := time.Unix(end, 0).Add(-timeQuantum)
timeData := timedata.ResampleTimeSeriesData(cacheData, float64(newStart.UnixMilli()), float64(newEnd.UnixMilli()), chart.GetChartDataSize(maxX))
// Extract just the values from the data
var data []float64 var data []float64
for i := range timeData { timeQuantum := timedata.CalculateTimeQuantum(cacheData) // will be 0 if <2 points
value := timeData[i][1] if timeQuantum > 0 {
if math.IsNaN(value) { // Resample cachedata
value = 0.0 newStart := cacheData[0][0] // use the first data point
newEnd := time.Unix(end, 0).Add(-timeQuantum)
timeData := timedata.ResampleTimeSeriesData(cacheData, newStart, float64(newEnd.UnixMilli()), chart.GetChartDataSize(maxX))
labels = timedata.BuildTimeSeriesLabels(timeData)
// Extract just the values from the data
for i := range timeData {
value := timeData[i][1]
if math.IsNaN(value) {
value = 0.0
}
data = append(data, value)
} }
data = append(data, value)
} }
chart.SetData(data) chart.SetData(data)
chart.SetDataLabels(labels)
ct.State.chartPoints = chart.GetChartPoints(maxX) ct.State.chartPoints = chart.GetChartPoints(maxX)
return nil return nil
@ -280,39 +285,48 @@ func (ct *Cointop) PortfolioChart() error {
break // use the first one break // use the first one
} }
} }
newStart := time.Unix(start, 0).Add(timeQuantum)
newEnd := time.Unix(end, 0).Add(-timeQuantum)
// Resample and sum data // If there is data, resample and sum
var data []float64 var data []float64
for _, cacheData := range allCacheData { var labels []string
coinData := timedata.ResampleTimeSeriesData(cacheData.data, float64(newStart.UnixMilli()), float64(newEnd.UnixMilli()), chart.GetChartDataSize(maxX)) if timeQuantum > 0 {
// sum (excluding NaN) newStart := time.Unix(start, 0).Add(timeQuantum)
for i := range coinData { newEnd := time.Unix(end, 0).Add(-timeQuantum)
price := coinData[i][1]
if math.IsNaN(price) { // Resample and sum data
price = 0.0 for i, cacheData := range allCacheData {
coinData := timedata.ResampleTimeSeriesData(cacheData.data, float64(newStart.UnixMilli()), float64(newEnd.UnixMilli()), chart.GetChartDataSize(maxX))
if i == 0 {
labels = timedata.BuildTimeSeriesLabels(coinData)
} }
sum := cacheData.coin.Holdings * price // sum (excluding NaN)
if i < len(data) { for i := range coinData {
data[i] += sum price := coinData[i][1]
} else { if math.IsNaN(price) {
data = append(data, sum) price = 0.0
}
sum := cacheData.coin.Holdings * price
if i < len(data) {
data[i] += sum
} else {
data = append(data, sum)
}
} }
} }
}
// Scale Portfolio Balances to hide value // Scale Portfolio Balances to hide value
if ct.State.hidePortfolioBalances { if ct.State.hidePortfolioBalances {
var lastPrice = data[len(data)-1] var lastPrice = data[len(data)-1]
if lastPrice > 0.0 { if lastPrice > 0.0 {
for i, price := range data { for i, price := range data {
data[i] = 100 * price / lastPrice data[i] = 100 * price / lastPrice
}
} }
} }
} }
chart.SetData(data) chart.SetData(data)
chart.SetDataLabels(labels)
ct.State.chartPoints = chart.GetChartPoints(maxX) ct.State.chartPoints = chart.GetChartPoints(maxX)
return nil return nil

@ -55,6 +55,11 @@ func (c *ChartPlot) SetData(data []float64) {
c.t.Data = data c.t.Data = data
} }
// SetDataLabels ...
func (c *ChartPlot) SetDataLabels(labels []string) {
c.t.DataLabels = labels
}
// GetChartDataSize ... // GetChartDataSize ...
func (c *ChartPlot) GetChartDataSize(width int) int { func (c *ChartPlot) GetChartDataSize(width int) int {
axisYWidth := 30 axisYWidth := 30

@ -4,11 +4,9 @@ import (
"math" "math"
"sort" "sort"
"time" "time"
log "github.com/sirupsen/logrus"
) )
// Resample the [timestamp,value] data given to numsteps between start-end (returns numSteps+1 points). // ResampleTimeSeriesData resamples the given [timestamp,value] data to numsteps between start-end (returns numSteps+1 points).
// If the data does not extend past start/end then there will likely be NaN in the output data. // If the data does not extend past start/end then there will likely be NaN in the output data.
func ResampleTimeSeriesData(data [][]float64, start float64, end float64, numSteps int) [][]float64 { func ResampleTimeSeriesData(data [][]float64, start float64, end float64, numSteps int) [][]float64 {
var newData [][]float64 var newData [][]float64
@ -33,7 +31,7 @@ func ResampleTimeSeriesData(data [][]float64, start float64, end float64, numSte
return newData return newData
} }
// Assuming that the [timestamp,value] data provided is roughly evenly spaced, calculate that interval. // CalculateTimeQuantum determines the given [timestamp,value] data
func CalculateTimeQuantum(data [][]float64) time.Duration { func CalculateTimeQuantum(data [][]float64) time.Duration {
if len(data) > 1 { if len(data) > 1 {
minTime := time.UnixMilli(int64(data[0][0])) minTime := time.UnixMilli(int64(data[0][0]))
@ -43,9 +41,25 @@ func CalculateTimeQuantum(data [][]float64) time.Duration {
return 0 return 0
} }
// Print out all the [timestamp,value] data provided // BuildTimeSeriesLabels returns a list of short labels representing time values from the given [timestamp,value] data
func DebugLogPriceData(data [][]float64) { func BuildTimeSeriesLabels(data [][]float64) []string {
minTime := time.UnixMilli(int64(data[0][0]))
maxTime := time.UnixMilli(int64(data[len(data)-1][0]))
timeRange := maxTime.Sub(minTime)
var timeFormat string
if timeRange.Hours() < 24 {
timeFormat = "15:04"
} else if timeRange.Hours() < 24*7 {
timeFormat = "Mon 15:04"
} else if timeRange.Hours() < 24*365 {
timeFormat = "02-Jan"
} else {
timeFormat = "Jan 2006"
}
var labels []string
for i := range data { for i := range data {
log.Debugf("%s %.2f", time.Unix(int64(data[i][0]/1000), 0), data[i][1]) labels = append(labels, time.UnixMilli(int64(data[i][0])).Format(timeFormat))
} }
return labels
} }

Loading…
Cancel
Save