Skip to content

Commit b83796f

Browse files
author
go-numb
committed
supported string keys and custom sort, like a v2
1 parent ebb0f76 commit b83796f

File tree

10 files changed

+1062
-0
lines changed

10 files changed

+1062
-0
lines changed

v2s/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 _numbP
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

v2s/books.go

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
package obm
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
7+
"github.com/emirpasic/gods/maps/treemap"
8+
"github.com/shopspring/decimal"
9+
)
10+
11+
type Books struct {
12+
isBid bool
13+
cap int
14+
remover Remover
15+
tree *treemap.Map
16+
Books []Book
17+
}
18+
19+
func (p *Books) Len() int {
20+
return len(p.Books)
21+
}
22+
23+
func (p *Books) Less(i, j int) bool {
24+
return p.Books[j].Price.GreaterThan(p.Books[i].Price)
25+
}
26+
27+
func (p *Books) Swap(i, j int) {
28+
p.Books[i], p.Books[j] = p.Books[j], p.Books[i]
29+
}
30+
31+
type Book struct {
32+
Price decimal.Decimal
33+
Size decimal.Decimal
34+
}
35+
36+
func (p *Books) String() string {
37+
c := make([]Book, len(p.Books))
38+
copy(c, p.Books)
39+
40+
s := make([]string, len(c))
41+
for i := range c {
42+
s[i] = fmt.Sprintf("%d - %s:%s", i, c[i].Price.String(), c[i].Size.String())
43+
}
44+
return strings.Join(s, "\n")
45+
}
46+
47+
func (p *Books) Size() int {
48+
return p.tree.Size()
49+
}
50+
51+
// Get depth default:10 with sort
52+
// bids: reverse, asks: sort
53+
func (p *Books) Get(depth int) *Books {
54+
l := p.tree.Size()
55+
56+
if depth < 10 {
57+
depth = 10
58+
}
59+
if depth > l {
60+
depth = l
61+
}
62+
63+
// sorted
64+
keys := p.tree.Keys()
65+
// Convert keys to decimal and sort
66+
decimalKeys := make([]decimal.Decimal, len(keys))
67+
for i, key := range keys {
68+
decimalKeys[i], _ = decimal.NewFromString(key.(string))
69+
}
70+
71+
b := make([]Book, depth)
72+
for i := 0; i < depth; i++ {
73+
keyStr := decimalKeys[i].String()
74+
b[i] = p.getBookValues(keyStr)
75+
}
76+
77+
// sort
78+
p.Books = b
79+
80+
return p
81+
}
82+
83+
func (p *Books) Put(book Book) {
84+
// インプット情報はすべて入力保存
85+
p.tree.Put(book.Price.String(), book.Size.String())
86+
87+
// If map size is the upper limit, delete data from the upper or lower limits.
88+
if p.tree.Size() >= p.cap {
89+
switch p.remover {
90+
case MAX: // asks
91+
maxPrice, _ := p.tree.Max()
92+
p.tree.Remove(maxPrice)
93+
94+
case MIN: // bids
95+
minPrice, _ := p.tree.Min()
96+
p.tree.Remove(minPrice)
97+
98+
}
99+
}
100+
}
101+
102+
func (p *Books) Remove(key any) {
103+
p.tree.Remove(key)
104+
}
105+
106+
func (p *Books) Each(fn func(key, val string)) {
107+
p.tree.Each(func(key, val any) {
108+
fn(key.(string), val.(string))
109+
})
110+
}
111+
112+
func (p *Books) _all() []Book {
113+
var books []Book
114+
115+
keys := p.tree.Keys()
116+
117+
for i := range keys {
118+
books = append(books, p.getBookValues(keys[i]))
119+
}
120+
121+
return books
122+
}
123+
124+
func (p *Books) getBookValues(key any) Book {
125+
val, isFound := p.tree.Get(key)
126+
if !isFound {
127+
return Book{}
128+
}
129+
130+
return Converter(key, val)
131+
}
132+
133+
// Converter is a function that converts the price and size of the book.
134+
func Converter(price, size any) Book {
135+
switch v := price.(type) {
136+
case int:
137+
return converterI(v, size.(int))
138+
case float32:
139+
return converterF32(v, size.(float32))
140+
case float64:
141+
return converterF(v, size.(float64))
142+
case string:
143+
return converterS(v, size.(string))
144+
145+
case decimal.Decimal:
146+
if s, ok := size.(decimal.Decimal); ok {
147+
return Book{
148+
Price: v,
149+
Size: s,
150+
}
151+
}
152+
}
153+
154+
return Book{}
155+
}
156+
157+
func converterI(price, size int) Book {
158+
return Book{
159+
Price: decimal.NewFromInt(int64(price)),
160+
Size: decimal.NewFromInt(int64(size)),
161+
}
162+
}
163+
164+
func converterF32(price, size float32) Book {
165+
return Book{
166+
Price: decimal.NewFromFloat32(price),
167+
Size: decimal.NewFromFloat32(size),
168+
}
169+
}
170+
171+
func converterF(price, size float64) Book {
172+
return Book{
173+
Price: decimal.NewFromFloat(price),
174+
Size: decimal.NewFromFloat(size),
175+
}
176+
}
177+
178+
func converterS(price, size string) Book {
179+
p, err := decimal.NewFromString(price)
180+
if err != nil {
181+
p = decimal.Zero
182+
}
183+
s, err := decimal.NewFromString(size)
184+
if err != nil {
185+
s = decimal.Zero
186+
}
187+
188+
return Book{
189+
Price: p,
190+
Size: s,
191+
}
192+
}

