stockchart

package
v0.7.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 20, 2022 License: MIT Imports: 18 Imported by: 0

Documentation

Overview

stockchart generate interactive, responsive, and performant chart with HTML5 canvas and web assembly.

Index

Examples

Constants

This section is empty.

Variables

View Source
var DEBUG = DBG_OFF //DBG_SELCHANGE | DBG_REDRAW

Change this global variable to activate debug mode

View Source
var Origin = Point{X: 0, Y: 0}

Functions

func Debug added in v0.7.0

func Debug(debug DebugOutput, format string, data ...any)

if debug match with the DEBUG global flag, then Debug print out strprint

Types

type Align

type Align uint
const (
	AlignCenter Align = 0b00000000
	AlignStart  Align = 0b00000001
	AlignEnd    Align = 0b00000010
	AlignTop    Align = 0b00000100
	AlignBottom Align = 0b00001000
)

type DataList

type DataList struct {
	Name      string        // the name of the data list, usually the name of the pair and its precision
	Precision time.Duration // the precision of this serie, used for drawing candles
	Tail      *DataStock    // the tail !-----...
	Head      *DataStock    // ...-----! the head
}

DataList is a time ordered chained list of DataPoint. We assume that ordered points are linked in chronological order

func (*DataList) Append

func (dl *DataList) Append(newdata *DataStock)

Append a dataPoint to the head

func (DataList) DataRange

func (dl DataList) DataRange(ts *timeline.TimeSlice, maxSteps uint) (dr datarange.DataRange)

DataRange returns the data boundaries of the DataList, scanning all datapoint between the timeslice boundaries

ts == nil scan all data points between the Head and the Tail:
if maxSteps == 0 the returned datarange doesn't have any stepzise.
if maxSteps > 0 the returned datarange gets a stepzise and boudaries are rounded.

returns an empty datarange if the list is empty or if missing head or tail.

func (DataList) GetDataAt

func (dl DataList) GetDataAt(t time.Time) (data *DataStock)

return the dataPoint at t time, nil if no points found

func (*DataList) Insert added in v0.7.0

func (dl *DataList) Insert(newdata *DataStock)

Insert a dataPoint at the right position according to dates backward lookup to find the insert position

func (DataList) IsEmpty added in v0.7.0

func (dl DataList) IsEmpty() bool

func (DataList) Size added in v0.7.0

func (pdl DataList) Size() (size int)

func (DataList) String added in v0.7.0

func (dl DataList) String() string

func (DataList) TimeSlice

func (dl DataList) TimeSlice() timeline.TimeSlice

TimeSlice returns the time boundaries of the DataList, between the Head and the Tail.

returns an empty timeslice if the list is empty or if missing head or tail

func (DataList) VolumeDataRange added in v0.7.0

func (dl DataList) VolumeDataRange(ts *timeline.TimeSlice, maxSteps uint) (dr datarange.DataRange)

VolumeDataRange returns the data boundaries of the DataList, scanning all datapoint between the timeslice boundaries

ts == nil scan all data points between the Head and the Tail:
if maxSteps == 0 the returned datarange doesn t have any stepzise.
if maxSteps > 0 the returned datarange gets a stepzise and boudaries are rounded.

returns an empty datarange if the list is empty or if missing head or tail.

type DataStock

type DataStock struct {
	timeline.TimeSlice `json:"timeslice"`

	Open   float64 `json:"open"`
	Low    float64 `json:"low"`
	High   float64 `json:"high"`
	Close  float64 `json:"close"`
	Volume float64 `json:"volule"`

	Next *DataStock `json:"-"` // going to the head
	Prev *DataStock `json:"-"` // going to the tail
}

DataStock is a value at a given timestamp. It's linked with previous and following data

func (*DataStock) String

func (dp *DataStock) String() string

type DebugOutput added in v0.7.0

type DebugOutput int
const (
	DBG_OFF       DebugOutput = 0b000000000
	DBG_REDRAW    DebugOutput = 0b000000001
	DBG_EVENT     DebugOutput = 0b000000010
	DBG_RESIZE    DebugOutput = 0b000000100
	DBG_SELCHANGE DebugOutput = 0b000001000
	DBG_ALL       DebugOutput = 0b11111111
)

