can fill values now

This commit is contained in:
Will Charczuk 2017-02-28 17:55:48 -08:00
parent 9a9af15fd4
commit 114738a2de
6 changed files with 179 additions and 5 deletions

46
date.go
View file

@ -345,14 +345,22 @@ func (d date) CalculateMarketSecondsBetween(start, end, marketOpen, marketClose
}
const (
_secondsPerDay = 60 * 60 * 24
_secondsPerHour = 60 * 60
_secondsPerDay = 60 * 60 * 24
)
func (d date) Diff(t1, t2 time.Time) (days int64) {
func (d date) DiffDays(t1, t2 time.Time) (days int) {
t1n := t1.Unix()
t2n := t2.Unix()
diff := t1n - t2n
return diff / (_secondsPerDay)
diff := t2n - t1n //yields seconds
return int(diff / (_secondsPerDay))
}
func (d date) DiffHours(t1, t2 time.Time) (hours int) {
t1n := t1.Unix()
t2n := t2.Unix()
diff := t2n - t1n //yields seconds
return int(diff / (_secondsPerHour))
}
// NextDay returns the timestamp advanced a day.
@ -386,3 +394,33 @@ func (d date) NextDayOfWeek(after time.Time, dayOfWeek time.Weekday) time.Time {
dayDelta := 7 - int(afterWeekday-dayOfWeek)
return after.AddDate(0, 0, dayDelta)
}
// Start returns the earliest (min) time in a list of times.
func (d date) Start(times []time.Time) time.Time {
if len(times) == 0 {
return time.Time{}
}
start := times[0]
for _, t := range times[1:] {
if t.Before(start) {
start = t
}
}
return start
}
// Start returns the earliest (min) time in a list of times.
func (d date) End(times []time.Time) time.Time {
if len(times) == 0 {
return time.Time{}
}
end := times[0]
for _, t := range times[1:] {
if t.After(end) {
end = t
}
}
return end
}

View file

@ -236,3 +236,53 @@ func TestDateIsNYSEHoliday(t *testing.T) {
}
assert.Equal(holidays, 55)
}
func TestTimeStart(t *testing.T) {
assert := assert.New(t)
times := []time.Time{
time.Now().AddDate(0, 0, -4),
time.Now().AddDate(0, 0, -2),
time.Now().AddDate(0, 0, -1),
time.Now().AddDate(0, 0, -3),
time.Now().AddDate(0, 0, -5),
}
assert.InTimeDelta(Date.Start(times), times[4], time.Millisecond)
}
func TestTimeEnd(t *testing.T) {
assert := assert.New(t)
times := []time.Time{
time.Now().AddDate(0, 0, -4),
time.Now().AddDate(0, 0, -2),
time.Now().AddDate(0, 0, -1),
time.Now().AddDate(0, 0, -3),
time.Now().AddDate(0, 0, -5),
}
assert.InTimeDelta(Date.End(times), times[2], time.Millisecond)
}
func TestDateDiffDays(t *testing.T) {
assert := assert.New(t)
t1 := time.Date(2017, 02, 27, 12, 0, 0, 0, time.UTC)
t2 := time.Date(2017, 01, 10, 3, 0, 0, 0, time.UTC)
t3 := time.Date(2017, 02, 24, 16, 0, 0, 0, time.UTC)
assert.Equal(48, Date.DiffDays(t2, t1))
assert.Equal(2, Date.DiffDays(t3, t1)) // technically we should round down.
}
func TestDateDiffHours(t *testing.T) {
assert := assert.New(t)
t1 := time.Date(2017, 02, 27, 12, 0, 0, 0, time.UTC)
t2 := time.Date(2017, 02, 24, 16, 0, 0, 0, time.UTC)
t3 := time.Date(2017, 02, 28, 12, 0, 0, 0, time.UTC)
assert.Equal(68, Date.DiffHours(t2, t1))
assert.Equal(24, Date.DiffHours(t1, t3))
}

View file

@ -148,6 +148,14 @@ func (m mathUtil) AbsInt(value int) int {
return value
}
// AbsInt64 returns the absolute value of a long.
func (m mathUtil) AbsInt64(value int64) int64 {
if value < 0 {
return -value
}
return value
}
// Mean returns the mean of a set of values
func (m mathUtil) Mean(values ...float64) float64 {
return m.Sum(values...) / float64(len(values))

View file

@ -155,3 +155,34 @@ func (s sequence) MarketDayMondayCloses(from, to time.Time, marketOpen, marketCl
}
return times
}
func (s sequence) Hours(start time.Time, totalHours int) []time.Time {
times := make([]time.Time, totalHours)
last := start
for i := 0; i < totalHours; i++ {
times[i] = last
last = last.Add(time.Hour)
}
return times
}
// HoursFill adds zero values for the data bounded by the start and end of the xdata array.
func (s sequence) HoursFill(xdata []time.Time, ydata []float64) ([]time.Time, []float64) {
start := Date.Start(xdata)
end := Date.End(xdata)
totalHours := Math.AbsInt(Date.DiffHours(start, end))
finalTimes := s.Hours(start, totalHours+1)
finalValues := make([]float64, totalHours+1)
var hoursFromStart int
for i, xd := range xdata {
hoursFromStart = Date.DiffHours(start, xd)
finalValues[hoursFromStart] = ydata[i]
}
return finalTimes, finalValues
}

View file

@ -43,3 +43,50 @@ func TestSequenceMarketQuarters(t *testing.T) {
assert.Equal(00, mh[2].Minute())
assert.Equal(Date.Eastern(), mh[2].Location())
}
func TestSequenceHours(t *testing.T) {
assert := assert.New(t)
today := time.Date(2016, 07, 01, 12, 0, 0, 0, time.UTC)
seq := Sequence.Hours(today, 24)
end := Date.End(seq)
assert.Len(seq, 24)
assert.Equal(2016, end.Year())
assert.Equal(07, int(end.Month()))
assert.Equal(02, end.Day())
assert.Equal(11, end.Hour())
}
func TestSequenceHoursFill(t *testing.T) {
assert := assert.New(t)
xdata := []time.Time{
time.Date(2016, 07, 01, 12, 0, 0, 0, time.UTC),
time.Date(2016, 07, 01, 13, 0, 0, 0, time.UTC),
time.Date(2016, 07, 01, 14, 0, 0, 0, time.UTC),
time.Date(2016, 07, 02, 4, 0, 0, 0, time.UTC),
time.Date(2016, 07, 02, 5, 0, 0, 0, time.UTC),
time.Date(2016, 07, 03, 12, 0, 0, 0, time.UTC),
time.Date(2016, 07, 03, 14, 0, 0, 0, time.UTC),
}
ydata := []float64{
1.1,
1.2,
1.4,
0.8,
2.1,
0.4,
0.6,
}
filledTimes, filledValues := Sequence.HoursFill(xdata, ydata)
assert.Len(filledTimes, Date.DiffHours(Date.Start(xdata), Date.End(xdata))+1)
assert.Equal(len(filledValues), len(filledTimes))
assert.NotZero(filledValues[0])
assert.NotZero(filledValues[len(filledValues)-1])
assert.NotZero(filledValues[16])
}

View file

@ -17,4 +17,4 @@ func (tu timeUtil) ToFloat64(t time.Time) float64 {
// Float64ToTime returns a time from a float64.
func (tu timeUtil) FromFloat64(tf float64) time.Time {
return time.Unix(0, int64(tf))
}
}