go-chart/market_hours_range.go

126 lines
3.5 KiB
Go
Raw Normal View History

2016-07-22 07:09:09 +02:00
package chart
import (
"fmt"
"time"
"github.com/wcharczuk/go-chart/date"
)
2016-07-23 20:50:30 +02:00
// MarketHoursRange is a special type of range that compresses a time range into just the
2016-07-22 07:09:09 +02:00
// market (i.e. NYSE operating hours and days) range.
2016-07-23 20:50:30 +02:00
type MarketHoursRange struct {
Min time.Time
Max time.Time
MarketOpen time.Time
MarketClose time.Time
HolidayProvider date.HolidayProvider
2016-07-22 07:09:09 +02:00
Domain int
}
2016-07-22 07:22:22 +02:00
// IsZero returns if the range is setup or not.
2016-07-23 20:50:30 +02:00
func (mhr MarketHoursRange) IsZero() bool {
2016-07-22 07:22:22 +02:00
return mhr.Min.IsZero() && mhr.Max.IsZero()
}
2016-07-22 07:09:09 +02:00
// GetMin returns the min value.
2016-07-23 20:50:30 +02:00
func (mhr MarketHoursRange) GetMin() float64 {
2016-07-22 07:09:09 +02:00
return TimeToFloat64(mhr.Min)
}
// GetMax returns the max value.
2016-07-23 20:50:30 +02:00
func (mhr MarketHoursRange) GetMax() float64 {
2016-07-27 17:21:05 +02:00
return TimeToFloat64(mhr.GetEffectiveMax())
}
// GetEffectiveMax gets either the close on the max, or the max itself.
func (mhr MarketHoursRange) GetEffectiveMax() time.Time {
maxClose := date.On(mhr.MarketClose, mhr.Max)
if maxClose.After(mhr.Max) {
return maxClose
}
return mhr.Max
2016-07-22 07:09:09 +02:00
}
// SetMin sets the min value.
2016-07-23 20:50:30 +02:00
func (mhr *MarketHoursRange) SetMin(min float64) {
2016-07-22 07:09:09 +02:00
mhr.Min = Float64ToTime(min)
}
// SetMax sets the max value.
2016-07-23 20:50:30 +02:00
func (mhr *MarketHoursRange) SetMax(max float64) {
2016-07-22 07:09:09 +02:00
mhr.Max = Float64ToTime(max)
}
// GetDelta gets the delta.
2016-07-23 20:50:30 +02:00
func (mhr MarketHoursRange) GetDelta() float64 {
2016-07-27 17:21:05 +02:00
min := mhr.GetMin()
max := mhr.GetMax()
2016-07-22 07:09:09 +02:00
return max - min
}
// GetDomain gets the domain.
2016-07-23 20:50:30 +02:00
func (mhr MarketHoursRange) GetDomain() int {
2016-07-22 07:09:09 +02:00
return mhr.Domain
}
// SetDomain sets the domain.
2016-07-23 20:50:30 +02:00
func (mhr *MarketHoursRange) SetDomain(domain int) {
2016-07-22 07:09:09 +02:00
mhr.Domain = domain
}
2016-07-24 00:35:49 +02:00
// GetHolidayProvider coalesces a userprovided holiday provider and the date.DefaultHolidayProvider.
func (mhr MarketHoursRange) GetHolidayProvider() date.HolidayProvider {
if mhr.HolidayProvider == nil {
return date.DefaultHolidayProvider
}
return mhr.HolidayProvider
}
// GetTicks returns the ticks for the range.
// This is to override the default continous ticks that would be generated for the range.
func (mhr *MarketHoursRange) GetTicks(vf ValueFormatter) []Tick {
// return one tick per day
// figure out how to advance one ticke per market day.
var ticks []Tick
2016-07-24 22:48:10 +02:00
cursor := date.On(mhr.MarketClose, mhr.Min)
2016-07-24 00:35:49 +02:00
maxClose := date.On(mhr.MarketClose, mhr.Max)
for date.BeforeDate(cursor, maxClose) {
if date.IsWeekDay(cursor.Weekday()) && !mhr.GetHolidayProvider()(cursor) {
ticks = append(ticks, Tick{
Value: TimeToFloat64(cursor),
Label: vf(cursor),
})
}
cursor = cursor.AddDate(0, 0, 1)
}
2016-07-24 22:48:10 +02:00
endMarketClose := date.On(mhr.MarketClose, cursor)
if date.IsWeekDay(endMarketClose.Weekday()) && !mhr.GetHolidayProvider()(endMarketClose) {
ticks = append(ticks, Tick{
Value: TimeToFloat64(endMarketClose),
Label: vf(endMarketClose),
})
}
2016-07-24 00:35:49 +02:00
return ticks
}
2016-07-23 20:50:30 +02:00
func (mhr MarketHoursRange) String() string {
2016-07-22 07:09:09 +02:00
return fmt.Sprintf("MarketHoursRange [%s, %s] => %d", mhr.Min.Format(DefaultDateFormat), mhr.Max.Format(DefaultDateFormat), mhr.Domain)
}
// Translate maps a given value into the ContinuousRange space.
2016-07-23 20:50:30 +02:00
func (mhr MarketHoursRange) Translate(value float64) int {
2016-07-22 07:09:09 +02:00
valueTime := Float64ToTime(value)
valueTimeEastern := valueTime.In(date.Eastern())
2016-07-27 17:21:05 +02:00
deltaSeconds := date.CalculateMarketSecondsBetween(mhr.Min, mhr.GetEffectiveMax(), mhr.MarketOpen, mhr.MarketClose, mhr.HolidayProvider)
valueDelta := date.CalculateMarketSecondsBetween(mhr.Min, valueTimeEastern, mhr.MarketOpen, mhr.MarketClose, mhr.HolidayProvider)
2016-07-23 07:43:27 +02:00
translated := int((float64(valueDelta) / float64(deltaSeconds)) * float64(mhr.Domain))
return translated
2016-07-22 07:09:09 +02:00
}