Skip to content

Commit

Permalink
cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
dylanlott committed May 23, 2023
1 parent 1239361 commit 7c96c30
Show file tree
Hide file tree
Showing 5 changed files with 341 additions and 318 deletions.
2 changes: 1 addition & 1 deletion cmd/golem/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func main() {
out := make(chan *orderbook.Match)
status := make(chan []orderbook.Order)

go orderbook.Run(ctx, in, out, status)
go orderbook.Run(ctx, accts, in, out, status)

engine := server.NewServer(accts, in, out, status)
return engine.Run()
Expand Down
316 changes: 316 additions & 0 deletions pkg/orderbook/attempt_fill.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import (
"context"
"fmt"
"log"
"math/rand"
"sync"
"testing"
"time"

"github.com/dylanlott/orderbook/pkg/accounts"
"github.com/sasha-s/go-deadlock"
Expand Down Expand Up @@ -241,3 +245,315 @@ func greedy(

matchCh <- *match
}

// TESTS

var numOps = 10_000
var bufferSize = 1000

func TestRun(t *testing.T) {
ctx := context.Background()
wg := &sync.WaitGroup{}

accts := &accounts.InMemoryManager{}
writes := make(chan OpWrite, bufferSize)
errs := make(chan error, bufferSize)
fills := make(chan FillResult, bufferSize)

go func() {
for err := range errs {
t.Logf("[error]: %+v", err)
}
}()

go func() {
for fill := range fills {
t.Logf("[fill]: %+v", fill)
}
}()

go Start(ctx, accts, writes, fills, errs)

for i := 0; i < numOps; i++ {
// BUY WRITE
buyWrite := OpWrite{
Order: Order{
ID: fmt.Sprintf("%v", i),
Kind: "limit",
Side: "buy",
Price: uint64(rand.Intn(100)),
Open: 100,
Filled: 0,
Metadata: map[string]string{
"createdAt": fmt.Sprintf("%v", time.Now()),
},
},
Result: make(chan WriteResult),
}
go func() {
<-buyWrite.Result
wg.Done()
}()
wg.Add(1)
writes <- buyWrite

// SELL WRITE
sellWrite := OpWrite{
Order: Order{
ID: fmt.Sprintf("%v", i),
Kind: "limit",
Side: "sell",
Price: uint64(rand.Intn(100)),
Open: 100,
Filled: 0,
Metadata: map[string]string{
"createdAt": fmt.Sprintf("%v", time.Now()),
},
},
Result: make(chan WriteResult),
}
go func() {
<-sellWrite.Result
wg.Done()
}()
wg.Add(1)
writes <- sellWrite
}

wg.Wait()
}

func TestAttemptFill(t *testing.T) {
acc := &accounts.InMemoryManager{
Accounts: map[string]*accounts.UserAccount{
"foo@test.com": {
Email: "foo@test.com",
CurrentBalance: 1000.0,
},
"bar@test.com": {
Email: "bar@test.com",
CurrentBalance: 1000.0,
},
},
}
var fillorder = &Order{
Price: 11,
ID: "foo",
Side: "buy",
Filled: 0,
Open: 10,
AccountID: "foo@test.com",
Kind: "market",
History: make([]Match, 0),
}
var sellorder = &Order{
Price: 9,
ID: "bar",
Side: "sell",
Filled: 0,
Open: 10,
AccountID: "bar@test.com",
Kind: "market",
History: make([]Match, 0),
}
type args struct {
book *Book
acc accounts.AccountManager
fillorder *Order
matches chan Match
errs chan error
}
tests := []struct {
name string
args args
}{
{
name: "should fill exact",
args: args{
book: &Book{
buy: &Node{
Price: 10,
Orders: []*Order{},
Left: &Node{},
Right: &Node{
Price: 11,
Orders: []*Order{
fillorder,
},
Left: &Node{},
Right: &Node{},
},
},
sell: &Node{
Price: 10,
Orders: []*Order{},
Left: &Node{
Price: 9,
Orders: []*Order{
sellorder,
},
},
Right: &Node{},
},
},
acc: acc,
fillorder: fillorder,
matches: make(chan Match, 1000),
errs: make(chan error, 1000),
},
},
{
name: "should fill greedy",
args: args{
book: &Book{
buy: &Node{
Price: 10,
Orders: []*Order{},
Left: &Node{},
Right: &Node{
Price: 11,
Orders: []*Order{
{
Price: 11,
ID: "foo",
Side: "buy",
Filled: 0,
Open: 20,
AccountID: "foo@test.com",
Kind: "market",
History: make([]Match, 0),
},
},
Left: &Node{},
Right: &Node{},
},
},
sell: &Node{
Price: 10,
Orders: []*Order{},
Left: &Node{
Price: 9,
Orders: []*Order{
{
Price: 9,
ID: "bar",
Side: "sell",
Filled: 0,
Open: 10,
AccountID: "bar@test.com",
Kind: "market",
History: make([]Match, 0),
},
{
Price: 9,
ID: "baz",
Side: "sell",
Filled: 0,
Open: 10,
AccountID: "baz@test.com",
Kind: "market",
History: make([]Match, 0),
},
{
Price: 9,
ID: "baz",
Side: "sell",
Filled: 0,
Open: 10,
AccountID: "baz@test.com",
Kind: "market",
History: make([]Match, 0),
},
},
},
Right: &Node{},
},
},
acc: acc,
fillorder: fillorder,
matches: make(chan Match, 1000),
errs: make(chan error, 1000),
},
},
{
name: "should fill humble",
args: args{
book: &Book{
buy: &Node{
Price: 10,
Orders: []*Order{},
Left: &Node{},
Right: &Node{
Price: 11,
Orders: []*Order{
{
Price: 11,
ID: "foo",
Side: "buy",
Filled: 0,
Open: 20,
AccountID: "foo@test.com",
Kind: "market",
History: make([]Match, 0),
},
},
Left: &Node{},
Right: &Node{},
},
},
sell: &Node{
Price: 10,
Orders: []*Order{},
Left: &Node{
Price: 9,
Orders: []*Order{
{
Price: 9,
ID: "bar",
Side: "sell",
Filled: 0,
Open: 10,
AccountID: "bar@test.com",
Kind: "market",
History: make([]Match, 0),
},
{
Price: 9,
ID: "baz",
Side: "sell",
Filled: 0,
Open: 10,
AccountID: "baz@test.com",
Kind: "market",
History: make([]Match, 0),
},
{
Price: 9,
ID: "baz",
Side: "sell",
Filled: 0,
Open: 10,
AccountID: "baz@test.com",
Kind: "market",
History: make([]Match, 0),
},
},
},
Right: &Node{},
},
},
acc: acc,
fillorder: fillorder,
matches: make(chan Match, 1000),
errs: make(chan error, 1000),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
go AttemptFill(tt.args.book, tt.args.acc, fillorder, tt.args.matches, tt.args.errs)
got := <-tt.args.matches
t.Logf("[got]: %+v", got)
})
}
}
6 changes: 3 additions & 3 deletions pkg/orderbook/orderbook.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,15 @@ type Orderbook interface {
}

// Run starts looping the MatchOrders function.
func Run(ctx context.Context, in chan Order, out chan *Match, status chan []Order) {
accts := &accounts.InMemoryManager{}
func Run(ctx context.Context, accounts accounts.AccountManager, in chan Order, out chan *Match, status chan []Order) {
var buy, sell []Order
handleMatches(accts, buy, sell, in, out, status)
handleMatches(ctx, accounts, buy, sell, in, out, status)
}

// handleMatches is a blocking function that handles the matches.
// It's meant to be called and held open while it matches orders.
func handleMatches(
ctx context.Context,
accts accounts.AccountManager,
buy, sell []Order,
in chan Order,
Expand Down

0 comments on commit 7c96c30

Please sign in to comment.