diff --git a/pkg/accounting/cost_distribution.go b/pkg/accounting/cost_distribution.go index cedf7666b..7bdfb3d3e 100644 --- a/pkg/accounting/cost_distribution.go +++ b/pkg/accounting/cost_distribution.go @@ -1,7 +1,6 @@ package accounting import ( - "fmt" "math" "sort" "strconv" @@ -16,19 +15,15 @@ func zero(a float64) bool { return int(math.Round(a*1e8)) == 0 } -func round(a float64) float64 { - return math.Round(a*1e8) / 1e8 -} - type Stock types.Trade func (stock *Stock) String() string { - return fmt.Sprintf("%f (%f)", stock.Price, stock.Quantity) + return stock.Price.String() + " (" + stock.Quantity.String() + ")" } func (stock *Stock) Consume(quantity fixedpoint.Value) fixedpoint.Value { q := fixedpoint.Min(stock.Quantity, quantity) - stock.Quantity = stock.Quantity.Sub(q).Round(0, fixedpoint.Down) + stock.Quantity = stock.Quantity.Sub(q) return q } @@ -41,7 +36,7 @@ func (slice StockSlice) QuantityBelowPrice(price fixedpoint.Value) (quantity fix } } - return quantity.Round(0, fixedpoint.Down) + return quantity } func (slice StockSlice) Quantity() (total fixedpoint.Value) { @@ -49,7 +44,7 @@ func (slice StockSlice) Quantity() (total fixedpoint.Value) { total = total.Add(stock.Quantity) } - return total.Round(0, fixedpoint.Down) + return total } type StockDistribution struct { @@ -77,10 +72,7 @@ func (m *StockDistribution) DistributionStats(level int) *DistributionStats { for _, stock := range m.Stocks { n := math.Ceil(math.Log10(stock.Price.Float64())) digits := int(n - math.Max(float64(level), 1.0)) - // TODO: use Round function in fixedpoint - div := math.Pow10(digits) - priceLevel := math.Floor(stock.Price.Float64()/div) * div - key := strconv.FormatFloat(priceLevel, 'f', 2, 64) + key := stock.Price.Round(-digits, fixedpoint.Down).FormatString(2) d.TotalQuantity = d.TotalQuantity.Add(stock.Quantity) d.Stocks[key] = append(d.Stocks[key], stock) @@ -98,8 +90,6 @@ func (m *StockDistribution) DistributionStats(level int) *DistributionStats { d.PriceLevels = append(d.PriceLevels, strconv.FormatFloat(price, 'f', 2, 64)) } - sort.Float64s(priceLevels) - return &d } diff --git a/pkg/accounting/cost_distribution_test.go b/pkg/accounting/cost_distribution_test.go index 2a899a6a4..5c1fd91a7 100644 --- a/pkg/accounting/cost_distribution_test.go +++ b/pkg/accounting/cost_distribution_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/c9s/bbgo/pkg/types" + "github.com/c9s/bbgo/pkg/fixedpoint" ) func TestStockManager(t *testing.T) { @@ -28,7 +29,7 @@ func TestStockManager(t *testing.T) { _, err = stockManager.AddTrades(trades) assert.NoError(t, err) - assert.Equal(t, 0.72970242, stockManager.Stocks.Quantity()) + assert.Equal(t, "0.72970242", stockManager.Stocks.Quantity().String()) assert.NotEmpty(t, stockManager.Stocks) assert.Equal(t, 20, len(stockManager.Stocks)) assert.Equal(t, 0, len(stockManager.PendingSells)) @@ -37,9 +38,9 @@ func TestStockManager(t *testing.T) { t.Run("stock", func(t *testing.T) { var trades = []types.Trade{ - {Symbol: "BTCUSDT", Price: 9100.0, Quantity: 0.05, IsBuyer: true}, - {Symbol: "BTCUSDT", Price: 9100.0, Quantity: 0.05, IsBuyer: true}, - {Symbol: "BTCUSDT", Price: 9200.0, Quantity: 0.01, IsBuyer: false}, + {Symbol: "BTCUSDT", Price: fixedpoint.MustNewFromString("9100.0"), Quantity: fixedpoint.MustNewFromString("0.05"), IsBuyer: true}, + {Symbol: "BTCUSDT", Price: fixedpoint.MustNewFromString("9100.0"), Quantity: fixedpoint.MustNewFromString("0.05"), IsBuyer: true}, + {Symbol: "BTCUSDT", Price: fixedpoint.MustNewFromString("9200.0"), Quantity: fixedpoint.MustNewFromString("0.01"), IsBuyer: false}, } var stockManager = &StockDistribution{ @@ -53,14 +54,14 @@ func TestStockManager(t *testing.T) { assert.Equal(t, StockSlice{ { Symbol: "BTCUSDT", - Price: 9100.0, - Quantity: 0.05, + Price: fixedpoint.MustNewFromString("9100.0"), + Quantity: fixedpoint.MustNewFromString("0.05"), IsBuyer: true, }, { Symbol: "BTCUSDT", - Price: 9100.0, - Quantity: 0.04, + Price: fixedpoint.MustNewFromString("9100.0"), + Quantity: fixedpoint.MustNewFromString("0.04"), IsBuyer: true, }, }, stockManager.Stocks) @@ -69,10 +70,10 @@ func TestStockManager(t *testing.T) { t.Run("sold out", func(t *testing.T) { var trades = []types.Trade{ - {Symbol: "BTCUSDT", Price: 9100.0, Quantity: 0.05, IsBuyer: true}, - {Symbol: "BTCUSDT", Price: 9200.0, Quantity: 0.05, IsBuyer: false}, - {Symbol: "BTCUSDT", Price: 9100.0, Quantity: 0.05, IsBuyer: true}, - {Symbol: "BTCUSDT", Price: 9200.0, Quantity: 0.05, IsBuyer: false}, + {Symbol: "BTCUSDT", Price: fixedpoint.MustNewFromString("9100.0"), Quantity: fixedpoint.MustNewFromString("0.05"), IsBuyer: true}, + {Symbol: "BTCUSDT", Price: fixedpoint.MustNewFromString("9200.0"), Quantity: fixedpoint.MustNewFromString("0.05"), IsBuyer: false}, + {Symbol: "BTCUSDT", Price: fixedpoint.MustNewFromString("9100.0"), Quantity: fixedpoint.MustNewFromString("0.05"), IsBuyer: true}, + {Symbol: "BTCUSDT", Price: fixedpoint.MustNewFromString("9200.0"), Quantity: fixedpoint.MustNewFromString("0.05"), IsBuyer: false}, } var stockManager = &StockDistribution{ @@ -88,9 +89,9 @@ func TestStockManager(t *testing.T) { t.Run("oversell", func(t *testing.T) { var trades = []types.Trade{ - {Symbol: "BTCUSDT", Price: 9100.0, Quantity: 0.05, IsBuyer: true}, - {Symbol: "BTCUSDT", Price: 9200.0, Quantity: 0.05, IsBuyer: false}, - {Symbol: "BTCUSDT", Price: 9200.0, Quantity: 0.05, IsBuyer: false}, + {Symbol: "BTCUSDT", Price: fixedpoint.MustNewFromString("9100.0"), Quantity: fixedpoint.MustNewFromString("0.05"), IsBuyer: true}, + {Symbol: "BTCUSDT", Price: fixedpoint.MustNewFromString("9200.0"), Quantity: fixedpoint.MustNewFromString("0.05"), IsBuyer: false}, + {Symbol: "BTCUSDT", Price: fixedpoint.MustNewFromString("9200.0"), Quantity: fixedpoint.MustNewFromString("0.05"), IsBuyer: false}, } var stockManager = &StockDistribution{ @@ -106,9 +107,9 @@ func TestStockManager(t *testing.T) { t.Run("loss sell", func(t *testing.T) { var trades = []types.Trade{ - {Symbol: "BTCUSDT", Price: 9100.0, Quantity: 0.05, IsBuyer: true}, - {Symbol: "BTCUSDT", Price: 9200.0, Quantity: 0.02, IsBuyer: false}, - {Symbol: "BTCUSDT", Price: 8000.0, Quantity: 0.01, IsBuyer: false}, + {Symbol: "BTCUSDT", Price: fixedpoint.MustNewFromString("9100.0"), Quantity: fixedpoint.MustNewFromString("0.05"), IsBuyer: true}, + {Symbol: "BTCUSDT", Price: fixedpoint.MustNewFromString("9200.0"), Quantity: fixedpoint.MustNewFromString("0.02"), IsBuyer: false}, + {Symbol: "BTCUSDT", Price: fixedpoint.MustNewFromString("8000.0"), Quantity: fixedpoint.MustNewFromString("0.01"), IsBuyer: false}, } var stockManager = &StockDistribution{ @@ -122,8 +123,8 @@ func TestStockManager(t *testing.T) { assert.Equal(t, StockSlice{ { Symbol: "BTCUSDT", - Price: 9100.0, - Quantity: 0.02, + Price: fixedpoint.MustNewFromString("9100.0"), + Quantity: fixedpoint.MustNewFromString("0.02"), IsBuyer: true, }, }, stockManager.Stocks) @@ -132,8 +133,8 @@ func TestStockManager(t *testing.T) { t.Run("pending sell 1", func(t *testing.T) { var trades = []types.Trade{ - {Symbol: "BTCUSDT", Price: 9200.0, Quantity: 0.02}, - {Symbol: "BTCUSDT", Price: 9100.0, Quantity: 0.05, IsBuyer: true}, + {Symbol: "BTCUSDT", Price: fixedpoint.MustNewFromString("9200.0"), Quantity: fixedpoint.MustNewFromString("0.02")}, + {Symbol: "BTCUSDT", Price: fixedpoint.MustNewFromString("9100.0"), Quantity: fixedpoint.MustNewFromString("0.05"), IsBuyer: true}, } var stockManager = &StockDistribution{ @@ -147,8 +148,8 @@ func TestStockManager(t *testing.T) { assert.Equal(t, StockSlice{ { Symbol: "BTCUSDT", - Price: 9100.0, - Quantity: 0.03, + Price: fixedpoint.MustNewFromString("9100.0"), + Quantity: fixedpoint.MustNewFromString("0.03"), IsBuyer: true, }, }, stockManager.Stocks) @@ -157,8 +158,8 @@ func TestStockManager(t *testing.T) { t.Run("pending sell 2", func(t *testing.T) { var trades = []types.Trade{ - {Symbol: "BTCUSDT", Price: 9200.0, Quantity: 0.1}, - {Symbol: "BTCUSDT", Price: 9100.0, Quantity: 0.05, IsBuyer: true}, + {Symbol: "BTCUSDT", Price: fixedpoint.MustNewFromString("9200.0"), Quantity: fixedpoint.MustNewFromString("0.1")}, + {Symbol: "BTCUSDT", Price: fixedpoint.MustNewFromString("9100.0"), Quantity: fixedpoint.MustNewFromString("0.05"), IsBuyer: true}, } var stockManager = &StockDistribution{ @@ -173,8 +174,8 @@ func TestStockManager(t *testing.T) { assert.Equal(t, StockSlice{ { Symbol: "BTCUSDT", - Price: 9200.0, - Quantity: 0.05, + Price: fixedpoint.MustNewFromString("9200.0"), + Quantity: fixedpoint.MustNewFromString("0.05"), IsBuyer: false, }, }, stockManager.PendingSells) diff --git a/pkg/fixedpoint/dec.go b/pkg/fixedpoint/dec.go index 1a607b030..c2aac4c5c 100644 --- a/pkg/fixedpoint/dec.go +++ b/pkg/fixedpoint/dec.go @@ -7,7 +7,6 @@ import ( "strconv" "strings" "database/sql/driver" - "encoding/json" "fmt" "errors" ) @@ -1001,29 +1000,10 @@ func (v Value) MarshalJSON() ([]byte, error) { } func (v *Value) UnmarshalJSON(data []byte) error { - var a interface{} - err := json.Unmarshal(data, &a) - if err != nil { + var err error + if *v, err = NewFromBytes(data); err != nil { return err } - switch d := a.(type) { - case float64: - *v = NewFromFloat(d) - case float32: - *v = NewFromFloat(float64(d)) - case int: - *v = NewFromInt(int64(d)) - case int64: - *v = NewFromInt(d) - case string: - v2, err := NewFromString(d) - if err != nil { - return err - } - *v = v2; - default: - return fmt.Errorf("unsupported type :%T %v", d, d) - } return nil } diff --git a/pkg/fixedpoint/dec_test.go b/pkg/fixedpoint/dec_test.go index 691d6b26d..163cfd1fb 100644 --- a/pkg/fixedpoint/dec_test.go +++ b/pkg/fixedpoint/dec_test.go @@ -70,6 +70,22 @@ func TestNew(t *testing.T) { assert.Equal(t, "0.10%", f.FormatPercentage(2)) } +func TestRound(t *testing.T) { + f := NewFromFloat(1.2345) + f = f.Round(0, Down) + assert.Equal(t, "1", f.String()) + w := NewFromFloat(1.2345) + w = w.Trunc() + assert.Equal(t, "1", w.String()) + s := NewFromFloat(1.2345) + assert.Equal(t, "1.23", s.Round(2, Down).String()) +} + +func TestFromString(t *testing.T) { + f := MustNewFromString("0.004075") + assert.Equal(t, "0.004075", f.String()) +} + // Not used /*func TestParse(t *testing.T) { type args struct { diff --git a/pkg/indicator/ewma_test.go b/pkg/indicator/ewma_test.go index d752b5f0c..45a60ef3c 100644 --- a/pkg/indicator/ewma_test.go +++ b/pkg/indicator/ewma_test.go @@ -3,15 +3,17 @@ package indicator import ( "math" "testing" + "encoding/json" "github.com/c9s/bbgo/pkg/types" + "github.com/c9s/bbgo/pkg/fixedpoint" ) // generated from: // 2020/12/05 10:25 // curl -s 'https://www.binance.com/api/v3/klines?symbol=ETHUSDT&interval=5m&endTime=1607135400000&limit=1000' | jq '. | map({ closePrice: (.[4] | tonumber), openTime: .[0] })' // curl -s 'https://www.binance.com/api/v3/klines?symbol=ETHUSDT&interval=5m&endTime=1607135400000&limit=1000' | jq '. | map(.[4] | tonumber)' -var ethusdt5m = []float64{ +var ethusdt5m = []byte(`[ 614.36, 613.62, 611.68, @@ -1011,10 +1013,10 @@ var ethusdt5m = []float64{ 572.85, 572.21, 572.63, - 572.74, -} + 572.74 +]`) -func buildKLines(prices []float64) (klines []types.KLine) { +func buildKLines(prices []fixedpoint.Value) (klines []types.KLine) { for _, p := range prices { klines = append(klines, types.KLine{Close: p}) } @@ -1028,6 +1030,10 @@ func Test_calculateEWMA(t *testing.T) { priceF KLinePriceMapper window int } + var input []fixedpoint.Value; + if err := json.Unmarshal(ethusdt5m, &input); err != nil { + panic(err) + } tests := []struct { name string args args @@ -1036,7 +1042,7 @@ func Test_calculateEWMA(t *testing.T) { { name: "ETHUSDT EMA 7", args: args{ - allKLines: buildKLines(ethusdt5m), + allKLines: buildKLines(input), priceF: KLineClosePriceMapper, window: 7, }, @@ -1045,7 +1051,7 @@ func Test_calculateEWMA(t *testing.T) { { name: "ETHUSDT EMA 25", args: args{ - allKLines: buildKLines(ethusdt5m), + allKLines: buildKLines(input), priceF: KLineClosePriceMapper, window: 25, }, @@ -1054,7 +1060,7 @@ func Test_calculateEWMA(t *testing.T) { { name: "ETHUSDT EMA 99", args: args{ - allKLines: buildKLines(ethusdt5m), + allKLines: buildKLines(input), priceF: KLineClosePriceMapper, window: 99, }, diff --git a/pkg/indicator/macd_test.go b/pkg/indicator/macd_test.go index 6fb80b4fe..d22c8adc5 100644 --- a/pkg/indicator/macd_test.go +++ b/pkg/indicator/macd_test.go @@ -3,8 +3,10 @@ package indicator import ( "math" "testing" + "encoding/json" "github.com/c9s/bbgo/pkg/types" + "github.com/c9s/bbgo/pkg/fixedpoint" ) /* @@ -18,7 +20,11 @@ print(fast - slow) */ func Test_calculateMACD(t *testing.T) { - var randomPrices = []float64{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9} + var randomPrices = []byte(`[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]`) + var input []fixedpoint.Value + if err := json.Unmarshal(randomPrices, &input); err != nil { + panic(err) + } tests := []struct { name string kLines []types.KLine @@ -26,7 +32,7 @@ func Test_calculateMACD(t *testing.T) { }{ { name: "random_case", - kLines: buildKLines(randomPrices), + kLines: buildKLines(input), want: 0.7967670223776384, }, } diff --git a/pkg/indicator/obv.go b/pkg/indicator/obv.go index 4ed3d7d71..e5ce76046 100644 --- a/pkg/indicator/obv.go +++ b/pkg/indicator/obv.go @@ -32,14 +32,11 @@ func (inc *OBV) update(kLine types.KLine, priceF KLinePriceMapper) { return } - var sign float64 = 0.0 - if volume > inc.PrePrice { - sign = 1.0 - } else if volume < inc.PrePrice { - sign = -1.0 + if volume < inc.PrePrice { + inc.Values.Push(inc.Last() - volume) + } else { + inc.Values.Push(inc.Last() + volume) } - obv := inc.Last() + sign*volume - inc.Values.Push(obv) } func (inc *OBV) Last() float64 { diff --git a/pkg/indicator/obv_test.go b/pkg/indicator/obv_test.go index 473c8a290..5b9247dd8 100644 --- a/pkg/indicator/obv_test.go +++ b/pkg/indicator/obv_test.go @@ -1,19 +1,30 @@ package indicator import ( - "reflect" "testing" + "encoding/json" + + "github.com/stretchr/testify/assert" "github.com/c9s/bbgo/pkg/types" + "github.com/c9s/bbgo/pkg/fixedpoint" ) +const Delta = 1e-9 + func Test_calculateOBV(t *testing.T) { - buildKLines := func(prices, volumes []float64) (kLines []types.KLine) { + buildKLines := func(prices, volumes []fixedpoint.Value) (kLines []types.KLine) { for i, p := range prices { kLines = append(kLines, types.KLine{High: p, Low: p, Close: p, Volume: volumes[i]}) } return kLines } + var easy1 = []byte(`[3, 2, 1, 4]`) + var easy2 = []byte(`[3, 2, 2, 6]`) + var input1 []fixedpoint.Value + var input2 []fixedpoint.Value + _ = json.Unmarshal(easy1, &input1) + _ = json.Unmarshal(easy2, &input2) tests := []struct { name string @@ -23,13 +34,15 @@ func Test_calculateOBV(t *testing.T) { }{ { name: "trivial_case", - kLines: buildKLines([]float64{0}, []float64{1}), + kLines: buildKLines( + []fixedpoint.Value{fixedpoint.Zero}, []fixedpoint.Value{fixedpoint.One}, + ), window: 0, want: types.Float64Slice{1.0}, }, { name: "easy_case", - kLines: buildKLines([]float64{3, 2, 1, 4}, []float64{3, 2, 2, 6}), + kLines: buildKLines(input1, input2), window: 0, want: types.Float64Slice{3, 1, -1, 5}, }, @@ -39,8 +52,9 @@ func Test_calculateOBV(t *testing.T) { t.Run(tt.name, func(t *testing.T) { obv := OBV{IntervalWindow: types.IntervalWindow{Window: tt.window}} obv.calculateAndUpdate(tt.kLines) - if !reflect.DeepEqual(obv.Values, tt.want) { - t.Errorf("calculateAndUpdate() = %v, want %v", obv.Values, tt.want) + assert.Equal(t, len(obv.Values), len(tt.want)) + for i, v := range(obv.Values) { + assert.InDelta(t, v, tt.want[i], Delta) } }) } diff --git a/pkg/indicator/stoch_test.go b/pkg/indicator/stoch_test.go index 19f7fe3f2..9b349c24a 100644 --- a/pkg/indicator/stoch_test.go +++ b/pkg/indicator/stoch_test.go @@ -4,8 +4,10 @@ import ( "math" "testing" "time" + "encoding/json" "github.com/c9s/bbgo/pkg/types" + "github.com/c9s/bbgo/pkg/fixedpoint" ) /* @@ -18,17 +20,22 @@ df = pd.DataFrame(klines, columns=['open', 'high', 'low', 'close', 'volume']) print(df.ta.stoch(df['high'], df['low'], df['close'], k=14, d=3, smooth_k=1)) */ func TestSTOCH_update(t *testing.T) { - open := []float64{8273.0, 8280.0, 8280.0, 8275.0, 8281.0, 8277.0, 8279.0, 8280.0, 8284.0, 8286.0, 8283.0, 8283.0, 8284.0, 8286.0, 8285.0, 8287.0, 8289.0, 8282.0, 8286.0, 8279.0, 8275.0, 8276.0, 8276.0, 8281.0, 8269.0, 8256.0, 8258.0, 8252.0, 8241.0, 8232.0, 8218.0, 8221.0, 8216.0, 8210.0, 8212.0, 8201.0, 8197.0, 8200.0, 8193.0, 8181.0, 8185.0, 8190.0, 8184.0, 8185.0, 8163.0, 8153.0, 8162.0, 8165.0, 8162.0, 8157.0, 8159.0, 8141.0, 8140.0, 8141.0, 8130.0, 8144.0, 8141.0, 8148.0, 8145.0, 8134.0, 8123.0, 8127.0, 8130.0, 8125.0, 8122.0, 8105.0, 8096.0, 8103.0, 8102.0, 8110.0, 8104.0, 8109.0, 8103.0, 8111.0, 8112.0, 8109.0, 8092.0, 8100.0, 8101.0, 8100.0, 8096.0, 8095.0, 8094.0, 8101.0, 8095.0, 8069.0, 8067.0, 8070.0, 8069.0, 8066.0, 8047.0, 8046.0, 8042.0, 8039.0, 8049.0, 8055.0, 8063.0, 8061.0, 8056.0, 8057.0, 8056.0, 8057.0, 8057.0, 8054.0, 8056.0, 8056.0, 8065.0, 8065.0, 8070.0, 8065.0, 8064.0, 8063.0, 8060.0, 8065.0, 8068.0, 8068.0, 8069.0, 8073.0, 8073.0, 8084.0, 8084.0, 8076.0, 8074.0, 8074.0, 8074.0, 8078.0, 8080.0, 8082.0, 8085.0, 8083.0, 8087.0, 8087.0, 8083.0, 8083.0, 8082.0, 8074.0, 8074.0, 8071.0, 8071.0, 8072.0, 8075.0, 8075.0, 8076.0, 8073.0, 8071.0, 8070.0, 8075.0, 8078.0, 8077.0, 8075.0, 8073.0, 8079.0, 8084.0, 8082.0, 8085.0, 8085.0, 8085.0, 8101.0, 8106.0, 8113.0, 8109.0, 8104.0, 8105.0, 8105.0, 8107.0, 8106.0, 8104.0, 8106.0, 8106.0, 8110.0, 8107.0, 8110.0, 8111.0, 8104.0, 8098.0, 8098.0, 8098.0, 8098.0, 8094.0, 8097.0, 8096.0, 8099.0, 8098.0, 8099.0, 8098.0, 8095.0, 8096.0, 8086.0, 8088.0, 8093.0, 8092.0, 8096.0, 8100.0, 8104.0, 8104.0, 8108.0, 8107.0, 8103.0, 8104.0, 8110.0, 8105.0, 8102.0, 8104.0, 8096.0, 8099.0, 8103.0, 8102.0, 8108.0, 8107.0, 8107.0, 8104.0, 8095.0, 8091.0, 8092.0, 8090.0, 8093.0, 8093.0, 8094.0, 8095.0, 8096.0, 8088.0, 8090.0, 8079.0, 8077.0, 8079.0, 8081.0, 8083.0, 8084.0, 8084.0, 8087.0, 8091.0, 8089.0, 8089.0, 8091.0, 8087.0, 8093.0, 8090.0, 8090.0, 8095.0, 8093.0, 8088.0, 8087.0, 8090.0, 8089.0, 8087.0, 8084.0, 8087.0, 8084.0, 8080.0, 8078.0, 8077.0, 8077.0, 8076.0, 8072.0, 8072.0, 8075.0, 8076.0, 8074.0, 8077.0, 8081.0, 8080.0, 8076.0, 8075.0, 8077.0, 8080.0, 8077.0, 8076.0, 8076.0, 8070.0, 8071.0, 8070.0, 8073.0, 8069.0, 8069.0, 8068.0, 8072.0, 8078.0, 8077.0, 8079.0, 8081.0, 8076.0, 8076.0, 8077.0, 8077.0, 8078.0, 8075.0, 8066.0, 8064.0, 8064.0, 8062.0, 8062.0, 8065.0, 8062.0, 8063.0, 8074.0, 8070.0, 8069.0, 8068.0, 8074.0, 8075.0} - high := []float64{8279.0, 8282.0, 8280.0, 8280.0, 8284.0, 8284.0, 8280.0, 8282.0, 8284.0, 8289.0, 8288.0, 8285.0, 8284.0, 8287.0, 8286.0, 8294.0, 8290.0, 8292.0, 8289.0, 8288.0, 8278.0, 8279.0, 8279.0, 8284.0, 8282.0, 8270.0, 8261.0, 8260.0, 8252.0, 8244.0, 8233.0, 8227.0, 8222.0, 8217.0, 8217.0, 8211.0, 8202.0, 8203.0, 8203.0, 8196.0, 8186.0, 8193.0, 8194.0, 8187.0, 8185.0, 8168.0, 8165.0, 8169.0, 8166.0, 8163.0, 8162.0, 8159.0, 8143.0, 8148.0, 8143.0, 8146.0, 8152.0, 8149.0, 8152.0, 8147.0, 8138.0, 8128.0, 8134.0, 8131.0, 8133.0, 8123.0, 8106.0, 8105.0, 8104.0, 8113.0, 8112.0, 8112.0, 8111.0, 8114.0, 8115.0, 8114.0, 8110.0, 8101.0, 8107.0, 8103.0, 8100.0, 8101.0, 8100.0, 8102.0, 8101.0, 8100.0, 8070.0, 8076.0, 8072.0, 8072.0, 8069.0, 8050.0, 8048.0, 8044.0, 8049.0, 8055.0, 8063.0, 8070.0, 8067.0, 8061.0, 8059.0, 8060.0, 8063.0, 8058.0, 8061.0, 8061.0, 8068.0, 8066.0, 8071.0, 8073.0, 8068.0, 8066.0, 8066.0, 8065.0, 8070.0, 8072.0, 8072.0, 8075.0, 8078.0, 8084.0, 8085.0, 8084.0, 8077.0, 8076.0, 8075.0, 8079.0, 8081.0, 8083.0, 8088.0, 8086.0, 8088.0, 8088.0, 8092.0, 8086.0, 8086.0, 8083.0, 8075.0, 8074.0, 8073.0, 8073.0, 8077.0, 8077.0, 8078.0, 8077.0, 8076.0, 8073.0, 8075.0, 8079.0, 8079.0, 8078.0, 8074.0, 8080.0, 8086.0, 8086.0, 8085.0, 8085.0, 8087.0, 8102.0, 8109.0, 8113.0, 8114.0, 8110.0, 8105.0, 8106.0, 8109.0, 8114.0, 8107.0, 8106.0, 8106.0, 8110.0, 8111.0, 8110.0, 8112.0, 8112.0, 8109.0, 8102.0, 8098.0, 8099.0, 8098.0, 8097.0, 8099.0, 8099.0, 8099.0, 8102.0, 8099.0, 8099.0, 8096.0, 8097.0, 8091.0, 8094.0, 8094.0, 8096.0, 8102.0, 8106.0, 8109.0, 8109.0, 8110.0, 8108.0, 8106.0, 8110.0, 8122.0, 8105.0, 8105.0, 8104.0, 8103.0, 8104.0, 8103.0, 8110.0, 8110.0, 8107.0, 8109.0, 8105.0, 8097.0, 8095.0, 8093.0, 8094.0, 8097.0, 8096.0, 8096.0, 8096.0, 8097.0, 8092.0, 8090.0, 8081.0, 8081.0, 8083.0, 8087.0, 8085.0, 8085.0, 8087.0, 8092.0, 8094.0, 8090.0, 8093.0, 8092.0, 8094.0, 8093.0, 8091.0, 8095.0, 8095.0, 8092.0, 8089.0, 8090.0, 8090.0, 8091.0, 8088.0, 8089.0, 8089.0, 8085.0, 8081.0, 8080.0, 8078.0, 8078.0, 8076.0, 8073.0, 8077.0, 8078.0, 8077.0, 8077.0, 8083.0, 8082.0, 8082.0, 8077.0, 8079.0, 8082.0, 8080.0, 8077.0, 8078.0, 8076.0, 8073.0, 8074.0, 8073.0, 8073.0, 8070.0, 8070.0, 8072.0, 8079.0, 8078.0, 8079.0, 8081.0, 8083.0, 8077.0, 8078.0, 8080.0, 8079.0, 8080.0, 8077.0, 8069.0, 8071.0, 8066.0, 8064.0, 8066.0, 8066.0, 8063.0, 8074.0, 8075.0, 8071.0, 8070.0, 8075.0, 8075.0} - low := []float64{8260.0, 8272.0, 8275.0, 8274.0, 8275.0, 8277.0, 8276.0, 8278.0, 8277.0, 8283.0, 8282.0, 8283.0, 8283.0, 8283.0, 8283.0, 8279.0, 8281.0, 8282.0, 8277.0, 8276.0, 8273.0, 8275.0, 8274.0, 8275.0, 8266.0, 8256.0, 8255.0, 8250.0, 8239.0, 8230.0, 8214.0, 8218.0, 8216.0, 8208.0, 8209.0, 8201.0, 8190.0, 8195.0, 8193.0, 8181.0, 8175.0, 8183.0, 8182.0, 8181.0, 8159.0, 8152.0, 8150.0, 8160.0, 8161.0, 8153.0, 8153.0, 8137.0, 8135.0, 8139.0, 8130.0, 8130.0, 8140.0, 8137.0, 8145.0, 8134.0, 8123.0, 8116.0, 8122.0, 8124.0, 8122.0, 8105.0, 8096.0, 8096.0, 8097.0, 8100.0, 8100.0, 8104.0, 8101.0, 8103.0, 8109.0, 8108.0, 8089.0, 8092.0, 8097.0, 8098.0, 8094.0, 8092.0, 8087.0, 8094.0, 8094.0, 8069.0, 8058.0, 8065.0, 8066.0, 8065.0, 8046.0, 8041.0, 8036.0, 8038.0, 8039.0, 8047.0, 8053.0, 8058.0, 8056.0, 8056.0, 8053.0, 8052.0, 8054.0, 8051.0, 8053.0, 8056.0, 8055.0, 8063.0, 8064.0, 8063.0, 8062.0, 8061.0, 8059.0, 8059.0, 8063.0, 8066.0, 8067.0, 8068.0, 8071.0, 8071.0, 8079.0, 8074.0, 8073.0, 8074.0, 8073.0, 8073.0, 8076.0, 8079.0, 8080.0, 8083.0, 8083.0, 8085.0, 8082.0, 8082.0, 8081.0, 8072.0, 8072.0, 8068.0, 8070.0, 8070.0, 8072.0, 8074.0, 8075.0, 8073.0, 8071.0, 8070.0, 8067.0, 8074.0, 8076.0, 8072.0, 8070.0, 8072.0, 8079.0, 8081.0, 8082.0, 8082.0, 8084.0, 8083.0, 8097.0, 8103.0, 8107.0, 8104.0, 8103.0, 8104.0, 8103.0, 8105.0, 8103.0, 8102.0, 8102.0, 8103.0, 8106.0, 8107.0, 8108.0, 8102.0, 8098.0, 8096.0, 8095.0, 8096.0, 8093.0, 8094.0, 8094.0, 8096.0, 8097.0, 8097.0, 8096.0, 8094.0, 8094.0, 8086.0, 8086.0, 8087.0, 8090.0, 8091.0, 8095.0, 8099.0, 8104.0, 8102.0, 8106.0, 8101.0, 8103.0, 8104.0, 8104.0, 8101.0, 8102.0, 8096.0, 8096.0, 8098.0, 8100.0, 8102.0, 8106.0, 8103.0, 8103.0, 8094.0, 8090.0, 8090.0, 8089.0, 8088.0, 8090.0, 8093.0, 8094.0, 8094.0, 8088.0, 8087.0, 8079.0, 8075.0, 8076.0, 8077.0, 8081.0, 8083.0, 8083.0, 8084.0, 8087.0, 8089.0, 8088.0, 8088.0, 8086.0, 8087.0, 8090.0, 8088.0, 8090.0, 8091.0, 8087.0, 8087.0, 8086.0, 8088.0, 8087.0, 8082.0, 8083.0, 8083.0, 8078.0, 8077.0, 8077.0, 8072.0, 8074.0, 8071.0, 8070.0, 8072.0, 8073.0, 8073.0, 8072.0, 8076.0, 8079.0, 8075.0, 8075.0, 8075.0, 8076.0, 8076.0, 8074.0, 8076.0, 8069.0, 8068.0, 8069.0, 8069.0, 8065.0, 8067.0, 8067.0, 8067.0, 8073.0, 8075.0, 8076.0, 8077.0, 8075.0, 8072.0, 8074.0, 8075.0, 8074.0, 8072.0, 8066.0, 8063.0, 8062.0, 8058.0, 8060.0, 8059.0, 8060.0, 8059.0, 8062.0, 8067.0, 8068.0, 8067.0, 8068.0, 8071.0} - close := []float64{8262.0, 8273.0, 8279.0, 8279.0, 8275.0, 8282.0, 8278.0, 8279.0, 8281.0, 8285.0, 8287.0, 8284.0, 8283.0, 8283.0, 8285.0, 8286.0, 8287.0, 8290.0, 8283.0, 8287.0, 8278.0, 8275.0, 8276.0, 8275.0, 8281.0, 8270.0, 8257.0, 8258.0, 8252.0, 8243.0, 8231.0, 8219.0, 8220.0, 8216.0, 8210.0, 8211.0, 8201.0, 8197.0, 8201.0, 8193.0, 8183.0, 8184.0, 8191.0, 8184.0, 8185.0, 8161.0, 8154.0, 8163.0, 8164.0, 8162.0, 8156.0, 8158.0, 8141.0, 8139.0, 8142.0, 8130.0, 8145.0, 8140.0, 8149.0, 8146.0, 8136.0, 8123.0, 8126.0, 8130.0, 8125.0, 8122.0, 8106.0, 8096.0, 8103.0, 8102.0, 8111.0, 8105.0, 8111.0, 8103.0, 8112.0, 8113.0, 8109.0, 8093.0, 8101.0, 8101.0, 8100.0, 8095.0, 8096.0, 8095.0, 8100.0, 8095.0, 8069.0, 8068.0, 8072.0, 8068.0, 8067.0, 8046.0, 8045.0, 8043.0, 8040.0, 8049.0, 8055.0, 8062.0, 8062.0, 8058.0, 8056.0, 8055.0, 8058.0, 8057.0, 8054.0, 8056.0, 8057.0, 8066.0, 8065.0, 8069.0, 8064.0, 8063.0, 8064.0, 8059.0, 8065.0, 8069.0, 8068.0, 8069.0, 8072.0, 8074.0, 8084.0, 8084.0, 8076.0, 8074.0, 8074.0, 8075.0, 8077.0, 8080.0, 8082.0, 8086.0, 8084.0, 8087.0, 8087.0, 8083.0, 8083.0, 8082.0, 8074.0, 8073.0, 8072.0, 8071.0, 8072.0, 8075.0, 8076.0, 8076.0, 8074.0, 8071.0, 8071.0, 8075.0, 8079.0, 8077.0, 8074.0, 8072.0, 8079.0, 8084.0, 8082.0, 8085.0, 8086.0, 8084.0, 8102.0, 8107.0, 8113.0, 8109.0, 8104.0, 8104.0, 8105.0, 8108.0, 8106.0, 8104.0, 8106.0, 8105.0, 8110.0, 8107.0, 8109.0, 8112.0, 8104.0, 8099.0, 8097.0, 8097.0, 8098.0, 8095.0, 8096.0, 8097.0, 8099.0, 8098.0, 8099.0, 8099.0, 8095.0, 8097.0, 8086.0, 8088.0, 8093.0, 8092.0, 8096.0, 8101.0, 8105.0, 8105.0, 8109.0, 8107.0, 8103.0, 8104.0, 8109.0, 8105.0, 8102.0, 8104.0, 8097.0, 8100.0, 8103.0, 8103.0, 8109.0, 8107.0, 8106.0, 8104.0, 8096.0, 8090.0, 8092.0, 8089.0, 8093.0, 8093.0, 8094.0, 8095.0, 8096.0, 8088.0, 8089.0, 8079.0, 8077.0, 8079.0, 8082.0, 8083.0, 8084.0, 8084.0, 8087.0, 8091.0, 8088.0, 8088.0, 8091.0, 8087.0, 8092.0, 8090.0, 8091.0, 8095.0, 8092.0, 8088.0, 8087.0, 8090.0, 8089.0, 8087.0, 8084.0, 8088.0, 8084.0, 8079.0, 8078.0, 8078.0, 8076.0, 8075.0, 8071.0, 8072.0, 8074.0, 8077.0, 8074.0, 8077.0, 8081.0, 8080.0, 8076.0, 8076.0, 8078.0, 8079.0, 8076.0, 8076.0, 8076.0, 8070.0, 8072.0, 8069.0, 8072.0, 8070.0, 8069.0, 8069.0, 8073.0, 8078.0, 8077.0, 8079.0, 8080.0, 8076.0, 8076.0, 8076.0, 8077.0, 8078.0, 8075.0, 8067.0, 8064.0, 8064.0, 8062.0, 8062.0, 8065.0, 8062.0, 8063.0, 8074.0, 8070.0, 8069.0, 8068.0, 8074.0} + open := []byte(`[8273.0, 8280.0, 8280.0, 8275.0, 8281.0, 8277.0, 8279.0, 8280.0, 8284.0, 8286.0, 8283.0, 8283.0, 8284.0, 8286.0, 8285.0, 8287.0, 8289.0, 8282.0, 8286.0, 8279.0, 8275.0, 8276.0, 8276.0, 8281.0, 8269.0, 8256.0, 8258.0, 8252.0, 8241.0, 8232.0, 8218.0, 8221.0, 8216.0, 8210.0, 8212.0, 8201.0, 8197.0, 8200.0, 8193.0, 8181.0, 8185.0, 8190.0, 8184.0, 8185.0, 8163.0, 8153.0, 8162.0, 8165.0, 8162.0, 8157.0, 8159.0, 8141.0, 8140.0, 8141.0, 8130.0, 8144.0, 8141.0, 8148.0, 8145.0, 8134.0, 8123.0, 8127.0, 8130.0, 8125.0, 8122.0, 8105.0, 8096.0, 8103.0, 8102.0, 8110.0, 8104.0, 8109.0, 8103.0, 8111.0, 8112.0, 8109.0, 8092.0, 8100.0, 8101.0, 8100.0, 8096.0, 8095.0, 8094.0, 8101.0, 8095.0, 8069.0, 8067.0, 8070.0, 8069.0, 8066.0, 8047.0, 8046.0, 8042.0, 8039.0, 8049.0, 8055.0, 8063.0, 8061.0, 8056.0, 8057.0, 8056.0, 8057.0, 8057.0, 8054.0, 8056.0, 8056.0, 8065.0, 8065.0, 8070.0, 8065.0, 8064.0, 8063.0, 8060.0, 8065.0, 8068.0, 8068.0, 8069.0, 8073.0, 8073.0, 8084.0, 8084.0, 8076.0, 8074.0, 8074.0, 8074.0, 8078.0, 8080.0, 8082.0, 8085.0, 8083.0, 8087.0, 8087.0, 8083.0, 8083.0, 8082.0, 8074.0, 8074.0, 8071.0, 8071.0, 8072.0, 8075.0, 8075.0, 8076.0, 8073.0, 8071.0, 8070.0, 8075.0, 8078.0, 8077.0, 8075.0, 8073.0, 8079.0, 8084.0, 8082.0, 8085.0, 8085.0, 8085.0, 8101.0, 8106.0, 8113.0, 8109.0, 8104.0, 8105.0, 8105.0, 8107.0, 8106.0, 8104.0, 8106.0, 8106.0, 8110.0, 8107.0, 8110.0, 8111.0, 8104.0, 8098.0, 8098.0, 8098.0, 8098.0, 8094.0, 8097.0, 8096.0, 8099.0, 8098.0, 8099.0, 8098.0, 8095.0, 8096.0, 8086.0, 8088.0, 8093.0, 8092.0, 8096.0, 8100.0, 8104.0, 8104.0, 8108.0, 8107.0, 8103.0, 8104.0, 8110.0, 8105.0, 8102.0, 8104.0, 8096.0, 8099.0, 8103.0, 8102.0, 8108.0, 8107.0, 8107.0, 8104.0, 8095.0, 8091.0, 8092.0, 8090.0, 8093.0, 8093.0, 8094.0, 8095.0, 8096.0, 8088.0, 8090.0, 8079.0, 8077.0, 8079.0, 8081.0, 8083.0, 8084.0, 8084.0, 8087.0, 8091.0, 8089.0, 8089.0, 8091.0, 8087.0, 8093.0, 8090.0, 8090.0, 8095.0, 8093.0, 8088.0, 8087.0, 8090.0, 8089.0, 8087.0, 8084.0, 8087.0, 8084.0, 8080.0, 8078.0, 8077.0, 8077.0, 8076.0, 8072.0, 8072.0, 8075.0, 8076.0, 8074.0, 8077.0, 8081.0, 8080.0, 8076.0, 8075.0, 8077.0, 8080.0, 8077.0, 8076.0, 8076.0, 8070.0, 8071.0, 8070.0, 8073.0, 8069.0, 8069.0, 8068.0, 8072.0, 8078.0, 8077.0, 8079.0, 8081.0, 8076.0, 8076.0, 8077.0, 8077.0, 8078.0, 8075.0, 8066.0, 8064.0, 8064.0, 8062.0, 8062.0, 8065.0, 8062.0, 8063.0, 8074.0, 8070.0, 8069.0, 8068.0, 8074.0, 8075.0]`) + high := []byte(`[8279.0, 8282.0, 8280.0, 8280.0, 8284.0, 8284.0, 8280.0, 8282.0, 8284.0, 8289.0, 8288.0, 8285.0, 8284.0, 8287.0, 8286.0, 8294.0, 8290.0, 8292.0, 8289.0, 8288.0, 8278.0, 8279.0, 8279.0, 8284.0, 8282.0, 8270.0, 8261.0, 8260.0, 8252.0, 8244.0, 8233.0, 8227.0, 8222.0, 8217.0, 8217.0, 8211.0, 8202.0, 8203.0, 8203.0, 8196.0, 8186.0, 8193.0, 8194.0, 8187.0, 8185.0, 8168.0, 8165.0, 8169.0, 8166.0, 8163.0, 8162.0, 8159.0, 8143.0, 8148.0, 8143.0, 8146.0, 8152.0, 8149.0, 8152.0, 8147.0, 8138.0, 8128.0, 8134.0, 8131.0, 8133.0, 8123.0, 8106.0, 8105.0, 8104.0, 8113.0, 8112.0, 8112.0, 8111.0, 8114.0, 8115.0, 8114.0, 8110.0, 8101.0, 8107.0, 8103.0, 8100.0, 8101.0, 8100.0, 8102.0, 8101.0, 8100.0, 8070.0, 8076.0, 8072.0, 8072.0, 8069.0, 8050.0, 8048.0, 8044.0, 8049.0, 8055.0, 8063.0, 8070.0, 8067.0, 8061.0, 8059.0, 8060.0, 8063.0, 8058.0, 8061.0, 8061.0, 8068.0, 8066.0, 8071.0, 8073.0, 8068.0, 8066.0, 8066.0, 8065.0, 8070.0, 8072.0, 8072.0, 8075.0, 8078.0, 8084.0, 8085.0, 8084.0, 8077.0, 8076.0, 8075.0, 8079.0, 8081.0, 8083.0, 8088.0, 8086.0, 8088.0, 8088.0, 8092.0, 8086.0, 8086.0, 8083.0, 8075.0, 8074.0, 8073.0, 8073.0, 8077.0, 8077.0, 8078.0, 8077.0, 8076.0, 8073.0, 8075.0, 8079.0, 8079.0, 8078.0, 8074.0, 8080.0, 8086.0, 8086.0, 8085.0, 8085.0, 8087.0, 8102.0, 8109.0, 8113.0, 8114.0, 8110.0, 8105.0, 8106.0, 8109.0, 8114.0, 8107.0, 8106.0, 8106.0, 8110.0, 8111.0, 8110.0, 8112.0, 8112.0, 8109.0, 8102.0, 8098.0, 8099.0, 8098.0, 8097.0, 8099.0, 8099.0, 8099.0, 8102.0, 8099.0, 8099.0, 8096.0, 8097.0, 8091.0, 8094.0, 8094.0, 8096.0, 8102.0, 8106.0, 8109.0, 8109.0, 8110.0, 8108.0, 8106.0, 8110.0, 8122.0, 8105.0, 8105.0, 8104.0, 8103.0, 8104.0, 8103.0, 8110.0, 8110.0, 8107.0, 8109.0, 8105.0, 8097.0, 8095.0, 8093.0, 8094.0, 8097.0, 8096.0, 8096.0, 8096.0, 8097.0, 8092.0, 8090.0, 8081.0, 8081.0, 8083.0, 8087.0, 8085.0, 8085.0, 8087.0, 8092.0, 8094.0, 8090.0, 8093.0, 8092.0, 8094.0, 8093.0, 8091.0, 8095.0, 8095.0, 8092.0, 8089.0, 8090.0, 8090.0, 8091.0, 8088.0, 8089.0, 8089.0, 8085.0, 8081.0, 8080.0, 8078.0, 8078.0, 8076.0, 8073.0, 8077.0, 8078.0, 8077.0, 8077.0, 8083.0, 8082.0, 8082.0, 8077.0, 8079.0, 8082.0, 8080.0, 8077.0, 8078.0, 8076.0, 8073.0, 8074.0, 8073.0, 8073.0, 8070.0, 8070.0, 8072.0, 8079.0, 8078.0, 8079.0, 8081.0, 8083.0, 8077.0, 8078.0, 8080.0, 8079.0, 8080.0, 8077.0, 8069.0, 8071.0, 8066.0, 8064.0, 8066.0, 8066.0, 8063.0, 8074.0, 8075.0, 8071.0, 8070.0, 8075.0, 8075.0]`) + low := []byte(`[8260.0, 8272.0, 8275.0, 8274.0, 8275.0, 8277.0, 8276.0, 8278.0, 8277.0, 8283.0, 8282.0, 8283.0, 8283.0, 8283.0, 8283.0, 8279.0, 8281.0, 8282.0, 8277.0, 8276.0, 8273.0, 8275.0, 8274.0, 8275.0, 8266.0, 8256.0, 8255.0, 8250.0, 8239.0, 8230.0, 8214.0, 8218.0, 8216.0, 8208.0, 8209.0, 8201.0, 8190.0, 8195.0, 8193.0, 8181.0, 8175.0, 8183.0, 8182.0, 8181.0, 8159.0, 8152.0, 8150.0, 8160.0, 8161.0, 8153.0, 8153.0, 8137.0, 8135.0, 8139.0, 8130.0, 8130.0, 8140.0, 8137.0, 8145.0, 8134.0, 8123.0, 8116.0, 8122.0, 8124.0, 8122.0, 8105.0, 8096.0, 8096.0, 8097.0, 8100.0, 8100.0, 8104.0, 8101.0, 8103.0, 8109.0, 8108.0, 8089.0, 8092.0, 8097.0, 8098.0, 8094.0, 8092.0, 8087.0, 8094.0, 8094.0, 8069.0, 8058.0, 8065.0, 8066.0, 8065.0, 8046.0, 8041.0, 8036.0, 8038.0, 8039.0, 8047.0, 8053.0, 8058.0, 8056.0, 8056.0, 8053.0, 8052.0, 8054.0, 8051.0, 8053.0, 8056.0, 8055.0, 8063.0, 8064.0, 8063.0, 8062.0, 8061.0, 8059.0, 8059.0, 8063.0, 8066.0, 8067.0, 8068.0, 8071.0, 8071.0, 8079.0, 8074.0, 8073.0, 8074.0, 8073.0, 8073.0, 8076.0, 8079.0, 8080.0, 8083.0, 8083.0, 8085.0, 8082.0, 8082.0, 8081.0, 8072.0, 8072.0, 8068.0, 8070.0, 8070.0, 8072.0, 8074.0, 8075.0, 8073.0, 8071.0, 8070.0, 8067.0, 8074.0, 8076.0, 8072.0, 8070.0, 8072.0, 8079.0, 8081.0, 8082.0, 8082.0, 8084.0, 8083.0, 8097.0, 8103.0, 8107.0, 8104.0, 8103.0, 8104.0, 8103.0, 8105.0, 8103.0, 8102.0, 8102.0, 8103.0, 8106.0, 8107.0, 8108.0, 8102.0, 8098.0, 8096.0, 8095.0, 8096.0, 8093.0, 8094.0, 8094.0, 8096.0, 8097.0, 8097.0, 8096.0, 8094.0, 8094.0, 8086.0, 8086.0, 8087.0, 8090.0, 8091.0, 8095.0, 8099.0, 8104.0, 8102.0, 8106.0, 8101.0, 8103.0, 8104.0, 8104.0, 8101.0, 8102.0, 8096.0, 8096.0, 8098.0, 8100.0, 8102.0, 8106.0, 8103.0, 8103.0, 8094.0, 8090.0, 8090.0, 8089.0, 8088.0, 8090.0, 8093.0, 8094.0, 8094.0, 8088.0, 8087.0, 8079.0, 8075.0, 8076.0, 8077.0, 8081.0, 8083.0, 8083.0, 8084.0, 8087.0, 8089.0, 8088.0, 8088.0, 8086.0, 8087.0, 8090.0, 8088.0, 8090.0, 8091.0, 8087.0, 8087.0, 8086.0, 8088.0, 8087.0, 8082.0, 8083.0, 8083.0, 8078.0, 8077.0, 8077.0, 8072.0, 8074.0, 8071.0, 8070.0, 8072.0, 8073.0, 8073.0, 8072.0, 8076.0, 8079.0, 8075.0, 8075.0, 8075.0, 8076.0, 8076.0, 8074.0, 8076.0, 8069.0, 8068.0, 8069.0, 8069.0, 8065.0, 8067.0, 8067.0, 8067.0, 8073.0, 8075.0, 8076.0, 8077.0, 8075.0, 8072.0, 8074.0, 8075.0, 8074.0, 8072.0, 8066.0, 8063.0, 8062.0, 8058.0, 8060.0, 8059.0, 8060.0, 8059.0, 8062.0, 8067.0, 8068.0, 8067.0, 8068.0, 8071.0]`) + close := []byte(`[8262.0, 8273.0, 8279.0, 8279.0, 8275.0, 8282.0, 8278.0, 8279.0, 8281.0, 8285.0, 8287.0, 8284.0, 8283.0, 8283.0, 8285.0, 8286.0, 8287.0, 8290.0, 8283.0, 8287.0, 8278.0, 8275.0, 8276.0, 8275.0, 8281.0, 8270.0, 8257.0, 8258.0, 8252.0, 8243.0, 8231.0, 8219.0, 8220.0, 8216.0, 8210.0, 8211.0, 8201.0, 8197.0, 8201.0, 8193.0, 8183.0, 8184.0, 8191.0, 8184.0, 8185.0, 8161.0, 8154.0, 8163.0, 8164.0, 8162.0, 8156.0, 8158.0, 8141.0, 8139.0, 8142.0, 8130.0, 8145.0, 8140.0, 8149.0, 8146.0, 8136.0, 8123.0, 8126.0, 8130.0, 8125.0, 8122.0, 8106.0, 8096.0, 8103.0, 8102.0, 8111.0, 8105.0, 8111.0, 8103.0, 8112.0, 8113.0, 8109.0, 8093.0, 8101.0, 8101.0, 8100.0, 8095.0, 8096.0, 8095.0, 8100.0, 8095.0, 8069.0, 8068.0, 8072.0, 8068.0, 8067.0, 8046.0, 8045.0, 8043.0, 8040.0, 8049.0, 8055.0, 8062.0, 8062.0, 8058.0, 8056.0, 8055.0, 8058.0, 8057.0, 8054.0, 8056.0, 8057.0, 8066.0, 8065.0, 8069.0, 8064.0, 8063.0, 8064.0, 8059.0, 8065.0, 8069.0, 8068.0, 8069.0, 8072.0, 8074.0, 8084.0, 8084.0, 8076.0, 8074.0, 8074.0, 8075.0, 8077.0, 8080.0, 8082.0, 8086.0, 8084.0, 8087.0, 8087.0, 8083.0, 8083.0, 8082.0, 8074.0, 8073.0, 8072.0, 8071.0, 8072.0, 8075.0, 8076.0, 8076.0, 8074.0, 8071.0, 8071.0, 8075.0, 8079.0, 8077.0, 8074.0, 8072.0, 8079.0, 8084.0, 8082.0, 8085.0, 8086.0, 8084.0, 8102.0, 8107.0, 8113.0, 8109.0, 8104.0, 8104.0, 8105.0, 8108.0, 8106.0, 8104.0, 8106.0, 8105.0, 8110.0, 8107.0, 8109.0, 8112.0, 8104.0, 8099.0, 8097.0, 8097.0, 8098.0, 8095.0, 8096.0, 8097.0, 8099.0, 8098.0, 8099.0, 8099.0, 8095.0, 8097.0, 8086.0, 8088.0, 8093.0, 8092.0, 8096.0, 8101.0, 8105.0, 8105.0, 8109.0, 8107.0, 8103.0, 8104.0, 8109.0, 8105.0, 8102.0, 8104.0, 8097.0, 8100.0, 8103.0, 8103.0, 8109.0, 8107.0, 8106.0, 8104.0, 8096.0, 8090.0, 8092.0, 8089.0, 8093.0, 8093.0, 8094.0, 8095.0, 8096.0, 8088.0, 8089.0, 8079.0, 8077.0, 8079.0, 8082.0, 8083.0, 8084.0, 8084.0, 8087.0, 8091.0, 8088.0, 8088.0, 8091.0, 8087.0, 8092.0, 8090.0, 8091.0, 8095.0, 8092.0, 8088.0, 8087.0, 8090.0, 8089.0, 8087.0, 8084.0, 8088.0, 8084.0, 8079.0, 8078.0, 8078.0, 8076.0, 8075.0, 8071.0, 8072.0, 8074.0, 8077.0, 8074.0, 8077.0, 8081.0, 8080.0, 8076.0, 8076.0, 8078.0, 8079.0, 8076.0, 8076.0, 8076.0, 8070.0, 8072.0, 8069.0, 8072.0, 8070.0, 8069.0, 8069.0, 8073.0, 8078.0, 8077.0, 8079.0, 8080.0, 8076.0, 8076.0, 8076.0, 8077.0, 8078.0, 8075.0, 8067.0, 8064.0, 8064.0, 8062.0, 8062.0, 8065.0, 8062.0, 8063.0, 8074.0, 8070.0, 8069.0, 8068.0, 8074.0]`) - buildKLines := func(open, high, low, close []float64) (kLines []types.KLine) { + buildKLines := func(open, high, low, close []fixedpoint.Value) (kLines []types.KLine) { for i := range high { kLines = append(kLines, types.KLine{Open: open[i], High: high[i], Low: low[i], Close: close[i], EndTime: types.Time(time.Now())}) } return kLines } + var o, h, l, c []fixedpoint.Value + _ = json.Unmarshal(open, &o) + _ = json.Unmarshal(high, &h) + _ = json.Unmarshal(low, &l) + _ = json.Unmarshal(close, &c) tests := []struct { name string @@ -39,7 +46,7 @@ func TestSTOCH_update(t *testing.T) { }{ { name: "TXF1-1min_2016/1/4", - kLines: buildKLines(open, high, low, close), + kLines: buildKLines(o, h, l, c), window: 14, want_k: 84.210526, want_d: 59.888357, diff --git a/pkg/indicator/vwap_test.go b/pkg/indicator/vwap_test.go index f3be41d40..b56ecb2b9 100644 --- a/pkg/indicator/vwap_test.go +++ b/pkg/indicator/vwap_test.go @@ -3,15 +3,25 @@ package indicator import ( "math" "testing" + "encoding/json" "github.com/c9s/bbgo/pkg/types" + "github.com/c9s/bbgo/pkg/fixedpoint" ) - -var randomPrices = []float64{0.6046702879796195, 0.9405190880450124, 0.6645700532184904, 0.4377241871869802, 0.4246474970712657, 0.6868330728671094, 0.06564701921747622, 0.15652925473279125, 0.09697951891448456, 0.3009218605852871} -var randomVolumes = []float64{0.5152226285020653, 0.8136499609900968, 0.21427387258237493, 0.380667189299686, 0.31806817433032986, 0.4688998449024232, 0.2830441511804452, 0.2931118573368158, 0.6790946759202162, 0.2185630525927643} +var trivialPrices = []byte(`[0]`) +var trivialVolumes = []byte(`[1]`) +var easyPrices = []byte(`[1, 2, 3]`) +var easyVolumes = []byte(`[4, 5, 6]`) +var windowPrices = []byte(`[1, 2, 3, 4]`) +var windowVolumes = []byte(`[4, 5, 6, 7]`) +var randomPrices = []byte(`[0.6046702879796195, 0.9405190880450124, 0.6645700532184904, 0.4377241871869802, 0.4246474970712657, 0.6868330728671094, 0.06564701921747622, 0.15652925473279125, 0.09697951891448456, 0.3009218605852871]`) +var randomVolumes = []byte(`[0.5152226285020653, 0.8136499609900968, 0.21427387258237493, 0.380667189299686, 0.31806817433032986, 0.4688998449024232, 0.2830441511804452, 0.2931118573368158, 0.6790946759202162, 0.2185630525927643]`) func Test_calculateVWAP(t *testing.T) { - buildKLines := func(prices, volumes []float64) (kLines []types.KLine) { + buildKLines := func(pb, vb []byte) (kLines []types.KLine) { + var prices, volumes []fixedpoint.Value + _ = json.Unmarshal(pb, &prices) + _ = json.Unmarshal(vb, &volumes) for i, p := range prices { kLines = append(kLines, types.KLine{High: p, Low: p, Close: p, Volume: volumes[i]}) } @@ -26,19 +36,19 @@ func Test_calculateVWAP(t *testing.T) { }{ { name: "trivial_case", - kLines: buildKLines([]float64{0}, []float64{1}), + kLines: buildKLines(trivialPrices, trivialVolumes), window: 0, want: 0.0, }, { name: "easy_case", - kLines: buildKLines([]float64{1, 2, 3}, []float64{4, 5, 6}), + kLines: buildKLines(easyPrices, easyVolumes), window: 0, want: (1*4 + 2*5 + 3*6) / float64(4+5+6), }, { name: "window_case", - kLines: buildKLines([]float64{1, 2, 3, 4}, []float64{4, 5, 6, 7}), + kLines: buildKLines(windowPrices, windowVolumes), window: 3, want: (2*5 + 3*6 + 4*7) / float64(5+6+7), },