type Drawing

type Drawing struct {
	Name            string    // drawing name, mainly for debugging, but culd be used in the drawing
	MainColor       rgb.Color // optional, fully transparent by default
	BackgroundColor rgb.Color // optional, fully transparent by default

	*Layer // the parent layer

	OnRedraw func()

	// optional functions to be defined by upper drawings
	DrawArea func(clipArea Rect) Rect

	OnMouseDown  func(xy Point, event *htmlevent.MouseEvent)
	OnMouseUp    func(xy Point, event *htmlevent.MouseEvent)
	OnMouseMove  func(xy Point, event *htmlevent.MouseEvent)
	OnMouseEnter func(xy Point, event *htmlevent.MouseEvent)
	OnMouseLeave func(xy Point, event *htmlevent.MouseEvent)
	OnWheel      func(event *htmlevent.WheelEvent)
	OnClick      func(xy Point, event *htmlevent.MouseEvent)
	NeedRedraw   func() bool
	// contains filtered or unexported fields
}

Drawing provides primitives

func (*Drawing) DrawTextBox

func (drawing *Drawing) DrawTextBox(txt string, xy Point, align Align, backgroundcolor rgb.Color, textcolor rgb.Color, margin int, border int, padding int)

DrawTextBox draw a text within a box.

xy position is defined in a canvas coordinates and corresponds to the corner defined by align, the border, the margin and the padding.

Font must be set before

func (*Drawing) DrawVLine added in v0.7.0

func (drawing *Drawing) DrawVLine(at time.Time, color rgb.Color, full bool) (xpos float64)

Draw Vertical Line. returns -1 if at is out of range

func (*Drawing) ResetSeries added in v0.7.0

func (drawing *Drawing) ResetSeries(series *DataList)

SetMainSeries set or reset the MainSeries of the chart and its drawings. Reset the timerange. Need to redraw

func (Drawing) String

func (drawing Drawing) String() string

type DrawingBackground

type DrawingBackground struct {
	Drawing
}

func NewDrawingBackground

func NewDrawingBackground(series *DataList) *DrawingBackground

type DrawingBars added in v0.7.0

type DrawingBars struct {
	Drawing
	// contains filtered or unexported fields
}

Drawing a series of bars like for volumes

func NewDrawingBars added in v0.7.0

func NewDrawingBars(series *DataList) *DrawingBars

Drawing factory

type DrawingCandles

type DrawingCandles struct {
	Drawing
	// contains filtered or unexported fields
}

Drawing a series of Candles

func NewDrawingCandles

func NewDrawingCandles(series *DataList, alpha float32, dashstyle bool) *DrawingCandles

Drawing factory initAlpha must be within 0 (0% opacity = full transparent) and 1 (100% opacity)

type DrawingHoverCandles

type DrawingHoverCandles struct {
	Drawing
	// contains filtered or unexported fields
}

func NewDrawingHoverCandles

func NewDrawingHoverCandles(series *DataList) *DrawingHoverCandles

type DrawingSeries

type DrawingSeries struct {
	Drawing
	// contains filtered or unexported fields
}

func NewDrawingSeries

func NewDrawingSeries(series *DataList, fFillArea bool) *DrawingSeries

type DrawingTimeSelector

type DrawingTimeSelector struct {
	Drawing

	MinZoomTime time.Duration // 5 minutes by default, can be changed
	// contains filtered or unexported fields
}

func NewDrawingTimeSelector

func NewDrawingTimeSelector(series *DataList) *DrawingTimeSelector

Drawing factory

type DrawingXGrid added in v0.7.0

type DrawingXGrid struct {
	Drawing
	// contains filtered or unexported fields
}

func NewDrawingXGrid

func NewDrawingXGrid(series *DataList, fFullGrid bool, timeSelDependant bool) *DrawingXGrid

type DrawingYGrid

type DrawingYGrid struct {
	Drawing
	// contains filtered or unexported fields
}

func NewDrawingYGrid

func NewDrawingYGrid(series *DataList, fscale bool) *DrawingYGrid

type Layer

type Layer struct {
	ClipArea Rect
	Ctx2D    *canvas.CanvasRenderingContext2D

	Name string // the name of the layer, for debugging purpose
	// contains filtered or unexported fields
}