v2s/books_test.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package obm_test
2+
3+
import (
4+
"fmt"
5+
"math/rand"
6+
"sort"
7+
"testing"
8+
"time"
9+
10+
obmv2s "github.com/go-numb/go-obm/v2s"
11+
"github.com/shopspring/decimal"
12+
"github.com/stretchr/testify/assert"
13+
)
14+
15+
func TestSort(t *testing.T) {
16+
now := time.Now()
17+
defer func() {
18+
// exec time: 2.114597 s
19+
fmt.Printf("exec time: %f s\n", time.Since(now).Seconds())
20+
}()
21+
22+
count := 10000
23+
o := obmv2s.New("test").SetCap(count, count)
24+
25+
prices := make([]float64, count)
26+
27+
s := rand.NewSource(time.Now().Unix())
28+
r := rand.New(s)
29+
30+
for i := 0; i < count; i++ {
31+
price, _ := decimal.NewFromString(fmt.Sprintf("%f", r.NormFloat64()*200))
32+
size, _ := decimal.NewFromString(fmt.Sprintf("%f", r.NormFloat64()))
33+
34+
prices = append(prices, price.InexactFloat64())
35+
o.Asks.Put(obmv2s.Book{
36+
Price: price,
37+
Size: size,
38+
})
39+
40+
price, _ = decimal.NewFromString(fmt.Sprintf("%f", r.NormFloat64()*100))
41+
size, _ = decimal.NewFromString(fmt.Sprintf("%f", r.NormFloat64()))
42+
o.Bids.Put(obmv2s.Book{
43+
Price: price,
44+
Size: size,
45+
})
46+
}
47+
48+
assert.Equal(t, count, o.Asks.Size())
49+
50+
for i := 0; i < len(prices); i++ {
51+
fmt.Printf("array: %f\n", prices[i])
52+
}
53+
fmt.Println("")
54+
55+
// depth default 10
56+
books := o.Asks.Get(2)
57+
fmt.Println(books)
58+
assert.Equal(t, 10, len(books.Books))
59+
fmt.Println("")
60+
sort.Sort(sort.Reverse(books))
61+
fmt.Println("reverse sort")
62+
fmt.Println(books)
63+
64+
fmt.Println("sort")
65+
sort.Sort(books)
66+
fmt.Println(books)
67+
}

v2s/go.mod

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module github.com/go-numb/go-obm/v2s
2+
3+
go 1.22
4+
5+
require (
6+
github.com/emirpasic/gods v1.18.1
7+
github.com/shopspring/decimal v1.4.0
8+
github.com/stretchr/testify v1.9.0
9+
)
10+
11+
require (
12+
github.com/davecgh/go-spew v1.1.1 // indirect
13+
github.com/pmezard/go-difflib v1.0.0 // indirect
14+
gopkg.in/yaml.v3 v3.0.1 // indirect
15+
)

v2s/go.sum

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
2+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
4+
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
5+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
6+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
7+
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
8+
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
9+
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
10+
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
11+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
12+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
13+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
14+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

0 commit comments

Comments
 (0)