103 lines
4.2 KiB
Go
103 lines
4.2 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"time"
|
|
|
|
"github.com/egoist/mygo/ui"
|
|
|
|
"git.zacharyzhang.com/ZacharyZhang-NY/MujicaUI/chart"
|
|
"git.zacharyzhang.com/ZacharyZhang-NY/MujicaUI/core"
|
|
"git.zacharyzhang.com/ZacharyZhang-NY/MujicaUI/data"
|
|
"git.zacharyzhang.com/ZacharyZhang-NY/MujicaUI/input"
|
|
)
|
|
|
|
type mktDemoState struct {
|
|
candles []chart.Candle
|
|
points []chart.QuotePoint
|
|
bids, asks []chart.DepthLevel
|
|
bins []chart.ProfileBin
|
|
window chart.MarketView
|
|
second chart.MarketView
|
|
sync chart.ChartSync
|
|
layout chart.MultiChartState
|
|
interval chart.Interval
|
|
favorites []chart.Interval
|
|
rangeValue chart.MarketRange
|
|
chartType chart.ChartType
|
|
overlays []chart.IndicatorOverlay
|
|
panes chart.IndicatorPanes
|
|
drawings chart.DrawingTools
|
|
compare []chart.CompareSymbol
|
|
alerts []chart.PriceAlertLine
|
|
status string
|
|
disabled, raw, redUp, hidden, extended bool
|
|
previous, fraction float64
|
|
}
|
|
|
|
func mktInitial() mktDemoState {
|
|
s := mktDemoState{status: "Ready", interval: "1h", favorites: []chart.Interval{"1m", "1h", "1D"}, previous: 100, fraction: 0.7, extended: true}
|
|
start := time.Date(2026, 10, 5, 8, 0, 0, 0, time.UTC)
|
|
price := 100.0
|
|
compare := make([]float64, 180)
|
|
for i := range 180 {
|
|
closeAt := price + math.Sin(float64(i)*0.7)*1.5 + math.Cos(float64(i)*0.13)*0.8
|
|
s.candles = append(s.candles, chart.Candle{Time: start.Add(time.Duration(i) * time.Hour), Open: price, High: max(price, closeAt) + 0.8, Low: min(price, closeAt) - 0.7, Close: closeAt, Volume: 1000 + float64(i%17)*130})
|
|
s.points = append(s.points, chart.QuotePoint{Time: start.Add(time.Duration(i) * 5 * time.Minute), Price: 100 + 2*math.Sin(float64(i)/10), Volume: 100 + float64(i%7)*20})
|
|
compare[i] = 20 + float64(i)*0.08
|
|
price = closeAt
|
|
}
|
|
for i := range 40 {
|
|
s.bids = append(s.bids, chart.DepthLevel{Price: 99.9 - float64(i)*0.1, Size: float64(10 + i*3)})
|
|
s.asks = append(s.asks, chart.DepthLevel{Price: 100.1 + float64(i)*0.1, Size: float64(8 + i*4)})
|
|
}
|
|
s.bins = chart.VolumeProfileOf(s.candles, 24)
|
|
s.compare = []chart.CompareSymbol{{Name: "ETH", Closes: compare}}
|
|
s.alerts = []chart.PriceAlertLine{{ID: "target", Price: 104, Label: "Target"}}
|
|
s.overlays = []chart.IndicatorOverlay{{Kind: chart.IndicatorMA, Params: []float64{10}}}
|
|
s.panes = chart.IndicatorPanes{Panes: []chart.IndicatorPaneSpec{{Kind: chart.IndicatorMACD}, {Kind: chart.IndicatorRSI}}}
|
|
s.layout.Count = 2
|
|
for i := range s.layout.Cells {
|
|
s.layout.Cells[i] = chart.ChartCell{Symbol: fmt.Sprintf("Symbol %d", i+1), Interval: "1h"}
|
|
}
|
|
return s
|
|
}
|
|
|
|
func mktControls(c *ui.Context, s *mktDemoState, log func(string)) chart.ChartFrame {
|
|
ui.Row(c).Gap(12).Wrap().Children(func() {
|
|
if input.Select(c, &s.status, []input.SelectOption[string]{{Value: "Ready", Label: "Ready"}, {Value: "Loading", Label: "Loading"}, {Value: "Failed", Label: "Failed"}, {Value: "Empty", Label: "Empty"}}, input.SelectOptions{Label: "Data state"}).Changed() {
|
|
log("Data state: " + s.status)
|
|
}
|
|
if input.Checkbox(c, &s.disabled, "Disabled", input.CheckboxOptions{}).Changed() {
|
|
log(fmt.Sprintf("Disabled: %v", s.disabled))
|
|
}
|
|
if input.Checkbox(c, &s.redUp, "Red up", input.CheckboxOptions{}).Changed() {
|
|
log(fmt.Sprintf("Red up: %v", s.redUp))
|
|
}
|
|
})
|
|
trend := core.GreenUp
|
|
if s.redUp {
|
|
trend = core.RedUp
|
|
}
|
|
core.UseTrend(c, trend)
|
|
f := chart.ChartFrame{Label: "BTC", Height: 220}
|
|
switch s.status {
|
|
case "Loading":
|
|
f.Status = data.DataLoading
|
|
case "Failed":
|
|
f.Status = data.DataFailed
|
|
f.Error = "Archive unavailable"
|
|
}
|
|
return f
|
|
}
|
|
|
|
func mktLog(log func(string), name string, r chart.ChartResult) {
|
|
if r.Changed() {
|
|
log(fmt.Sprintf("%s: point %d", name, r.Point))
|
|
}
|
|
if r.Retried() {
|
|
log(name + ": retry")
|
|
}
|
|
}
|