A Layer correspond to a single canvas with an html5 2D drawing context. It's embedding a stack of drawings.

func NewLayer added in v0.7.0

func NewLayer(id string, chart *StockChart, layout layoutT, xaxisrange *timeline.TimeSlice, canvasE canvas.HTMLCanvasElement) *Layer

func (*Layer) AddDrawing

func (layer *Layer) AddDrawing(dr *Drawing, bgcolor rgb.Color, ontop bool) *Drawing

AddDrawing add a new drawing to the stack of drawings appearing on this layer. The bgcolor is only used by the drawing.

if ontop is false, the drawing is added just after the drawing on top of the stack

func (*Layer) Clear

func (layer *Layer) Clear()

Clear the layer

func (*Layer) HandledEvents

func (layer *Layer) HandledEvents() evtHandler

func (*Layer) Redraw

func (layer *Layer) Redraw()

Clear the layer and redraw all drawings.

func (*Layer) RedrawOnlyNeeds added in v0.7.0

func (layer *Layer) RedrawOnlyNeeds()

Redraw the layer if at least one drawings need to be redrawn. Then update selection on the layer

func (*Layer) Resize

func (layer *Layer) Resize(newarea Rect)

Resize resize the drawing buffer according to the canvas element size. We need to extend the drawingbuffer to the same size of the canvas HTML element to avoid blurry effect, and take into account the DevicePixelRatio. It's more accurate to use GetBoundingClientRect than ClientWidth(), unfortunately thers'no easy way to take into account border size and padding withing the canvas element, so when resizing we assume there's no border, no padding and no margin within the canvas. https://webglfundamentals.org/webgl/lessons/webgl-resizing-the-canvas.html

Resize calls automatically redraw

func (*Layer) SetEventDispatcher

func (layer *Layer) SetEventDispatcher()

SetEventDispatcher activates mouse event handler on the canvas of the layer. When setup, if the mouse is located in the cliparea of the layer, the event is propagated to all drawings having defined their own MouseEvent func.

Usually SetEventDispatcher is called by the chart factory.

func (Layer) String

func (layer Layer) String() string

Default string interface

type Point

type Point struct {
	X int
	Y int
}

A simple point in a 2D plan

func (Point) IsIn

func (pt Point) IsIn(r Rect) bool

IsIn returns true if the point is inside the rect

type Rect

type Rect struct {
	O      Point // the orgin of the rect, can be negative
	Width  int
	Height int
}

A simple rect in a 2d plan

func (Rect) And

func (thisRect Rect) And(anotherRect Rect) (AndRect *Rect)

And returns a rect which correspond to common area of thisRect and anotherRect. rteurns nul if there's no common area

Example
r1 := &Rect{Width: 100, Height: 100}
r2 := &Rect{O: Point{X: 20, Y: 20}, Width: 100, Height: 100}
r3 := r1.And(*r2)
fmt.Printf("%v\n", r3)
r3bis := r2.And(*r1)
fmt.Printf("%v\n", r3bis)
r4 := r3.And(*r3)
fmt.Printf("%v\n", r4)
r5 := &Rect{Width: 10, Height: 10}
r6 := r5.And(*r3)
fmt.Printf("%v\n", r6)
Output:

x=20 y=20 width=80 height=80
x=20 y=20 width=80 height=80
x=20 y=20 width=80 height=80
<nil>

func (Rect) BoundX

func (r Rect) BoundX(x int) int

BoundX returns X bounded by the rect boundaries

func (Rect) BoundY

func (r Rect) BoundY(y int) int

BoundY returns y bounded by the rect boundaries

func (*Rect) Box

func (r *Rect) Box(area Rect) error

Box r within the area. That means r is inside the area, if required recalculate its position. size stays unchanged. If the box is greater than the area, then return an error.

func (Rect) End

func (r Rect) End() Point

returns the endpoint of the rect

func (*Rect) Equal

func (pr1 *Rect) Equal(pr2 *Rect) bool

Equal

func (*Rect) FlipPositive

func (pr *Rect) FlipPositive()

FlipPositive flip the rect to make it positive in both dimensions with at least a height and and width of 1

