fixed matcher

This commit is contained in:
Michael Hegel 2022-11-20 09:48:48 +01:00
parent 0bcc168c41
commit e079a0785a
9 changed files with 62 additions and 25 deletions

View File

@ -42,7 +42,7 @@ var (
startMoney float64 = 1000.0
roundDuration time.Duration = 10 * time.Minute
matcherUpdateInterval time.Duration = time.Millisecond * 2000
matcherUpdateInterval time.Duration = time.Second
)
type ServiceHandler struct {
@ -222,6 +222,7 @@ func main() {
)
defer match.Close()
go match.Start()
// create some bots so the market has some actual movement
bots := make([]bot.Bot, 0, 40)

View File

@ -68,8 +68,11 @@ func (m *Matcher) Start() {
m.l.Info("shutting down")
return
case <-ticker.C:
//m.l.Info("running matcher")
allMatches := m.matchStonks()
if len(allMatches) > 0 {
m.l.Info("matcher found new matches")
// NOTE: blocking, but the channel is buffered
m.matchUpdateCh <- allMatches
}
@ -78,11 +81,18 @@ func (m *Matcher) Start() {
}
func (m *Matcher) matchStonks() []*store.Match {
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
var allMatches []*store.Match
for _, stonk := range m.stonks {
// Run the matching process
orders, _ := m.orderP.GetOrders(m.ctx, stonk, nil)
orders, err := m.orderP.GetOrders(ctx, stonk, nil)
if err != nil {
m.l.Error("matcher run failed")
return nil
}
// sort in ascending order w.r.t. time
sort.Slice(orders, func(i, j int) bool {
return orders[i].Time.Before(orders[j].Time)
@ -96,25 +106,41 @@ func (m *Matcher) matchStonks() []*store.Match {
buyOrders = append(buyOrders, o)
}
}
m.l.Debug("got order",
zap.Int("len", len(orders)),
zap.Int("buy_len", len(buyOrders)),
zap.Int("sell_len", len(sellOrders)),
)
// sort sell price low-high
sort.Slice(sellOrders, func(i, j int) bool {
return orders[i].Price < orders[j].Price
})
// sort buy price high-low
sort.Slice(buyOrders, func(i, j int) bool {
return orders[i].Price > orders[j].Price
})
m.l.Debug("11", zap.Int("len_matches", len(allMatches)))
for _, sellOrder := range sellOrders {
if len(buyOrders) == 0 || sellOrder.Price > buyOrders[0].Price {
// no possible match
break
}
qty := sellOrder.Quantity
// sort buy price high-low
sort.Slice(buyOrders, func(i, j int) bool {
return orders[i].Price > orders[j].Price
})
m.l.Debug("23", zap.Int("len_matches", len(allMatches)))
// if len(buyOrders) == 0 || sellOrder.Price > buyOrders[0].Price {
// // no possible match
// m.l.Info("skipping further checks")
// break
// }
m.l.Debug("42", zap.Int("len_matches", len(allMatches)))
qty := sellOrder.Quantity
newBuyOrders := make([]*store.Order, 0, len(buyOrders))
m.l.Debug("69", zap.Int("len_matches", len(allMatches)))
for _, buyOrder := range buyOrders {
m.l.Debug("180", zap.Int("len_matches", len(allMatches)))
match := &store.Match{
Id: uuid.New().String(),
Stonk: sellOrder.Stonk,
@ -124,6 +150,8 @@ func (m *Matcher) matchStonks() []*store.Match {
Quantity: min(qty, buyOrder.Quantity),
}
allMatches = append(allMatches, match)
m.l.Debug("added new match", zap.Int("len_matches", len(allMatches)))
m.matchP.AddMatch(m.ctx, match)
qty -= buyOrder.Quantity
@ -172,5 +200,7 @@ func (m *Matcher) matchStonks() []*store.Match {
}
}
m.l.Debug("finished matchin", zap.Int("len_matches", len(allMatches)))
return allMatches
}

View File

@ -315,13 +315,16 @@ func (s *StonksService) GetStonkInfo(w http.ResponseWriter, r *http.Request, sto
// update the prices before we retrieve them
updated := s.update()
if updated {
state := State{
Start: nil,
Reload: true,
Finish: nil,
}
go func() {
time.Sleep(time.Millisecond * 500)
state := State{
Start: nil,
Reload: true,
Finish: nil,
}
s.sseCh <- state
s.sseCh <- state
}()
}
ts, ok := s.prices[stonk]

View File

@ -3,7 +3,6 @@ package stonks
type StonkName string
const (
stonkEmpty StonkName = "" // INVALID!
StonkPaperClip StonkName = "paperClip"
StonkScissors StonkName = "scissors"
StonkPencil StonkName = "pencil"

View File

@ -11,6 +11,8 @@ import (
)
func (s *StonksService) update() bool {
s.l.Debug("initiating update")
defer s.l.Debug("finished update")
// drain the updates chanel until it is empty
updated := false
for {
@ -29,17 +31,18 @@ func (s *StonksService) update() bool {
Time: time,
Value: value,
})
s.l.Warn("newest timestamp", zap.Int("ts", time))
}
// Add a new entry to the users NetWorthTimeSeries-DataPoints
for userId, user := range s.activeUsers {
user.mu.Lock()
//user.mu.Lock()
user.NetWorthTimeSeries = append(user.NetWorthTimeSeries, DataPoint{
Time: user.NetWorthTimeSeries.LatestTime() + 1,
Value: user.NetWorthTimeSeries.LatestValue(),
})
s.activeUsers[userId] = user
user.mu.Unlock()
//user.mu.Unlock()
}
// update the value to the actual new on if there is a match for this stock
@ -51,7 +54,7 @@ func (s *StonksService) update() bool {
// update the users stock position
for userId, user := range s.activeUsers {
user.mu.Lock()
//user.mu.Lock()
if userId == match.BuyOrder.User.ID { // if buyer
user.Stonks[stonkName] += match.Quantity
user.ReservedStonks[stonkName] -= match.Quantity
@ -61,7 +64,7 @@ func (s *StonksService) update() bool {
user.Stonks[stonkName] -= match.Quantity
user.Money += float64(match.Quantity) * match.SellOrder.Price
} else {
user.mu.Unlock()
//user.mu.Unlock()
continue
}
@ -75,7 +78,7 @@ func (s *StonksService) update() bool {
user.NetWorthTimeSeries[len(user.NetWorthTimeSeries)-1].Value = user.NetWorth
s.activeUsers[userId] = user
user.mu.Unlock()
//user.mu.Unlock()
}
}

View File

@ -39,11 +39,13 @@ func (p *MemoryMatchPersistor) GetMatches(ctx context.Context, stonk string) ([]
filter := bson.D{}
if stonk != "" {
filter = append(filter, bson.E{Key: "stonk", Value: string(stonk)})
} else {
filter = append(filter, bson.E{})
}
cur, err := p.col.Find(ctx, filter)
if errors.Is(err, mongo.ErrNoDocuments) {
return []*Match{}, nil
return nil, mongo.ErrNoDocuments
} else if err != nil {
p.l.Error("Unable to find matches", zap.Error(err))
}

View File

@ -183,7 +183,7 @@ export const vanillaStore = vanillaCreate<StonksState & StonksModifiers>(
}
// filter out empty infos
resp = resp.filter((r) => r.ret.Name !== "");
//resp = resp.filter((r) => r.ret.Name !== "");
set({
stonkInfos: resp.map((resp) => {

View File

@ -55,7 +55,6 @@ export enum StonkName {
StonkPaperClip = "paperClip",
StonkPencil = "pencil",
StonkScissors = "scissors",
StonkEmpty = "",
}
// github.com/hackaTUM/GameOfStonks/services/stonks.UpdateOrderCmd
export interface UpdateOrderCmd {

View File

@ -55,7 +55,7 @@ function Search() {
<Card>
<StonkPositionList
stonks={Object.values(StonkName)
.filter((val) => val.valueOf().includes(query) && val !== "")
//.filter((val) => val.valueOf().includes(query) && val !== "")
.reduce((acc, entry) => {
acc[entry] = -1;
return acc;