Skip to content

Commit

Permalink
app: Improve market making logs UI
Browse files Browse the repository at this point in the history
Makes the UI look more similar to other pages, and also adds filtering and
pagination.
  • Loading branch information
martonp committed Jul 9, 2024
1 parent 14ad16b commit 14b765c
Show file tree
Hide file tree
Showing 14 changed files with 551 additions and 244 deletions.
8 changes: 6 additions & 2 deletions client/mm/event_log.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ type eventLogDB interface {
// all of the events will be returned. If refID is not nil, the events
// including and after the event with the ID will be returned. If
// pendingOnly is true, only pending events will be returned.
runEvents(startTime int64, mkt *MarketWithHost, n uint64, refID *uint64, pendingOnly bool) ([]*MarketMakingEvent, error)
runEvents(startTime int64, mkt *MarketWithHost, n uint64, refID *uint64, pendingOnly bool, filters *RunLogFilters) ([]*MarketMakingEvent, error)
}

// eventUpdate is used to asynchronously add events to the event log.
Expand Down Expand Up @@ -623,7 +623,7 @@ func decodeMarketMakingEvent(eventB []byte) (*MarketMakingEvent, error) {
// events will be returned. If refID is not nil, the events including and after the
// event with the ID will be returned. If pendingOnly is true, only pending events
// will be returned.
func (db *boltEventLogDB) runEvents(startTime int64, mkt *MarketWithHost, n uint64, refID *uint64, pendingOnly bool) ([]*MarketMakingEvent, error) {
func (db *boltEventLogDB) runEvents(startTime int64, mkt *MarketWithHost, n uint64, refID *uint64, pendingOnly bool, filter *RunLogFilters) ([]*MarketMakingEvent, error) {
events := make([]*MarketMakingEvent, 0, 32)

return events, db.View(func(tx *bbolt.Tx) error {
Expand Down Expand Up @@ -667,6 +667,10 @@ func (db *boltEventLogDB) runEvents(startTime int64, mkt *MarketWithHost, n uint
continue
}

if !filter.filter(e) {
continue
}

events = append(events, e)
if n > 0 && uint64(len(events)) >= n {
break
Expand Down
4 changes: 4 additions & 0 deletions client/mm/exchange_adaptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -3236,6 +3236,7 @@ type ProfitLoss struct {
ModsUSD float64 `json:"modsUSD"`
Final map[uint32]*Amount `json:"final"`
FinalUSD float64 `json:"finalUSD"`
Diffs map[uint32]*Amount `json:"diffs"`
Profit float64 `json:"profit"`
ProfitRatio float64 `json:"profitRatio"`
}
Expand All @@ -3250,6 +3251,7 @@ func newProfitLoss(
pl := &ProfitLoss{
Initial: make(map[uint32]*Amount, len(initialBalances)),
Mods: make(map[uint32]*Amount, len(mods)),
Diffs: make(map[uint32]*Amount, len(initialBalances)),
Final: make(map[uint32]*Amount, len(finalBalances)),
}
for assetID, v := range initialBalances {
Expand All @@ -3262,6 +3264,8 @@ func newProfitLoss(
mod := NewAmount(assetID, mods[assetID], fiatRate)
pl.InitialUSD += init.USD
pl.ModsUSD += mod.USD
diff := int64(finalBalances[assetID]) - int64(initialBalances[assetID]) - mods[assetID]
pl.Diffs[assetID] = NewAmount(assetID, diff, fiatRate)
}
for assetID, v := range finalBalances {
if v == 0 {
Expand Down
66 changes: 57 additions & 9 deletions client/mm/mm.go
Original file line number Diff line number Diff line change
Expand Up @@ -1237,25 +1237,72 @@ func (m *MarketMaker) updatePendingEvent(mkt *MarketWithHost, event *MarketMakin
}
}

type RunLogFilters struct {
DexBuys bool `json:"dexBuys"`
DexSells bool `json:"dexSells"`
CexBuys bool `json:"cexBuys"`
CexSells bool `json:"cexSells"`
Deposits bool `json:"deposits"`
Withdrawals bool `json:"withdrawals"`
}

func (f *RunLogFilters) filter(event *MarketMakingEvent) bool {
switch {
case event.DEXOrderEvent != nil:
if event.DEXOrderEvent.Sell {
return f.DexSells
}
return f.DexBuys
case event.CEXOrderEvent != nil:
if event.CEXOrderEvent.Sell {
return f.CexSells
}
return f.CexBuys
case event.DepositEvent != nil:
return f.Deposits
case event.WithdrawalEvent != nil:
return f.Withdrawals
default:
return false
}
}

var noFilters = &RunLogFilters{
DexBuys: true,
DexSells: true,
CexBuys: true,
CexSells: true,
Deposits: true,
Withdrawals: true,
}

// RunLogs returns the event logs of a market making run. At most n events are
// returned, if n == 0 then all events are returned. If refID is not nil, then
// the events including and after refID are returned.
func (m *MarketMaker) RunLogs(startTime int64, mkt *MarketWithHost, n uint64, refID *uint64) ([]*MarketMakingEvent, *MarketMakingRunOverview, error) {
// Updated events are events that were updated from pending to confirmed during
// this call. For completed runs, on each call to RunLogs, all pending events are
// checked for updates, and anything that was updated is returned.
func (m *MarketMaker) RunLogs(startTime int64, mkt *MarketWithHost, n uint64, refID *uint64, filters *RunLogFilters) (events, updatedEvents []*MarketMakingEvent, overview *MarketMakingRunOverview, err error) {
var running bool
runningBotsLookup := m.runningBotsLookup()
if bot, found := runningBotsLookup[*mkt]; found {
running = bot.timeStart() == startTime
}

if filters == nil {
filters = noFilters
}

if !running {
pendingEvents, err := m.eventLogDB.runEvents(startTime, mkt, 0, nil, true)
pendingEvents, err := m.eventLogDB.runEvents(startTime, mkt, 0, nil, true, noFilters)
if err != nil {
return nil, nil, err
return nil, nil, nil, err
}
if len(pendingEvents) > 0 {
updatedEvents = make([]*MarketMakingEvent, 0, len(pendingEvents))
overview, err := m.eventLogDB.runOverview(startTime, mkt)
if err != nil {
return nil, nil, err
return nil, nil, nil, err
}
for _, event := range pendingEvents {
if event.Pending {
Expand All @@ -1264,23 +1311,24 @@ func (m *MarketMaker) RunLogs(startTime int64, mkt *MarketWithHost, n uint64, re
m.log.Errorf("Error updating pending event: %v", err)
continue
}
updatedEvents = append(updatedEvents, updatedEvent)
m.eventLogDB.storeEvent(startTime, mkt, updatedEvent, nil)
}
}
}
}

events, err := m.eventLogDB.runEvents(startTime, mkt, n, refID, false)
events, err = m.eventLogDB.runEvents(startTime, mkt, n, refID, false, filters)
if err != nil {
return nil, nil, err
return nil, nil, nil, err
}

overview, err := m.eventLogDB.runOverview(startTime, mkt)
overview, err = m.eventLogDB.runOverview(startTime, mkt)
if err != nil {
return nil, nil, err
return nil, nil, nil, err
}

return events, overview, nil
return events, updatedEvents, overview, nil
}

// CEXBook generates a snapshot of the specified CEX order book.
Expand Down
17 changes: 10 additions & 7 deletions client/webserver/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -1745,25 +1745,28 @@ func (s *WebServer) apiRunLogs(w http.ResponseWriter, r *http.Request) {
Market *mm.MarketWithHost `json:"market"`
N uint64 `json:"n"`
RefID *uint64 `json:"refID,omitempty"`
Filters *mm.RunLogFilters `json:"filters,omitempty"`
}
if !readPost(w, r, &req) {
return
}

logs, overview, err := s.mm.RunLogs(req.StartTime, req.Market, req.N, req.RefID)
logs, updatedLogs, overview, err := s.mm.RunLogs(req.StartTime, req.Market, req.N, req.RefID, req.Filters)
if err != nil {
s.writeAPIError(w, fmt.Errorf("error getting run logs: %w", err))
return
}

writeJSON(w, &struct {
OK bool `json:"ok"`
Overview *mm.MarketMakingRunOverview `json:"overview"`
Logs []*mm.MarketMakingEvent `json:"logs"`
OK bool `json:"ok"`
Overview *mm.MarketMakingRunOverview `json:"overview"`
Logs []*mm.MarketMakingEvent `json:"logs"`
UpdatedLogs []*mm.MarketMakingEvent `json:"updatedLogs"`
}{
OK: true,
Overview: overview,
Logs: logs,
OK: true,
Overview: overview,
Logs: logs,
UpdatedLogs: updatedLogs,
})
}

Expand Down
11 changes: 11 additions & 0 deletions client/webserver/locales/en-us.go
Original file line number Diff line number Diff line change
Expand Up @@ -622,4 +622,15 @@ var EnUS = map[string]*intl.Translation{
"remotegap_tooltip": {T: "The buy-sell spread on the linked cex market"},
"max_zero_no_fees": {T: `<span id="maxZeroNoFeesTicker"></span> balance < min fees ~<span id="maxZeroMinFees"></span>`},
"max_zero_no_bal": {T: `low <span id="maxZeroNoBalTicker"></span> balance`},
"balance_diff": {T: "Balance Diff"},
"usd_diff": {T: "USD Diff"},
"usd_rate": {T: "USD Rate"},
"dex_sell": {T: "DEX Sell"},
"dex_buy": {T: "DEX Buy"},
"cex_sell": {T: "CEX Sell"},
"cex_buy": {T: "CEX Buy"},
"deposit": {T: "Deposit"},
"withdrawal": {T: "Withdrawal"},
"filters": {T: "Filters"},
"Apply": {T: "Apply"},
}
1 change: 1 addition & 0 deletions client/webserver/site/src/css/components.scss
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ div[data-handler=order],
div[data-handler=orders],
div[data-handler=register],
div[data-handler=settings],
div[data-handler=mmlogs],
div[data-handler=wallets] {
#forms>form:not(.plain) {
border-radius: 5px;
Expand Down
9 changes: 9 additions & 0 deletions client/webserver/site/src/css/mm.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ div[data-handler=mm] {
width: 300px;
}

#eventsTablePanel {
& > div {
@include stylish-overflow;

height: 100%;
overflow-x: hidden;
}
}

.gap-factor-input,
.lots-input {
max-width: 75px;
Expand Down
48 changes: 25 additions & 23 deletions client/webserver/site/src/html/mmarchives.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,31 @@
<div class="flex-center fs24 p-2 flex-grow-1">[[[previous_mm_runs]]]</div>
</div>
<div class="px-5 py-3 w-100">
<table id="runTable" class="my-3 striped row-hover compact border row-border fs18">
<thead>
<th scope="col">[[[start_time]]]</th>
<th scope="col">[[[Host]]]</th>
<th scope="col">[[[Market]]]</th>
<th scope="col">[[[logs]]]</th>
<th scope="col">[[[Settings]]]</th>
</thead>
<tbody id="runTableBody">
<tr id="runTableRowTmpl">
<td data-tmpl="startTime"></td>
<td data-host></td>
<td>
<img class="mini-icon" data-base-logo>
<span data-base-ticker></span> -
<img class="mini-icon" data-quote-logo>
<span data-quote-ticker></span>
</td>
<td><button data-tmpl="logs">[[[view_logs]]]</button></td>
<td><span class="ico-settings fs20 pointer mx-2" data-tmpl="settings"></span></td>
</tr>
</tbody>
</table>
<section>
<table id="runTable" class="striped row-hover row-border">
<thead>
<th scope="col">[[[start_time]]]</th>
<th scope="col">[[[Host]]]</th>
<th scope="col">[[[Market]]]</th>
<th scope="col">[[[logs]]]</th>
<th scope="col">[[[Settings]]]</th>
</thead>
<tbody id="runTableBody">
<tr id="runTableRowTmpl">
<td data-tmpl="startTime"></td>
<td data-host></td>
<td>
<img class="mini-icon" data-base-logo>
<span data-base-ticker></span> -
<img class="mini-icon" data-quote-logo>
<span data-quote-ticker></span>
</td>
<td><button data-tmpl="logs">[[[view_logs]]]</button></td>
<td><span class="ico-settings fs20 pointer mx-2" data-tmpl="settings"></span></td>
</tr>
</tbody>
</table>
</section>
</div>
</div>
{{template "bottom"}}
Expand Down
Loading

0 comments on commit 14b765c

Please sign in to comment.