func (Rect) Middle

func (r Rect) Middle() Point

returns the Middle of the rect

func (Rect) Shift

func (r Rect) Shift(xy Point)

func (Rect) Shrink

func (r Rect) Shrink(x int, y int) Rect

Returns a Shrinked rect calculated from the center of r. x and y are added on both sides

x and y are expressed in Rect unit, not in rate.
if x or y are <0 then the rect is expanded.
if x or y are greater than the size then rect become a single point with zero size.

func (Rect) String

func (r Rect) String() string

String Interface for r

func (Rect) XRate

func (r Rect) XRate(x int) float64

returns where is y inside the rect

if x is over End.Y then return 1
if x is before O.X then return 0
if XSize is zero then return 0

func (Rect) YRate

func (r Rect) YRate(y int) float64

returns where is y inside the rect

if y is over EndPoint.Y then return 1
if y is before O.Y then return 0
if YSize is zero then return 0

type StockChart

type StockChart struct {
	ID string // the identifier of this chart, the canvas id

	MainSeries DataList

	NotifySelChangeTimeSlice func(strpair string, ts timeline.TimeSlice) // function called everytime the timeselection change, if not nil
	NotifySelChangeData      func(strpair string, data *DataStock)
	// contains filtered or unexported fields
}

StockChart is a 2D chart draw embedded into an HTML5 element

func NewStockChart

func NewStockChart(chartid string, bgcolor rgb.Color, series DataList, extendrate float64) (*StockChart, error)

NewStockChart initialize a stockchart within the <stockchart> HTML element idenfied by chartid. An HTML page can have multiple <stockchart> but with different chartid. The layout of the chart is composed of multiples layers which are stacked canvas.

Returns the stockchart created or an error if canvasid is not found.

func (*StockChart) AddSubChart added in v0.7.0

func (pchart *StockChart) AddSubChart(layerid int, dr *Drawing)

AddSubChart add another drawing to draw within the same X and Y ranges than the main series on the choosen layer. Drawing is made just before drawing of the main drawin on the layer. This drawing is associated to it's own series of data

func (*StockChart) DoChangeSelData added in v0.7.1

func (pchart *StockChart) DoChangeSelData(strpair string, newdata *DataStock, fNotify bool)

func (*StockChart) DoChangeSelTimeSlice added in v0.7.1

func (pchart *StockChart) DoChangeSelTimeSlice(strpair string, newts timeline.TimeSlice, fNotify bool)

DoChangeSelTimeSlice updates all drawings to reflect the new timsel.

It's called by the time selector in the navbar when user navigates, but can be called directly outside of the chart.

call OnDoChangeTimeSelection if setup

func (*StockChart) DoChangeTimeZone added in v0.7.1

func (pchart *StockChart) DoChangeTimeZone(localZone bool)

func (*StockChart) Redraw

func (pchart *StockChart) Redraw()

Redraw all layers (canvas) of the stockchart.

Do not need to be called after a resize as layers automatically redrawn themselves

func (*StockChart) RedrawOnlyNeeds added in v0.7.0

func (pchart *StockChart) RedrawOnlyNeeds()

Redraw all layers (canvas) of the stockchart.

Do not need to be called after a resize as layers automatically redrawn themselves

func (*StockChart) ResetMainSeries added in v0.7.0

func (pchart *StockChart) ResetMainSeries(series DataList, extendrate float64, redrawNow bool)

SetMainSeries set or reset the MainSeries of the chart and its drawings. Reset the timerange

func (*StockChart) Resize added in v0.7.0

func (pchart *StockChart) Resize()

resize all layers according to the master element dimensions.

func (*StockChart) SetTimeRange

func (pchart *StockChart) SetTimeRange(timerange timeline.TimeSlice, extendrate float64) timeline.TimeSlice

SetTimeRange defines the overall time range to display. Extend the end with extendCoef.

extendCoef == 0 no extension
extendCoef == 0.1 for 10% extention in duration

Update timeselection if required. If the timeselection change the RedrawOnlyNeeds Returns the setup timerange

func (StockChart) String

func (chart StockChart) String() string

String interface for StockChart, mainly for debugging purpose

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL