Skip to content

Commit

Permalink
switch spread off when in auction
Browse files Browse the repository at this point in the history
  • Loading branch information
wwestgarth committed Oct 30, 2024
1 parent 09018d0 commit 85c8d13
Show file tree
Hide file tree
Showing 6 changed files with 1,634 additions and 1,580 deletions.
21 changes: 21 additions & 0 deletions core/execution/amm/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ type Engine struct {
minCommitmentQuantum *num.Uint
maxCalculationLevels *num.Uint
allowedEmptyAMMLevels uint64

inAuction bool
}

func New(
Expand Down Expand Up @@ -211,13 +213,16 @@ func NewFromProto(
e.add(p)
}

e.inAuction = state.Auction

return e, nil
}

func (e *Engine) IntoProto() *v1.AmmState {
state := &v1.AmmState{
AmmPartyIds: make([]*v1.StringMapEntry, 0, len(e.ammParties)),
Pools: make([]*v1.PoolMapEntry, 0, len(e.pools)),
Auction: e.inAuction,
}

for k, v := range e.ammParties {
Expand All @@ -237,6 +242,20 @@ func (e *Engine) IntoProto() *v1.AmmState {
return state
}

func (e *Engine) EnterAuction() {
e.inAuction = true
for _, p := range e.poolsCpy {
p.inAuction = true
}
}

func (e *Engine) LeaveAuction() {
e.inAuction = false
for _, p := range e.poolsCpy {
p.inAuction = false
}
}

func (e *Engine) OnMinCommitmentQuantumUpdate(ctx context.Context, c *num.Uint) {
e.minCommitmentQuantum = c.Clone()
}
Expand Down Expand Up @@ -708,6 +727,8 @@ func (e *Engine) Create(
return nil, err
}

pool.inAuction = e.inAuction

// sanity check, a *new* AMM should not already have a position. If it does it means that the party
// previously had an AMM but it was stopped/cancelled while still holding a position which should not happen.
// It should have either handed its position over to the liquidation engine, or be in reduce-only mode
Expand Down
19 changes: 12 additions & 7 deletions core/execution/amm/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ type Pool struct {
oneTick *num.Uint // one price tick

cache *poolCache

inAuction bool
}

func NewPool(
Expand Down Expand Up @@ -337,6 +339,7 @@ func NewPoolFromProto(
SlippageTolerance: slippageTolerance,
MinimumPriceChangeTrigger: minimumPriceChangeTrigger,
Spread: spread,
inAuction: state.Auction,
}, nil
}

Expand Down Expand Up @@ -405,6 +408,7 @@ func (p *Pool) IntoProto() *snapshotpb.PoolMapEntry_Pool {
SlippageTolerance: p.SlippageTolerance.String(),
MinimumPriceChangeTrigger: p.MinimumPriceChangeTrigger.String(),
Spread: p.Spread.String(),
Auction: p.inAuction,
}
}

Expand Down Expand Up @@ -480,6 +484,7 @@ func (p *Pool) Update(
SlippageTolerance: amend.SlippageTolerance,
MinimumPriceChangeTrigger: amend.MinimumPriceChangeTrigger,
Spread: amend.Spread,
inAuction: p.inAuction,
}

// data source has changed, if the old base price is within bounds we'll keep it until the update comes in
Expand Down Expand Up @@ -1071,7 +1076,7 @@ func (p *Pool) BestPrice(side types.Side) (*num.Uint, bool, bool) {
}

bestPrice := num.UintZero().Add(fairPrice, p.oneTick)
if !p.Spread.IsZero() {
if !p.inAuction && !p.Spread.IsZero() {
// calculate the spread from the fair price
spreadPrice := num.DecimalOne().Add(p.Spread).Mul(fairPrice.ToDecimal())
if spreadPrice.GreaterThan(bestPrice.ToDecimal()) {
Expand All @@ -1096,7 +1101,7 @@ func (p *Pool) BestPrice(side types.Side) (*num.Uint, bool, bool) {
}

bestPrice := num.UintZero().Sub(fairPrice, p.oneTick)
if !p.Spread.IsZero() {
if !p.inAuction && !p.Spread.IsZero() {
spreadPrice := num.DecimalOne().Sub(p.Spread).Mul(fairPrice.ToDecimal())
if spreadPrice.LessThan(bestPrice.ToDecimal()) {
bestPrice, _ = num.UintFromDecimal(spreadPrice)
Expand All @@ -1119,7 +1124,7 @@ func (p *Pool) BestPriceAndVolume(side types.Side) (*num.Uint, uint64) {
// check cache
pos := p.getPosition()

if p, v, ok := p.cache.getBestPrice(pos, side, p.status); ok {
if p, v, ok := p.cache.getBestPrice(pos, side, p.status, p.inAuction); ok {
return p, v
}

Expand All @@ -1131,22 +1136,22 @@ func (p *Pool) BestPriceAndVolume(side types.Side) (*num.Uint, uint64) {
// now calculate the volume
if side == types.SideBuy {
if lowVolume {
p.cache.setBestPrice(pos, side, p.status, price, 1)
p.cache.setBestPrice(pos, side, p.status, p.inAuction, price, 1)
return price, 1 // its low volume so 1 by construction
}

volume := p.TradableVolumeForPrice(types.SideSell, price)
p.cache.setBestPrice(pos, side, p.status, price, volume)
p.cache.setBestPrice(pos, side, p.status, p.inAuction, price, volume)
return price, volume
}

if lowVolume {
p.cache.setBestPrice(pos, side, p.status, price, 1)
p.cache.setBestPrice(pos, side, p.status, p.inAuction, price, 1)
return price, 1 // its low volume so 1 by construction
}

volume := p.TradableVolumeForPrice(types.SideBuy, price)
p.cache.setBestPrice(pos, side, p.status, price, volume)
p.cache.setBestPrice(pos, side, p.status, p.inAuction, price, volume)
return price, volume
}

Expand Down
19 changes: 11 additions & 8 deletions core/execution/amm/pool_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ import (
)

type key struct {
pos int64
status types.AMMPoolStatus
pos int64
status types.AMMPoolStatus
inAuction bool
}

type priceVolume struct {
Expand Down Expand Up @@ -59,25 +60,27 @@ func (pc *poolCache) setFairPrice(pos int64, fp *num.Uint) {
}
}

func (pc *poolCache) getBestPrice(pos int64, side types.Side, status types.AMMPoolStatus) (*num.Uint, uint64, bool) {
func (pc *poolCache) getBestPrice(pos int64, side types.Side, status types.AMMPoolStatus, auction bool) (*num.Uint, uint64, bool) {
cache := pc.sell
if side == types.SideBuy {
cache = pc.buy
}

if pv, ok := cache[key{
pos: pos,
status: status,
pos: pos,
status: status,
inAuction: auction,
}]; ok {
return pv.price, pv.volume, true
}
return nil, 0, false
}

func (pc *poolCache) setBestPrice(pos int64, side types.Side, status types.AMMPoolStatus, price *num.Uint, volume uint64) {
func (pc *poolCache) setBestPrice(pos int64, side types.Side, status types.AMMPoolStatus, auction bool, price *num.Uint, volume uint64) {
k := key{
pos: pos,
status: status,
pos: pos,
status: status,
inAuction: auction,
}
cache := map[key]*priceVolume{
k: {
Expand Down
4 changes: 4 additions & 0 deletions core/execution/future/market.go
Original file line number Diff line number Diff line change
Expand Up @@ -1650,6 +1650,8 @@ func (m *Market) enterAuction(ctx context.Context) {
// Change market type to auction
ordersToCancel := m.matching.EnterAuction()

m.amm.EnterAuction()

// Move into auction mode to prevent pegged order repricing
event := m.as.AuctionStarted(ctx, m.timeService.GetTimeNow())

Expand Down Expand Up @@ -1684,6 +1686,8 @@ func (m *Market) uncrossOnLeaveAuction(ctx context.Context) ([]*types.OrderConfi
m.log.Error("Error leaving auction", logging.Error(err))
}

m.amm.LeaveAuction()

// Process each confirmation & apply fee calculations to each trade
evts := make([]events.Event, 0, len(uncrossedOrders))
for _, uncrossedOrder := range uncrossedOrders {
Expand Down
2 changes: 2 additions & 0 deletions protos/sources/vega/snapshot/v1/snapshot.proto
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,7 @@ message AmmState {
repeated StringMapEntry sqrter = 1;
repeated StringMapEntry amm_party_ids = 2;
repeated PoolMapEntry pools = 3;
bool auction = 4;
}

message PoolMapEntry {
Expand All @@ -601,6 +602,7 @@ message PoolMapEntry {
string slippage_tolerance = 11;
string minimum_price_change_trigger = 12;
string spread = 13;
bool auction = 14;
}

string party = 1;
Expand Down
Loading

0 comments on commit 85c8d13

Please sign in to comment.